Subversion Repositories Kolibri OS

Rev

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

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