Subversion Repositories Kolibri OS

Rev

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