Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4158 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  HTTP library for KolibriOS                                     ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
9
;;                                                                 ;;
10
;;         GNU GENERAL PUBLIC LICENSE                              ;;
11
;;          Version 2, June 1991                                   ;;
12
;;                                                                 ;;
13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14
 
15
; references:
16
; "HTTP made really easy", http://www.jmarshall.com/easy/http/
17
; "Hypertext Transfer Protocol -- HTTP/1.1", http://tools.ietf.org/html/rfc2616
18
 
19
 
20
        URLMAXLEN       = 65535
21
        BUFFERSIZE      = 4096
22
 
23
        __DEBUG__       = 1
24
        __DEBUG_LEVEL__ = 1
25
 
26
 
27
format MS COFF
28
 
29
public @EXPORT as 'EXPORTS'
30
 
31
include '../../../struct.inc'
32
include '../../../proc32.inc'
33
include '../../../macros.inc'
34
purge section,mov,add,sub
35
include '../../../debug-fdo.inc'
36
 
37
include '../../../network.inc'
38
include 'http.inc'
39
 
40
virtual at 0
41
        http_msg http_msg
42
end virtual
43
 
44
macro copy_till_zero {
45
  @@:
46
        lodsb
47
        test    al, al
48
        jz      @f
49
        stosb
50
        jmp     @r
51
  @@:
52
}
53
 
54
section '.flat' code readable align 16
55
 
56
;;===========================================================================;;
57
lib_init: ;//////////////////////////////////////////////////////////////////;;
58
;;---------------------------------------------------------------------------;;
59
;? Library entry point (called after library load)                           ;;
60
;;---------------------------------------------------------------------------;;
61
;> eax = pointer to memory allocation routine                                ;;
62
;> ebx = pointer to memory freeing routine                                   ;;
63
;> ecx = pointer to memory reallocation routine                              ;;
64
;> edx = pointer to library loading routine                                  ;;
65
;;---------------------------------------------------------------------------;;
66
;< eax = 1 (fail) / 0 (ok) (library initialization result)                   ;;
67
;;===========================================================================;;
68
        mov     [mem.alloc], eax
69
        mov     [mem.free], ebx
70
        mov     [mem.realloc], ecx
71
        mov     [dll.load], edx
72
 
73
        invoke  dll.load, @IMPORT
74
        or      eax, eax
75
        jz      .ok
76
 
77
; load proxy settings
78
        invoke  ini.get_str, inifile, sec_proxy, key_proxy, proxyAddr, 256, proxyAddr
79
        invoke  ini.get_int, inifile, sec_proxy, key_proxyport, 80
80
        mov     [proxyPort], eax
81
        invoke  ini.get_str, inifile, sec_proxy, key_user, proxyUser, 256, proxyUser
82
        invoke  ini.get_str, inifile, sec_proxy, key_password, proxyPassword, 256, proxyPassword
83
 
84
        xor     eax, eax
85
        inc     eax
86
        ret
87
 
88
  .ok:
89
        xor     eax, eax
90
        ret
91
 
92
 
93
 
94
 
95
 
96
;;================================================================================================;;
97
proc HTTP_get URL ;///////////////////////////////////////////////////////////////////////////////;;
98
;;------------------------------------------------------------------------------------------------;;
99
;?                                                                                                ;;
100
;;------------------------------------------------------------------------------------------------;;
101
;> _                                                                                              ;;
102
;;------------------------------------------------------------------------------------------------;;
103
;< eax = 0 (error) / buffer ptr                                                                   ;;
104
;;================================================================================================;;
105
locals
106
        hostname        dd ?
107
        pageaddr        dd ?
108
        sockaddr        dd ?
109
        socketnum       dd ?
110
        buffer          dd ?
111
endl
112
 
113
; split the URL into hostname and pageaddr
114
        stdcall parse_url, [URL]
115
        test    eax, eax
116
        jz      .error
117
        mov     [hostname], eax
118
        mov     [pageaddr], ebx
119
 
120
; Do we need to use a proxy?
121
        cmp     [proxyAddr], 0
122
        jne     .proxy_done
123
 
124
        ; TODO
125
  .proxy_done:
126
 
127
; Resolve the hostname
128
        DEBUGF  1, "Resolving hostname\n"
129
        push    esp     ; reserve stack place
130
        push    esp     ; fourth parameter
131
        push    0       ; third parameter
132
        push    0       ; second parameter
133
        push    [hostname]
134
        call    [getaddrinfo]
135
        pop     esi
136
        test    eax, eax
137
        jnz     .error
138
 
139
; getaddrinfo returns addrinfo struct, make the pointer to sockaddr struct
140
        mov     esi, [esi + addrinfo.ai_addr]
141
        mov     [sockaddr], esi
142
        mov     eax, [esi + sockaddr_in.sin_addr]
143
        test    eax, eax
144
        jz      .error
145
 
146
        DEBUGF  1, "Server ip=%u.%u.%u.%u\n", \
147
        [esi + sockaddr_in.sin_addr]:1, [esi + sockaddr_in.sin_addr + 1]:1, \
148
        [esi + sockaddr_in.sin_addr + 2]:1, [esi + sockaddr_in.sin_addr + 3]:1
149
 
150
        mov     [esi + sockaddr_in.sin_family], AF_INET4
151
        mov     [esi + sockaddr_in.sin_port], 80 shl 8  ;;; FIXME
152
 
153
; Connect to the server.
154
        mcall   socket, AF_INET4, SOCK_STREAM, 0
155
        test    eax, eax
156
        jz      .error
157
        mov     [socketnum], eax
158
        DEBUGF  1, "Socket: 0x%x\n", eax
159
 
160
        mcall   connect, [socketnum], [sockaddr], 18
161
        test    eax, eax
162
        jnz     .error
163
        DEBUGF  1, "Socket is now connected.\n"
164
 
165
        ; TODO: free address buffer(s)
166
 
167
; Create the HTTP request.
168
        invoke  mem.alloc, BUFFERSIZE
169
        test    eax, eax
170
        jz      .error
171
        mov     [buffer], eax
172
        DEBUGF  1, "Buffer has been allocated.\n"
173
 
174
        mov     dword[eax], 'GET '
175
        lea     edi, [eax + 4]
176
        mov     esi, [pageaddr] ; TODO: for proxy use http:// and then full URL
177
        copy_till_zero
178
 
179
        mov     esi, str_http11
180
        mov     ecx, str_http11.length
181
        rep     movsb
182
 
183
        mov     esi, [hostname]
184
        copy_till_zero
185
 
186
        mov     esi, str_close
187
        mov     ecx, str_close.length
188
        rep     movsb
189
 
190
        mov     byte[edi], 0
191
        DEBUGF  1, "Request:\n%s", [buffer]
192
 
193
; now send the request
194
        mov     esi, edi
195
        sub     esi, [buffer]   ; length
196
        xor     edi, edi        ; flags
197
 
198
        mcall   send, [socketnum], [buffer]
199
        test    eax, eax
200
        jz      .error
201
        DEBUGF  1, "Request has been sent to server.\n"
202
 
203
; Now that we have sent the request, re-purpose buffer as receive buffer
204
        mov     eax, [buffer]
205
        push    [socketnum]
206
        popd    [eax + http_msg.socket]
207
        lea     esi, [eax + http_msg.data]
208
        mov     [eax + http_msg.flags], 0
209
        mov     [eax + http_msg.write_ptr], esi
210
        mov     [eax + http_msg.buffer_length], BUFFERSIZE -  http_msg.data
211
        mov     [eax + http_msg.chunk_ptr], 0
212
 
213
        mov     [eax + http_msg.status], 0
214
        mov     [eax + http_msg.header_length], 0
215
        mov     [eax + http_msg.content_length], 0
216
 
217
        ret                     ; return buffer ptr
218
 
219
  .error:
220
        DEBUGF  1, "Error!\n"
221
        xor     eax, eax        ; return 0 = error
222
        ret
223
 
224
endp
225
 
226
 
227
 
228
;;================================================================================================;;
229
proc HTTP_process identifier ;////////////////////////////////////////////////////////////////////;;
230
;;------------------------------------------------------------------------------------------------;;
231
;?                                                                                                ;;
232
;;------------------------------------------------------------------------------------------------;;
233
;> _                                                                                              ;;
234
;;------------------------------------------------------------------------------------------------;;
235
;< eax = -1 (not finished) / 0 finished                                                           ;;
236
;;================================================================================================;;
237
        pusha
238
        mov     ebp, [identifier]
4162 hidnplayr 239
 
240
; Receive some data
4158 hidnplayr 241
        mcall   recv, [ebp + http_msg.socket], [ebp + http_msg.write_ptr], \
242
                      [ebp + http_msg.buffer_length], MSG_DONTWAIT
243
        cmp     eax, 0xffffffff
244
        je      .check_socket
245
        DEBUGF  1, "Received %u bytes\n", eax
246
 
4162 hidnplayr 247
; Update pointers
4158 hidnplayr 248
        mov     edi, [ebp + http_msg.write_ptr]
249
        add     [ebp + http_msg.write_ptr], eax
250
        sub     [ebp + http_msg.buffer_length], eax
251
        jz      .got_all_data
4162 hidnplayr 252
 
253
; If data is chunked, combine chunks into contiguous data.
254
        test    [ebp + http_msg.flags], FLAG_CHUNKED
255
        jnz     .chunk_loop
256
 
257
; Did we detect the header yet?
4158 hidnplayr 258
        test    [ebp + http_msg.flags], FLAG_GOT_HEADER
259
        jnz     .header_parsed
260
 
4162 hidnplayr 261
; We havent found the header yet, search for it..
4158 hidnplayr 262
        sub     eax, 4
4162 hidnplayr 263
        jl      .need_more_data
4158 hidnplayr 264
  .scan:
265
        ; scan for end of header (empty line)
266
        cmp     dword[edi], 0x0a0d0a0d                  ; end of header
267
        je      .end_of_header
268
        cmp     word[edi+2], 0x0a0a
269
        je      .end_of_header
270
        inc     edi
271
        dec     eax
272
        jnz     .scan
273
 
274
  .end_of_header:
275
        add     edi, 4 - http_msg.data
276
        sub     edi, ebp
277
        mov     [ebp + http_msg.header_length], edi
278
        or      [ebp + http_msg.flags], FLAG_GOT_HEADER
279
        DEBUGF  1, "Header length: %u\n", edi
280
 
281
; Ok, we have found header:
282
        cmp     dword[ebp + http_msg.data], 'HTTP'
283
        jne     .invalid_header
284
        cmp     dword[ebp + http_msg.data+4], '/1.0'
285
        je      .http_1.0
286
        cmp     dword[ebp + http_msg.data+4], '/1.1'
287
        jne     .invalid_header
288
        or      [ebp + http_msg.flags], FLAG_HTTP11
289
  .http_1.0:
290
        cmp     byte[ebp + http_msg.data+8], ' '
291
        jne     .invalid_header
292
        DEBUGF  1, "Header seems valid.\n"
293
 
294
        lea     esi, [ebp + http_msg.data+9]
295
        xor     eax, eax
296
        xor     ebx, ebx
297
        mov     ecx, 3
298
  .statusloop:
299
        lodsb
300
        sub     al, '0'
301
        jb      .invalid_header
302
        cmp     al, 9
303
        ja      .invalid_header
304
        lea     ebx, [ebx + 4*ebx]
305
        shl     ebx, 1
306
        add     ebx, eax
307
        dec     ecx
308
        jnz     .statusloop
309
        mov     [ebp + http_msg.status], ebx
310
        DEBUGF  1, "Status: %u\n", ebx
311
 
312
; Now, convert all header names to lowercase.
313
; This way, it will be much easier to find certain header fields, later on.
314
 
315
        lea     esi, [ebp + http_msg.data]
316
        mov     ecx, [ebp + http_msg.header_length]
317
  .need_newline:
318
        inc     esi
319
        dec     ecx
320
        jz      .convert_done
321
        cmp     byte[esi], 10
322
        jne     .need_newline
323
; Ok, we have a newline, a line beginning with space or tabs has no header fields.
324
 
325
        inc     esi
326
        dec     ecx
327
        jz      .convert_done
328
        cmp     byte[esi], ' '
329
        je      .need_newline
330
        cmp     byte[esi], 9    ; horizontal tab
331
        je      .need_newline
332
        jmp     .convert_loop
333
  .next_char:
334
        inc     esi
335
        dec     ecx
336
        jz      .convert_done
337
  .convert_loop:
338
        cmp     byte[esi], ':'
339
        je      .need_newline
340
        cmp     byte[esi], 'A'
341
        jb      .next_char
342
        cmp     byte[esi], 'Z'
343
        ja      .next_char
344
        or      byte[esi], 0x20 ; convert to lowercase
345
        jmp     .next_char
346
  .convert_done:
347
        mov     byte[esi-1], 0
348
        lea     esi, [ebp + http_msg.data]
349
        DEBUGF  1, "Header names converted to lowercase:\n%s\n", esi
350
 
351
; Check for content-length header field.
352
        stdcall find_header_field, ebp, str_cl
353
        test    eax, eax
354
        jz      .no_content
355
        or      [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
356
 
357
        xor     edx, edx
358
  .cl_loop:
359
        movzx   ebx, byte[eax]
360
        inc     eax
361
        cmp     bl, 10
362
        je      .cl_ok
363
        cmp     bl, 13
364
        je      .cl_ok
365
        cmp     bl, ' '
366
        je      .cl_ok
367
        sub     bl, '0'
368
        jb      .invalid_header
369
        cmp     bl, 9
370
        ja      .invalid_header
371
        lea     edx, [edx + edx*4]      ; edx = edx*10
372
        shl     edx, 1                  ;
373
        add     edx, ebx
374
        jmp     .cl_loop
375
 
376
  .cl_ok:
377
        mov     [ebp + http_msg.content_length], edx
378
        DEBUGF  1, "Content-length: %u\n", edx
379
 
380
; Resize buffer according to content-length.
381
        mov     eax, [ebp + http_msg.header_length]
382
        add     eax, [ebp + http_msg.content_length]
383
        add     eax, http_msg.data
384
 
385
        mov     ecx, eax
386
        sub     ecx, [ebp + http_msg.write_ptr]
387
        mov     [ebp + http_msg.buffer_length], ecx
388
 
389
        invoke  mem.realloc, ebp, eax
390
        or      eax, eax
391
        jz      .no_ram
392
        jmp     .header_parsed  ; hooray!
393
 
394
  .no_content:
395
        DEBUGF  1, "Content-length not found.\n"
396
 
397
; We didnt find 'content-length', maybe server is using chunked transfer encoding?
398
; Try to find 'transfer-encoding' header.
399
        stdcall find_header_field, ebp, str_te
400
        test    eax, eax
401
        jz      .invalid_header
402
 
403
        mov     ebx, dword[eax]
4162 hidnplayr 404
        or      ebx, 0x20202020
4158 hidnplayr 405
        cmp     ebx, 'chun'
406
        jne     .invalid_header
407
        mov     ebx, dword[eax+4]
4162 hidnplayr 408
        or      ebx, 0x00202020
409
        and     ebx, 0x00ffffff
4158 hidnplayr 410
        cmp     ebx, 'ked'
411
        jne     .invalid_header
412
 
413
        or      [ebp + http_msg.flags], FLAG_CHUNKED
414
        DEBUGF  1, "Transfer type is: chunked\n"
415
 
416
; Set chunk pointer where first chunk should begin.
4162 hidnplayr 417
        lea     eax, [ebp + http_msg.data]
418
        add     eax, [ebp + http_msg.header_length]
4158 hidnplayr 419
        mov     [ebp + http_msg.chunk_ptr], eax
420
 
4162 hidnplayr 421
  .chunk_loop:
4158 hidnplayr 422
        mov     ecx, [ebp + http_msg.write_ptr]
423
        sub     ecx, [ebp + http_msg.chunk_ptr]
4162 hidnplayr 424
        jb      .need_more_data_chunked
4158 hidnplayr 425
 
4162 hidnplayr 426
; TODO: make sure we have the complete chunkline header
4158 hidnplayr 427
        mov     esi, [ebp + http_msg.chunk_ptr]
428
        xor     ebx, ebx
429
  .chunk_hexloop:
430
        lodsb
431
        sub     al, '0'
432
        jb      .chunk_
433
        cmp     al, 9
434
        jbe     .chunk_hex
4162 hidnplayr 435
        sub     al, 'A' - '0' - 10
4158 hidnplayr 436
        jb      .chunk_
4162 hidnplayr 437
        cmp     al, 15
4158 hidnplayr 438
        jbe     .chunk_hex
439
        sub     al, 'a' - 'A'
4162 hidnplayr 440
        cmp     al, 15
4158 hidnplayr 441
        ja      .chunk_
442
  .chunk_hex:
443
        shl     ebx, 4
444
        add     bl, al
445
        jmp     .chunk_hexloop
446
  .chunk_:
447
        DEBUGF  1, "got chunk of %u bytes\n", ebx
448
; If chunk size is 0, all chunks have been received.
449
        test    ebx, ebx
4162 hidnplayr 450
        jz      .got_all_data_chunked           ; last chunk, hooray! FIXME: what if it wasnt a valid hex number???
451
        mov     edi, [ebp + http_msg.chunk_ptr] ; we'll need this in about 25 lines...
4158 hidnplayr 452
        add     [ebp + http_msg.chunk_ptr], ebx
453
 
454
; Chunkline ends with a CR, LF or simply LF
455
  .end_of_chunkline?:           ; FIXME: buffer overflow possible!
456
        cmp     al, 10
457
        je      .end_of_chunkline
458
        lodsb
459
        jmp     .end_of_chunkline?
460
 
461
  .end_of_chunkline:
4162 hidnplayr 462
; Realloc buffer, make it 'chunksize' bigger.
463
        mov     eax, [ebp + http_msg.buffer_length]
464
        add     eax, ebx
465
        invoke  mem.realloc, ebp, eax
466
        or      eax, eax
467
        jz      .no_ram
468
        add     [ebp + http_msg.buffer_length], ebx
469
 
470
; Update write ptr
471
        mov     eax, esi
472
        sub     eax, edi
473
        sub     [ebp + http_msg.write_ptr], eax
474
 
4158 hidnplayr 475
; Now move all received data to the left (remove chunk header).
4162 hidnplayr 476
; Update content_length accordingly.
4158 hidnplayr 477
        mov     ecx, [ebp + http_msg.write_ptr]
478
        sub     ecx, esi
479
        add     [ebp + http_msg.content_length], ecx
480
        rep     movsb
4162 hidnplayr 481
        jmp     .chunk_loop
4158 hidnplayr 482
 
483
; Check if we got all the data.
4162 hidnplayr 484
  .header_parsed:
4158 hidnplayr 485
        mov     eax, [ebp + http_msg.header_length]
486
        add     eax, [ebp + http_msg.content_length]
487
        cmp     eax, [ebp + http_msg.buffer_length]
488
        je      .got_all_data
4162 hidnplayr 489
  .need_more_data:
490
        popa
491
        xor     eax, eax
492
        dec     eax
493
        ret
4158 hidnplayr 494
 
4162 hidnplayr 495
  .need_more_data_chunked:
496
        add     [ebp + http_msg.content_length], eax
4158 hidnplayr 497
        popa
498
        xor     eax, eax
499
        dec     eax
500
        ret
501
 
4162 hidnplayr 502
  .got_all_data_chunked:
503
        mov     eax, [ebp + http_msg.chunk_ptr]
504
        sub     eax, [ebp + http_msg.header_length]
505
        sub     eax, http_msg.data
506
        sub     eax, ebp
507
        mov     [ebp + http_msg.content_length], eax
508
 
4158 hidnplayr 509
  .got_all_data:
4162 hidnplayr 510
        DEBUGF  1, "We got all the data! (%u bytes)\n", [ebp + http_msg.content_length]
4158 hidnplayr 511
        or      [ebp + http_msg.flags], FLAG_GOT_DATA
512
        mcall   close, [ebp + http_msg.socket]
513
        popa
514
        xor     eax, eax
515
        ret
516
 
517
  .check_socket:
518
        cmp     ebx, EWOULDBLOCK
4162 hidnplayr 519
        je      .need_more_data
4158 hidnplayr 520
        DEBUGF  1, "ERROR: socket error %u\n", ebx
521
 
522
        or      [ebp + http_msg.flags], FLAG_SOCKET_ERROR
523
        popa
524
        xor     eax, eax
525
        ret
526
 
527
  .invalid_header:
528
        DEBUGF  1, "ERROR: invalid header\n"
529
        or      [ebp + http_msg.flags], FLAG_INVALID_HEADER
530
        popa
531
        xor     eax, eax
532
        ret
533
 
534
  .no_ram:
535
        DEBUGF  1, "ERROR: out of RAM\n"
536
        or      [ebp + http_msg.flags], FLAG_NO_RAM
537
        popa
538
        xor     eax, eax
539
        ret
540
 
541
endp
542
 
543
 
544
 
545
;;================================================================================================;;
546
proc find_header_field identifier, headername ;///////////////////////////////////////////////////;;
547
;;------------------------------------------------------------------------------------------------;;
548
;?                                                                                                ;;
549
;;------------------------------------------------------------------------------------------------;;
550
;> _                                                                                              ;;
551
;;------------------------------------------------------------------------------------------------;;
552
;< eax = -1 (error) / 0                                                                           ;;
553
;;================================================================================================;;
554
        push    ebx ecx edx esi edi
555
 
556
        DEBUGF  1, "Find header field: %s\n", [headername]
557
 
558
        mov     ebx, [identifier]
559
        lea     edx, [ebx + http_msg.data]
560
        mov     ecx, edx
561
        add     ecx, [ebx + http_msg.header_length]
562
 
563
  .restart:
564
        mov     esi, [headername]
565
        mov     edi, edx
566
  .loop:
567
        cmp     edi, ecx
568
        jae     .fail
569
        lodsb
570
        scasb
571
        je      .loop
572
        test    al, al
573
        jz      .done?
574
  .next:
575
        inc     edx
576
        jmp     .restart
577
 
578
  .not_done:
579
        inc     edi
580
  .done?:
581
        cmp     byte[edi-1], ':'
582
        je      .almost_done
583
        cmp     byte[edi-1], ' '
584
        je      .not_done
585
        cmp     byte[edi-1], 9  ; tab
586
        je      .not_done
587
 
588
        jmp     .next
589
 
590
  .almost_done:                 ; FIXME: buffer overflow?
591
        dec     edi
592
        DEBUGF  1, "Found header field\n"
593
  .spaceloop:
594
        inc     edi
595
        cmp     byte[edi], ' '
596
        je      .spaceloop
597
        cmp     byte[edi], 9    ; tab
598
        je      .spaceloop
599
 
600
        mov     eax, edi
601
        pop     edi esi edx ecx ebx
602
        ret
603
 
604
  .fail:
605
        pop     edi esi edx ecx ebx
606
        xor     eax, eax
607
        ret
608
 
609
endp
610
 
611
 
612
; internal procedures start here:
613
 
614
 
615
;;================================================================================================;;
616
proc parse_url URL ;//////////////////////////////////////////////////////////////////////////////;;
617
;;------------------------------------------------------------------------------------------------;;
618
;?                                                                                                ;;
619
;;------------------------------------------------------------------------------------------------;;
620
;> _                                                                                              ;;
621
;;------------------------------------------------------------------------------------------------;;
622
;< eax = -1 (error) / 0                                                                           ;;
623
;;================================================================================================;;
624
 
625
locals
626
        urlsize         dd ?
627
        hostname        dd ?
628
        pageaddr        dd ?
629
endl
630
 
4161 hidnplayr 631
        DEBUGF  1, "parsing URL: %s\n", [URL]
4158 hidnplayr 632
 
633
; remove any leading protocol text
634
        mov     esi, [URL]
635
        mov     ecx, URLMAXLEN
636
        mov     ax, '//'
637
  .loop1:
638
        cmp     byte[esi], 0            ; end of URL?
639
        je      .url_ok                 ; yep, so not found
640
        cmp     [esi], ax
641
        je      .skip_proto
642
        inc     esi
643
        dec     ecx
644
        jnz     .loop1
645
 
4161 hidnplayr 646
        DEBUGF  1, "Invalid URL\n"
4158 hidnplayr 647
        xor     eax, eax
648
        ret
649
 
650
  .skip_proto:
651
        inc     esi                     ; skip the two '/'
652
        inc     esi
653
        mov     [URL], esi              ; update pointer so it skips protocol
654
        jmp     .loop1                  ; we still need to find the length of the URL
655
 
656
  .url_ok:
657
        sub     esi, [URL]              ; calculate total length of URL
658
        mov     [urlsize], esi
659
 
660
 
661
; now look for page delimiter - it's a '/' character
662
        mov     ecx, esi                ; URL length
663
        mov     edi, [URL]
664
        mov     al, '/'
665
        repne   scasb
4161 hidnplayr 666
        jne     @f
4158 hidnplayr 667
        dec     edi                     ; return one char, '/' must be part of the pageaddr
668
        inc     ecx                     ;
4161 hidnplayr 669
  @@:
4158 hidnplayr 670
        push    ecx edi                 ; remember the pointer and length of pageaddr
671
 
672
        mov     ecx, edi
673
        sub     ecx, [URL]
674
        inc     ecx                     ; we will add a 0 byte at the end
675
        invoke  mem.alloc, ecx
676
        or      eax, eax
677
        jz      .no_mem
678
 
679
        mov     [hostname], eax         ; copy hostname to buffer
680
        mov     edi, eax
681
        mov     esi, [URL]
682
        dec     ecx
683
        rep     movsb
684
        xor     al, al
685
        stosb
686
 
4161 hidnplayr 687
        mov     [pageaddr], str_slash   ; assume there is no pageaddr
4158 hidnplayr 688
        pop     esi ecx
689
        test    ecx, ecx
690
        jz      .no_page
691
        inc     ecx                     ; we will add a 0 byte at the end
692
        invoke  mem.alloc, ecx
693
        or      eax, eax
694
        jz      .no_mem
695
 
696
        mov     [pageaddr], eax         ; copy pageaddr to buffer
697
        mov     edi, eax
698
        dec     ecx
699
        rep     movsb
700
        xor     al, al
701
        stosb
702
  .no_page:
703
 
704
        mov     eax, [hostname]
705
        mov     ebx, [pageaddr]
706
 
707
        DEBUGF  1, "hostname: %s\n", eax
708
        DEBUGF  1, "pageaddr: %s\n", ebx
709
 
710
        ret
711
 
712
  .no_mem:
713
        xor     eax, eax
714
        ret
715
 
716
endp
717
 
718
 
719
 
720
 
721
 
722
;;================================================================================================;;
723
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
724
;;================================================================================================;;
725
;! Imported functions section                                                                     ;;
726
;;================================================================================================;;
727
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
728
;;================================================================================================;;
729
 
730
 
731
align 16
732
@IMPORT:
733
 
734
library \
735
        libini, 'libini.obj', \
736
        network, 'network.obj'
737
 
738
import  libini, \
739
        ini.get_str, 'ini_get_str', \
740
        ini.get_int, 'ini_get_int'
741
 
742
import  network,\
743
        getaddrinfo, 'getaddrinfo',\
744
        freeaddrinfo,  'freeaddrinfo',\
745
        inet_ntoa, 'inet_ntoa'
746
 
747
;;===========================================================================;;
748
;;///////////////////////////////////////////////////////////////////////////;;
749
;;===========================================================================;;
750
;! Exported functions section                                                ;;
751
;;===========================================================================;;
752
;;///////////////////////////////////////////////////////////////////////////;;
753
;;===========================================================================;;
754
 
755
 
756
align 4
757
@EXPORT:
758
export  \
759
        lib_init                , 'lib_init'            , \
760
        0x00010001              , 'version'             , \
761
        HTTP_get                , 'get'                 , \
762
        find_header_field       , 'find_header_field'   , \
763
        HTTP_process            , 'process'
764
 
765
;        HTTP_head               , 'head'                , \
766
;        HTTP_post               , 'post'                , \
767
;        HTTP_put                , 'put'                 , \
768
;        HTTP_delete             , 'delete'              , \
769
;        HTTP_trace              , 'trace'               , \
770
;        HTTP_connect            , 'connect'             , \
771
 
772
 
773
 
774
section '.data' data readable writable align 16
775
 
776
inifile         db '/sys/settings/network.ini', 0
777
 
778
sec_proxy:
779
key_proxy       db 'proxy', 0
780
key_proxyport   db 'port', 0
781
key_user        db 'user', 0
782
key_password    db 'password', 0
783
 
784
str_http11      db ' HTTP/1.1', 13, 10, 'Host: '
785
  .length       = $ - str_http11
786
str_close       db 13, 10, 'User-Agent: KolibriOS libHTTP/1.0', 13, 10, 'Connection: Close', 13, 10, 13, 10
787
  .length       = $ - str_close
788
str_proxy_auth  db 13, 10, 'Proxy-Authorization: Basic '
789
  .length       = $ - str_proxy_auth
790
 
791
base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
792
                db '0123456789+/'
793
 
794
str_cl          db 'content-length', 0
4161 hidnplayr 795
str_slash       db '/', 0
4158 hidnplayr 796
str_te          db 'transfer-encoding', 0
797
 
798
include_debug_strings
799
 
800
; uninitialized data
801
mem.alloc       dd ?
802
mem.free        dd ?
803
mem.realloc     dd ?
804
dll.load        dd ?
805
 
806
proxyAddr       rb 256
807
proxyUser       rb 256
808
proxyPassword   rb 256
809
proxyPort       dd ?