Subversion Repositories Kolibri OS

Rev

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