Subversion Repositories Kolibri OS

Rev

Rev 4217 | Rev 4221 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4158 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  HTTP library for KolibriOS                                     ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
9
;;                                                                 ;;
10
;;         GNU GENERAL PUBLIC LICENSE                              ;;
11
;;          Version 2, June 1991                                   ;;
12
;;                                                                 ;;
13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14
 
15
; references:
16
; "HTTP made really easy", http://www.jmarshall.com/easy/http/
17
; "Hypertext Transfer Protocol -- HTTP/1.1", http://tools.ietf.org/html/rfc2616
18
 
19
 
20
        URLMAXLEN       = 65535
21
        BUFFERSIZE      = 4096
4206 hidnplayr 22
        TIMEOUT         = 1000  ; in 1/100 s
4158 hidnplayr 23
 
24
        __DEBUG__       = 1
25
        __DEBUG_LEVEL__ = 1
26
 
27
 
28
format MS COFF
29
 
30
public @EXPORT as 'EXPORTS'
31
 
32
include '../../../struct.inc'
33
include '../../../proc32.inc'
34
include '../../../macros.inc'
35
purge section,mov,add,sub
36
include '../../../debug-fdo.inc'
37
 
38
include '../../../network.inc'
39
include 'http.inc'
40
 
41
virtual at 0
42
        http_msg http_msg
43
end virtual
44
 
45
macro copy_till_zero {
46
  @@:
47
        lodsb
48
        test    al, al
49
        jz      @f
50
        stosb
51
        jmp     @r
52
  @@:
53
}
54
 
4167 hidnplayr 55
macro HTTP_init_buffer buffer, socketnum {
56
 
57
        mov     eax, buffer
58
        push    socketnum
59
        popd    [eax + http_msg.socket]
60
        lea     esi, [eax + http_msg.data]
4205 hidnplayr 61
        mov     [eax + http_msg.flags], FLAG_CONNECTED
4167 hidnplayr 62
        mov     [eax + http_msg.write_ptr], esi
63
        mov     [eax + http_msg.buffer_length], BUFFERSIZE -  http_msg.data
64
        mov     [eax + http_msg.chunk_ptr], 0
65
 
66
        mov     [eax + http_msg.status], 0
67
        mov     [eax + http_msg.header_length], 0
68
        mov     [eax + http_msg.content_length], 0
4168 hidnplayr 69
        mov     [eax + http_msg.content_received], 0
4206 hidnplayr 70
 
71
        push    eax ebp
72
        mov     ebp, eax
73
        mcall   29, 9
74
        mov     [ebp + http_msg.timestamp], eax
75
        pop     ebp eax
4167 hidnplayr 76
}
77
 
4158 hidnplayr 78
section '.flat' code readable align 16
79
 
80
;;===========================================================================;;
81
lib_init: ;//////////////////////////////////////////////////////////////////;;
82
;;---------------------------------------------------------------------------;;
83
;? Library entry point (called after library load)                           ;;
84
;;---------------------------------------------------------------------------;;
85
;> eax = pointer to memory allocation routine                                ;;
86
;> ebx = pointer to memory freeing routine                                   ;;
87
;> ecx = pointer to memory reallocation routine                              ;;
88
;> edx = pointer to library loading routine                                  ;;
89
;;---------------------------------------------------------------------------;;
4209 hidnplayr 90
;< eax = 1 (fail) / 0 (ok)                                                   ;;
4158 hidnplayr 91
;;===========================================================================;;
92
        mov     [mem.alloc], eax
93
        mov     [mem.free], ebx
94
        mov     [mem.realloc], ecx
95
        mov     [dll.load], edx
96
 
97
        invoke  dll.load, @IMPORT
4209 hidnplayr 98
        test    eax, eax
99
        jnz     .error
4158 hidnplayr 100
 
101
; load proxy settings
4216 hidnplayr 102
        pusha
4158 hidnplayr 103
        invoke  ini.get_str, inifile, sec_proxy, key_proxy, proxyAddr, 256, proxyAddr
104
        invoke  ini.get_int, inifile, sec_proxy, key_proxyport, 80
105
        mov     [proxyPort], eax
106
        invoke  ini.get_str, inifile, sec_proxy, key_user, proxyUser, 256, proxyUser
107
        invoke  ini.get_str, inifile, sec_proxy, key_password, proxyPassword, 256, proxyPassword
4216 hidnplayr 108
        popa
4158 hidnplayr 109
 
4212 hidnplayr 110
        DEBUGF  1, "HTTP library: init OK\n"
4211 hidnplayr 111
 
4158 hidnplayr 112
        xor     eax, eax
113
        ret
114
 
4209 hidnplayr 115
  .error:
4212 hidnplayr 116
        DEBUGF  1, "ERROR loading libraries\n"
4211 hidnplayr 117
 
4158 hidnplayr 118
        xor     eax, eax
4209 hidnplayr 119
        inc     eax
120
 
4158 hidnplayr 121
        ret
122
 
123
 
124
 
125
 
126
;;================================================================================================;;
127
proc HTTP_get URL ;///////////////////////////////////////////////////////////////////////////////;;
128
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 129
;? Initiates a HTTP connection, using 'GET' method.                                               ;;
4158 hidnplayr 130
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 131
;> URL = pointer to ASCIIZ URL                                                                    ;;
4158 hidnplayr 132
;;------------------------------------------------------------------------------------------------;;
133
;< eax = 0 (error) / buffer ptr                                                                   ;;
134
;;================================================================================================;;
135
locals
136
        hostname        dd ?
137
        pageaddr        dd ?
138
        sockaddr        dd ?
139
        socketnum       dd ?
140
        buffer          dd ?
4167 hidnplayr 141
        port            dd ?
4158 hidnplayr 142
endl
143
 
4216 hidnplayr 144
        pusha
145
 
4158 hidnplayr 146
; split the URL into hostname and pageaddr
147
        stdcall parse_url, [URL]
148
        test    eax, eax
149
        jz      .error
150
        mov     [hostname], eax
151
        mov     [pageaddr], ebx
152
 
153
; Do we need to use a proxy?
154
        cmp     [proxyAddr], 0
155
        jne     .proxy_done
156
 
157
  .proxy_done:
158
 
4167 hidnplayr 159
;;;;
160
        mov     [port], 80      ;;;; FIXME
161
 
162
; Connect to the other side.
163
        stdcall open_connection, [hostname], [port]
4158 hidnplayr 164
        test    eax, eax
4167 hidnplayr 165
        jz      .error
166
        mov     [socketnum], eax
4158 hidnplayr 167
 
4167 hidnplayr 168
; Create the HTTP request.
169
        invoke  mem.alloc, BUFFERSIZE
4158 hidnplayr 170
        test    eax, eax
171
        jz      .error
4167 hidnplayr 172
        mov     [buffer], eax
173
        mov     edi, eax
174
        DEBUGF  1, "Buffer has been allocated.\n"
4158 hidnplayr 175
 
4167 hidnplayr 176
        mov     esi, str_get
177
        copy_till_zero
4158 hidnplayr 178
 
4167 hidnplayr 179
        mov     esi, [pageaddr]
180
        copy_till_zero
4158 hidnplayr 181
 
4167 hidnplayr 182
        mov     esi, str_http11
183
        mov     ecx, str_http11.length
184
        rep     movsb
185
 
186
        mov     esi, [hostname]
187
        copy_till_zero
188
 
189
        mov     esi, str_close
190
        mov     ecx, str_close.length
191
        rep     movsb
192
 
193
        mov     byte[edi], 0
194
        DEBUGF  1, "Request:\n%s", [buffer]
195
 
196
; Send the request
197
        mov     esi, edi
198
        sub     esi, [buffer]   ; length
199
        xor     edi, edi        ; flags
200
 
201
        mcall   send, [socketnum], [buffer]
4158 hidnplayr 202
        test    eax, eax
203
        jz      .error
4167 hidnplayr 204
        DEBUGF  1, "Request has been sent to server.\n"
4158 hidnplayr 205
 
4167 hidnplayr 206
        HTTP_init_buffer [buffer], [socketnum]
207
 
4216 hidnplayr 208
        popa
209
        mov     eax, [buffer]   ; return buffer ptr
210
        ret
4167 hidnplayr 211
 
212
  .error:
213
        DEBUGF  1, "Error!\n"
4216 hidnplayr 214
        popa
4167 hidnplayr 215
        xor     eax, eax        ; return 0 = error
216
        ret
217
 
218
endp
219
 
220
 
221
 
222
;;================================================================================================;;
4202 hidnplayr 223
proc HTTP_head URL ;//////////////////////////////////////////////////////////////////////////////;;
4167 hidnplayr 224
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 225
;? Initiates a HTTP connection, using 'HEAD' method.                                              ;;
4167 hidnplayr 226
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 227
;> URL = pointer to ASCIIZ URL                                                                    ;;
4167 hidnplayr 228
;;------------------------------------------------------------------------------------------------;;
229
;< eax = 0 (error) / buffer ptr                                                                   ;;
230
;;================================================================================================;;
231
locals
232
        hostname        dd ?
233
        pageaddr        dd ?
234
        sockaddr        dd ?
235
        socketnum       dd ?
236
        buffer          dd ?
237
        port            dd ?
238
endl
239
 
4216 hidnplayr 240
        pusha
4167 hidnplayr 241
; split the URL into hostname and pageaddr
242
        stdcall parse_url, [URL]
4158 hidnplayr 243
        test    eax, eax
4167 hidnplayr 244
        jz      .error
245
        mov     [hostname], eax
246
        mov     [pageaddr], ebx
4158 hidnplayr 247
 
4167 hidnplayr 248
; Do we need to use a proxy?
249
        cmp     [proxyAddr], 0
250
        jne     .proxy_done
4158 hidnplayr 251
 
4167 hidnplayr 252
        ; TODO: set hostname to that of the
253
  .proxy_done:
254
 
255
;;;;
256
        mov     [port], 80      ;;;; FIXME
257
 
258
; Connect to the other side.
259
        stdcall open_connection, [hostname], [port]
260
        test    eax, eax
261
        jz      .error
262
        mov     [socketnum], eax
263
 
4158 hidnplayr 264
; Create the HTTP request.
265
        invoke  mem.alloc, BUFFERSIZE
266
        test    eax, eax
267
        jz      .error
268
        mov     [buffer], eax
4167 hidnplayr 269
        mov     edi, eax
4158 hidnplayr 270
        DEBUGF  1, "Buffer has been allocated.\n"
271
 
4167 hidnplayr 272
        mov     esi, str_head
4158 hidnplayr 273
        copy_till_zero
274
 
4167 hidnplayr 275
        mov     esi, [pageaddr]
276
        copy_till_zero
277
 
4158 hidnplayr 278
        mov     esi, str_http11
279
        mov     ecx, str_http11.length
280
        rep     movsb
281
 
282
        mov     esi, [hostname]
283
        copy_till_zero
284
 
285
        mov     esi, str_close
286
        mov     ecx, str_close.length
287
        rep     movsb
288
 
289
        mov     byte[edi], 0
290
        DEBUGF  1, "Request:\n%s", [buffer]
291
 
4167 hidnplayr 292
; Send the request
4158 hidnplayr 293
        mov     esi, edi
294
        sub     esi, [buffer]   ; length
295
        xor     edi, edi        ; flags
296
 
297
        mcall   send, [socketnum], [buffer]
298
        test    eax, eax
299
        jz      .error
300
        DEBUGF  1, "Request has been sent to server.\n"
301
 
4167 hidnplayr 302
        HTTP_init_buffer [buffer], [socketnum]
4158 hidnplayr 303
 
4216 hidnplayr 304
        popa
305
        mov     eax, [buffer]
4167 hidnplayr 306
        ret                     ; return buffer ptr
4158 hidnplayr 307
 
4167 hidnplayr 308
  .error:
309
        DEBUGF  1, "Error!\n"
4216 hidnplayr 310
        popa
4167 hidnplayr 311
        xor     eax, eax        ; return 0 = error
312
        ret
313
 
314
endp
315
 
316
 
317
;;================================================================================================;;
4168 hidnplayr 318
proc HTTP_post URL, content_type, content_length ;////////////////////////////////////////////////;;
4167 hidnplayr 319
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 320
;? Initiates a HTTP connection, using 'GET' method.                                               ;;
4167 hidnplayr 321
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 322
;> URL                  = pointer to ASCIIZ URL                                                   ;;
323
;> content_type         = pointer to ASCIIZ string containing content type                        ;;
324
;> content_length       = length of content (in bytes)                                            ;;
4167 hidnplayr 325
;;------------------------------------------------------------------------------------------------;;
326
;< eax = 0 (error) / buffer ptr                                                                   ;;
327
;;================================================================================================;;
328
locals
329
        hostname        dd ?
330
        pageaddr        dd ?
331
        sockaddr        dd ?
332
        socketnum       dd ?
333
        buffer          dd ?
334
        port            dd ?
335
endl
336
 
4216 hidnplayr 337
        pusha
4167 hidnplayr 338
; split the URL into hostname and pageaddr
339
        stdcall parse_url, [URL]
340
        test    eax, eax
341
        jz      .error
342
        mov     [hostname], eax
343
        mov     [pageaddr], ebx
344
 
345
; Do we need to use a proxy?
346
        cmp     [proxyAddr], 0
347
        jne     .proxy_done
348
 
349
        ; TODO: set hostname to that of the
350
  .proxy_done:
351
 
352
;;;;
353
        mov     [port], 80      ;;;; FIXME
354
 
355
; Connect to the other side.
356
        stdcall open_connection, [hostname], [port]
357
        test    eax, eax
358
        jz      .error
359
        mov     [socketnum], eax
360
 
361
; Create the HTTP request.
362
        invoke  mem.alloc, BUFFERSIZE
363
        test    eax, eax
364
        jz      .error
365
        mov     [buffer], eax
366
        mov     edi, eax
367
        DEBUGF  1, "Buffer has been allocated.\n"
368
 
369
        mov     esi, str_post
370
        copy_till_zero
371
 
372
        mov     esi, [pageaddr]
373
        copy_till_zero
374
 
375
        mov     esi, str_http11
376
        mov     ecx, str_http11.length
377
        rep     movsb
378
 
379
        mov     esi, [hostname]
380
        copy_till_zero
381
 
382
        mov     esi, str_post_cl
383
        mov     ecx, str_post_cl.length
384
        rep     movsb
385
 
386
        mov     eax, [content_length]
387
        call    ascii_dec
388
 
389
        mov     esi, str_post_ct
390
        mov     ecx, str_post_ct.length
391
        rep     movsb
392
 
393
        mov     esi, [content_type]
394
        rep     movsb
395
 
396
        mov     esi, str_close
397
        mov     ecx, str_close.length
398
        rep     movsb
399
 
400
        mov     byte[edi], 0
401
        DEBUGF  1, "Request:\n%s", [buffer]
402
 
403
; Send the request
404
        mov     esi, edi
405
        sub     esi, [buffer]   ; length
406
        xor     edi, edi        ; flags
407
        mcall   send, [socketnum], [buffer]
408
        test    eax, eax
409
        jz      .error
410
        DEBUGF  1, "Request has been sent to server.\n"
411
 
412
        HTTP_init_buffer [buffer], [socketnum]
4206 hidnplayr 413
 
4216 hidnplayr 414
        popa
415
        mov     eax, [buffer]
4158 hidnplayr 416
        ret                     ; return buffer ptr
417
 
418
  .error:
419
        DEBUGF  1, "Error!\n"
4216 hidnplayr 420
        popa
4158 hidnplayr 421
        xor     eax, eax        ; return 0 = error
422
        ret
423
 
424
endp
425
 
426
 
427
 
428
;;================================================================================================;;
429
proc HTTP_process identifier ;////////////////////////////////////////////////////////////////////;;
430
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 431
;? Receive data from the server, parse headers and put data in receive buffer.                    ;;
432
;? To complete a transfer, this procedure must be called over and over again untill it returns 0. ;;
4158 hidnplayr 433
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 434
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
4158 hidnplayr 435
;;------------------------------------------------------------------------------------------------;;
436
;< eax = -1 (not finished) / 0 finished                                                           ;;
437
;;================================================================================================;;
438
        pusha
439
        mov     ebp, [identifier]
4162 hidnplayr 440
 
4209 hidnplayr 441
; If the connection is closed, return immediately
4205 hidnplayr 442
        test    [ebp + http_msg.flags], FLAG_CONNECTED
443
        jz      .connection_closed
444
 
4162 hidnplayr 445
; Receive some data
4158 hidnplayr 446
        mcall   recv, [ebp + http_msg.socket], [ebp + http_msg.write_ptr], \
447
                      [ebp + http_msg.buffer_length], MSG_DONTWAIT
448
        cmp     eax, 0xffffffff
449
        je      .check_socket
4220 hidnplayr 450
 
451
        test    eax, eax
452
        jz      .server_closed
4158 hidnplayr 453
        DEBUGF  1, "Received %u bytes\n", eax
454
 
4209 hidnplayr 455
; Update timestamp
4206 hidnplayr 456
        push    eax
457
        mcall   29, 9
458
        mov     [ebp + http_msg.timestamp], eax
459
        pop     eax
460
 
4162 hidnplayr 461
; Update pointers
4158 hidnplayr 462
        mov     edi, [ebp + http_msg.write_ptr]
463
        add     [ebp + http_msg.write_ptr], eax
464
        sub     [ebp + http_msg.buffer_length], eax
465
        jz      .got_all_data
4162 hidnplayr 466
 
467
; If data is chunked, combine chunks into contiguous data.
468
        test    [ebp + http_msg.flags], FLAG_CHUNKED
469
        jnz     .chunk_loop
470
 
4212 hidnplayr 471
; Did we detect the (final) header yet?
4158 hidnplayr 472
        test    [ebp + http_msg.flags], FLAG_GOT_HEADER
473
        jnz     .header_parsed
474
 
4212 hidnplayr 475
; We havent found the (final) header yet, search for it..
476
  .scan_again:
477
        ; eax = total number of bytes received so far
478
        mov     eax, [ebp + http_msg.write_ptr]
479
        sub     eax, http_msg.data
480
        sub     eax, ebp
481
        sub     eax, [ebp + http_msg.header_length]
482
        ; edi is ptr to begin of header
483
        lea     edi, [ebp + http_msg.data]
484
        add     edi, [ebp + http_msg.header_length]
485
        ; put it in esi for next proc too
486
        mov     esi, edi
487
        sub     eax, 3
488
        jle     .need_more_data
489
  .scan_loop:
4158 hidnplayr 490
        ; scan for end of header (empty line)
491
        cmp     dword[edi], 0x0a0d0a0d                  ; end of header
492
        je      .end_of_header
4212 hidnplayr 493
        cmp     word[edi+2], 0x0a0a                     ; notice the use of offset + 2, to calculate header length correctly :)
4158 hidnplayr 494
        je      .end_of_header
495
        inc     edi
496
        dec     eax
4212 hidnplayr 497
        jnz     .scan_loop
498
        jmp     .need_more_data
4158 hidnplayr 499
 
500
  .end_of_header:
501
        add     edi, 4 - http_msg.data
502
        sub     edi, ebp
4212 hidnplayr 503
        mov     [ebp + http_msg.header_length], edi     ; If this isnt the final header, we'll use this as an offset to find real header.
4158 hidnplayr 504
        DEBUGF  1, "Header length: %u\n", edi
505
 
506
; Ok, we have found header:
4212 hidnplayr 507
        cmp     dword[esi], 'HTTP'
4158 hidnplayr 508
        jne     .invalid_header
4212 hidnplayr 509
        cmp     dword[esi+4], '/1.0'
4158 hidnplayr 510
        je      .http_1.0
4212 hidnplayr 511
        cmp     dword[esi+4], '/1.1'
4158 hidnplayr 512
        jne     .invalid_header
513
        or      [ebp + http_msg.flags], FLAG_HTTP11
514
  .http_1.0:
4212 hidnplayr 515
        cmp     byte[esi+8], ' '
4158 hidnplayr 516
        jne     .invalid_header
517
 
4212 hidnplayr 518
        add     esi, 9
4158 hidnplayr 519
        xor     eax, eax
520
        xor     ebx, ebx
521
        mov     ecx, 3
522
  .statusloop:
523
        lodsb
524
        sub     al, '0'
525
        jb      .invalid_header
526
        cmp     al, 9
527
        ja      .invalid_header
528
        lea     ebx, [ebx + 4*ebx]
529
        shl     ebx, 1
530
        add     ebx, eax
531
        dec     ecx
532
        jnz     .statusloop
4212 hidnplayr 533
 
534
; Ignore "100 - Continue" headers
535
        cmp     ebx, 100
536
        je      .scan_again
537
 
538
        DEBUGF  1, "Status: %u\n", ebx
4158 hidnplayr 539
        mov     [ebp + http_msg.status], ebx
4212 hidnplayr 540
        or      [ebp + http_msg.flags], FLAG_GOT_HEADER
4158 hidnplayr 541
 
542
; Now, convert all header names to lowercase.
543
; This way, it will be much easier to find certain header fields, later on.
544
 
545
        lea     esi, [ebp + http_msg.data]
546
        mov     ecx, [ebp + http_msg.header_length]
547
  .need_newline:
548
        inc     esi
549
        dec     ecx
550
        jz      .convert_done
551
        cmp     byte[esi], 10
552
        jne     .need_newline
553
; Ok, we have a newline, a line beginning with space or tabs has no header fields.
554
 
555
        inc     esi
556
        dec     ecx
557
        jz      .convert_done
558
        cmp     byte[esi], ' '
559
        je      .need_newline
560
        cmp     byte[esi], 9    ; horizontal tab
561
        je      .need_newline
562
        jmp     .convert_loop
563
  .next_char:
564
        inc     esi
565
        dec     ecx
566
        jz      .convert_done
567
  .convert_loop:
568
        cmp     byte[esi], ':'
569
        je      .need_newline
570
        cmp     byte[esi], 'A'
571
        jb      .next_char
572
        cmp     byte[esi], 'Z'
573
        ja      .next_char
574
        or      byte[esi], 0x20 ; convert to lowercase
575
        jmp     .next_char
576
  .convert_done:
577
        mov     byte[esi-1], 0
578
        lea     esi, [ebp + http_msg.data]
579
        DEBUGF  1, "Header names converted to lowercase:\n%s\n", esi
580
 
581
; Check for content-length header field.
582
        stdcall find_header_field, ebp, str_cl
583
        test    eax, eax
584
        jz      .no_content
585
        or      [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
586
 
587
        xor     edx, edx
588
  .cl_loop:
589
        movzx   ebx, byte[eax]
590
        inc     eax
591
        cmp     bl, 10
592
        je      .cl_ok
593
        cmp     bl, 13
594
        je      .cl_ok
595
        cmp     bl, ' '
596
        je      .cl_ok
597
        sub     bl, '0'
598
        jb      .invalid_header
599
        cmp     bl, 9
600
        ja      .invalid_header
601
        lea     edx, [edx + edx*4]      ; edx = edx*10
602
        shl     edx, 1                  ;
603
        add     edx, ebx
604
        jmp     .cl_loop
605
 
606
  .cl_ok:
607
        mov     [ebp + http_msg.content_length], edx
608
        DEBUGF  1, "Content-length: %u\n", edx
609
 
610
; Resize buffer according to content-length.
4168 hidnplayr 611
        add     edx, [ebp + http_msg.header_length]
612
        add     edx, http_msg.data
4158 hidnplayr 613
 
4168 hidnplayr 614
        mov     ecx, edx
4158 hidnplayr 615
        sub     ecx, [ebp + http_msg.write_ptr]
616
        mov     [ebp + http_msg.buffer_length], ecx
617
 
4168 hidnplayr 618
        invoke  mem.realloc, ebp, edx
4158 hidnplayr 619
        or      eax, eax
4212 hidnplayr 620
        jz      .no_ram
4203 hidnplayr 621
 
4220 hidnplayr 622
  .not_chunked:
4212 hidnplayr 623
        mov     eax, [ebp + http_msg.write_ptr]
4168 hidnplayr 624
        sub     eax, [ebp + http_msg.header_length]
4212 hidnplayr 625
        sub     eax, http_msg.data
626
        sub     eax, ebp
4158 hidnplayr 627
        jmp     .header_parsed  ; hooray!
628
 
629
  .no_content:
630
        DEBUGF  1, "Content-length not found.\n"
631
 
632
; We didnt find 'content-length', maybe server is using chunked transfer encoding?
633
; Try to find 'transfer-encoding' header.
634
        stdcall find_header_field, ebp, str_te
635
        test    eax, eax
4220 hidnplayr 636
        jz      .not_chunked
4158 hidnplayr 637
 
638
        mov     ebx, dword[eax]
4162 hidnplayr 639
        or      ebx, 0x20202020
4158 hidnplayr 640
        cmp     ebx, 'chun'
4220 hidnplayr 641
        jne     .not_chunked
4158 hidnplayr 642
        mov     ebx, dword[eax+4]
4162 hidnplayr 643
        or      ebx, 0x00202020
644
        and     ebx, 0x00ffffff
4158 hidnplayr 645
        cmp     ebx, 'ked'
4220 hidnplayr 646
        jne     .not_chunked
4158 hidnplayr 647
 
648
        or      [ebp + http_msg.flags], FLAG_CHUNKED
649
        DEBUGF  1, "Transfer type is: chunked\n"
650
 
651
; Set chunk pointer where first chunk should begin.
4162 hidnplayr 652
        lea     eax, [ebp + http_msg.data]
653
        add     eax, [ebp + http_msg.header_length]
4158 hidnplayr 654
        mov     [ebp + http_msg.chunk_ptr], eax
655
 
4162 hidnplayr 656
  .chunk_loop:
4158 hidnplayr 657
        mov     ecx, [ebp + http_msg.write_ptr]
658
        sub     ecx, [ebp + http_msg.chunk_ptr]
4202 hidnplayr 659
        jb      .need_more_data_chunked         ; TODO: use this ecx !!!
4158 hidnplayr 660
 
4202 hidnplayr 661
; Chunkline starts here, convert the ASCII hex number into ebx
4158 hidnplayr 662
        mov     esi, [ebp + http_msg.chunk_ptr]
663
        xor     ebx, ebx
664
  .chunk_hexloop:
665
        lodsb
666
        sub     al, '0'
667
        jb      .chunk_
668
        cmp     al, 9
669
        jbe     .chunk_hex
4162 hidnplayr 670
        sub     al, 'A' - '0' - 10
4158 hidnplayr 671
        jb      .chunk_
4162 hidnplayr 672
        cmp     al, 15
4158 hidnplayr 673
        jbe     .chunk_hex
674
        sub     al, 'a' - 'A'
4162 hidnplayr 675
        cmp     al, 15
4158 hidnplayr 676
        ja      .chunk_
677
  .chunk_hex:
678
        shl     ebx, 4
679
        add     bl, al
680
        jmp     .chunk_hexloop
681
  .chunk_:
682
        DEBUGF  1, "got chunk of %u bytes\n", ebx
4202 hidnplayr 683
;;        cmp     esi, [ebp + http_msg.chunk_ptr]
684
;;        je
4158 hidnplayr 685
; If chunk size is 0, all chunks have been received.
686
        test    ebx, ebx
4162 hidnplayr 687
        jz      .got_all_data_chunked           ; last chunk, hooray! FIXME: what if it wasnt a valid hex number???
4158 hidnplayr 688
 
689
; Chunkline ends with a CR, LF or simply LF
4202 hidnplayr 690
  .end_of_chunkline?:
4158 hidnplayr 691
        cmp     al, 10
692
        je      .end_of_chunkline
693
        lodsb
4202 hidnplayr 694
        cmp     edi, [ebp + http_msg.write_ptr]
695
        jb      .end_of_chunkline?
696
        jmp     .need_more_data
4158 hidnplayr 697
 
698
  .end_of_chunkline:
4202 hidnplayr 699
; Update chunk ptr, and remember old one
700
        mov     edi, [ebp + http_msg.chunk_ptr]
701
        add     [ebp + http_msg.chunk_ptr], ebx
4162 hidnplayr 702
; Realloc buffer, make it 'chunksize' bigger.
703
        mov     eax, [ebp + http_msg.buffer_length]
704
        add     eax, ebx
705
        invoke  mem.realloc, ebp, eax
706
        or      eax, eax
707
        jz      .no_ram
708
        add     [ebp + http_msg.buffer_length], ebx
709
 
710
; Update write ptr
711
        mov     eax, esi
712
        sub     eax, edi
713
        sub     [ebp + http_msg.write_ptr], eax
714
 
4158 hidnplayr 715
; Now move all received data to the left (remove chunk header).
4162 hidnplayr 716
; Update content_length accordingly.
4158 hidnplayr 717
        mov     ecx, [ebp + http_msg.write_ptr]
718
        sub     ecx, esi
4168 hidnplayr 719
        add     [ebp + http_msg.content_received], ecx
4158 hidnplayr 720
        rep     movsb
4162 hidnplayr 721
        jmp     .chunk_loop
4158 hidnplayr 722
 
723
; Check if we got all the data.
4162 hidnplayr 724
  .header_parsed:
4168 hidnplayr 725
        add     [ebp + http_msg.content_received], eax
4220 hidnplayr 726
        test    [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
727
        jz      .need_more_data_and_space
4217 hidnplayr 728
        mov     eax, [ebp + http_msg.content_received]
729
        cmp     eax, [ebp + http_msg.content_length]
4168 hidnplayr 730
        jae     .got_all_data
4220 hidnplayr 731
        jmp     .need_more_data
4212 hidnplayr 732
 
4220 hidnplayr 733
  .need_more_data_and_space:
734
        mov     eax, [ebp + http_msg.write_ptr]
735
        add     eax, BUFFERSIZE
736
        sub     eax, ebp
737
        invoke  mem.realloc, ebp, eax
738
        or      eax, eax
739
        jz      .no_ram
740
        mov     [ebp + http_msg.buffer_length], BUFFERSIZE
741
 
4162 hidnplayr 742
  .need_more_data:
743
        popa
744
        xor     eax, eax
745
        dec     eax
746
        ret
4158 hidnplayr 747
 
4162 hidnplayr 748
  .need_more_data_chunked:
4168 hidnplayr 749
        add     [ebp + http_msg.content_received], eax
4158 hidnplayr 750
        popa
751
        xor     eax, eax
752
        dec     eax
753
        ret
754
 
4162 hidnplayr 755
  .got_all_data_chunked:
756
        mov     eax, [ebp + http_msg.chunk_ptr]
757
        sub     eax, [ebp + http_msg.header_length]
758
        sub     eax, http_msg.data
759
        sub     eax, ebp
760
        mov     [ebp + http_msg.content_length], eax
4168 hidnplayr 761
        mov     [ebp + http_msg.content_received], eax
4158 hidnplayr 762
  .got_all_data:
4217 hidnplayr 763
        DEBUGF  1, "We got all the data! (%u bytes)\n", [ebp + http_msg.content_received]
4205 hidnplayr 764
        or      [ebp + http_msg.flags], FLAG_GOT_ALL_DATA
765
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
4158 hidnplayr 766
        mcall   close, [ebp + http_msg.socket]
767
        popa
768
        xor     eax, eax
769
        ret
770
 
771
  .check_socket:
772
        cmp     ebx, EWOULDBLOCK
4206 hidnplayr 773
        jne     .socket_error
4158 hidnplayr 774
 
4206 hidnplayr 775
        mcall   29, 9
776
        sub     eax, TIMEOUT
777
        cmp     eax, [ebp + http_msg.timestamp]
4207 hidnplayr 778
        jb      .need_more_data
4206 hidnplayr 779
        DEBUGF  1, "ERROR: timeout\n"
780
        or      [ebp + http_msg.flags], FLAG_TIMEOUT_ERROR
781
        jmp     .disconnect
4158 hidnplayr 782
 
4220 hidnplayr 783
  .server_closed:
784
        DEBUGF  1, "server closed connection, transfer complete?\n"
785
        test    [ebp + http_msg.flags], FLAG_GOT_HEADER
786
        jz      .server_error
787
        test    [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
788
        jz      .got_all_data
789
 
790
  .server_error:
791
        pop     eax
792
        DEBUGF  1, "ERROR: server closed connection unexpectedly\n"
793
        or      [ebp + http_msg.flags], FLAG_TRANSFER_FAILED
794
        jmp     .disconnect
795
 
4158 hidnplayr 796
  .invalid_header:
4203 hidnplayr 797
        pop     eax
4158 hidnplayr 798
        DEBUGF  1, "ERROR: invalid header\n"
799
        or      [ebp + http_msg.flags], FLAG_INVALID_HEADER
4206 hidnplayr 800
        jmp     .disconnect
4158 hidnplayr 801
 
802
  .no_ram:
803
        DEBUGF  1, "ERROR: out of RAM\n"
804
        or      [ebp + http_msg.flags], FLAG_NO_RAM
4206 hidnplayr 805
        jmp     .disconnect
806
 
807
  .socket_error:
808
        DEBUGF  1, "ERROR: socket error %u\n", ebx
809
        or      [ebp + http_msg.flags], FLAG_SOCKET_ERROR
810
  .disconnect:
4205 hidnplayr 811
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
812
        mcall   close, [ebp + http_msg.socket]
4206 hidnplayr 813
  .connection_closed:
4158 hidnplayr 814
        popa
815
        xor     eax, eax
816
        ret
817
 
818
endp
819
 
820
 
821
 
4205 hidnplayr 822
 
4158 hidnplayr 823
;;================================================================================================;;
4205 hidnplayr 824
proc HTTP_free identifier ;///////////////////////////////////////////////////////////////////////;;
825
;;------------------------------------------------------------------------------------------------;;
826
;? Free the http_msg structure                                                                    ;;
827
;;------------------------------------------------------------------------------------------------;;
828
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
829
;;------------------------------------------------------------------------------------------------;;
830
;< none                                                                                           ;;
831
;;================================================================================================;;
832
 
833
        pusha
834
        mov     ebp, [identifier]
835
 
836
        test    [ebp + http_msg.flags], FLAG_CONNECTED
837
        jz      .not_connected
838
 
839
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
840
        mcall   close, [ebp + http_msg.socket]
841
 
842
  .not_connected:
843
        invoke  mem.free, ebp
844
 
845
        popa
846
        ret
847
 
848
endp
849
 
850
 
851
 
852
;;================================================================================================;;
853
proc HTTP_stop identifier ;///////////////////////////////////////////////////////////////////////;;
854
;;------------------------------------------------------------------------------------------------;;
855
;? Stops the open connection                                                                      ;;
856
;;------------------------------------------------------------------------------------------------;;
857
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
858
;;------------------------------------------------------------------------------------------------;;
859
;< none                                                                                           ;;
860
;;================================================================================================;;
861
 
862
        pusha
863
        mov     ebp, [identifier]
864
 
865
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
866
        mcall   close, [ebp + http_msg.socket]
867
 
868
        popa
869
        ret
870
 
871
endp
872
 
873
 
874
 
875
;;================================================================================================;;
4158 hidnplayr 876
proc find_header_field identifier, headername ;///////////////////////////////////////////////////;;
877
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 878
;? Find a header field in the received HTTP header                                                ;;
4158 hidnplayr 879
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 880
;> identifier   = ptr to http_msg struct                                                          ;;
881
;> headername   = ptr to ASCIIZ string containg field you want to find (must be in lowercase)     ;;
4158 hidnplayr 882
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 883
;< eax = 0 (error) / ptr to content of the HTTP header field                                      ;;
4158 hidnplayr 884
;;================================================================================================;;
885
        push    ebx ecx edx esi edi
886
 
887
        DEBUGF  1, "Find header field: %s\n", [headername]
888
 
889
        mov     ebx, [identifier]
4202 hidnplayr 890
        test    [ebx + http_msg.flags], FLAG_GOT_HEADER
891
        jz      .fail
892
 
4158 hidnplayr 893
        lea     edx, [ebx + http_msg.data]
894
        mov     ecx, edx
895
        add     ecx, [ebx + http_msg.header_length]
896
 
897
  .restart:
898
        mov     esi, [headername]
899
        mov     edi, edx
900
  .loop:
901
        cmp     edi, ecx
902
        jae     .fail
903
        lodsb
904
        scasb
905
        je      .loop
906
        test    al, al
907
        jz      .done?
908
  .next:
909
        inc     edx
910
        jmp     .restart
911
 
912
  .not_done:
913
        inc     edi
914
  .done?:
915
        cmp     byte[edi-1], ':'
916
        je      .almost_done
917
        cmp     byte[edi-1], ' '
918
        je      .not_done
919
        cmp     byte[edi-1], 9  ; tab
920
        je      .not_done
921
 
922
        jmp     .next
923
 
924
  .almost_done:                 ; FIXME: buffer overflow?
925
        dec     edi
926
        DEBUGF  1, "Found header field\n"
927
  .spaceloop:
928
        inc     edi
929
        cmp     byte[edi], ' '
930
        je      .spaceloop
931
        cmp     byte[edi], 9    ; tab
932
        je      .spaceloop
933
 
934
        mov     eax, edi
935
        pop     edi esi edx ecx ebx
936
        ret
937
 
938
  .fail:
939
        pop     edi esi edx ecx ebx
940
        xor     eax, eax
941
        ret
942
 
943
endp
944
 
945
 
946
 
4209 hidnplayr 947
;;================================================================================================;;
948
proc URI_escape URI ;/////////////////////////////////////////////////////////////////////////////;;
949
;;------------------------------------------------------------------------------------------------;;
950
;?                                                                                                ;;
951
;;------------------------------------------------------------------------------------------------;;
952
;> URI = ptr to ASCIIZ URI                                                                        ;;
953
;;------------------------------------------------------------------------------------------------;;
954
;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
955
;;================================================================================================;;
4202 hidnplayr 956
 
4209 hidnplayr 957
        pusha
4205 hidnplayr 958
 
4209 hidnplayr 959
        invoke  mem.alloc, URLMAXLEN
960
        test    eax, eax
961
        jz      .error
962
        mov     [esp + 7 * 4], eax              ; return ptr in eax
963
        mov     esi, [URI]
964
        mov     edi, eax
965
        xor     ebx, ebx
966
        xor     ecx, ecx
967
  .loop:
968
        lodsb
969
        test    al, al
970
        jz      .done
971
 
972
        mov     cl, al
973
        and     cl, 0x1f
974
        mov     bl, al
975
        shr     bl, 5
976
        bt      dword[bits_must_escape + ebx], ecx
977
        jc      .escape
978
 
979
        stosb
980
        jmp     .loop
981
 
982
  .escape:
983
        mov     al, '%'
984
        stosb
985
        mov     bl, byte[esi-1]
986
        shr     bl, 4
987
        mov     al, byte[str_hex + ebx]
988
        stosb
989
        mov     bl, byte[esi-1]
990
        and     bl, 0x0f
991
        mov     al, byte[str_hex + ebx]
992
        stosb
993
        jmp     .loop
994
 
995
 
996
  .done:
997
        stosb
998
 
999
        popa
1000
        ret
1001
 
1002
  .error:
1003
        popa
1004
        xor     eax, eax
1005
        ret
1006
 
1007
endp
1008
 
1009
 
1010
 
4167 hidnplayr 1011
;;================================================================================================;;
4209 hidnplayr 1012
proc URI_unescape URI ;///////////////////////////////////////////////////////////////////////////;;
1013
;;------------------------------------------------------------------------------------------------;;
1014
;?                                                                                                ;;
1015
;;------------------------------------------------------------------------------------------------;;
1016
;> URI = ptr to ASCIIZ URI                                                                        ;;
1017
;;------------------------------------------------------------------------------------------------;;
1018
;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
1019
;;================================================================================================;;
1020
 
1021
        pusha
1022
 
1023
        invoke  mem.alloc, URLMAXLEN
1024
        test    eax, eax
1025
        jz      .error
1026
        mov     [esp + 7 * 4], eax              ; return ptr in eax
1027
        mov     esi, [URI]
1028
        mov     edi, eax
1029
  .loop:
1030
        lodsb
1031
        test    al, al
1032
        jz      .done
1033
 
1034
        cmp     al, '%'
1035
        je      .unescape
1036
 
1037
        stosb
1038
        jmp     .loop
1039
 
1040
  .unescape:
1041
        xor     ebx, ebx
1042
        xor     ecx, ecx
1043
  .unescape_nibble:
1044
        lodsb
1045
        sub     al, '0'
1046
        jb      .fail
1047
        cmp     al, 9
1048
        jbe     .nibble_ok
1049
        sub     al, 'A' - '0' - 10
1050
        jb      .fail
1051
        cmp     al, 15
1052
        jbe     .nibble_ok
1053
        sub     al, 'a' - 'A'
1054
        cmp     al, 15
1055
        ja      .fail
1056
  .nibble_ok:
1057
        shl     bl, 8
1058
        or      bl, al
1059
        dec     ecx
1060
        jc      .unescape_nibble
1061
        mov     al, bl
1062
        stosb
1063
        jmp     .loop
1064
 
1065
  .fail:
1066
        DEBUGF  1, "ERROR: invalid URI!\n"
1067
        jmp     .loop
1068
 
1069
  .done:
1070
        stosb
1071
 
1072
        popa
1073
        ret
1074
 
1075
  .error:
1076
        popa
1077
        xor     eax, eax
1078
        ret
1079
 
1080
endp
1081
 
1082
 
1083
 
1084
 
1085
 
1086
;;================================================================================================;;
4202 hidnplayr 1087
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1088
;;================================================================================================;;
1089
;! Internal procedures section                                                                    ;;
4220 hidnplayr 1090
;;                                                                                                ;;
1091
;; NOTICE: These procedures do not follow stdcall conventions and thus may destroy any register.  ;;
4202 hidnplayr 1092
;;================================================================================================;;
1093
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1094
;;================================================================================================;;
1095
 
1096
 
1097
 
1098
 
1099
;;================================================================================================;;
4167 hidnplayr 1100
proc open_connection hostname, port ;/////////////////////////////////////////////////////////////;;
1101
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1102
;? Connects to a HTTP server                                                                      ;;
4167 hidnplayr 1103
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1104
;> hostname     = ptr to ASCIIZ hostname                                                          ;;
1105
;> port         = port (x86 byte order)                                                           ;;
4167 hidnplayr 1106
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1107
;< eax = 0 (error) / socketnum                                                                    ;;
4167 hidnplayr 1108
;;================================================================================================;;
4158 hidnplayr 1109
 
4167 hidnplayr 1110
locals
1111
        sockaddr        dd ?
1112
        socketnum       dd ?
1113
endl
1114
 
1115
; Resolve the hostname
1116
        DEBUGF  1, "Resolving hostname\n"
1117
        push    esp     ; reserve stack place
1118
        push    esp     ; fourth parameter
1119
        push    0       ; third parameter
1120
        push    0       ; second parameter
1121
        push    [hostname]
1122
        call    [getaddrinfo]
1123
        pop     esi
1124
        test    eax, eax
1125
        jnz     .error1
1126
 
1127
; getaddrinfo returns addrinfo struct, make the pointer to sockaddr struct
1128
        mov     esi, [esi + addrinfo.ai_addr]
1129
        mov     [sockaddr], esi
1130
        mov     eax, [esi + sockaddr_in.sin_addr]
1131
        test    eax, eax
1132
        jz      .error2
1133
 
1134
        DEBUGF  1, "Server ip=%u.%u.%u.%u\n", \
1135
        [esi + sockaddr_in.sin_addr]:1, [esi + sockaddr_in.sin_addr + 1]:1, \
1136
        [esi + sockaddr_in.sin_addr + 2]:1, [esi + sockaddr_in.sin_addr + 3]:1
1137
 
1138
        mov     [esi + sockaddr_in.sin_family], AF_INET4
1139
        mov     eax, [port]
1140
        xchg    al, ah
1141
        mov     [esi + sockaddr_in.sin_port], ax
1142
 
1143
; Connect to the server.
1144
        mcall   socket, AF_INET4, SOCK_STREAM, 0
1145
        test    eax, eax
1146
        jz      .error2
1147
        mov     [socketnum], eax
1148
        DEBUGF  1, "Socket: 0x%x\n", eax
1149
 
1150
        mcall   connect, [socketnum], [sockaddr], 18
1151
        test    eax, eax
1152
        jnz     .error2
1153
        DEBUGF  1, "Socket is now connected.\n"
1154
 
1155
; free allocated memory
1156
        push    [sockaddr]
1157
        call    [freeaddrinfo]
1158
 
1159
        mov     eax, [socketnum]
1160
        ret
1161
 
1162
  .error2:
1163
 
1164
; free allocated memory
1165
        push    [sockaddr]
1166
        call    [freeaddrinfo]
1167
 
1168
  .error1:
1169
        xor     eax, eax
1170
        ret
1171
 
1172
endp
1173
 
1174
 
4158 hidnplayr 1175
;;================================================================================================;;
1176
proc parse_url URL ;//////////////////////////////////////////////////////////////////////////////;;
1177
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1178
;? Split a given URL into hostname and pageaddr                                                   ;;
4158 hidnplayr 1179
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1180
;> URL = ptr to ASCIIZ URL                                                                        ;;
4158 hidnplayr 1181
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1182
;< eax = 0 (error) / ptr to ASCIIZ hostname                                                       ;;
1183
;< ebx = ptr to ASCIIZ pageaddr                                                                   ;;
4158 hidnplayr 1184
;;================================================================================================;;
1185
 
1186
locals
1187
        urlsize         dd ?
1188
        hostname        dd ?
1189
        pageaddr        dd ?
1190
endl
1191
 
4161 hidnplayr 1192
        DEBUGF  1, "parsing URL: %s\n", [URL]
4158 hidnplayr 1193
 
1194
; remove any leading protocol text
1195
        mov     esi, [URL]
1196
        mov     ecx, URLMAXLEN
1197
        mov     ax, '//'
1198
  .loop1:
1199
        cmp     byte[esi], 0            ; end of URL?
1200
        je      .url_ok                 ; yep, so not found
1201
        cmp     [esi], ax
1202
        je      .skip_proto
1203
        inc     esi
1204
        dec     ecx
1205
        jnz     .loop1
1206
 
4161 hidnplayr 1207
        DEBUGF  1, "Invalid URL\n"
4158 hidnplayr 1208
        xor     eax, eax
1209
        ret
1210
 
1211
  .skip_proto:
1212
        inc     esi                     ; skip the two '/'
1213
        inc     esi
1214
        mov     [URL], esi              ; update pointer so it skips protocol
1215
        jmp     .loop1                  ; we still need to find the length of the URL
1216
 
1217
  .url_ok:
1218
        sub     esi, [URL]              ; calculate total length of URL
1219
        mov     [urlsize], esi
1220
 
1221
 
1222
; now look for page delimiter - it's a '/' character
1223
        mov     ecx, esi                ; URL length
1224
        mov     edi, [URL]
1225
        mov     al, '/'
1226
        repne   scasb
4161 hidnplayr 1227
        jne     @f
4158 hidnplayr 1228
        dec     edi                     ; return one char, '/' must be part of the pageaddr
1229
        inc     ecx                     ;
4161 hidnplayr 1230
  @@:
4158 hidnplayr 1231
        push    ecx edi                 ; remember the pointer and length of pageaddr
1232
 
1233
        mov     ecx, edi
1234
        sub     ecx, [URL]
1235
        inc     ecx                     ; we will add a 0 byte at the end
1236
        invoke  mem.alloc, ecx
1237
        or      eax, eax
1238
        jz      .no_mem
1239
 
1240
        mov     [hostname], eax         ; copy hostname to buffer
1241
        mov     edi, eax
1242
        mov     esi, [URL]
1243
        dec     ecx
1244
        rep     movsb
1245
        xor     al, al
1246
        stosb
1247
 
4161 hidnplayr 1248
        mov     [pageaddr], str_slash   ; assume there is no pageaddr
4158 hidnplayr 1249
        pop     esi ecx
1250
        test    ecx, ecx
1251
        jz      .no_page
1252
        inc     ecx                     ; we will add a 0 byte at the end
1253
        invoke  mem.alloc, ecx
1254
        or      eax, eax
1255
        jz      .no_mem
1256
 
1257
        mov     [pageaddr], eax         ; copy pageaddr to buffer
1258
        mov     edi, eax
1259
        dec     ecx
1260
        rep     movsb
1261
        xor     al, al
1262
        stosb
1263
  .no_page:
1264
 
1265
        mov     eax, [hostname]
1266
        mov     ebx, [pageaddr]
1267
 
1268
        DEBUGF  1, "hostname: %s\n", eax
1269
        DEBUGF  1, "pageaddr: %s\n", ebx
1270
 
1271
        ret
1272
 
1273
  .no_mem:
1274
        xor     eax, eax
1275
        ret
1276
 
1277
endp
1278
 
1279
 
4202 hidnplayr 1280
;;================================================================================================;;
1281
proc ascii_dec ;//////////////////////////////////////////////////////////////////////////////////;;
1282
;;------------------------------------------------------------------------------------------------;;
1283
;? Convert eax to ASCII decimal number                                                            ;;
1284
;;------------------------------------------------------------------------------------------------;;
1285
;> eax = number                                                                                   ;;
1286
;> edi = ptr where to write ASCII decimal number                                                  ;;
1287
;;------------------------------------------------------------------------------------------------;;
1288
;< /                                                                                              ;;
1289
;;================================================================================================;;
4158 hidnplayr 1290
 
4168 hidnplayr 1291
        push    -'0'
4167 hidnplayr 1292
        mov     ecx, 10
1293
  .loop:
1294
        xor     edx, edx
1295
        div     ecx
1296
        add     dl, '0'
4168 hidnplayr 1297
        push    edx
4167 hidnplayr 1298
        test    eax, eax
1299
        jnz     .loop
4158 hidnplayr 1300
 
4168 hidnplayr 1301
  .loop2:
1302
        pop     eax
1303
        add     al, '0'
1304
        jz      .done
1305
        stosb
1306
        jmp     .loop2
1307
  .done:
1308
 
4167 hidnplayr 1309
        ret
4158 hidnplayr 1310
 
4202 hidnplayr 1311
endp
4167 hidnplayr 1312
 
4202 hidnplayr 1313
 
4158 hidnplayr 1314
;;================================================================================================;;
1315
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1316
;;================================================================================================;;
1317
;! Imported functions section                                                                     ;;
1318
;;================================================================================================;;
1319
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1320
;;================================================================================================;;
1321
 
1322
 
1323
align 16
1324
@IMPORT:
1325
 
1326
library \
1327
        libini, 'libini.obj', \
1328
        network, 'network.obj'
1329
 
1330
import  libini, \
1331
        ini.get_str, 'ini_get_str', \
1332
        ini.get_int, 'ini_get_int'
1333
 
1334
import  network,\
1335
        getaddrinfo, 'getaddrinfo',\
1336
        freeaddrinfo,  'freeaddrinfo',\
1337
        inet_ntoa, 'inet_ntoa'
1338
 
1339
;;===========================================================================;;
1340
;;///////////////////////////////////////////////////////////////////////////;;
1341
;;===========================================================================;;
1342
;! Exported functions section                                                ;;
1343
;;===========================================================================;;
1344
;;///////////////////////////////////////////////////////////////////////////;;
1345
;;===========================================================================;;
1346
 
1347
 
1348
align 4
1349
@EXPORT:
1350
export  \
1351
        lib_init                , 'lib_init'            , \
1352
        0x00010001              , 'version'             , \
1353
        HTTP_get                , 'get'                 , \
4167 hidnplayr 1354
        HTTP_head               , 'head'                , \
1355
        HTTP_post               , 'post'                , \
4158 hidnplayr 1356
        find_header_field       , 'find_header_field'   , \
4205 hidnplayr 1357
        HTTP_process            , 'process'             , \
1358
        HTTP_free               , 'free'                , \
4209 hidnplayr 1359
        HTTP_stop               , 'stop'                , \
1360
        URI_escape              , 'escape'              , \
1361
        URI_unescape            , 'unescape'
4158 hidnplayr 1362
 
1363
;        HTTP_put                , 'put'                 , \
1364
;        HTTP_delete             , 'delete'              , \
1365
;        HTTP_trace              , 'trace'               , \
1366
;        HTTP_connect            , 'connect'             , \
1367
 
1368
 
1369
 
1370
section '.data' data readable writable align 16
1371
 
1372
inifile         db '/sys/settings/network.ini', 0
1373
 
1374
sec_proxy:
1375
key_proxy       db 'proxy', 0
1376
key_proxyport   db 'port', 0
1377
key_user        db 'user', 0
1378
key_password    db 'password', 0
1379
 
1380
str_http11      db ' HTTP/1.1', 13, 10, 'Host: '
1381
  .length       = $ - str_http11
4167 hidnplayr 1382
str_post_cl     db 13, 10, 'Content-Length: '
1383
  .length       = $ - str_post_cl
1384
str_post_ct     db 13, 10, 'Content-Type: '
1385
  .length       = $ - str_post_ct
4158 hidnplayr 1386
str_close       db 13, 10, 'User-Agent: KolibriOS libHTTP/1.0', 13, 10, 'Connection: Close', 13, 10, 13, 10
1387
  .length       = $ - str_close
1388
str_proxy_auth  db 13, 10, 'Proxy-Authorization: Basic '
1389
  .length       = $ - str_proxy_auth
1390
 
1391
base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
1392
                db '0123456789+/'
1393
 
1394
str_cl          db 'content-length', 0
4161 hidnplayr 1395
str_slash       db '/', 0
4158 hidnplayr 1396
str_te          db 'transfer-encoding', 0
4167 hidnplayr 1397
str_get         db 'GET ', 0
1398
str_head        db 'HEAD ', 0
1399
str_post        db 'POST ', 0
4158 hidnplayr 1400
 
4209 hidnplayr 1401
bits_must_escape:
1402
dd      0xffffffff                                                      ; 00-1F
1403
dd      1 shl 0 + 1 shl 2 + 1 shl 3 + 1 shl 5 + 1 shl 28 + 1 shl 30     ; "#%<>
1404
dd      1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 30                       ;[\]^
1405
dd      1 shl 0 + 1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 31             ;`{|} DEL
1406
 
1407
dd      0xffffffff
1408
dd      0xffffffff
1409
dd      0xffffffff
1410
dd      0xffffffff
1411
 
1412
str_hex:
1413
db '0123456789ABCDEF'
1414
 
4158 hidnplayr 1415
include_debug_strings
1416
 
1417
; uninitialized data
1418
mem.alloc       dd ?
1419
mem.free        dd ?
1420
mem.realloc     dd ?
1421
dll.load        dd ?
1422
 
1423
proxyAddr       rb 256
1424
proxyUser       rb 256
1425
proxyPassword   rb 256
1426
proxyPort       dd ?