Subversion Repositories Kolibri OS

Rev

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

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