Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4158 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
5534 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
4158 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  HTTP library for KolibriOS                                     ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
4233 hidnplayr 9
;;   Proxy code written by CleverMouse                             ;;
4158 hidnplayr 10
;;                                                                 ;;
11
;;         GNU GENERAL PUBLIC LICENSE                              ;;
12
;;          Version 2, June 1991                                   ;;
13
;;                                                                 ;;
14
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
 
16
; references:
17
; "HTTP made really easy", http://www.jmarshall.com/easy/http/
18
; "Hypertext Transfer Protocol -- HTTP/1.1", http://tools.ietf.org/html/rfc2616
19
 
20
 
21
        URLMAXLEN       = 65535
4541 hidnplayr 22
        BUFFERSIZE      = 8192
4690 hidnplayr 23
        TIMEOUT         = 500  ; in 1/100 s
4158 hidnplayr 24
 
25
        __DEBUG__       = 1
5732 hidnplayr 26
        __DEBUG_LEVEL__ = 2
4158 hidnplayr 27
 
28
 
29
format MS COFF
30
 
31
public @EXPORT as 'EXPORTS'
32
 
33
include '../../../struct.inc'
34
include '../../../proc32.inc'
35
include '../../../macros.inc'
36
purge section,mov,add,sub
37
include '../../../debug-fdo.inc'
38
 
39
include '../../../network.inc'
40
include 'http.inc'
41
 
42
virtual at 0
43
        http_msg http_msg
44
end virtual
45
 
46
macro copy_till_zero {
4241 hidnplayr 47
local   .copyloop, .copydone
48
  .copyloop:
4158 hidnplayr 49
        lodsb
50
        test    al, al
4241 hidnplayr 51
        jz      .copydone
4158 hidnplayr 52
        stosb
4241 hidnplayr 53
        jmp     .copyloop
54
  .copydone:
4158 hidnplayr 55
}
56
 
5534 hidnplayr 57
macro HTTP_init_buffer buffer, socketnum, flags {
4167 hidnplayr 58
 
59
        mov     eax, buffer
60
        push    socketnum
61
        popd    [eax + http_msg.socket]
4541 hidnplayr 62
        lea     esi, [eax + http_msg.http_header]
5534 hidnplayr 63
        push    flags
64
        pop     [eax + http_msg.flags]
65
        or      [eax + http_msg.flags], FLAG_CONNECTED
4167 hidnplayr 66
        mov     [eax + http_msg.write_ptr], esi
4541 hidnplayr 67
        mov     [eax + http_msg.buffer_length], BUFFERSIZE -  http_msg.http_header
4167 hidnplayr 68
        mov     [eax + http_msg.chunk_ptr], 0
69
 
70
        mov     [eax + http_msg.status], 0
71
        mov     [eax + http_msg.header_length], 0
4541 hidnplayr 72
        mov     [eax + http_msg.content_ptr], 0
4167 hidnplayr 73
        mov     [eax + http_msg.content_length], 0
4168 hidnplayr 74
        mov     [eax + http_msg.content_received], 0
4206 hidnplayr 75
 
76
        push    eax ebp
77
        mov     ebp, eax
4690 hidnplayr 78
        mcall   26, 9
4206 hidnplayr 79
        mov     [ebp + http_msg.timestamp], eax
80
        pop     ebp eax
4167 hidnplayr 81
}
82
 
4158 hidnplayr 83
section '.flat' code readable align 16
84
 
85
;;===========================================================================;;
86
lib_init: ;//////////////////////////////////////////////////////////////////;;
87
;;---------------------------------------------------------------------------;;
88
;? Library entry point (called after library load)                           ;;
89
;;---------------------------------------------------------------------------;;
90
;> eax = pointer to memory allocation routine                                ;;
91
;> ebx = pointer to memory freeing routine                                   ;;
92
;> ecx = pointer to memory reallocation routine                              ;;
93
;> edx = pointer to library loading routine                                  ;;
94
;;---------------------------------------------------------------------------;;
4209 hidnplayr 95
;< eax = 1 (fail) / 0 (ok)                                                   ;;
4158 hidnplayr 96
;;===========================================================================;;
97
        mov     [mem.alloc], eax
98
        mov     [mem.free], ebx
99
        mov     [mem.realloc], ecx
100
        mov     [dll.load], edx
101
 
102
        invoke  dll.load, @IMPORT
4209 hidnplayr 103
        test    eax, eax
104
        jnz     .error
4158 hidnplayr 105
 
106
; load proxy settings
4216 hidnplayr 107
        pusha
4158 hidnplayr 108
        invoke  ini.get_str, inifile, sec_proxy, key_proxy, proxyAddr, 256, proxyAddr
109
        invoke  ini.get_int, inifile, sec_proxy, key_proxyport, 80
110
        mov     [proxyPort], eax
111
        invoke  ini.get_str, inifile, sec_proxy, key_user, proxyUser, 256, proxyUser
112
        invoke  ini.get_str, inifile, sec_proxy, key_password, proxyPassword, 256, proxyPassword
4216 hidnplayr 113
        popa
4158 hidnplayr 114
 
4212 hidnplayr 115
        DEBUGF  1, "HTTP library: init OK\n"
4158 hidnplayr 116
        xor     eax, eax
117
        ret
118
 
4209 hidnplayr 119
  .error:
5732 hidnplayr 120
        DEBUGF  2, "ERROR loading http.obj dependencies\n"
4158 hidnplayr 121
        xor     eax, eax
4209 hidnplayr 122
        inc     eax
4158 hidnplayr 123
        ret
124
 
125
 
4996 hidnplayr 126
;;================================================================================================;;
127
proc HTTP_disconnect identifier ;/////////////////////////////////////////////////////////////////;;
128
;;------------------------------------------------------------------------------------------------;;
129
;? Stops the open connection                                                                      ;;
130
;;------------------------------------------------------------------------------------------------;;
131
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
132
;;------------------------------------------------------------------------------------------------;;
133
;< none                                                                                           ;;
134
;;================================================================================================;;
4158 hidnplayr 135
 
4996 hidnplayr 136
        pusha
137
        mov     ebp, [identifier]
4158 hidnplayr 138
 
4996 hidnplayr 139
        test    [ebp + http_msg.flags], FLAG_CONNECTED
140
        jz      .error
141
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
142
        mcall   close, [ebp + http_msg.socket]
143
 
144
        popa
145
        ret
146
 
147
  .error:
5732 hidnplayr 148
        DEBUGF  2, "Cant close already closed connection!\n"
4996 hidnplayr 149
        popa
150
        ret
151
 
152
endp
153
 
154
 
4158 hidnplayr 155
;;================================================================================================;;
4996 hidnplayr 156
proc HTTP_free identifier ;///////////////////////////////////////////////////////////////////////;;
157
;;------------------------------------------------------------------------------------------------;;
158
;? Free the http_msg structure                                                                    ;;
159
;;------------------------------------------------------------------------------------------------;;
160
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
161
;;------------------------------------------------------------------------------------------------;;
162
;< none                                                                                           ;;
163
;;================================================================================================;;
164
        DEBUGF  1, "HTTP_free: 0x%x\n", [identifier]
165
        pusha
166
        mov     ebp, [identifier]
167
 
168
        test    [ebp + http_msg.flags], FLAG_CONNECTED
169
        jz      .not_connected
170
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
171
        mcall   close, [ebp + http_msg.socket]
172
 
173
  .not_connected:
174
        invoke  mem.free, ebp
175
 
176
        popa
177
        ret
178
 
179
endp
180
 
5534 hidnplayr 181
 
182
 
4996 hidnplayr 183
;;================================================================================================;;
5534 hidnplayr 184
proc HTTP_get URL, identifier, flags, add_header ;////////////////////////////////////////////////;;
4158 hidnplayr 185
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 186
;? Initiates a HTTP connection, using 'GET' method.                                               ;;
4158 hidnplayr 187
;;------------------------------------------------------------------------------------------------;;
5534 hidnplayr 188
;> URL                  = pointer to ASCIIZ URL                                                   ;;
189
;> identifier           = Identifier of an already open connection, or NULL to create a new one.  ;;
190
;> flags                = Flags indicating how to threat the connection.                          ;;
191
;> add_header           = pointer to additional header parameters (ASCIIZ), or NULL for none.     ;;
4158 hidnplayr 192
;;------------------------------------------------------------------------------------------------;;
193
;< eax = 0 (error) / buffer ptr                                                                   ;;
194
;;================================================================================================;;
195
locals
196
        hostname        dd ?
197
        pageaddr        dd ?
198
        socketnum       dd ?
199
        buffer          dd ?
4167 hidnplayr 200
        port            dd ?
4158 hidnplayr 201
endl
202
 
5537 hidnplayr 203
        and     [flags], 0xff00       ; filter out invalid flags
5534 hidnplayr 204
 
4216 hidnplayr 205
        pusha
206
 
4158 hidnplayr 207
; split the URL into hostname and pageaddr
208
        stdcall parse_url, [URL]
209
        test    eax, eax
210
        jz      .error
211
        mov     [hostname], eax
212
        mov     [pageaddr], ebx
4221 hidnplayr 213
        mov     [port], ecx
4158 hidnplayr 214
 
5534 hidnplayr 215
        mov     eax, [identifier]
216
        test    eax, eax
217
        jz      .open_new
218
        test    [eax + http_msg.flags], FLAG_CONNECTED
219
        jz      .error
220
        mov     eax, [eax + http_msg.socket]
221
        mov     [socketnum], eax
222
        jmp     .send_request
223
 
4167 hidnplayr 224
; Connect to the other side.
5534 hidnplayr 225
  .open_new:
4167 hidnplayr 226
        stdcall open_connection, [hostname], [port]
4158 hidnplayr 227
        test    eax, eax
4167 hidnplayr 228
        jz      .error
229
        mov     [socketnum], eax
4158 hidnplayr 230
 
4167 hidnplayr 231
; Create the HTTP request.
5534 hidnplayr 232
  .send_request:
4167 hidnplayr 233
        invoke  mem.alloc, BUFFERSIZE
4158 hidnplayr 234
        test    eax, eax
235
        jz      .error
4167 hidnplayr 236
        mov     [buffer], eax
237
        mov     edi, eax
4541 hidnplayr 238
        DEBUGF  1, "Buffer allocated: 0x%x\n", eax
4158 hidnplayr 239
 
4167 hidnplayr 240
        mov     esi, str_get
241
        copy_till_zero
4158 hidnplayr 242
 
4233 hidnplayr 243
; If we are using a proxy, send complete URL, otherwise send only page address.
244
        cmp     [proxyAddr], 0
245
        je      .no_proxy
246
        mov     esi, str_http           ; prepend 'http://'
247
        copy_till_zero
248
        mov     esi, [hostname]
249
        copy_till_zero
250
  .no_proxy:
4167 hidnplayr 251
        mov     esi, [pageaddr]
252
        copy_till_zero
4158 hidnplayr 253
 
4167 hidnplayr 254
        mov     esi, str_http11
255
        mov     ecx, str_http11.length
256
        rep     movsb
257
 
258
        mov     esi, [hostname]
259
        copy_till_zero
260
 
4241 hidnplayr 261
        cmp     byte[proxyUser], 0
262
        je      @f
263
        call    append_proxy_auth_header
264
  @@:
265
 
266
        mov     ax, 0x0a0d
267
        stosw
268
 
4221 hidnplayr 269
        mov     esi, [add_header]
270
        test    esi, esi
271
        jz      @f
272
        copy_till_zero
273
  @@:
274
 
4167 hidnplayr 275
        mov     esi, str_close
276
        mov     ecx, str_close.length
5534 hidnplayr 277
        test    [flags], FLAG_KEEPALIVE
278
        jz      @f
279
        mov     esi, str_keep
280
        mov     ecx, str_keep.length
281
  @@:
4167 hidnplayr 282
        rep     movsb
283
 
284
        mov     byte[edi], 0
285
        DEBUGF  1, "Request:\n%s", [buffer]
286
 
4222 hidnplayr 287
; Free unused memory
288
        push    edi
289
        invoke  mem.free, [pageaddr]
290
        invoke  mem.free, [hostname]
291
        pop     esi
292
 
4167 hidnplayr 293
; Send the request
294
        sub     esi, [buffer]   ; length
295
        xor     edi, edi        ; flags
296
        mcall   send, [socketnum], [buffer]
4158 hidnplayr 297
        test    eax, eax
298
        jz      .error
4167 hidnplayr 299
        DEBUGF  1, "Request has been sent to server.\n"
4158 hidnplayr 300
 
5534 hidnplayr 301
        cmp     [identifier], 0
302
        jne     .old_connection
303
        HTTP_init_buffer [buffer], [socketnum], [flags]
4167 hidnplayr 304
 
4216 hidnplayr 305
        popa
306
        mov     eax, [buffer]   ; return buffer ptr
307
        ret
4167 hidnplayr 308
 
5534 hidnplayr 309
  .old_connection:
310
        invoke  mem.free, [buffer]
311
        popa
312
        mov     eax, [identifier]
313
        ret
314
 
4167 hidnplayr 315
  .error:
5732 hidnplayr 316
        DEBUGF  2, "HTTP GET error!\n"
4216 hidnplayr 317
        popa
4167 hidnplayr 318
        xor     eax, eax        ; return 0 = error
319
        ret
320
 
321
endp
322
 
323
 
324
 
325
;;================================================================================================;;
5534 hidnplayr 326
proc HTTP_head URL, identifier, flags, add_header ;///////////////////////////////////////////////;;
4167 hidnplayr 327
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 328
;? Initiates a HTTP connection, using 'HEAD' method.                                              ;;
4541 hidnplayr 329
;? This will only return HTTP header and status, no content                                       ;;
4167 hidnplayr 330
;;------------------------------------------------------------------------------------------------;;
5534 hidnplayr 331
;> URL                  = pointer to ASCIIZ URL                                                   ;;
332
;> identifier           = Identifier of an already open connection, or NULL to create a new one.  ;;
333
;> flags                = Flags indicating how to threat the connection.                          ;;
334
;> add_header           = pointer to additional header parameters (ASCIIZ), or NULL for none.     ;;
4167 hidnplayr 335
;;------------------------------------------------------------------------------------------------;;
336
;< eax = 0 (error) / buffer ptr                                                                   ;;
337
;;================================================================================================;;
338
locals
339
        hostname        dd ?
340
        pageaddr        dd ?
341
        socketnum       dd ?
342
        buffer          dd ?
343
        port            dd ?
344
endl
345
 
5537 hidnplayr 346
        and     [flags], 0xff00         ; filter out invalid flags
5534 hidnplayr 347
 
4216 hidnplayr 348
        pusha
4167 hidnplayr 349
; split the URL into hostname and pageaddr
350
        stdcall parse_url, [URL]
4158 hidnplayr 351
        test    eax, eax
4167 hidnplayr 352
        jz      .error
353
        mov     [hostname], eax
354
        mov     [pageaddr], ebx
4221 hidnplayr 355
        mov     [port], ecx
4158 hidnplayr 356
 
5534 hidnplayr 357
        mov     eax, [identifier]
358
        test    eax, eax
359
        jz      .open_new
360
        test    [eax + http_msg.flags], FLAG_CONNECTED
361
        jz      .error
362
        mov     eax, [eax + http_msg.socket]
363
        mov     [socketnum], eax
364
        jmp     .send_request
365
 
4167 hidnplayr 366
; Connect to the other side.
5534 hidnplayr 367
  .open_new:
4167 hidnplayr 368
        stdcall open_connection, [hostname], [port]
369
        test    eax, eax
370
        jz      .error
371
        mov     [socketnum], eax
372
 
4158 hidnplayr 373
; Create the HTTP request.
5534 hidnplayr 374
  .send_request:
4158 hidnplayr 375
        invoke  mem.alloc, BUFFERSIZE
376
        test    eax, eax
377
        jz      .error
378
        mov     [buffer], eax
4167 hidnplayr 379
        mov     edi, eax
4158 hidnplayr 380
        DEBUGF  1, "Buffer has been allocated.\n"
381
 
4167 hidnplayr 382
        mov     esi, str_head
4158 hidnplayr 383
        copy_till_zero
384
 
4233 hidnplayr 385
; If we are using a proxy, send complete URL, otherwise send only page address.
386
        cmp     [proxyAddr], 0
387
        je      .no_proxy
388
        mov     esi, str_http           ; prepend 'http://'
389
        copy_till_zero
390
        mov     esi, [hostname]
391
        copy_till_zero
392
  .no_proxy:
4167 hidnplayr 393
        mov     esi, [pageaddr]
394
        copy_till_zero
395
 
4158 hidnplayr 396
        mov     esi, str_http11
397
        mov     ecx, str_http11.length
398
        rep     movsb
399
 
400
        mov     esi, [hostname]
401
        copy_till_zero
402
 
4241 hidnplayr 403
        cmp     byte[proxyUser], 0
404
        je      @f
405
        call    append_proxy_auth_header
406
  @@:
407
 
408
        mov     ax, 0x0a0d
409
        stosw
410
 
4221 hidnplayr 411
        mov     esi, [add_header]
412
        test    esi, esi
413
        jz      @f
414
        copy_till_zero
415
  @@:
416
 
4158 hidnplayr 417
        mov     esi, str_close
418
        mov     ecx, str_close.length
5534 hidnplayr 419
        test    [flags], FLAG_KEEPALIVE
420
        jz      @f
421
        mov     esi, str_keep
422
        mov     ecx, str_keep.length
423
  @@:
4158 hidnplayr 424
        rep     movsb
425
 
426
        mov     byte[edi], 0
427
        DEBUGF  1, "Request:\n%s", [buffer]
428
 
4222 hidnplayr 429
; Free unused memory
430
        push    edi
431
        invoke  mem.free, [pageaddr]
432
        invoke  mem.free, [hostname]
433
        pop     esi
434
 
4167 hidnplayr 435
; Send the request
4158 hidnplayr 436
        sub     esi, [buffer]   ; length
437
        xor     edi, edi        ; flags
438
        mcall   send, [socketnum], [buffer]
439
        test    eax, eax
440
        jz      .error
441
        DEBUGF  1, "Request has been sent to server.\n"
442
 
5534 hidnplayr 443
        cmp     [identifier], 0
444
        jne     .old_connection
445
        HTTP_init_buffer [buffer], [socketnum], [flags]
4158 hidnplayr 446
 
4216 hidnplayr 447
        popa
5534 hidnplayr 448
        mov     eax, [buffer]   ; return buffer ptr
449
        ret
4158 hidnplayr 450
 
5534 hidnplayr 451
  .old_connection:
452
        invoke  mem.free, [buffer]
453
        popa
454
        mov     eax, [identifier]
455
        ret
456
 
4167 hidnplayr 457
  .error:
5732 hidnplayr 458
        DEBUGF  2, "HTTP HEAD error!\n"
4216 hidnplayr 459
        popa
4167 hidnplayr 460
        xor     eax, eax        ; return 0 = error
461
        ret
462
 
463
endp
464
 
465
 
466
;;================================================================================================;;
5534 hidnplayr 467
proc HTTP_post URL, identifier, flags, add_header, content_type, content_length ;/////////////////;;
4167 hidnplayr 468
;;------------------------------------------------------------------------------------------------;;
4541 hidnplayr 469
;? Initiates a HTTP connection, using 'POST' method.                                              ;;
470
;? This method is used to send data to the HTTP server                                            ;;
4167 hidnplayr 471
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 472
;> URL                  = pointer to ASCIIZ URL                                                   ;;
5534 hidnplayr 473
;> identifier           = Identifier of an already open connection, or NULL to create a new one.  ;;
474
;> flags                = Flags indicating how to threat the connection.                          ;;
475
;> add_header           = pointer to additional header parameters (ASCIIZ), or NULL for none.     ;;
4202 hidnplayr 476
;> content_type         = pointer to ASCIIZ string containing content type                        ;;
477
;> content_length       = length of content (in bytes)                                            ;;
4167 hidnplayr 478
;;------------------------------------------------------------------------------------------------;;
5534 hidnplayr 479
;< eax = 0 (error) / buffer ptr (aka Identifier)                                                  ;;
4167 hidnplayr 480
;;================================================================================================;;
481
locals
482
        hostname        dd ?
483
        pageaddr        dd ?
484
        socketnum       dd ?
485
        buffer          dd ?
486
        port            dd ?
487
endl
488
 
5537 hidnplayr 489
        and     [flags], 0xff00       ; filter out invalid flags
5534 hidnplayr 490
 
4216 hidnplayr 491
        pusha
4167 hidnplayr 492
; split the URL into hostname and pageaddr
493
        stdcall parse_url, [URL]
494
        test    eax, eax
495
        jz      .error
496
        mov     [hostname], eax
497
        mov     [pageaddr], ebx
4221 hidnplayr 498
        mov     [port], ecx
4167 hidnplayr 499
 
5534 hidnplayr 500
        mov     eax, [identifier]
501
        test    eax, eax
502
        jz      .open_new
503
        test    [eax + http_msg.flags], FLAG_CONNECTED
504
        jz      .error
505
        mov     eax, [eax + http_msg.socket]
506
        mov     [socketnum], eax
507
        jmp     .send_request
508
 
4167 hidnplayr 509
; Connect to the other side.
5534 hidnplayr 510
  .open_new:
4167 hidnplayr 511
        stdcall open_connection, [hostname], [port]
512
        test    eax, eax
513
        jz      .error
514
        mov     [socketnum], eax
515
 
516
; Create the HTTP request.
5534 hidnplayr 517
  .send_request:
4167 hidnplayr 518
        invoke  mem.alloc, BUFFERSIZE
519
        test    eax, eax
520
        jz      .error
521
        mov     [buffer], eax
522
        mov     edi, eax
523
        DEBUGF  1, "Buffer has been allocated.\n"
524
 
525
        mov     esi, str_post
526
        copy_till_zero
527
 
4233 hidnplayr 528
; If we are using a proxy, send complete URL, otherwise send only page address.
529
        cmp     [proxyAddr], 0
530
        je      .no_proxy
531
        mov     esi, str_http           ; prepend 'http://'
532
        copy_till_zero
533
        mov     esi, [hostname]
534
        copy_till_zero
535
  .no_proxy:
4167 hidnplayr 536
        mov     esi, [pageaddr]
537
        copy_till_zero
538
 
539
        mov     esi, str_http11
540
        mov     ecx, str_http11.length
541
        rep     movsb
542
 
543
        mov     esi, [hostname]
544
        copy_till_zero
545
 
546
        mov     esi, str_post_cl
547
        mov     ecx, str_post_cl.length
548
        rep     movsb
549
 
550
        mov     eax, [content_length]
4233 hidnplayr 551
        call    eax_ascii_dec
4167 hidnplayr 552
 
553
        mov     esi, str_post_ct
554
        mov     ecx, str_post_ct.length
555
        rep     movsb
556
 
557
        mov     esi, [content_type]
4221 hidnplayr 558
        copy_till_zero
4167 hidnplayr 559
 
4241 hidnplayr 560
        cmp     byte[proxyUser], 0
561
        je      @f
562
        call    append_proxy_auth_header
563
  @@:
564
 
565
        mov     ax, 0x0a0d
566
        stosw
567
 
4221 hidnplayr 568
        mov     esi, [add_header]
569
        test    esi, esi
570
        jz      @f
571
        copy_till_zero
572
  @@:
573
 
4167 hidnplayr 574
        mov     esi, str_close
575
        mov     ecx, str_close.length
5534 hidnplayr 576
        test    [flags], FLAG_KEEPALIVE
577
        jz      @f
578
        mov     esi, str_keep
579
        mov     ecx, str_keep.length
580
  @@:
4167 hidnplayr 581
        rep     movsb
582
 
583
        mov     byte[edi], 0
584
        DEBUGF  1, "Request:\n%s", [buffer]
585
 
4222 hidnplayr 586
; Free unused memory
587
        push    edi
588
        invoke  mem.free, [pageaddr]
589
        invoke  mem.free, [hostname]
590
        pop     esi
591
 
4167 hidnplayr 592
; Send the request
593
        sub     esi, [buffer]   ; length
594
        xor     edi, edi        ; flags
595
        mcall   send, [socketnum], [buffer]
596
        test    eax, eax
597
        jz      .error
598
        DEBUGF  1, "Request has been sent to server.\n"
599
 
5534 hidnplayr 600
        cmp     [identifier], 0
601
        jne     .old_connection
602
        HTTP_init_buffer [buffer], [socketnum], [flags]
4206 hidnplayr 603
 
4216 hidnplayr 604
        popa
5534 hidnplayr 605
        mov     eax, [buffer]   ; return buffer ptr
606
        ret
4158 hidnplayr 607
 
5534 hidnplayr 608
  .old_connection:
609
        invoke  mem.free, [buffer]
610
        mov     ebx, [flags]
611
        mov     eax, [identifier]
612
        or      [eax + http_msg.flags], ebx
613
        popa
614
        mov     eax, [identifier]
615
        ret
616
 
4158 hidnplayr 617
  .error:
5732 hidnplayr 618
        DEBUGF  1, "HTTP POST error!\n"
4216 hidnplayr 619
        popa
4158 hidnplayr 620
        xor     eax, eax        ; return 0 = error
621
        ret
622
 
623
endp
624
 
625
 
626
 
627
;;================================================================================================;;
4996 hidnplayr 628
proc HTTP_receive identifier ;////////////////////////////////////////////////////////////////////;;
4158 hidnplayr 629
;;------------------------------------------------------------------------------------------------;;
4996 hidnplayr 630
;? Receive data from the server, parse headers and put data in receive buffer(s).                 ;;
4202 hidnplayr 631
;? To complete a transfer, this procedure must be called over and over again untill it returns 0. ;;
4158 hidnplayr 632
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 633
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
4158 hidnplayr 634
;;------------------------------------------------------------------------------------------------;;
635
;< eax = -1 (not finished) / 0 finished                                                           ;;
636
;;================================================================================================;;
4690 hidnplayr 637
 
4158 hidnplayr 638
        pusha
639
        mov     ebp, [identifier]
4162 hidnplayr 640
 
4209 hidnplayr 641
; If the connection is closed, return immediately
4205 hidnplayr 642
        test    [ebp + http_msg.flags], FLAG_CONNECTED
643
        jz      .connection_closed
644
 
5534 hidnplayr 645
; If the buffer is full, allocate a new one
646
        cmp     [ebp + http_msg.buffer_length], 0
647
        jne     .receive
648
 
5537 hidnplayr 649
        test    [ebp + http_msg.flags], FLAG_STREAM
5534 hidnplayr 650
        jz      .err_header
651
 
5537 hidnplayr 652
        test    [ebp + http_msg.flags], FLAG_REUSE_BUFFER
653
        jz      .new_buffer
654
 
655
        mov     eax, [ebp + http_msg.content_ptr]
656
        mov     [ebp + http_msg.write_ptr], eax
657
        mov     [ebp + http_msg.buffer_length], BUFFERSIZE
658
        jmp     .receive
659
 
660
  .new_buffer:
5534 hidnplayr 661
        invoke  mem.alloc, BUFFERSIZE
662
        test    eax, eax
663
        jz      .err_no_ram
664
        mov     [ebp + http_msg.content_ptr], eax
665
        mov     [ebp + http_msg.write_ptr], eax
666
        mov     [ebp + http_msg.buffer_length], BUFFERSIZE
5537 hidnplayr 667
        DEBUGF  1, "New buffer: 0x%x\n", eax
5534 hidnplayr 668
 
4162 hidnplayr 669
; Receive some data
5534 hidnplayr 670
  .receive:
5732 hidnplayr 671
        mov     edi, MSG_DONTWAIT
672
        test    [ebp + http_msg.flags], FLAG_BLOCK
673
        jz      @f
674
        xor     edi, edi
675
  @@:
4158 hidnplayr 676
        mcall   recv, [ebp + http_msg.socket], [ebp + http_msg.write_ptr], \
5732 hidnplayr 677
                      [ebp + http_msg.buffer_length]
4158 hidnplayr 678
        cmp     eax, 0xffffffff
679
        je      .check_socket
4220 hidnplayr 680
 
681
        test    eax, eax
682
        jz      .server_closed
4158 hidnplayr 683
        DEBUGF  1, "Received %u bytes\n", eax
684
 
4209 hidnplayr 685
; Update timestamp
4206 hidnplayr 686
        push    eax
4690 hidnplayr 687
        mcall   26, 9
4206 hidnplayr 688
        mov     [ebp + http_msg.timestamp], eax
689
        pop     eax
690
 
4162 hidnplayr 691
; Update pointers
4158 hidnplayr 692
        mov     edi, [ebp + http_msg.write_ptr]
693
        add     [ebp + http_msg.write_ptr], eax
694
        sub     [ebp + http_msg.buffer_length], eax
4162 hidnplayr 695
 
696
; If data is chunked, combine chunks into contiguous data.
697
        test    [ebp + http_msg.flags], FLAG_CHUNKED
698
        jnz     .chunk_loop
699
 
4212 hidnplayr 700
; Did we detect the (final) header yet?
4158 hidnplayr 701
        test    [ebp + http_msg.flags], FLAG_GOT_HEADER
702
        jnz     .header_parsed
703
 
4690 hidnplayr 704
;--------------------------------------------------------------
705
;
706
; Header parsing code begins here
707
;
708
 
4212 hidnplayr 709
; We havent found the (final) header yet, search for it..
710
  .scan_again:
711
        ; eax = total number of bytes received so far
712
        mov     eax, [ebp + http_msg.write_ptr]
4541 hidnplayr 713
        sub     eax, http_msg.http_header
4212 hidnplayr 714
        sub     eax, ebp
715
        sub     eax, [ebp + http_msg.header_length]
716
        ; edi is ptr to begin of header
4541 hidnplayr 717
        lea     edi, [ebp + http_msg.http_header]
4212 hidnplayr 718
        add     edi, [ebp + http_msg.header_length]
719
        ; put it in esi for next proc too
720
        mov     esi, edi
721
        sub     eax, 3
4690 hidnplayr 722
        jle     .need_more_data_for_header
4212 hidnplayr 723
  .scan_loop:
4158 hidnplayr 724
        ; scan for end of header (empty line)
725
        cmp     dword[edi], 0x0a0d0a0d                  ; end of header
726
        je      .end_of_header
4212 hidnplayr 727
        cmp     word[edi+2], 0x0a0a                     ; notice the use of offset + 2, to calculate header length correctly :)
4158 hidnplayr 728
        je      .end_of_header
729
        inc     edi
730
        dec     eax
4212 hidnplayr 731
        jnz     .scan_loop
4690 hidnplayr 732
        jmp     .need_more_data_for_header
4158 hidnplayr 733
 
734
  .end_of_header:
4541 hidnplayr 735
        add     edi, 4 - http_msg.http_header
4158 hidnplayr 736
        sub     edi, ebp
4212 hidnplayr 737
        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 738
        DEBUGF  1, "Header length: %u\n", edi
739
 
4690 hidnplayr 740
; Ok, we have found the header
4212 hidnplayr 741
        cmp     dword[esi], 'HTTP'
4690 hidnplayr 742
        jne     .err_header
4212 hidnplayr 743
        cmp     dword[esi+4], '/1.0'
4158 hidnplayr 744
        je      .http_1.0
4212 hidnplayr 745
        cmp     dword[esi+4], '/1.1'
4690 hidnplayr 746
        jne     .err_header
4158 hidnplayr 747
        or      [ebp + http_msg.flags], FLAG_HTTP11
748
  .http_1.0:
4212 hidnplayr 749
        cmp     byte[esi+8], ' '
4690 hidnplayr 750
        jne     .err_header
4158 hidnplayr 751
 
4212 hidnplayr 752
        add     esi, 9
4158 hidnplayr 753
        xor     eax, eax
754
        xor     ebx, ebx
755
        mov     ecx, 3
756
  .statusloop:
757
        lodsb
758
        sub     al, '0'
4690 hidnplayr 759
        jb      .err_header
4158 hidnplayr 760
        cmp     al, 9
4690 hidnplayr 761
        ja      .err_header
4158 hidnplayr 762
        lea     ebx, [ebx + 4*ebx]
763
        shl     ebx, 1
764
        add     ebx, eax
765
        dec     ecx
766
        jnz     .statusloop
4212 hidnplayr 767
 
4690 hidnplayr 768
; Ignore "100 - Continue" lines
4212 hidnplayr 769
        cmp     ebx, 100
770
        je      .scan_again
771
 
772
        DEBUGF  1, "Status: %u\n", ebx
4158 hidnplayr 773
        mov     [ebp + http_msg.status], ebx
4212 hidnplayr 774
        or      [ebp + http_msg.flags], FLAG_GOT_HEADER
4158 hidnplayr 775
 
776
; Now, convert all header names to lowercase.
777
; This way, it will be much easier to find certain header fields, later on.
4541 hidnplayr 778
        lea     esi, [ebp + http_msg.http_header]
4158 hidnplayr 779
        mov     ecx, [ebp + http_msg.header_length]
780
  .need_newline:
781
        inc     esi
782
        dec     ecx
783
        jz      .convert_done
784
        cmp     byte[esi], 10
785
        jne     .need_newline
4690 hidnplayr 786
; We have found a newline
787
; A line beginning with space or tabs has no header fields.
4158 hidnplayr 788
        inc     esi
789
        dec     ecx
790
        jz      .convert_done
791
        cmp     byte[esi], ' '
792
        je      .need_newline
793
        cmp     byte[esi], 9    ; horizontal tab
794
        je      .need_newline
795
        jmp     .convert_loop
796
  .next_char:
797
        inc     esi
798
        dec     ecx
799
        jz      .convert_done
800
  .convert_loop:
801
        cmp     byte[esi], ':'
802
        je      .need_newline
803
        cmp     byte[esi], 'A'
804
        jb      .next_char
805
        cmp     byte[esi], 'Z'
806
        ja      .next_char
807
        or      byte[esi], 0x20 ; convert to lowercase
808
        jmp     .next_char
809
  .convert_done:
810
        mov     byte[esi-1], 0
4541 hidnplayr 811
        lea     esi, [ebp + http_msg.http_header]
4158 hidnplayr 812
        DEBUGF  1, "Header names converted to lowercase:\n%s\n", esi
813
 
814
; Check for content-length header field.
4222 hidnplayr 815
        stdcall HTTP_find_header_field, ebp, str_cl
4158 hidnplayr 816
        test    eax, eax
817
        jz      .no_content
818
        or      [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
819
 
820
        xor     edx, edx
821
  .cl_loop:
822
        movzx   ebx, byte[eax]
823
        inc     eax
824
        cmp     bl, 10
825
        je      .cl_ok
826
        cmp     bl, 13
827
        je      .cl_ok
828
        cmp     bl, ' '
829
        je      .cl_ok
830
        sub     bl, '0'
4690 hidnplayr 831
        jb      .err_header
4158 hidnplayr 832
        cmp     bl, 9
4690 hidnplayr 833
        ja      .err_header
4158 hidnplayr 834
        lea     edx, [edx + edx*4]      ; edx = edx*10
835
        shl     edx, 1                  ;
836
        add     edx, ebx
837
        jmp     .cl_loop
838
 
839
  .cl_ok:
840
        mov     [ebp + http_msg.content_length], edx
841
        DEBUGF  1, "Content-length: %u\n", edx
842
 
4541 hidnplayr 843
        test    edx, edx
844
        jz      .got_all_data
4158 hidnplayr 845
 
4541 hidnplayr 846
        call    alloc_contentbuff
847
        test    eax, eax
4690 hidnplayr 848
        jz      .err_no_ram
4541 hidnplayr 849
        xor     eax, eax
850
        jmp     .header_parsed
4203 hidnplayr 851
 
4158 hidnplayr 852
  .no_content:
853
        DEBUGF  1, "Content-length not found.\n"
854
; We didnt find 'content-length', maybe server is using chunked transfer encoding?
5537 hidnplayr 855
  .multibuffer:
4158 hidnplayr 856
; Try to find 'transfer-encoding' header.
4222 hidnplayr 857
        stdcall HTTP_find_header_field, ebp, str_te
4158 hidnplayr 858
        test    eax, eax
4541 hidnplayr 859
        jnz     .ct_hdr_found
4158 hidnplayr 860
 
4541 hidnplayr 861
  .not_chunked:
862
        mov     edx, BUFFERSIZE
863
        call    alloc_contentbuff
864
        test    eax, eax
4690 hidnplayr 865
        jz      .err_no_ram
4541 hidnplayr 866
        xor     eax, eax
867
        jmp     .header_parsed
868
 
869
  .ct_hdr_found:
4158 hidnplayr 870
        mov     ebx, dword[eax]
4162 hidnplayr 871
        or      ebx, 0x20202020
4158 hidnplayr 872
        cmp     ebx, 'chun'
4220 hidnplayr 873
        jne     .not_chunked
4158 hidnplayr 874
        mov     ebx, dword[eax+4]
4162 hidnplayr 875
        or      ebx, 0x00202020
876
        and     ebx, 0x00ffffff
4158 hidnplayr 877
        cmp     ebx, 'ked'
4220 hidnplayr 878
        jne     .not_chunked
4158 hidnplayr 879
 
880
        or      [ebp + http_msg.flags], FLAG_CHUNKED
881
        DEBUGF  1, "Transfer type is: chunked\n"
882
 
4541 hidnplayr 883
        mov     edx, BUFFERSIZE
884
        call    alloc_contentbuff
885
        test    eax, eax
4690 hidnplayr 886
        jz      .err_no_ram
4541 hidnplayr 887
 
4158 hidnplayr 888
; Set chunk pointer where first chunk should begin.
4541 hidnplayr 889
        mov     eax, [ebp + http_msg.content_ptr]
4158 hidnplayr 890
        mov     [ebp + http_msg.chunk_ptr], eax
891
 
4690 hidnplayr 892
;--------------------------------------------------------------
893
;
894
; Chunk parsing code begins here
895
;
896
 
4162 hidnplayr 897
  .chunk_loop:
4158 hidnplayr 898
        mov     ecx, [ebp + http_msg.write_ptr]
899
        sub     ecx, [ebp + http_msg.chunk_ptr]
4690 hidnplayr 900
        jbe     .need_more_data_chunked
901
 
4202 hidnplayr 902
; Chunkline starts here, convert the ASCII hex number into ebx
4158 hidnplayr 903
        mov     esi, [ebp + http_msg.chunk_ptr]
4690 hidnplayr 904
        DEBUGF  1, "Chunkline begins at 0x%x\n", esi
905
 
4158 hidnplayr 906
        xor     ebx, ebx
4690 hidnplayr 907
        cmp     byte[esi], 0x0d
908
        jne     .chunk_hex_loop
909
        dec     ecx
910
        jz      .need_more_data_chunked
911
        inc     esi
912
        cmp     byte[esi], 0x0a
913
        jne     .chunk_hex_loop
914
        dec     ecx
915
        jz      .need_more_data_chunked
916
        inc     esi
917
  .chunk_hex_loop:
4158 hidnplayr 918
        lodsb
919
        sub     al, '0'
4690 hidnplayr 920
        jb      .chunk_hex_end
4158 hidnplayr 921
        cmp     al, 9
922
        jbe     .chunk_hex
4162 hidnplayr 923
        sub     al, 'A' - '0' - 10
4690 hidnplayr 924
        jb      .chunk_hex_end
4162 hidnplayr 925
        cmp     al, 15
4158 hidnplayr 926
        jbe     .chunk_hex
927
        sub     al, 'a' - 'A'
4162 hidnplayr 928
        cmp     al, 15
4690 hidnplayr 929
        ja      .chunk_hex_end
4158 hidnplayr 930
  .chunk_hex:
931
        shl     ebx, 4
932
        add     bl, al
4690 hidnplayr 933
        dec     ecx
934
        jnz     .chunk_hex_loop
935
        jmp     .need_more_data_chunked
936
  .chunk_hex_end:
937
; Chunkline ends with a CR LF or simply LF
4541 hidnplayr 938
        dec     esi
4202 hidnplayr 939
  .end_of_chunkline?:
4541 hidnplayr 940
        lodsb
4690 hidnplayr 941
        cmp     al, 10                                  ; chunkline must always end with LF
4158 hidnplayr 942
        je      .end_of_chunkline
4690 hidnplayr 943
        dec     ecx
944
        jnz     .end_of_chunkline?
945
        xor     eax, eax
946
        jmp     .need_more_data_chunked                 ; chunkline is incomplete, request more data
4158 hidnplayr 947
  .end_of_chunkline:
4690 hidnplayr 948
        DEBUGF  1, "Chunk of 0x%x bytes\n", ebx
4541 hidnplayr 949
; If chunk size is 0, all chunks have been received.
950
        test    ebx, ebx
951
        jz      .got_all_data_chunked
4690 hidnplayr 952
; Calculate how many data bytes we have received already
4541 hidnplayr 953
        mov     ecx, [ebp + http_msg.write_ptr]
4690 hidnplayr 954
        sub     ecx, [ebp + http_msg.chunk_ptr]         ; ecx is now number of received data bytes
955
; Update content_received counter
956
        add     [ebp + http_msg.content_received], ecx
957
; Calculate new write ptr
958
        mov     edx, esi
959
        sub     edx, [ebp + http_msg.chunk_ptr]         ; edx is now length of chunkline
960
        sub     [ebp + http_msg.write_ptr], edx
5537 hidnplayr 961
        test    [ebp + http_msg.flags], FLAG_STREAM
5534 hidnplayr 962
        jnz     .dont_resize
4162 hidnplayr 963
; Realloc buffer, make it 'chunksize' bigger.
4690 hidnplayr 964
        lea     edx, [ebx + BUFFERSIZE]
965
        mov     [ebp + http_msg.buffer_length], edx     ; remaining space in new buffer
966
        add     edx, [ebp + http_msg.write_ptr]
967
        sub     edx, [ebp + http_msg.content_ptr]
968
        DEBUGF  1, "Resizing buffer 0x%x, it will now be %u bytes\n", [ebp + http_msg.content_ptr], edx
969
        invoke  mem.realloc, [ebp + http_msg.content_ptr], edx
4541 hidnplayr 970
        DEBUGF  1, "New buffer = 0x%x\n", eax
4162 hidnplayr 971
        or      eax, eax
4690 hidnplayr 972
        jz      .err_no_ram
973
        call    recalculate_pointers                    ; Because it's possible that buffer begins on another address now
974
        add     esi, eax                                ; recalculate esi too!
5534 hidnplayr 975
  .dont_resize:
4690 hidnplayr 976
; Remove chunk header (aka chunkline) from the buffer by shifting all received data after chunkt_ptr to the left
4541 hidnplayr 977
        mov     edi, [ebp + http_msg.chunk_ptr]
4690 hidnplayr 978
        rep movsb
979
; Update chunk ptr to point to next chunk
4541 hidnplayr 980
        add     [ebp + http_msg.chunk_ptr], ebx
4690 hidnplayr 981
; Set number of received bytes to 0, we already updated content_received
4541 hidnplayr 982
        xor     eax, eax
4162 hidnplayr 983
        jmp     .chunk_loop
4158 hidnplayr 984
 
4690 hidnplayr 985
;--------------------------------------------------------------
986
;
987
; end of proc code begins here
988
;
989
 
4162 hidnplayr 990
  .header_parsed:
4690 hidnplayr 991
        ; Header was already parsed and connection isnt chunked.
992
        ; Update content_received
4168 hidnplayr 993
        add     [ebp + http_msg.content_received], eax
4690 hidnplayr 994
        ; If we received content-length parameter, check if we received all the data
4220 hidnplayr 995
        test    [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
4690 hidnplayr 996
        jz      @f
4217 hidnplayr 997
        mov     eax, [ebp + http_msg.content_received]
998
        cmp     eax, [ebp + http_msg.content_length]
4168 hidnplayr 999
        jae     .got_all_data
4690 hidnplayr 1000
  @@:
1001
        cmp     [ebp + http_msg.buffer_length], 0
1002
        je      .buffer_full
1003
        ; Need more data
1004
        popa
1005
        xor     eax, eax
1006
        dec     eax
1007
        ret
4212 hidnplayr 1008
 
4690 hidnplayr 1009
  .buffer_full:
5537 hidnplayr 1010
        test    [ebp + http_msg.flags], FLAG_STREAM
5534 hidnplayr 1011
        jnz     .multibuff
4220 hidnplayr 1012
        mov     eax, [ebp + http_msg.write_ptr]
1013
        add     eax, BUFFERSIZE
4541 hidnplayr 1014
        sub     eax, [ebp + http_msg.content_ptr]
1015
        invoke  mem.realloc, [ebp + http_msg.content_ptr], eax
4220 hidnplayr 1016
        or      eax, eax
4690 hidnplayr 1017
        jz      .err_no_ram
4541 hidnplayr 1018
        call    recalculate_pointers
4220 hidnplayr 1019
        mov     [ebp + http_msg.buffer_length], BUFFERSIZE
4690 hidnplayr 1020
        ; Need more data
1021
        popa
1022
        xor     eax, eax
1023
        dec     eax
1024
        ret
4220 hidnplayr 1025
 
5534 hidnplayr 1026
  .multibuff:
1027
        ; This buffer is full
1028
        popa
1029
        xor     eax, eax
1030
        ret
1031
 
4690 hidnplayr 1032
  .need_more_data_for_header:
1033
        cmp     [ebp + http_msg.buffer_length], 0
1034
        je      .err_header                     ; It's just too damn long!
1035
        ; Need more data
4162 hidnplayr 1036
        popa
1037
        xor     eax, eax
1038
        dec     eax
1039
        ret
4158 hidnplayr 1040
 
4162 hidnplayr 1041
  .need_more_data_chunked:
4690 hidnplayr 1042
        ; We only got a partial chunk, or need more chunks, update content_received and request more data
4168 hidnplayr 1043
        add     [ebp + http_msg.content_received], eax
4158 hidnplayr 1044
        popa
1045
        xor     eax, eax
1046
        dec     eax
1047
        ret
1048
 
4162 hidnplayr 1049
  .got_all_data_chunked:
4690 hidnplayr 1050
        ; Woohoo, we got all the chunked data, calculate total number of bytes received.
4162 hidnplayr 1051
        mov     eax, [ebp + http_msg.chunk_ptr]
4541 hidnplayr 1052
        sub     eax, [ebp + http_msg.content_ptr]
4162 hidnplayr 1053
        mov     [ebp + http_msg.content_length], eax
4168 hidnplayr 1054
        mov     [ebp + http_msg.content_received], eax
4158 hidnplayr 1055
  .got_all_data:
4217 hidnplayr 1056
        DEBUGF  1, "We got all the data! (%u bytes)\n", [ebp + http_msg.content_received]
4205 hidnplayr 1057
        or      [ebp + http_msg.flags], FLAG_GOT_ALL_DATA
1058
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
4158 hidnplayr 1059
        mcall   close, [ebp + http_msg.socket]
1060
        popa
1061
        xor     eax, eax
1062
        ret
1063
 
4690 hidnplayr 1064
;--------------------------------------------------------------
1065
;
1066
; error handeling code begins here
1067
;
1068
 
4158 hidnplayr 1069
  .check_socket:
1070
        cmp     ebx, EWOULDBLOCK
4690 hidnplayr 1071
        jne     .err_socket
1072
        mcall   26, 9
1073
        sub     eax, [ebp + http_msg.timestamp]
1074
        cmp     eax, TIMEOUT
1075
        ja      .err_timeout
1076
        ; Need more data
1077
        popa
1078
        xor     eax, eax
1079
        dec     eax
1080
        ret
4158 hidnplayr 1081
 
4220 hidnplayr 1082
  .server_closed:
1083
        DEBUGF  1, "server closed connection, transfer complete?\n"
1084
        test    [ebp + http_msg.flags], FLAG_GOT_HEADER
4690 hidnplayr 1085
        jz      .err_server_closed
4220 hidnplayr 1086
        test    [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
1087
        jz      .got_all_data
4690 hidnplayr 1088
  .err_server_closed:
4220 hidnplayr 1089
        pop     eax
5732 hidnplayr 1090
        DEBUGF  2, "ERROR: server closed connection unexpectedly\n"
4220 hidnplayr 1091
        or      [ebp + http_msg.flags], FLAG_TRANSFER_FAILED
4690 hidnplayr 1092
        jmp     .abort
4220 hidnplayr 1093
 
4690 hidnplayr 1094
  .err_header:
4203 hidnplayr 1095
        pop     eax
5732 hidnplayr 1096
        DEBUGF  2, "ERROR: invalid header\n"
4158 hidnplayr 1097
        or      [ebp + http_msg.flags], FLAG_INVALID_HEADER
4690 hidnplayr 1098
        jmp     .abort
4158 hidnplayr 1099
 
4690 hidnplayr 1100
  .err_no_ram:
5732 hidnplayr 1101
        DEBUGF  2, "ERROR: out of RAM\n"
4158 hidnplayr 1102
        or      [ebp + http_msg.flags], FLAG_NO_RAM
4690 hidnplayr 1103
        jmp     .abort
4206 hidnplayr 1104
 
4690 hidnplayr 1105
  .err_timeout:
5732 hidnplayr 1106
        DEBUGF  2, "ERROR: timeout\n"
4690 hidnplayr 1107
        or      [ebp + http_msg.flags], FLAG_TIMEOUT_ERROR
1108
        jmp     .abort
1109
 
1110
  .err_socket:
5732 hidnplayr 1111
        DEBUGF  2, "ERROR: socket error %u\n", ebx
4206 hidnplayr 1112
        or      [ebp + http_msg.flags], FLAG_SOCKET_ERROR
4690 hidnplayr 1113
  .abort:
4205 hidnplayr 1114
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
1115
        mcall   close, [ebp + http_msg.socket]
4206 hidnplayr 1116
  .connection_closed:
4158 hidnplayr 1117
        popa
1118
        xor     eax, eax
1119
        ret
1120
 
1121
endp
1122
 
1123
 
4541 hidnplayr 1124
alloc_contentbuff:
4158 hidnplayr 1125
 
5537 hidnplayr 1126
        test    [ebp + http_msg.flags], FLAG_STREAM
1127
        jz      @f
1128
        mov     edx, BUFFERSIZE
1129
  @@:
1130
 
4541 hidnplayr 1131
; Allocate content buffer
1132
        invoke  mem.alloc, edx
1133
        or      eax, eax
1134
        jz      .no_ram
4205 hidnplayr 1135
 
4541 hidnplayr 1136
        DEBUGF  1, "Content buffer allocated: 0x%x\n", eax
1137
 
1138
; Copy already received content into content buffer
1139
        mov     edi, eax
1140
        lea     esi, [ebp + http_msg.http_header]
1141
        add     esi, [ebp + http_msg.header_length]
1142
        mov     ecx, [ebp + http_msg.write_ptr]
1143
        sub     ecx, esi
1144
        mov     ebx, ecx
1145
        rep movsb
1146
 
1147
; Update pointers to point to new buffer
1148
        mov     [ebp + http_msg.content_ptr], eax
1149
        mov     [ebp + http_msg.content_received], ebx
1150
        sub     edx, ebx
1151
        mov     [ebp + http_msg.buffer_length], edx
1152
        add     eax, ebx
1153
        mov     [ebp + http_msg.write_ptr], eax
1154
 
1155
; Shrink header buffer
1156
        mov     eax, http_msg.http_header
1157
        add     eax, [ebp + http_msg.header_length]
1158
        invoke  mem.realloc, ebp, eax
1159
        or      eax, eax
1160
  .no_ram:
1161
 
1162
        ret
1163
 
1164
 
1165
 
1166
recalculate_pointers:
1167
 
1168
        sub     eax, [ebp + http_msg.content_ptr]
1169
        jz      .done
1170
        add     [ebp + http_msg.content_ptr], eax
1171
        add     [ebp + http_msg.write_ptr], eax
1172
        add     [ebp + http_msg.chunk_ptr], eax
1173
 
1174
  .done:
1175
        ret
1176
 
1177
 
1178
 
4158 hidnplayr 1179
;;================================================================================================;;
4996 hidnplayr 1180
proc HTTP_send identifier, dataptr, datalength ;//////////////////////////////////////////////////;;
4205 hidnplayr 1181
;;------------------------------------------------------------------------------------------------;;
4996 hidnplayr 1182
;? Send data to the server                                                                        ;;
4205 hidnplayr 1183
;;------------------------------------------------------------------------------------------------;;
1184
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
4996 hidnplayr 1185
;> dataptr      = pointer to data to be sent.                                                     ;;
1186
;> datalength   = length of data (in bytes) to be sent                                            ;;
4205 hidnplayr 1187
;;------------------------------------------------------------------------------------------------;;
4996 hidnplayr 1188
;< eax = number of bytes sent, -1 on error                                                        ;;
4205 hidnplayr 1189
;;================================================================================================;;
1190
 
4996 hidnplayr 1191
        push    ebx ecx edx esi edi
1192
        mov     edx, [identifier]
1193
        test    [edx + http_msg.flags], FLAG_CONNECTED
1194
        jz      .fail
1195
        mcall   send, [edx + http_msg.socket], [dataptr], [datalength], 0
1196
        pop     edi esi edx ecx ebx
4205 hidnplayr 1197
        ret
1198
 
4996 hidnplayr 1199
  .fail:
1200
        pop     edi esi edx ecx ebx
1201
        xor     eax, eax
1202
        dec     eax
4205 hidnplayr 1203
        ret
1204
 
1205
endp
1206
 
1207
 
1208
;;================================================================================================;;
4222 hidnplayr 1209
proc HTTP_find_header_field identifier, headername ;//////////////////////////////////////////////;;
4158 hidnplayr 1210
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1211
;? Find a header field in the received HTTP header                                                ;;
4996 hidnplayr 1212
;?                                                                                                ;;
1213
;? NOTE: this function returns a pointer which points into the original header data.              ;;
1214
;? The header field is terminated by a CR, LF, space or maybe even tab.                           ;;
1215
;? A free operation should not be operated on this pointer!                                       ;;
4158 hidnplayr 1216
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1217
;> identifier   = ptr to http_msg struct                                                          ;;
4996 hidnplayr 1218
;> headername   = ptr to ASCIIZ string containing field you want to find (must be in lowercase)   ;;
4158 hidnplayr 1219
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1220
;< eax = 0 (error) / ptr to content of the HTTP header field                                      ;;
4158 hidnplayr 1221
;;================================================================================================;;
1222
        push    ebx ecx edx esi edi
1223
 
1224
        DEBUGF  1, "Find header field: %s\n", [headername]
1225
 
1226
        mov     ebx, [identifier]
4202 hidnplayr 1227
        test    [ebx + http_msg.flags], FLAG_GOT_HEADER
1228
        jz      .fail
1229
 
4541 hidnplayr 1230
        lea     edx, [ebx + http_msg.http_header]
4158 hidnplayr 1231
        mov     ecx, edx
1232
        add     ecx, [ebx + http_msg.header_length]
1233
 
1234
  .restart:
1235
        mov     esi, [headername]
1236
        mov     edi, edx
1237
  .loop:
1238
        cmp     edi, ecx
1239
        jae     .fail
1240
        lodsb
1241
        scasb
1242
        je      .loop
1243
        test    al, al
1244
        jz      .done?
1245
  .next:
1246
        inc     edx
1247
        jmp     .restart
1248
 
1249
  .not_done:
1250
        inc     edi
1251
  .done?:
1252
        cmp     byte[edi-1], ':'
1253
        je      .almost_done
1254
        cmp     byte[edi-1], ' '
1255
        je      .not_done
1256
        cmp     byte[edi-1], 9  ; tab
1257
        je      .not_done
1258
 
1259
        jmp     .next
1260
 
1261
  .almost_done:                 ; FIXME: buffer overflow?
1262
        dec     edi
1263
        DEBUGF  1, "Found header field\n"
1264
  .spaceloop:
1265
        inc     edi
1266
        cmp     byte[edi], ' '
1267
        je      .spaceloop
1268
        cmp     byte[edi], 9    ; tab
1269
        je      .spaceloop
1270
 
1271
        mov     eax, edi
1272
        pop     edi esi edx ecx ebx
1273
        ret
1274
 
1275
  .fail:
5732 hidnplayr 1276
        DEBUGF  2, "Header field not found\n"
4158 hidnplayr 1277
        pop     edi esi edx ecx ebx
1278
        xor     eax, eax
1279
        ret
1280
 
1281
endp
1282
 
1283
 
1284
 
4209 hidnplayr 1285
;;================================================================================================;;
5534 hidnplayr 1286
proc HTTP_escape URI, length ;////////////////////////////////////////////////////////////////////;;
4209 hidnplayr 1287
;;------------------------------------------------------------------------------------------------;;
1288
;?                                                                                                ;;
1289
;;------------------------------------------------------------------------------------------------;;
5534 hidnplayr 1290
;> URI = ptr to ASCIIZ URI/data                                                                   ;;
1291
;> length = length of URI/data                                                                    ;;
4209 hidnplayr 1292
;;------------------------------------------------------------------------------------------------;;
4831 hidnplayr 1293
;< eax = 0 (error) / ptr to ASCIIZ URI/data                                                       ;;
1294
;< ebx = length of escaped URI/data                                                               ;;
4209 hidnplayr 1295
;;================================================================================================;;
4202 hidnplayr 1296
 
4848 hidnplayr 1297
        DEBUGF  1, "HTTP_escape: %s\n", [URI]
1298
 
4209 hidnplayr 1299
        pusha
4205 hidnplayr 1300
 
5534 hidnplayr 1301
        invoke  mem.alloc, URLMAXLEN            ; FIXME: use length provided by caller to guess final size.
4209 hidnplayr 1302
        test    eax, eax
1303
        jz      .error
1304
        mov     [esp + 7 * 4], eax              ; return ptr in eax
1305
        mov     esi, [URI]
1306
        mov     edi, eax
1307
        xor     ebx, ebx
1308
        xor     ecx, ecx
1309
  .loop:
1310
        lodsb
1311
        test    al, al
1312
        jz      .done
1313
 
1314
        mov     cl, al
1315
        and     cl, 0x1f
1316
        mov     bl, al
4831 hidnplayr 1317
        shr     bl, 3
1318
        and     bl, not 3
4209 hidnplayr 1319
        bt      dword[bits_must_escape + ebx], ecx
1320
        jc      .escape
1321
 
1322
        stosb
1323
        jmp     .loop
1324
 
1325
  .escape:
1326
        mov     al, '%'
1327
        stosb
1328
        mov     bl, byte[esi-1]
1329
        shr     bl, 4
1330
        mov     al, byte[str_hex + ebx]
1331
        stosb
1332
        mov     bl, byte[esi-1]
1333
        and     bl, 0x0f
1334
        mov     al, byte[str_hex + ebx]
1335
        stosb
1336
        jmp     .loop
1337
 
1338
 
1339
  .done:
1340
        stosb
4831 hidnplayr 1341
        sub     edi, [esp + 7 * 4]
1342
        dec     edi
1343
        mov     [esp + 4 * 4], edi
4209 hidnplayr 1344
 
1345
        popa
4848 hidnplayr 1346
        DEBUGF  1, "escaped URL: %s\n", eax
4209 hidnplayr 1347
        ret
1348
 
1349
  .error:
5732 hidnplayr 1350
        DEBUGF  2, "ERROR: out of RAM!\n"
4209 hidnplayr 1351
        popa
1352
        xor     eax, eax
1353
        ret
1354
 
1355
endp
1356
 
1357
 
1358
 
4167 hidnplayr 1359
;;================================================================================================;;
5534 hidnplayr 1360
proc HTTP_unescape URI, length ;//////////////////////////////////////////////////////////////////;;
4209 hidnplayr 1361
;;------------------------------------------------------------------------------------------------;;
1362
;?                                                                                                ;;
1363
;;------------------------------------------------------------------------------------------------;;
1364
;> URI = ptr to ASCIIZ URI                                                                        ;;
1365
;;------------------------------------------------------------------------------------------------;;
1366
;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
1367
;;================================================================================================;;
1368
 
4848 hidnplayr 1369
        DEBUGF  1, "HTTP_unescape: %s\n", [URI]
4209 hidnplayr 1370
        pusha
1371
 
5534 hidnplayr 1372
        invoke  mem.alloc, URLMAXLEN            ; FIXME: use length provided by caller
4209 hidnplayr 1373
        test    eax, eax
1374
        jz      .error
1375
        mov     [esp + 7 * 4], eax              ; return ptr in eax
1376
        mov     esi, [URI]
1377
        mov     edi, eax
1378
  .loop:
1379
        lodsb
1380
        test    al, al
1381
        jz      .done
1382
        cmp     al, '%'
1383
        je      .unescape
1384
        stosb
1385
        jmp     .loop
1386
 
1387
  .unescape:
1388
        xor     ebx, ebx
1389
        xor     ecx, ecx
1390
  .unescape_nibble:
1391
        lodsb
1392
        sub     al, '0'
1393
        jb      .fail
1394
        cmp     al, 9
1395
        jbe     .nibble_ok
1396
        sub     al, 'A' - '0' - 10
1397
        jb      .fail
1398
        cmp     al, 15
1399
        jbe     .nibble_ok
1400
        sub     al, 'a' - 'A'
1401
        cmp     al, 15
1402
        ja      .fail
1403
  .nibble_ok:
1404
        shl     bl, 8
1405
        or      bl, al
1406
        dec     ecx
1407
        jc      .unescape_nibble
1408
        mov     al, bl
1409
        stosb
1410
        jmp     .loop
1411
 
1412
  .fail:
5732 hidnplayr 1413
        DEBUGF  2, "ERROR: invalid URI!\n"
4209 hidnplayr 1414
        jmp     .loop
1415
 
1416
  .done:
1417
        stosb
1418
        popa
4848 hidnplayr 1419
        DEBUGF  1, "unescaped URL: %s\n", eax
4209 hidnplayr 1420
        ret
1421
 
1422
  .error:
5732 hidnplayr 1423
        DEBUGF  2, "ERROR: out of RAM!\n"
4209 hidnplayr 1424
        popa
1425
        xor     eax, eax
1426
        ret
1427
 
1428
endp
1429
 
1430
 
1431
 
1432
 
1433
 
1434
;;================================================================================================;;
4202 hidnplayr 1435
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1436
;;================================================================================================;;
1437
;! Internal procedures section                                                                    ;;
4220 hidnplayr 1438
;;                                                                                                ;;
1439
;; NOTICE: These procedures do not follow stdcall conventions and thus may destroy any register.  ;;
4202 hidnplayr 1440
;;================================================================================================;;
1441
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1442
;;================================================================================================;;
1443
 
1444
 
1445
 
1446
 
1447
;;================================================================================================;;
4167 hidnplayr 1448
proc open_connection hostname, port ;/////////////////////////////////////////////////////////////;;
1449
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1450
;? Connects to a HTTP server                                                                      ;;
4167 hidnplayr 1451
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1452
;> hostname     = ptr to ASCIIZ hostname                                                          ;;
1453
;> port         = port (x86 byte order)                                                           ;;
4167 hidnplayr 1454
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1455
;< eax = 0 (error) / socketnum                                                                    ;;
4167 hidnplayr 1456
;;================================================================================================;;
4158 hidnplayr 1457
 
4167 hidnplayr 1458
locals
1459
        sockaddr        dd ?
1460
        socketnum       dd ?
1461
endl
1462
 
4233 hidnplayr 1463
        cmp     [proxyAddr], 0
1464
        je      .no_proxy
1465
 
1466
        mov     [hostname], proxyAddr
1467
 
1468
        push    [proxyPort]
1469
        pop     [port]
1470
  .no_proxy:
1471
 
4167 hidnplayr 1472
; Resolve the hostname
1473
        DEBUGF  1, "Resolving hostname\n"
1474
        push    esp     ; reserve stack place
1475
        push    esp     ; fourth parameter
1476
        push    0       ; third parameter
1477
        push    0       ; second parameter
1478
        push    [hostname]
1479
        call    [getaddrinfo]
1480
        pop     esi
1481
        test    eax, eax
1482
        jnz     .error1
1483
 
1484
; getaddrinfo returns addrinfo struct, make the pointer to sockaddr struct
1485
        mov     esi, [esi + addrinfo.ai_addr]
1486
        mov     [sockaddr], esi
1487
        mov     eax, [esi + sockaddr_in.sin_addr]
1488
        test    eax, eax
1489
        jz      .error2
1490
 
1491
        DEBUGF  1, "Server ip=%u.%u.%u.%u\n", \
1492
        [esi + sockaddr_in.sin_addr]:1, [esi + sockaddr_in.sin_addr + 1]:1, \
1493
        [esi + sockaddr_in.sin_addr + 2]:1, [esi + sockaddr_in.sin_addr + 3]:1
1494
 
1495
        mov     [esi + sockaddr_in.sin_family], AF_INET4
1496
        mov     eax, [port]
1497
        xchg    al, ah
1498
        mov     [esi + sockaddr_in.sin_port], ax
1499
 
1500
; Connect to the server.
1501
        mcall   socket, AF_INET4, SOCK_STREAM, 0
1502
        test    eax, eax
1503
        jz      .error2
1504
        mov     [socketnum], eax
1505
        DEBUGF  1, "Socket: 0x%x\n", eax
1506
 
1507
        mcall   connect, [socketnum], [sockaddr], 18
1508
        test    eax, eax
1509
        jnz     .error2
1510
        DEBUGF  1, "Socket is now connected.\n"
1511
 
1512
; free allocated memory
1513
        push    [sockaddr]
1514
        call    [freeaddrinfo]
1515
 
1516
        mov     eax, [socketnum]
1517
        ret
1518
 
1519
  .error2:
1520
 
1521
; free allocated memory
1522
        push    [sockaddr]
1523
        call    [freeaddrinfo]
1524
 
1525
  .error1:
1526
        xor     eax, eax
1527
        ret
1528
 
1529
endp
1530
 
1531
 
4158 hidnplayr 1532
;;================================================================================================;;
1533
proc parse_url URL ;//////////////////////////////////////////////////////////////////////////////;;
1534
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1535
;? Split a given URL into hostname and pageaddr                                                   ;;
4158 hidnplayr 1536
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1537
;> URL = ptr to ASCIIZ URL                                                                        ;;
4158 hidnplayr 1538
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1539
;< eax = 0 (error) / ptr to ASCIIZ hostname                                                       ;;
1540
;< ebx = ptr to ASCIIZ pageaddr                                                                   ;;
4233 hidnplayr 1541
;< ecx = port number                                                                              ;;
4158 hidnplayr 1542
;;================================================================================================;;
1543
 
1544
locals
1545
        urlsize         dd ?
1546
        hostname        dd ?
1547
        pageaddr        dd ?
4233 hidnplayr 1548
        port            dd ?
4158 hidnplayr 1549
endl
1550
 
4161 hidnplayr 1551
        DEBUGF  1, "parsing URL: %s\n", [URL]
4158 hidnplayr 1552
 
1553
; remove any leading protocol text
4983 hidnplayr 1554
        mov     edi, [URL]
4158 hidnplayr 1555
        mov     ecx, URLMAXLEN
1556
        mov     ax, '//'
1557
  .loop1:
4983 hidnplayr 1558
        cmp     byte[edi], 0            ; end of URL?
4158 hidnplayr 1559
        je      .url_ok                 ; yep, so not found
4983 hidnplayr 1560
        cmp     [edi], ax
4158 hidnplayr 1561
        je      .skip_proto
4983 hidnplayr 1562
        inc     edi
4158 hidnplayr 1563
        dec     ecx
1564
        jnz     .loop1
4233 hidnplayr 1565
        jmp     .invalid
4158 hidnplayr 1566
 
1567
  .skip_proto:
4983 hidnplayr 1568
        inc     edi                     ; skip the two '/'
1569
        inc     edi
1570
        mov     [URL], edi              ; update pointer so it skips protocol
4158 hidnplayr 1571
 
4983 hidnplayr 1572
; Find the trailing 0 byte
1573
        xor     al, al
1574
        repne   scasb
1575
        jne     .invalid                ; ecx reached 0 before we reached end of string
1576
 
4158 hidnplayr 1577
  .url_ok:
4983 hidnplayr 1578
        sub     edi, [URL]              ; calculate total length of URL
1579
        mov     [urlsize], edi
4158 hidnplayr 1580
 
1581
; now look for page delimiter - it's a '/' character
4983 hidnplayr 1582
        mov     ecx, edi                ; URL length
4158 hidnplayr 1583
        mov     edi, [URL]
1584
        mov     al, '/'
1585
        repne   scasb
4161 hidnplayr 1586
        jne     @f
4158 hidnplayr 1587
        dec     edi                     ; return one char, '/' must be part of the pageaddr
1588
        inc     ecx                     ;
4161 hidnplayr 1589
  @@:
4158 hidnplayr 1590
        push    ecx edi                 ; remember the pointer and length of pageaddr
1591
 
4222 hidnplayr 1592
 
4233 hidnplayr 1593
; Create new buffer and put hostname in it.
4158 hidnplayr 1594
        mov     ecx, edi
1595
        sub     ecx, [URL]
1596
        inc     ecx                     ; we will add a 0 byte at the end
1597
        invoke  mem.alloc, ecx
1598
        or      eax, eax
1599
        jz      .no_mem
1600
 
1601
        mov     [hostname], eax         ; copy hostname to buffer
1602
        mov     edi, eax
1603
        mov     esi, [URL]
1604
        dec     ecx
1605
        rep     movsb
1606
        xor     al, al
1607
        stosb
1608
 
4233 hidnplayr 1609
; Check if user provided a port, and convert it if so.
1610
        mov     esi, [hostname]
1611
        mov     [port], 80              ; default port if user didnt provide one
1612
  .portloop:
1613
        lodsb
1614
        test    al, al
1615
        jz      .no_port
1616
        cmp     al, ':'
1617
        jne     .portloop
1618
 
1619
        push    esi
1620
        call    ascii_dec_ebx
1621
        pop     edi
1622
        cmp     byte[esi-1], 0
1623
        jne     .invalid
1624
        cmp     [proxyAddr], 0          ; remove port number from hostname
1625
        jne     @f                      ; unless when we are using proxy
1626
        mov     byte[edi-1], 0
1627
  @@:
1628
        test    ebx, ebx
1629
        je      .invalid
1630
        cmp     ebx, 0xffff
1631
        ja      .invalid
1632
        mov     [port], ebx
1633
  .no_port:
1634
 
1635
 
1636
; Did user provide a pageaddr?
4161 hidnplayr 1637
        mov     [pageaddr], str_slash   ; assume there is no pageaddr
4158 hidnplayr 1638
        pop     esi ecx
1639
        test    ecx, ecx
1640
        jz      .no_page
4233 hidnplayr 1641
 
1642
; Create new buffer and put pageaddr into it.
4158 hidnplayr 1643
        inc     ecx                     ; we will add a 0 byte at the end
1644
        invoke  mem.alloc, ecx
1645
        or      eax, eax
1646
        jz      .no_mem
1647
 
1648
        mov     [pageaddr], eax         ; copy pageaddr to buffer
1649
        mov     edi, eax
1650
        dec     ecx
1651
        rep     movsb
1652
        xor     al, al
1653
        stosb
4233 hidnplayr 1654
 
4158 hidnplayr 1655
  .no_page:
1656
        mov     eax, [hostname]
1657
        mov     ebx, [pageaddr]
4233 hidnplayr 1658
        mov     ecx, [port]
4158 hidnplayr 1659
 
1660
        DEBUGF  1, "hostname: %s\n", eax
1661
        DEBUGF  1, "pageaddr: %s\n", ebx
4221 hidnplayr 1662
        DEBUGF  1, "port: %u\n", ecx
4158 hidnplayr 1663
 
1664
        ret
1665
 
1666
  .no_mem:
5732 hidnplayr 1667
        DEBUGF  2, "Out of memory!\n"
4158 hidnplayr 1668
        xor     eax, eax
1669
        ret
1670
 
4233 hidnplayr 1671
  .invalid:
5732 hidnplayr 1672
        DEBUGF  2, "Invalid URL!\n"
4233 hidnplayr 1673
        xor     eax, eax
1674
        ret
1675
 
4158 hidnplayr 1676
endp
1677
 
1678
 
4233 hidnplayr 1679
 
1680
 
1681
 
4202 hidnplayr 1682
;;================================================================================================;;
4233 hidnplayr 1683
proc append_proxy_auth_header ;///////////////////////////////////////////////////////////////////;;
4202 hidnplayr 1684
;;------------------------------------------------------------------------------------------------;;
4233 hidnplayr 1685
;? Appends the proxy authentication header                                                        ;;
1686
;;------------------------------------------------------------------------------------------------;;
1687
;> /                                                                                              ;;
1688
;;------------------------------------------------------------------------------------------------;;
1689
;< /                                                                                              ;;
1690
;;================================================================================================;;
1691
        mov     esi, str_proxy_auth
1692
        mov     ecx, str_proxy_auth.length
1693
        rep     movsb
1694
; base64-encode string :
1695
        mov     esi, proxyUser
1696
 
1697
apah000:
1698
        lodsb
1699
        test    al, al
1700
        jz      apah001
1701
        call    encode_base64_byte
1702
        jmp     apah000
1703
 
1704
apah001:
1705
        mov     al, ':'
1706
        call    encode_base64_byte
1707
        mov     esi, proxyPassword
1708
 
1709
apah002:
1710
        lodsb
1711
        test    al, al
1712
        jz      apah003
1713
        call    encode_base64_byte
1714
        jmp     apah002
1715
 
1716
apah003:
1717
        call    encode_base64_final
1718
        ret
1719
 
1720
encode_base64_byte:
1721
        inc     ecx
1722
        shl     edx, 8
1723
        mov     dl, al
1724
        cmp     ecx, 3
1725
        je      ebb001
1726
        ret
1727
 
1728
ebb001:
1729
        shl     edx, 8
1730
        inc     ecx
1731
 
1732
ebb002:
1733
        rol     edx, 6
1734
        xor     eax, eax
1735
        xchg    al, dl
1736
        mov     al, [base64_table+eax]
1737
        stosb
1738
        loop    ebb002
1739
        ret
1740
 
1741
encode_base64_final:
1742
        mov     al, 0
1743
        test    ecx, ecx
1744
        jz      ebf000
1745
        call    encode_base64_byte
1746
        test    ecx, ecx
1747
        jz      ebf001
1748
        call    encode_base64_byte
1749
        mov     byte [edi-2], '='
1750
 
1751
ebf001:
1752
        mov     byte [edi-1], '='
1753
 
1754
ebf000:
1755
        ret
1756
 
1757
endp
1758
 
1759
 
1760
;;================================================================================================;;
1761
proc eax_ascii_dec ;//////////////////////////////////////////////////////////////////////////////;;
1762
;;------------------------------------------------------------------------------------------------;;
4202 hidnplayr 1763
;? Convert eax to ASCII decimal number                                                            ;;
1764
;;------------------------------------------------------------------------------------------------;;
1765
;> eax = number                                                                                   ;;
1766
;> edi = ptr where to write ASCII decimal number                                                  ;;
1767
;;------------------------------------------------------------------------------------------------;;
1768
;< /                                                                                              ;;
1769
;;================================================================================================;;
4158 hidnplayr 1770
 
4168 hidnplayr 1771
        push    -'0'
4167 hidnplayr 1772
        mov     ecx, 10
1773
  .loop:
1774
        xor     edx, edx
1775
        div     ecx
4168 hidnplayr 1776
        push    edx
4167 hidnplayr 1777
        test    eax, eax
1778
        jnz     .loop
4158 hidnplayr 1779
 
4168 hidnplayr 1780
  .loop2:
1781
        pop     eax
1782
        add     al, '0'
1783
        jz      .done
1784
        stosb
1785
        jmp     .loop2
1786
  .done:
1787
 
4167 hidnplayr 1788
        ret
4158 hidnplayr 1789
 
4202 hidnplayr 1790
endp
4167 hidnplayr 1791
 
4202 hidnplayr 1792
 
4158 hidnplayr 1793
;;================================================================================================;;
4233 hidnplayr 1794
proc ascii_dec_ebx ;//////////////////////////////////////////////////////////////////////////////;;
1795
;;------------------------------------------------------------------------------------------------;;
1796
;? Convert ASCII decimal number to ebx                                                            ;;
1797
;;------------------------------------------------------------------------------------------------;;
1798
;> esi = ptr where to read ASCII decimal number                                                   ;;
1799
;;------------------------------------------------------------------------------------------------;;
1800
;> ebx = number                                                                                   ;;
1801
;;================================================================================================;;
1802
 
1803
        xor     eax, eax
1804
        xor     ebx, ebx
1805
  .loop:
1806
        lodsb
1807
        sub     al, '0'
1808
        jb      .done
1809
        cmp     al, 9
1810
        ja      .done
1811
        lea     ebx, [ebx + 4*ebx]
1812
        shl     ebx, 1
1813
        add     ebx, eax
1814
        jmp     .loop
1815
  .done:
1816
 
1817
        ret
1818
 
1819
endp
1820
 
1821
 
1822
;;================================================================================================;;
4158 hidnplayr 1823
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1824
;;================================================================================================;;
1825
;! Imported functions section                                                                     ;;
1826
;;================================================================================================;;
1827
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1828
;;================================================================================================;;
1829
 
1830
 
1831
align 16
1832
@IMPORT:
1833
 
1834
library \
1835
        libini, 'libini.obj', \
1836
        network, 'network.obj'
1837
 
1838
import  libini, \
1839
        ini.get_str, 'ini_get_str', \
1840
        ini.get_int, 'ini_get_int'
1841
 
1842
import  network,\
1843
        getaddrinfo, 'getaddrinfo',\
1844
        freeaddrinfo,  'freeaddrinfo',\
1845
        inet_ntoa, 'inet_ntoa'
1846
 
1847
;;===========================================================================;;
1848
;;///////////////////////////////////////////////////////////////////////////;;
1849
;;===========================================================================;;
1850
;! Exported functions section                                                ;;
1851
;;===========================================================================;;
1852
;;///////////////////////////////////////////////////////////////////////////;;
1853
;;===========================================================================;;
1854
 
1855
 
4996 hidnplayr 1856
HTTP_stop = HTTP_disconnect
1857
HTTP_process = HTTP_receive
1858
 
4158 hidnplayr 1859
align 4
1860
@EXPORT:
1861
export  \
1862
        lib_init                , 'lib_init'            , \
1863
        0x00010001              , 'version'             , \
1864
        HTTP_get                , 'get'                 , \
4167 hidnplayr 1865
        HTTP_head               , 'head'                , \
1866
        HTTP_post               , 'post'                , \
4222 hidnplayr 1867
        HTTP_find_header_field  , 'find_header_field'   , \
4996 hidnplayr 1868
        HTTP_process            , 'process'             , \    ; To be removed
1869
        HTTP_send               , 'send'                , \
1870
        HTTP_receive            , 'receive'             , \
1871
        HTTP_disconnect         , 'disconnect'          , \
4205 hidnplayr 1872
        HTTP_free               , 'free'                , \
4996 hidnplayr 1873
        HTTP_stop               , 'stop'                , \    ; To be removed
4831 hidnplayr 1874
        HTTP_escape             , 'escape'              , \
1875
        HTTP_unescape           , 'unescape'
4158 hidnplayr 1876
;        HTTP_put                , 'put'                 , \
1877
;        HTTP_delete             , 'delete'              , \
1878
;        HTTP_trace              , 'trace'               , \
1879
;        HTTP_connect            , 'connect'             , \
1880
 
1881
 
1882
 
1883
section '.data' data readable writable align 16
1884
 
1885
inifile         db '/sys/settings/network.ini', 0
1886
 
1887
sec_proxy:
1888
key_proxy       db 'proxy', 0
1889
key_proxyport   db 'port', 0
1890
key_user        db 'user', 0
1891
key_password    db 'password', 0
1892
 
1893
str_http11      db ' HTTP/1.1', 13, 10, 'Host: '
1894
  .length       = $ - str_http11
4167 hidnplayr 1895
str_post_cl     db 13, 10, 'Content-Length: '
1896
  .length       = $ - str_post_cl
1897
str_post_ct     db 13, 10, 'Content-Type: '
1898
  .length       = $ - str_post_ct
4158 hidnplayr 1899
str_proxy_auth  db 13, 10, 'Proxy-Authorization: Basic '
1900
  .length       = $ - str_proxy_auth
5534 hidnplayr 1901
str_close       db 'User-Agent: KolibriOS libHTTP/1.1', 13, 10, 'Connection: Close', 13, 10, 13, 10
4241 hidnplayr 1902
  .length       = $ - str_close
5534 hidnplayr 1903
str_keep        db 'User-Agent: KolibriOS libHTTP/1.1', 13, 10, 'Connection: Keepalive', 13, 10, 13, 10
1904
  .length       = $ - str_close
4158 hidnplayr 1905
 
4233 hidnplayr 1906
str_http        db 'http://', 0
1907
 
4158 hidnplayr 1908
base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
1909
                db '0123456789+/'
1910
 
1911
str_cl          db 'content-length', 0
4161 hidnplayr 1912
str_slash       db '/', 0
4158 hidnplayr 1913
str_te          db 'transfer-encoding', 0
4167 hidnplayr 1914
str_get         db 'GET ', 0
1915
str_head        db 'HEAD ', 0
1916
str_post        db 'POST ', 0
4158 hidnplayr 1917
 
4209 hidnplayr 1918
bits_must_escape:
1919
dd      0xffffffff                                                      ; 00-1F
1920
dd      1 shl 0 + 1 shl 2 + 1 shl 3 + 1 shl 5 + 1 shl 28 + 1 shl 30     ; "#%<>
1921
dd      1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 30                       ;[\]^
1922
dd      1 shl 0 + 1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 31             ;`{|} DEL
1923
 
1924
dd      0xffffffff
1925
dd      0xffffffff
1926
dd      0xffffffff
1927
dd      0xffffffff
1928
 
1929
str_hex:
1930
db '0123456789ABCDEF'
1931
 
4158 hidnplayr 1932
include_debug_strings
1933
 
1934
; uninitialized data
1935
mem.alloc       dd ?
1936
mem.free        dd ?
1937
mem.realloc     dd ?
1938
dll.load        dd ?
1939
 
1940
proxyAddr       rb 256
1941
proxyUser       rb 256
1942
proxyPassword   rb 256
1943
proxyPort       dd ?