Subversion Repositories Kolibri OS

Rev

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