Subversion Repositories Kolibri OS

Rev

Rev 4216 | Rev 4220 | 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
450
        DEBUGF  1, "Received %u bytes\n", eax
451
 
4209 hidnplayr 452
; Update timestamp
4206 hidnplayr 453
        push    eax
454
        mcall   29, 9
455
        mov     [ebp + http_msg.timestamp], eax
456
        pop     eax
457
 
4162 hidnplayr 458
; Update pointers
4158 hidnplayr 459
        mov     edi, [ebp + http_msg.write_ptr]
460
        add     [ebp + http_msg.write_ptr], eax
461
        sub     [ebp + http_msg.buffer_length], eax
462
        jz      .got_all_data
4162 hidnplayr 463
 
464
; If data is chunked, combine chunks into contiguous data.
465
        test    [ebp + http_msg.flags], FLAG_CHUNKED
466
        jnz     .chunk_loop
467
 
4212 hidnplayr 468
; Did we detect the (final) header yet?
4158 hidnplayr 469
        test    [ebp + http_msg.flags], FLAG_GOT_HEADER
470
        jnz     .header_parsed
471
 
4212 hidnplayr 472
; We havent found the (final) header yet, search for it..
473
  .scan_again:
474
        ; eax = total number of bytes received so far
475
        mov     eax, [ebp + http_msg.write_ptr]
476
        sub     eax, http_msg.data
477
        sub     eax, ebp
478
        sub     eax, [ebp + http_msg.header_length]
479
        ; edi is ptr to begin of header
480
        lea     edi, [ebp + http_msg.data]
481
        add     edi, [ebp + http_msg.header_length]
482
        ; put it in esi for next proc too
483
        mov     esi, edi
484
        sub     eax, 3
485
        jle     .need_more_data
486
  .scan_loop:
4158 hidnplayr 487
        ; scan for end of header (empty line)
488
        cmp     dword[edi], 0x0a0d0a0d                  ; end of header
489
        je      .end_of_header
4212 hidnplayr 490
        cmp     word[edi+2], 0x0a0a                     ; notice the use of offset + 2, to calculate header length correctly :)
4158 hidnplayr 491
        je      .end_of_header
492
        inc     edi
493
        dec     eax
4212 hidnplayr 494
        jnz     .scan_loop
495
        jmp     .need_more_data
4158 hidnplayr 496
 
497
  .end_of_header:
498
        add     edi, 4 - http_msg.data
499
        sub     edi, ebp
4212 hidnplayr 500
        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 501
        DEBUGF  1, "Header length: %u\n", edi
502
 
503
; Ok, we have found header:
4212 hidnplayr 504
        cmp     dword[esi], 'HTTP'
4158 hidnplayr 505
        jne     .invalid_header
4212 hidnplayr 506
        cmp     dword[esi+4], '/1.0'
4158 hidnplayr 507
        je      .http_1.0
4212 hidnplayr 508
        cmp     dword[esi+4], '/1.1'
4158 hidnplayr 509
        jne     .invalid_header
510
        or      [ebp + http_msg.flags], FLAG_HTTP11
511
  .http_1.0:
4212 hidnplayr 512
        cmp     byte[esi+8], ' '
4158 hidnplayr 513
        jne     .invalid_header
514
 
4212 hidnplayr 515
        add     esi, 9
4158 hidnplayr 516
        xor     eax, eax
517
        xor     ebx, ebx
518
        mov     ecx, 3
519
  .statusloop:
520
        lodsb
521
        sub     al, '0'
522
        jb      .invalid_header
523
        cmp     al, 9
524
        ja      .invalid_header
525
        lea     ebx, [ebx + 4*ebx]
526
        shl     ebx, 1
527
        add     ebx, eax
528
        dec     ecx
529
        jnz     .statusloop
4212 hidnplayr 530
 
531
; Ignore "100 - Continue" headers
532
        cmp     ebx, 100
533
        je      .scan_again
534
 
535
        DEBUGF  1, "Status: %u\n", ebx
4158 hidnplayr 536
        mov     [ebp + http_msg.status], ebx
4212 hidnplayr 537
        or      [ebp + http_msg.flags], FLAG_GOT_HEADER
4158 hidnplayr 538
 
539
; Now, convert all header names to lowercase.
540
; This way, it will be much easier to find certain header fields, later on.
541
 
542
        lea     esi, [ebp + http_msg.data]
543
        mov     ecx, [ebp + http_msg.header_length]
544
  .need_newline:
545
        inc     esi
546
        dec     ecx
547
        jz      .convert_done
548
        cmp     byte[esi], 10
549
        jne     .need_newline
550
; Ok, we have a newline, a line beginning with space or tabs has no header fields.
551
 
552
        inc     esi
553
        dec     ecx
554
        jz      .convert_done
555
        cmp     byte[esi], ' '
556
        je      .need_newline
557
        cmp     byte[esi], 9    ; horizontal tab
558
        je      .need_newline
559
        jmp     .convert_loop
560
  .next_char:
561
        inc     esi
562
        dec     ecx
563
        jz      .convert_done
564
  .convert_loop:
565
        cmp     byte[esi], ':'
566
        je      .need_newline
567
        cmp     byte[esi], 'A'
568
        jb      .next_char
569
        cmp     byte[esi], 'Z'
570
        ja      .next_char
571
        or      byte[esi], 0x20 ; convert to lowercase
572
        jmp     .next_char
573
  .convert_done:
574
        mov     byte[esi-1], 0
575
        lea     esi, [ebp + http_msg.data]
576
        DEBUGF  1, "Header names converted to lowercase:\n%s\n", esi
577
 
578
; Check for content-length header field.
579
        stdcall find_header_field, ebp, str_cl
580
        test    eax, eax
581
        jz      .no_content
582
        or      [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
583
 
584
        xor     edx, edx
585
  .cl_loop:
586
        movzx   ebx, byte[eax]
587
        inc     eax
588
        cmp     bl, 10
589
        je      .cl_ok
590
        cmp     bl, 13
591
        je      .cl_ok
592
        cmp     bl, ' '
593
        je      .cl_ok
594
        sub     bl, '0'
595
        jb      .invalid_header
596
        cmp     bl, 9
597
        ja      .invalid_header
598
        lea     edx, [edx + edx*4]      ; edx = edx*10
599
        shl     edx, 1                  ;
600
        add     edx, ebx
601
        jmp     .cl_loop
602
 
603
  .cl_ok:
604
        mov     [ebp + http_msg.content_length], edx
605
        DEBUGF  1, "Content-length: %u\n", edx
606
 
607
; Resize buffer according to content-length.
4168 hidnplayr 608
        add     edx, [ebp + http_msg.header_length]
609
        add     edx, http_msg.data
4158 hidnplayr 610
 
4168 hidnplayr 611
        mov     ecx, edx
4158 hidnplayr 612
        sub     ecx, [ebp + http_msg.write_ptr]
613
        mov     [ebp + http_msg.buffer_length], ecx
614
 
4168 hidnplayr 615
        invoke  mem.realloc, ebp, edx
4158 hidnplayr 616
        or      eax, eax
4212 hidnplayr 617
        jz      .no_ram
4203 hidnplayr 618
 
4212 hidnplayr 619
        mov     eax, [ebp + http_msg.write_ptr]
4168 hidnplayr 620
        sub     eax, [ebp + http_msg.header_length]
4212 hidnplayr 621
        sub     eax, http_msg.data
622
        sub     eax, ebp
4158 hidnplayr 623
        jmp     .header_parsed  ; hooray!
624
 
625
  .no_content:
626
        DEBUGF  1, "Content-length not found.\n"
627
 
628
; We didnt find 'content-length', maybe server is using chunked transfer encoding?
629
; Try to find 'transfer-encoding' header.
630
        stdcall find_header_field, ebp, str_te
631
        test    eax, eax
632
        jz      .invalid_header
633
 
634
        mov     ebx, dword[eax]
4162 hidnplayr 635
        or      ebx, 0x20202020
4158 hidnplayr 636
        cmp     ebx, 'chun'
637
        jne     .invalid_header
638
        mov     ebx, dword[eax+4]
4162 hidnplayr 639
        or      ebx, 0x00202020
640
        and     ebx, 0x00ffffff
4158 hidnplayr 641
        cmp     ebx, 'ked'
642
        jne     .invalid_header
643
 
644
        or      [ebp + http_msg.flags], FLAG_CHUNKED
645
        DEBUGF  1, "Transfer type is: chunked\n"
646
 
647
; Set chunk pointer where first chunk should begin.
4162 hidnplayr 648
        lea     eax, [ebp + http_msg.data]
649
        add     eax, [ebp + http_msg.header_length]
4158 hidnplayr 650
        mov     [ebp + http_msg.chunk_ptr], eax
651
 
4162 hidnplayr 652
  .chunk_loop:
4158 hidnplayr 653
        mov     ecx, [ebp + http_msg.write_ptr]
654
        sub     ecx, [ebp + http_msg.chunk_ptr]
4202 hidnplayr 655
        jb      .need_more_data_chunked         ; TODO: use this ecx !!!
4158 hidnplayr 656
 
4202 hidnplayr 657
; Chunkline starts here, convert the ASCII hex number into ebx
4158 hidnplayr 658
        mov     esi, [ebp + http_msg.chunk_ptr]
659
        xor     ebx, ebx
660
  .chunk_hexloop:
661
        lodsb
662
        sub     al, '0'
663
        jb      .chunk_
664
        cmp     al, 9
665
        jbe     .chunk_hex
4162 hidnplayr 666
        sub     al, 'A' - '0' - 10
4158 hidnplayr 667
        jb      .chunk_
4162 hidnplayr 668
        cmp     al, 15
4158 hidnplayr 669
        jbe     .chunk_hex
670
        sub     al, 'a' - 'A'
4162 hidnplayr 671
        cmp     al, 15
4158 hidnplayr 672
        ja      .chunk_
673
  .chunk_hex:
674
        shl     ebx, 4
675
        add     bl, al
676
        jmp     .chunk_hexloop
677
  .chunk_:
678
        DEBUGF  1, "got chunk of %u bytes\n", ebx
4202 hidnplayr 679
;;        cmp     esi, [ebp + http_msg.chunk_ptr]
680
;;        je
4158 hidnplayr 681
; If chunk size is 0, all chunks have been received.
682
        test    ebx, ebx
4162 hidnplayr 683
        jz      .got_all_data_chunked           ; last chunk, hooray! FIXME: what if it wasnt a valid hex number???
4158 hidnplayr 684
 
685
; Chunkline ends with a CR, LF or simply LF
4202 hidnplayr 686
  .end_of_chunkline?:
4158 hidnplayr 687
        cmp     al, 10
688
        je      .end_of_chunkline
689
        lodsb
4202 hidnplayr 690
        cmp     edi, [ebp + http_msg.write_ptr]
691
        jb      .end_of_chunkline?
692
        jmp     .need_more_data
4158 hidnplayr 693
 
694
  .end_of_chunkline:
4202 hidnplayr 695
; Update chunk ptr, and remember old one
696
        mov     edi, [ebp + http_msg.chunk_ptr]
697
        add     [ebp + http_msg.chunk_ptr], ebx
4162 hidnplayr 698
; Realloc buffer, make it 'chunksize' bigger.
699
        mov     eax, [ebp + http_msg.buffer_length]
700
        add     eax, ebx
701
        invoke  mem.realloc, ebp, eax
702
        or      eax, eax
703
        jz      .no_ram
704
        add     [ebp + http_msg.buffer_length], ebx
705
 
706
; Update write ptr
707
        mov     eax, esi
708
        sub     eax, edi
709
        sub     [ebp + http_msg.write_ptr], eax
710
 
4158 hidnplayr 711
; Now move all received data to the left (remove chunk header).
4162 hidnplayr 712
; Update content_length accordingly.
4158 hidnplayr 713
        mov     ecx, [ebp + http_msg.write_ptr]
714
        sub     ecx, esi
4168 hidnplayr 715
        add     [ebp + http_msg.content_received], ecx
4158 hidnplayr 716
        rep     movsb
4162 hidnplayr 717
        jmp     .chunk_loop
4158 hidnplayr 718
 
719
; Check if we got all the data.
4162 hidnplayr 720
  .header_parsed:
4168 hidnplayr 721
        add     [ebp + http_msg.content_received], eax
4217 hidnplayr 722
        mov     eax, [ebp + http_msg.content_received]
723
        cmp     eax, [ebp + http_msg.content_length]
4168 hidnplayr 724
        jae     .got_all_data
4217 hidnplayr 725
;        jmp     .need_more_data
4212 hidnplayr 726
 
4162 hidnplayr 727
  .need_more_data:
728
        popa
729
        xor     eax, eax
730
        dec     eax
731
        ret
4158 hidnplayr 732
 
4162 hidnplayr 733
  .need_more_data_chunked:
4168 hidnplayr 734
        add     [ebp + http_msg.content_received], eax
4158 hidnplayr 735
        popa
736
        xor     eax, eax
737
        dec     eax
738
        ret
739
 
4162 hidnplayr 740
  .got_all_data_chunked:
741
        mov     eax, [ebp + http_msg.chunk_ptr]
742
        sub     eax, [ebp + http_msg.header_length]
743
        sub     eax, http_msg.data
744
        sub     eax, ebp
745
        mov     [ebp + http_msg.content_length], eax
4168 hidnplayr 746
        mov     [ebp + http_msg.content_received], eax
4158 hidnplayr 747
  .got_all_data:
4217 hidnplayr 748
        DEBUGF  1, "We got all the data! (%u bytes)\n", [ebp + http_msg.content_received]
4205 hidnplayr 749
        or      [ebp + http_msg.flags], FLAG_GOT_ALL_DATA
750
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
4158 hidnplayr 751
        mcall   close, [ebp + http_msg.socket]
752
        popa
753
        xor     eax, eax
754
        ret
755
 
756
  .check_socket:
757
        cmp     ebx, EWOULDBLOCK
4206 hidnplayr 758
        jne     .socket_error
4158 hidnplayr 759
 
4206 hidnplayr 760
        mcall   29, 9
761
        sub     eax, TIMEOUT
762
        cmp     eax, [ebp + http_msg.timestamp]
4207 hidnplayr 763
        jb      .need_more_data
4206 hidnplayr 764
        DEBUGF  1, "ERROR: timeout\n"
765
        or      [ebp + http_msg.flags], FLAG_TIMEOUT_ERROR
766
        jmp     .disconnect
4158 hidnplayr 767
 
768
  .invalid_header:
4203 hidnplayr 769
        pop     eax
4158 hidnplayr 770
        DEBUGF  1, "ERROR: invalid header\n"
771
        or      [ebp + http_msg.flags], FLAG_INVALID_HEADER
4206 hidnplayr 772
        jmp     .disconnect
4158 hidnplayr 773
 
774
  .no_ram:
775
        DEBUGF  1, "ERROR: out of RAM\n"
776
        or      [ebp + http_msg.flags], FLAG_NO_RAM
4206 hidnplayr 777
        jmp     .disconnect
778
 
779
  .socket_error:
780
        DEBUGF  1, "ERROR: socket error %u\n", ebx
781
        or      [ebp + http_msg.flags], FLAG_SOCKET_ERROR
782
  .disconnect:
4205 hidnplayr 783
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
784
        mcall   close, [ebp + http_msg.socket]
4206 hidnplayr 785
  .connection_closed:
4158 hidnplayr 786
        popa
787
        xor     eax, eax
788
        ret
789
 
790
endp
791
 
792
 
793
 
4205 hidnplayr 794
 
4158 hidnplayr 795
;;================================================================================================;;
4205 hidnplayr 796
proc HTTP_free identifier ;///////////////////////////////////////////////////////////////////////;;
797
;;------------------------------------------------------------------------------------------------;;
798
;? Free the http_msg structure                                                                    ;;
799
;;------------------------------------------------------------------------------------------------;;
800
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
801
;;------------------------------------------------------------------------------------------------;;
802
;< none                                                                                           ;;
803
;;================================================================================================;;
804
 
805
        pusha
806
        mov     ebp, [identifier]
807
 
808
        test    [ebp + http_msg.flags], FLAG_CONNECTED
809
        jz      .not_connected
810
 
811
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
812
        mcall   close, [ebp + http_msg.socket]
813
 
814
  .not_connected:
815
        invoke  mem.free, ebp
816
 
817
        popa
818
        ret
819
 
820
endp
821
 
822
 
823
 
824
;;================================================================================================;;
825
proc HTTP_stop identifier ;///////////////////////////////////////////////////////////////////////;;
826
;;------------------------------------------------------------------------------------------------;;
827
;? Stops the open connection                                                                      ;;
828
;;------------------------------------------------------------------------------------------------;;
829
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
830
;;------------------------------------------------------------------------------------------------;;
831
;< none                                                                                           ;;
832
;;================================================================================================;;
833
 
834
        pusha
835
        mov     ebp, [identifier]
836
 
837
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
838
        mcall   close, [ebp + http_msg.socket]
839
 
840
        popa
841
        ret
842
 
843
endp
844
 
845
 
846
 
847
;;================================================================================================;;
4158 hidnplayr 848
proc find_header_field identifier, headername ;///////////////////////////////////////////////////;;
849
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 850
;? Find a header field in the received HTTP header                                                ;;
4158 hidnplayr 851
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 852
;> identifier   = ptr to http_msg struct                                                          ;;
853
;> headername   = ptr to ASCIIZ string containg field you want to find (must be in lowercase)     ;;
4158 hidnplayr 854
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 855
;< eax = 0 (error) / ptr to content of the HTTP header field                                      ;;
4158 hidnplayr 856
;;================================================================================================;;
857
        push    ebx ecx edx esi edi
858
 
859
        DEBUGF  1, "Find header field: %s\n", [headername]
860
 
861
        mov     ebx, [identifier]
4202 hidnplayr 862
        test    [ebx + http_msg.flags], FLAG_GOT_HEADER
863
        jz      .fail
864
 
4158 hidnplayr 865
        lea     edx, [ebx + http_msg.data]
866
        mov     ecx, edx
867
        add     ecx, [ebx + http_msg.header_length]
868
 
869
  .restart:
870
        mov     esi, [headername]
871
        mov     edi, edx
872
  .loop:
873
        cmp     edi, ecx
874
        jae     .fail
875
        lodsb
876
        scasb
877
        je      .loop
878
        test    al, al
879
        jz      .done?
880
  .next:
881
        inc     edx
882
        jmp     .restart
883
 
884
  .not_done:
885
        inc     edi
886
  .done?:
887
        cmp     byte[edi-1], ':'
888
        je      .almost_done
889
        cmp     byte[edi-1], ' '
890
        je      .not_done
891
        cmp     byte[edi-1], 9  ; tab
892
        je      .not_done
893
 
894
        jmp     .next
895
 
896
  .almost_done:                 ; FIXME: buffer overflow?
897
        dec     edi
898
        DEBUGF  1, "Found header field\n"
899
  .spaceloop:
900
        inc     edi
901
        cmp     byte[edi], ' '
902
        je      .spaceloop
903
        cmp     byte[edi], 9    ; tab
904
        je      .spaceloop
905
 
906
        mov     eax, edi
907
        pop     edi esi edx ecx ebx
908
        ret
909
 
910
  .fail:
911
        pop     edi esi edx ecx ebx
912
        xor     eax, eax
913
        ret
914
 
915
endp
916
 
917
 
918
 
4209 hidnplayr 919
;;================================================================================================;;
920
proc URI_escape URI ;/////////////////////////////////////////////////////////////////////////////;;
921
;;------------------------------------------------------------------------------------------------;;
922
;?                                                                                                ;;
923
;;------------------------------------------------------------------------------------------------;;
924
;> URI = ptr to ASCIIZ URI                                                                        ;;
925
;;------------------------------------------------------------------------------------------------;;
926
;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
927
;;================================================================================================;;
4202 hidnplayr 928
 
4209 hidnplayr 929
        pusha
4205 hidnplayr 930
 
4209 hidnplayr 931
        invoke  mem.alloc, URLMAXLEN
932
        test    eax, eax
933
        jz      .error
934
        mov     [esp + 7 * 4], eax              ; return ptr in eax
935
        mov     esi, [URI]
936
        mov     edi, eax
937
        xor     ebx, ebx
938
        xor     ecx, ecx
939
  .loop:
940
        lodsb
941
        test    al, al
942
        jz      .done
943
 
944
        mov     cl, al
945
        and     cl, 0x1f
946
        mov     bl, al
947
        shr     bl, 5
948
        bt      dword[bits_must_escape + ebx], ecx
949
        jc      .escape
950
 
951
        stosb
952
        jmp     .loop
953
 
954
  .escape:
955
        mov     al, '%'
956
        stosb
957
        mov     bl, byte[esi-1]
958
        shr     bl, 4
959
        mov     al, byte[str_hex + ebx]
960
        stosb
961
        mov     bl, byte[esi-1]
962
        and     bl, 0x0f
963
        mov     al, byte[str_hex + ebx]
964
        stosb
965
        jmp     .loop
966
 
967
 
968
  .done:
969
        stosb
970
 
971
        popa
972
        ret
973
 
974
  .error:
975
        popa
976
        xor     eax, eax
977
        ret
978
 
979
endp
980
 
981
 
982
 
4167 hidnplayr 983
;;================================================================================================;;
4209 hidnplayr 984
proc URI_unescape URI ;///////////////////////////////////////////////////////////////////////////;;
985
;;------------------------------------------------------------------------------------------------;;
986
;?                                                                                                ;;
987
;;------------------------------------------------------------------------------------------------;;
988
;> URI = ptr to ASCIIZ URI                                                                        ;;
989
;;------------------------------------------------------------------------------------------------;;
990
;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
991
;;================================================================================================;;
992
 
993
        pusha
994
 
995
        invoke  mem.alloc, URLMAXLEN
996
        test    eax, eax
997
        jz      .error
998
        mov     [esp + 7 * 4], eax              ; return ptr in eax
999
        mov     esi, [URI]
1000
        mov     edi, eax
1001
  .loop:
1002
        lodsb
1003
        test    al, al
1004
        jz      .done
1005
 
1006
        cmp     al, '%'
1007
        je      .unescape
1008
 
1009
        stosb
1010
        jmp     .loop
1011
 
1012
  .unescape:
1013
        xor     ebx, ebx
1014
        xor     ecx, ecx
1015
  .unescape_nibble:
1016
        lodsb
1017
        sub     al, '0'
1018
        jb      .fail
1019
        cmp     al, 9
1020
        jbe     .nibble_ok
1021
        sub     al, 'A' - '0' - 10
1022
        jb      .fail
1023
        cmp     al, 15
1024
        jbe     .nibble_ok
1025
        sub     al, 'a' - 'A'
1026
        cmp     al, 15
1027
        ja      .fail
1028
  .nibble_ok:
1029
        shl     bl, 8
1030
        or      bl, al
1031
        dec     ecx
1032
        jc      .unescape_nibble
1033
        mov     al, bl
1034
        stosb
1035
        jmp     .loop
1036
 
1037
  .fail:
1038
        DEBUGF  1, "ERROR: invalid URI!\n"
1039
        jmp     .loop
1040
 
1041
  .done:
1042
        stosb
1043
 
1044
        popa
1045
        ret
1046
 
1047
  .error:
1048
        popa
1049
        xor     eax, eax
1050
        ret
1051
 
1052
endp
1053
 
1054
 
1055
 
1056
 
1057
 
1058
;;================================================================================================;;
4202 hidnplayr 1059
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1060
;;================================================================================================;;
1061
;! Internal procedures section                                                                    ;;
1062
;;================================================================================================;;
1063
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1064
;;================================================================================================;;
1065
 
1066
 
1067
 
1068
 
1069
;;================================================================================================;;
4167 hidnplayr 1070
proc open_connection hostname, port ;/////////////////////////////////////////////////////////////;;
1071
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1072
;? Connects to a HTTP server                                                                      ;;
4167 hidnplayr 1073
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1074
;> hostname     = ptr to ASCIIZ hostname                                                          ;;
1075
;> port         = port (x86 byte order)                                                           ;;
4167 hidnplayr 1076
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1077
;< eax = 0 (error) / socketnum                                                                    ;;
4167 hidnplayr 1078
;;================================================================================================;;
4158 hidnplayr 1079
 
4167 hidnplayr 1080
locals
1081
        sockaddr        dd ?
1082
        socketnum       dd ?
1083
endl
1084
 
1085
; Resolve the hostname
1086
        DEBUGF  1, "Resolving hostname\n"
1087
        push    esp     ; reserve stack place
1088
        push    esp     ; fourth parameter
1089
        push    0       ; third parameter
1090
        push    0       ; second parameter
1091
        push    [hostname]
1092
        call    [getaddrinfo]
1093
        pop     esi
1094
        test    eax, eax
1095
        jnz     .error1
1096
 
1097
; getaddrinfo returns addrinfo struct, make the pointer to sockaddr struct
1098
        mov     esi, [esi + addrinfo.ai_addr]
1099
        mov     [sockaddr], esi
1100
        mov     eax, [esi + sockaddr_in.sin_addr]
1101
        test    eax, eax
1102
        jz      .error2
1103
 
1104
        DEBUGF  1, "Server ip=%u.%u.%u.%u\n", \
1105
        [esi + sockaddr_in.sin_addr]:1, [esi + sockaddr_in.sin_addr + 1]:1, \
1106
        [esi + sockaddr_in.sin_addr + 2]:1, [esi + sockaddr_in.sin_addr + 3]:1
1107
 
1108
        mov     [esi + sockaddr_in.sin_family], AF_INET4
1109
        mov     eax, [port]
1110
        xchg    al, ah
1111
        mov     [esi + sockaddr_in.sin_port], ax
1112
 
1113
; Connect to the server.
1114
        mcall   socket, AF_INET4, SOCK_STREAM, 0
1115
        test    eax, eax
1116
        jz      .error2
1117
        mov     [socketnum], eax
1118
        DEBUGF  1, "Socket: 0x%x\n", eax
1119
 
1120
        mcall   connect, [socketnum], [sockaddr], 18
1121
        test    eax, eax
1122
        jnz     .error2
1123
        DEBUGF  1, "Socket is now connected.\n"
1124
 
1125
; free allocated memory
1126
        push    [sockaddr]
1127
        call    [freeaddrinfo]
1128
 
1129
        mov     eax, [socketnum]
1130
        ret
1131
 
1132
  .error2:
1133
 
1134
; free allocated memory
1135
        push    [sockaddr]
1136
        call    [freeaddrinfo]
1137
 
1138
  .error1:
1139
        xor     eax, eax
1140
        ret
1141
 
1142
endp
1143
 
1144
 
4158 hidnplayr 1145
;;================================================================================================;;
1146
proc parse_url URL ;//////////////////////////////////////////////////////////////////////////////;;
1147
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1148
;? Split a given URL into hostname and pageaddr                                                   ;;
4158 hidnplayr 1149
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1150
;> URL = ptr to ASCIIZ URL                                                                        ;;
4158 hidnplayr 1151
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1152
;< eax = 0 (error) / ptr to ASCIIZ hostname                                                       ;;
1153
;< ebx = ptr to ASCIIZ pageaddr                                                                   ;;
4158 hidnplayr 1154
;;================================================================================================;;
1155
 
1156
locals
1157
        urlsize         dd ?
1158
        hostname        dd ?
1159
        pageaddr        dd ?
1160
endl
1161
 
4161 hidnplayr 1162
        DEBUGF  1, "parsing URL: %s\n", [URL]
4158 hidnplayr 1163
 
1164
; remove any leading protocol text
1165
        mov     esi, [URL]
1166
        mov     ecx, URLMAXLEN
1167
        mov     ax, '//'
1168
  .loop1:
1169
        cmp     byte[esi], 0            ; end of URL?
1170
        je      .url_ok                 ; yep, so not found
1171
        cmp     [esi], ax
1172
        je      .skip_proto
1173
        inc     esi
1174
        dec     ecx
1175
        jnz     .loop1
1176
 
4161 hidnplayr 1177
        DEBUGF  1, "Invalid URL\n"
4158 hidnplayr 1178
        xor     eax, eax
1179
        ret
1180
 
1181
  .skip_proto:
1182
        inc     esi                     ; skip the two '/'
1183
        inc     esi
1184
        mov     [URL], esi              ; update pointer so it skips protocol
1185
        jmp     .loop1                  ; we still need to find the length of the URL
1186
 
1187
  .url_ok:
1188
        sub     esi, [URL]              ; calculate total length of URL
1189
        mov     [urlsize], esi
1190
 
1191
 
1192
; now look for page delimiter - it's a '/' character
1193
        mov     ecx, esi                ; URL length
1194
        mov     edi, [URL]
1195
        mov     al, '/'
1196
        repne   scasb
4161 hidnplayr 1197
        jne     @f
4158 hidnplayr 1198
        dec     edi                     ; return one char, '/' must be part of the pageaddr
1199
        inc     ecx                     ;
4161 hidnplayr 1200
  @@:
4158 hidnplayr 1201
        push    ecx edi                 ; remember the pointer and length of pageaddr
1202
 
1203
        mov     ecx, edi
1204
        sub     ecx, [URL]
1205
        inc     ecx                     ; we will add a 0 byte at the end
1206
        invoke  mem.alloc, ecx
1207
        or      eax, eax
1208
        jz      .no_mem
1209
 
1210
        mov     [hostname], eax         ; copy hostname to buffer
1211
        mov     edi, eax
1212
        mov     esi, [URL]
1213
        dec     ecx
1214
        rep     movsb
1215
        xor     al, al
1216
        stosb
1217
 
4161 hidnplayr 1218
        mov     [pageaddr], str_slash   ; assume there is no pageaddr
4158 hidnplayr 1219
        pop     esi ecx
1220
        test    ecx, ecx
1221
        jz      .no_page
1222
        inc     ecx                     ; we will add a 0 byte at the end
1223
        invoke  mem.alloc, ecx
1224
        or      eax, eax
1225
        jz      .no_mem
1226
 
1227
        mov     [pageaddr], eax         ; copy pageaddr to buffer
1228
        mov     edi, eax
1229
        dec     ecx
1230
        rep     movsb
1231
        xor     al, al
1232
        stosb
1233
  .no_page:
1234
 
1235
        mov     eax, [hostname]
1236
        mov     ebx, [pageaddr]
1237
 
1238
        DEBUGF  1, "hostname: %s\n", eax
1239
        DEBUGF  1, "pageaddr: %s\n", ebx
1240
 
1241
        ret
1242
 
1243
  .no_mem:
1244
        xor     eax, eax
1245
        ret
1246
 
1247
endp
1248
 
1249
 
4202 hidnplayr 1250
;;================================================================================================;;
1251
proc ascii_dec ;//////////////////////////////////////////////////////////////////////////////////;;
1252
;;------------------------------------------------------------------------------------------------;;
1253
;? Convert eax to ASCII decimal number                                                            ;;
1254
;;------------------------------------------------------------------------------------------------;;
1255
;> eax = number                                                                                   ;;
1256
;> edi = ptr where to write ASCII decimal number                                                  ;;
1257
;;------------------------------------------------------------------------------------------------;;
1258
;< /                                                                                              ;;
1259
;;================================================================================================;;
4158 hidnplayr 1260
 
4168 hidnplayr 1261
        push    -'0'
4167 hidnplayr 1262
        mov     ecx, 10
1263
  .loop:
1264
        xor     edx, edx
1265
        div     ecx
1266
        add     dl, '0'
4168 hidnplayr 1267
        push    edx
4167 hidnplayr 1268
        test    eax, eax
1269
        jnz     .loop
4158 hidnplayr 1270
 
4168 hidnplayr 1271
  .loop2:
1272
        pop     eax
1273
        add     al, '0'
1274
        jz      .done
1275
        stosb
1276
        jmp     .loop2
1277
  .done:
1278
 
4167 hidnplayr 1279
        ret
4158 hidnplayr 1280
 
4202 hidnplayr 1281
endp
4167 hidnplayr 1282
 
4202 hidnplayr 1283
 
4158 hidnplayr 1284
;;================================================================================================;;
1285
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1286
;;================================================================================================;;
1287
;! Imported functions section                                                                     ;;
1288
;;================================================================================================;;
1289
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1290
;;================================================================================================;;
1291
 
1292
 
1293
align 16
1294
@IMPORT:
1295
 
1296
library \
1297
        libini, 'libini.obj', \
1298
        network, 'network.obj'
1299
 
1300
import  libini, \
1301
        ini.get_str, 'ini_get_str', \
1302
        ini.get_int, 'ini_get_int'
1303
 
1304
import  network,\
1305
        getaddrinfo, 'getaddrinfo',\
1306
        freeaddrinfo,  'freeaddrinfo',\
1307
        inet_ntoa, 'inet_ntoa'
1308
 
1309
;;===========================================================================;;
1310
;;///////////////////////////////////////////////////////////////////////////;;
1311
;;===========================================================================;;
1312
;! Exported functions section                                                ;;
1313
;;===========================================================================;;
1314
;;///////////////////////////////////////////////////////////////////////////;;
1315
;;===========================================================================;;
1316
 
1317
 
1318
align 4
1319
@EXPORT:
1320
export  \
1321
        lib_init                , 'lib_init'            , \
1322
        0x00010001              , 'version'             , \
1323
        HTTP_get                , 'get'                 , \
4167 hidnplayr 1324
        HTTP_head               , 'head'                , \
1325
        HTTP_post               , 'post'                , \
4158 hidnplayr 1326
        find_header_field       , 'find_header_field'   , \
4205 hidnplayr 1327
        HTTP_process            , 'process'             , \
1328
        HTTP_free               , 'free'                , \
4209 hidnplayr 1329
        HTTP_stop               , 'stop'                , \
1330
        URI_escape              , 'escape'              , \
1331
        URI_unescape            , 'unescape'
4158 hidnplayr 1332
 
1333
;        HTTP_put                , 'put'                 , \
1334
;        HTTP_delete             , 'delete'              , \
1335
;        HTTP_trace              , 'trace'               , \
1336
;        HTTP_connect            , 'connect'             , \
1337
 
1338
 
1339
 
1340
section '.data' data readable writable align 16
1341
 
1342
inifile         db '/sys/settings/network.ini', 0
1343
 
1344
sec_proxy:
1345
key_proxy       db 'proxy', 0
1346
key_proxyport   db 'port', 0
1347
key_user        db 'user', 0
1348
key_password    db 'password', 0
1349
 
1350
str_http11      db ' HTTP/1.1', 13, 10, 'Host: '
1351
  .length       = $ - str_http11
4167 hidnplayr 1352
str_post_cl     db 13, 10, 'Content-Length: '
1353
  .length       = $ - str_post_cl
1354
str_post_ct     db 13, 10, 'Content-Type: '
1355
  .length       = $ - str_post_ct
4158 hidnplayr 1356
str_close       db 13, 10, 'User-Agent: KolibriOS libHTTP/1.0', 13, 10, 'Connection: Close', 13, 10, 13, 10
1357
  .length       = $ - str_close
1358
str_proxy_auth  db 13, 10, 'Proxy-Authorization: Basic '
1359
  .length       = $ - str_proxy_auth
1360
 
1361
base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
1362
                db '0123456789+/'
1363
 
1364
str_cl          db 'content-length', 0
4161 hidnplayr 1365
str_slash       db '/', 0
4158 hidnplayr 1366
str_te          db 'transfer-encoding', 0
4167 hidnplayr 1367
str_get         db 'GET ', 0
1368
str_head        db 'HEAD ', 0
1369
str_post        db 'POST ', 0
4158 hidnplayr 1370
 
4209 hidnplayr 1371
bits_must_escape:
1372
dd      0xffffffff                                                      ; 00-1F
1373
dd      1 shl 0 + 1 shl 2 + 1 shl 3 + 1 shl 5 + 1 shl 28 + 1 shl 30     ; "#%<>
1374
dd      1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 30                       ;[\]^
1375
dd      1 shl 0 + 1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 31             ;`{|} DEL
1376
 
1377
dd      0xffffffff
1378
dd      0xffffffff
1379
dd      0xffffffff
1380
dd      0xffffffff
1381
 
1382
str_hex:
1383
db '0123456789ABCDEF'
1384
 
4158 hidnplayr 1385
include_debug_strings
1386
 
1387
; uninitialized data
1388
mem.alloc       dd ?
1389
mem.free        dd ?
1390
mem.realloc     dd ?
1391
dll.load        dd ?
1392
 
1393
proxyAddr       rb 256
1394
proxyUser       rb 256
1395
proxyPassword   rb 256
1396
proxyPort       dd ?