Subversion Repositories Kolibri OS

Rev

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

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