Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3561 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2009-2013. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  downloader.asm - HTTP client for KolibriOS                     ;;
7
;;                                                                 ;;
8
;;  Based on HTTPC.asm for menuetos by ville turjanmaa             ;;
9
;;                                                                 ;;
10
;;  Programmers: Barsuk, Clevermouse, Marat Zakiyanov,             ;;
11
;;      Kirill Lipatov, dunkaist, HidnPlayr                        ;;
12
;;                                                                 ;;
13
;;          GNU GENERAL PUBLIC LICENSE                             ;;
14
;;             Version 2, June 1991                                ;;
15
;;                                                                 ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
 
3618 hidnplayr 18
URLMAXLEN       = 1024
19
BUFFERSIZE      = 4096
3561 hidnplayr 20
 
21
__DEBUG__       = 1
3618 hidnplayr 22
__DEBUG_LEVEL__ = 1
3561 hidnplayr 23
 
24
format binary as ""
25
 
26
use32
27
        org     0x0
28
 
29
        db      'MENUET01'      ; header
30
        dd      0x01            ; header version
31
        dd      START           ; entry point
32
        dd      IM_END          ; image size
3623 hidnplayr 33
        dd      I_END+0x1000    ; required memory
34
        dd      I_END+0x1000    ; esp
3561 hidnplayr 35
        dd      params          ; I_PARAM
36
        dd      0x0             ; I_Path
37
 
3618 hidnplayr 38
include '../../macros.inc'
39
include '../../proc32.inc'
40
include '../../network.inc'
3561 hidnplayr 41
include '../../develop/libraries/box_lib/trunk/box_lib.mac'
3618 hidnplayr 42
include '../../dll.inc'
43
include '../../debug-fdo.inc'
3561 hidnplayr 44
 
45
START:
46
 
47
        mcall   68, 11                  ; init heap so we can allocate memory dynamically
48
 
49
; load libraries
50
        stdcall dll.Load, @IMPORT
51
        test    eax, eax
52
        jnz     exit
53
 
3566 hidnplayr 54
; prepare webAddr area
3561 hidnplayr 55
        mov     al, ' '
56
        mov     edi, webAddr
57
        mov     ecx, URLMAXLEN
58
        rep     stosb
59
        xor     eax, eax
60
        stosb
61
 
62
; prepare document area
63
        mov     al, '/'
64
        mov     edi, document
65
        stosb
66
        mov     al, ' '
67
        mov     ecx, URLMAXLEN-1
68
        rep     stosb
69
 
3623 hidnplayr 70
; load proxy settings
71
        invoke  ini.get_str, inifile, sec_proxy, key_proxy, proxyAddr, 256, proxyAddr
72
        invoke  ini.get_int, inifile, sec_proxy, key_proxyport, 80
73
        mov     [proxyPort], eax
74
        invoke  ini.get_str, inifile, sec_proxy, key_user, proxyUser, 256, proxyUser
75
        invoke  ini.get_str, inifile, sec_proxy, key_password, proxyPassword, 256, proxyPassword
3561 hidnplayr 76
 
3623 hidnplayr 77
; check parameters
78
        cmp     byte[params], 0         ; no parameters ?
79
        je      reset_events            ; load the GUI
80
 
81
; we have an url, copy untill space or 0
3561 hidnplayr 82
        mov     esi, params
83
        mov     edi, document_user
3623 hidnplayr 84
        mov     ecx, 1024               ; max parameter size
85
        mov     [shared_name], 0
3561 hidnplayr 86
  .copy_param:
3623 hidnplayr 87
        lodsb
3561 hidnplayr 88
        test    al, al
89
        jz      .done
90
 
91
        cmp     al, ' '
3623 hidnplayr 92
        jz      .done_with_shared
3561 hidnplayr 93
 
3623 hidnplayr 94
        stosb
95
        dec     ecx
96
        jnz     .copy_param
97
        DEBUGF  2, "Invalid parameters\n"
98
        jmp     exit
3561 hidnplayr 99
 
3623 hidnplayr 100
  .done_with_shared:
101
        mov     [shared_name], esi
3561 hidnplayr 102
  .done:
3623 hidnplayr 103
        xor     al, al
104
        stosb
3561 hidnplayr 105
 
3623 hidnplayr 106
 
107
download:
108
 
109
        DEBUGF  1, "Starting download\n"
110
 
111
        call    parse_url
3970 hidnplayr 112
 
113
        cmp     [server_ip], 0
3971 hidnplayr 114
        je      dns_error
3970 hidnplayr 115
 
3623 hidnplayr 116
        call    open_socket
117
        call    send_request
118
 
119
        mcall   68, 12, BUFFERSIZE      ; create buffer, we'll resize it later if needed..
120
        mov     [buf_ptr], eax
121
        mov     [buf_size], 0
122
 
123
        call    read_incoming_data
124
 
125
        mcall   close, [socketnum]
126
 
127
        call    parse_result
128
        call    save
129
 
130
        mcall   68, 13, [final_buffer]  ; free buffer
131
 
3971 hidnplayr 132
dns_error:
3623 hidnplayr 133
        cmp     byte [params], 0
134
        jne     exit
135
 
136
reset_events:
137
 
138
        DEBUGF  1, "resetting events\n"
139
 
3561 hidnplayr 140
; Report events
3623 hidnplayr 141
; defaults + mouse
3948 mario79 142
        mcall   40,EVM_REDRAW+EVM_KEY+EVM_BUTTON+EVM_MOUSE+EVM_MOUSE_FILTER
3561 hidnplayr 143
 
3623 hidnplayr 144
redraw:
3561 hidnplayr 145
        call    draw_window
146
 
147
still:
3623 hidnplayr 148
        DEBUGF  1, "waiting for events\n"
3572 hidnplayr 149
 
3566 hidnplayr 150
        mcall   10      ; wait here for event
3561 hidnplayr 151
 
3623 hidnplayr 152
        cmp     eax, EV_REDRAW
153
        je      redraw
154
 
155
        cmp     eax, EV_KEY
3561 hidnplayr 156
        je      key
157
 
3623 hidnplayr 158
        cmp     eax, EV_BUTTON
3561 hidnplayr 159
        je      button
160
 
3623 hidnplayr 161
        cmp     eax, EV_MOUSE
3561 hidnplayr 162
        je      mouse
163
 
3566 hidnplayr 164
        jmp     still
3561 hidnplayr 165
 
166
key:
167
        mcall   2       ; read key
168
 
169
        stdcall [edit_box_key], dword edit1
170
 
3566 hidnplayr 171
        cmp     ax, 13 shl 8
172
        je      download
3561 hidnplayr 173
 
174
        jmp     still
175
 
176
button:
177
 
178
        mcall   17      ; get id
3623 hidnplayr 179
 
3561 hidnplayr 180
        cmp     ah, 26
3566 hidnplayr 181
        jne     @f
182
        call    save_to_file
183
        jmp     still
184
  @@:
3561 hidnplayr 185
        cmp     ah, 1   ; button id=1 ?
3566 hidnplayr 186
        je      exit
3561 hidnplayr 187
 
3566 hidnplayr 188
        jmp     download
3561 hidnplayr 189
 
3566 hidnplayr 190
mouse:
191
        stdcall [edit_box_mouse], edit1
192
        jmp     still
193
 
3561 hidnplayr 194
exit:
3704 hidnplayr 195
        DEBUGF  1, "Exiting\n"
196
        or      eax, -1 ; close this program
3561 hidnplayr 197
        mcall
3566 hidnplayr 198
 
199
 
3623 hidnplayr 200
save:
201
        cmp     [shared_name], 0
202
        je      .use_file
3566 hidnplayr 203
 
3623 hidnplayr 204
        call    save_in_shared
205
        jmp     .done
3566 hidnplayr 206
 
3623 hidnplayr 207
  .use_file:
3566 hidnplayr 208
 
3623 hidnplayr 209
        call    save_to_file
3566 hidnplayr 210
 
3623 hidnplayr 211
  .done:
3566 hidnplayr 212
 
213
; if called from command line, then exit
214
        cmp     byte[params], 0
215
        jne     exit
3561 hidnplayr 216
 
3704 hidnplayr 217
        mov     ecx, [sc.work_text]
218
        or      ecx, 0x80000000
219
        mcall   4, <10, 93>, , download_complete
220
 
3566 hidnplayr 221
        ret
3561 hidnplayr 222
 
3566 hidnplayr 223
save_in_shared:
3561 hidnplayr 224
 
3623 hidnplayr 225
; open the shared memory area
226
        mov     esi, 1
227
        mcall   68, 22, [shared_name], , 1 ; SHM_OPEN+SHM_WRITE
3566 hidnplayr 228
        test    eax, eax
229
        jz      exit
3561 hidnplayr 230
 
3566 hidnplayr 231
        mov     ecx, [final_size]
3623 hidnplayr 232
; store the size
233
        mov     [eax], ecx
3561 hidnplayr 234
 
3623 hidnplayr 235
; now copy the data
3566 hidnplayr 236
        lea     edi, [eax+4]
237
        mov     esi, [final_buffer]
3623 hidnplayr 238
        mov     eax, ecx
3566 hidnplayr 239
        shr     ecx, 2
240
        rep     movsd
3623 hidnplayr 241
        mov     ecx, eax
3566 hidnplayr 242
        and     ecx, 3
243
        rep     movsb
244
 
3623 hidnplayr 245
        ret
3566 hidnplayr 246
 
247
 
3561 hidnplayr 248
;****************************************************************************
249
;    Function
3566 hidnplayr 250
;       save_to_file
251
;
252
;   Description
253
;
254
;
255
;****************************************************************************
256
 
257
save_to_file:
258
 
259
        DEBUGF  2, "Saving to file\n"
260
        mcall   70, fileinfo
261
 
262
        ret
263
 
264
 
265
;****************************************************************************
266
;    Function
3561 hidnplayr 267
;       send_request
268
;
269
;   Description
270
;       Transmits the GET request to the server.
271
;       This is done as GET then URL then HTTP/1.1', 13, 10, 13, 10 in 3 packets
272
;
273
;****************************************************************************
274
send_request:
275
 
276
        DEBUGF  1, "Sending request\n"
277
 
278
        mov     esi, string0
279
        mov     edi, request
280
        movsd
281
; If proxy is used, make absolute URI - prepend http://
282
        cmp     byte[proxyAddr], 0
283
        jz      .noproxy
284
        mov     dword[edi], 'http'
285
        mov     byte[edi+4], ':'
286
        mov     word[edi+5], '//'
287
        add     edi, 7
288
        mov     esi, webAddr
289
 
290
  .copy_host_loop:
291
        lodsb
292
        cmp     al, ' '
293
        jz      .noproxy
294
        stosb
295
        jmp     .copy_host_loop
296
 
297
  .noproxy:
298
        xor     edx, edx ; 0
299
 
300
  .next_edx:
301
; Determine the length of the url to send in the GET request
302
        mov     al, [edx+document]
303
        cmp     al, ' '
304
        jbe     .document_done
305
        mov     [edi], al
306
        inc     edi
307
        inc     edx
308
        jmp     .next_edx
309
 
310
  .document_done:
311
        mov     esi, stringh
312
        mov     ecx, stringh_end-stringh
313
        rep     movsb
314
        xor     edx, edx ; 0
315
 
316
  .webaddr_next:
317
        mov     al, [webAddr + edx]
318
        cmp     al, ' '
319
        jbe     .webaddr_done
320
        mov     [edi], al
321
        inc     edi
322
        inc     edx
323
        jmp     .webaddr_next
324
 
325
  .webaddr_done:
326
        cmp     byte[proxyUser], 0
327
        jz      @f
328
        call    append_proxy_auth_header
329
    @@:
330
        mov     esi, connclose
331
        mov     ecx, connclose_end-connclose
332
        rep     movsb
333
 
334
        pusha
335
        mov     eax, 63
336
        mov     ebx, 1
337
        mov     edx, request
338
    @@:
339
        mov     cl, [edx]
340
        cmp     edx, edi
341
        jz      @f
342
        mcall
343
        inc     edx
344
        jmp     @b
345
    @@:
346
        popa
347
 
348
        mov     esi, edi
349
        sub     esi, request    ; length
350
        xor     edi, edi        ; flags
351
        mcall   send, [socketnum], request  ;' HTTP/1.1 .. '
3623 hidnplayr 352
 
3561 hidnplayr 353
        ret
354
 
355
;****************************************************************************
356
;    Function
357
;       read_incoming_data
358
;
359
;   Description
360
;       receive the web page from the server, storing it without processing
361
;
362
;****************************************************************************
363
read_incoming_data:
364
 
3564 hidnplayr 365
        DEBUGF  1, "Reading incoming data\n"
3561 hidnplayr 366
 
3566 hidnplayr 367
        mov     eax, [buf_ptr]
368
        mov     [pos], eax
3561 hidnplayr 369
  .read:
3737 hidnplayr 370
        mcall   recv, [socketnum], [pos], BUFFERSIZE, 0
3561 hidnplayr 371
        inc     eax             ; -1 = error (socket closed?)
372
        jz      .no_more_data
373
        dec     eax             ; 0 bytes...
3737 hidnplayr 374
        jz      .read
3564 hidnplayr 375
 
376
        DEBUGF  1, "Got chunk of %u bytes\n", eax
3566 hidnplayr 377
 
378
        add     [buf_size], eax
3561 hidnplayr 379
        add     [pos], eax
380
        push    eax
3566 hidnplayr 381
        mov     ecx, [buf_size]
382
        add     ecx, BUFFERSIZE
383
        mcall   68, 20, , [buf_ptr]     ; reallocate memory block (make bigger)
384
        ; TODO: parse header and resize buffer only once
385
        pop     eax
386
        jmp     .read
3561 hidnplayr 387
 
388
  .no_more_data:
3566 hidnplayr 389
        mov     eax, [buf_ptr]
390
        sub     [pos], eax
3561 hidnplayr 391
 
3564 hidnplayr 392
        DEBUGF  1, "No more data\n"
393
 
3561 hidnplayr 394
        ret
395
 
396
 
397
 
398
; this function cuts header, and removes chunk sizes if doc is chunked
399
; in: buf_ptr, pos; out: buf_ptr, pos.
400
 
401
parse_result:
3566 hidnplayr 402
 
3561 hidnplayr 403
        mov     edi, [buf_ptr]
404
        mov     edx, [pos]
3566 hidnplayr 405
;        mov     [buf_size], edx
3561 hidnplayr 406
;       mcall   70, fileinfo_tmp
3564 hidnplayr 407
        DEBUGF  1, "Parsing result (%u bytes)\n", edx
3561 hidnplayr 408
 
409
; first, find end of headers
410
  .next_byte:
411
        cmp     dword[edi], 0x0a0d0a0d
412
        je      .end_of_headers
413
        inc     edi
414
        dec     edx
3736 hidnplayr 415
        ja      .next_byte
3564 hidnplayr 416
        DEBUGF  1, "Uh-oh, there's no end of header!\n"
3561 hidnplayr 417
; no end of headers. it's an error. let client see all those headers.
418
        ret
419
 
420
  .end_of_headers:
421
; here we look at headers and search content-length or transfer-encoding headers
3564 hidnplayr 422
        DEBUGF  1, "Found end of header\n"
3561 hidnplayr 423
 
424
        sub     edi, [buf_ptr]
425
        add     edi, 4
426
        mov     [body_pos], edi  ; store position where document body starts
427
        mov     [is_chunked], 0
428
; find content-length in headers
429
; not good method, but should work for 'Content-Length:'
430
        mov     esi, [buf_ptr]
431
        mov     edi, s_contentlength
432
        mov     ebx, [body_pos]
433
        xor     edx, edx ; 0
434
  .cl_next:
435
        mov     al, [esi]
436
        cmp     al, [edi + edx]
437
        jne     .cl_fail
438
        inc     edx
439
        cmp     edx, len_contentlength
440
        je      .cl_found
441
        jmp     .cl_incr
442
  .cl_fail:
443
        xor     edx, edx ; 0
444
  .cl_incr:
445
        inc     esi
446
        dec     ebx
447
        je      .cl_error
448
        jmp     .cl_next
449
  .cl_error:
3564 hidnplayr 450
        DEBUGF  1, "content-length not found\n"
3561 hidnplayr 451
 
452
; find 'chunked'
453
; äà, ÿ êîïèðóþ êîä, ýòî óæàñíî, íî ìíå õî÷åòñÿ, ÷òîáû ïîñêîðåå çàðàáîòàëî
454
; à òàì óæ îòðåôàêòîðþ
455
        mov     esi, [buf_ptr]
456
        mov     edi, s_chunked
457
        mov     ebx, [body_pos]
458
        xor     edx, edx ; 0
459
 
460
  .ch_next:
461
        mov     al, [esi]
462
        cmp     al, [edi + edx]
463
        jne     .ch_fail
464
        inc     edx
465
        cmp     edx, len_chunked
466
        je      .ch_found
467
        jmp     .ch_incr
468
 
469
  .ch_fail:
470
        xor     edx, edx ; 0
471
 
472
  .ch_incr:
473
        inc     esi
474
        dec     ebx
475
        je      .ch_error
476
        jmp     .ch_next
477
 
478
  .ch_error:
479
; if neither of the 2 headers is found, it's an error
480
;       DEBUGF  1, "transfer-encoding: chunked not found\n"
481
        mov     eax, [pos]
482
        sub     eax, [body_pos]
483
        jmp     .write_final_size
484
 
485
  .ch_found:
486
        mov     [is_chunked], 1
487
        mov     eax, [body_pos]
488
        add     eax, [buf_ptr]
489
        sub     eax, 2
490
        mov     [prev_chunk_end], eax
491
        jmp     parse_chunks
492
 
493
  .cl_found:
494
        call    read_number     ; eax = number from *esi
3564 hidnplayr 495
        DEBUGF  1, "Content length: %u\n", eax
3561 hidnplayr 496
 
497
  .write_final_size:
498
 
3564 hidnplayr 499
        mov     ebx, [buf_size]
3561 hidnplayr 500
        sub     ebx, [body_pos]
3564 hidnplayr 501
        cmp     eax, ebx
502
        jbe     .size_ok
3566 hidnplayr 503
        sub     eax, ebx
504
        DEBUGF  2, "%u bytes of data are missing!\n", eax
3564 hidnplayr 505
        mov     eax, ebx
506
  .size_ok:
507
        mov     [final_size], eax
3561 hidnplayr 508
 
3564 hidnplayr 509
        mov     ebx, [body_pos]
510
        add     ebx, [buf_ptr]
3561 hidnplayr 511
        mov     [final_buffer], ebx
3564 hidnplayr 512
 
3561 hidnplayr 513
        ret
514
 
515
parse_chunks:
3564 hidnplayr 516
        DEBUGF  1, "parse chunks\n"
3561 hidnplayr 517
        ; we have to look through the data and remove sizes of chunks we see
518
        ; 1. read size of next chunk
519
        ; 2. if 0, it's end. if not, continue.
520
        ; 3. make a good buffer and copy a chunk there
521
        xor     eax, eax
522
        mov     [final_buffer], eax      ; 0
523
        mov     [final_size], eax        ; 0
524
 
525
.read_size:
526
        mov     eax, [prev_chunk_end]
527
        mov     ebx, eax
528
        sub     ebx, [buf_ptr]
529
        mov     edx, eax
3564 hidnplayr 530
        DEBUGF  1, "rs "
3561 hidnplayr 531
        cmp     ebx, [pos]
532
        jae     chunks_end      ; not good
533
 
534
        call    read_hex        ; in: eax=pointer to text. out:eax=hex number, ebx=end of text.
535
        cmp     eax, 0
536
        jz      chunks_end
537
 
538
        add     ebx, 1
539
        mov     edx, ebx ; edx = size of size of chunk
540
 
541
        add     ebx, eax
542
        mov     [prev_chunk_end], ebx
543
 
3564 hidnplayr 544
        DEBUGF  1, "sz "
3561 hidnplayr 545
 
546
; do copying: from buf_ptr+edx to final_buffer+prev_final_size count eax
547
; realloc final buffer
548
        push    eax
549
        push    edx
550
        push    dword [final_size]
551
        add     [final_size], eax
552
        mcall   68, 20, [final_size], [final_buffer]
553
        mov     [final_buffer], eax
3564 hidnplayr 554
        DEBUGF  1, "re "
3561 hidnplayr 555
        pop     edi
556
        pop     esi
557
        pop     ecx
558
;       add     [pos], ecx
559
        add     edi, [final_buffer]
3564 hidnplayr 560
        DEBUGF  1, "cp "
3561 hidnplayr 561
 
562
        rep     movsb
563
        jmp     .read_size
564
 
565
chunks_end:
566
        DEBUGF  1, "chunks end\n"
3566 hidnplayr 567
        mcall   68, 13, [buf_ptr]       ; free old buffer
3561 hidnplayr 568
 
569
        ret
570
 
571
; reads content-length from [edi+ecx], result in eax
572
read_number:
573
        push    ebx
574
        xor     eax, eax
575
        xor     ebx, ebx
576
 
577
  .next:
578
        mov     bl, [esi]
579
 
580
        cmp     bl, '0'
581
        jb      .not_number
582
        cmp     bl, '9'
583
        ja      .not_number
584
        sub     bl, '0'
585
        shl     eax, 1
586
        lea     eax, [eax + eax * 4]     ; eax *= 10
587
        add     eax, ebx
588
 
589
  .not_number:
590
        cmp     bl, 13
591
        je      .done
592
        inc     esi
593
        jmp     .next
594
 
595
  .done:
596
        pop     ebx
597
        ret
598
 
599
; reads hex from eax, result in eax, end of text in ebx
600
read_hex:
601
        add     eax, 2
602
        mov     ebx, eax
603
        mov     eax, [ebx]
604
        mov     [deba], eax
605
 
606
        xor     eax, eax
607
        xor     ecx, ecx
3623 hidnplayr 608
  .next:
3561 hidnplayr 609
        mov     cl, [ebx]
610
        inc     ebx
611
 
612
        cmp     cl, 0x0d
613
        jz      .done
614
 
615
        or      cl, 0x20
616
        sub     cl, '0'
617
        jb      .bad
618
 
619
        cmp     cl, 0x9
620
        jbe     .adding
621
 
622
        sub     cl, 'a'-'0'-10
623
        cmp     cl, 0x0a
624
        jb      .bad
625
 
626
        cmp     cl, 0x0f
627
        ja      .bad
628
 
3623 hidnplayr 629
  .adding:
3561 hidnplayr 630
        shl     eax, 4
631
        or      eax, ecx
3623 hidnplayr 632
  .bad:
3561 hidnplayr 633
        jmp     .next
3623 hidnplayr 634
  .done:
3561 hidnplayr 635
 
636
        ret
637
 
638
;****************************************************************************
639
;    Function
3566 hidnplayr 640
;       open_socket
3561 hidnplayr 641
;
642
;   Description
3566 hidnplayr 643
;       opens the socket
3561 hidnplayr 644
;
645
;****************************************************************************
3566 hidnplayr 646
open_socket:
3561 hidnplayr 647
 
648
        DEBUGF  1, "opening socket\n"
649
 
650
        mov     edx, 80
651
        cmp     byte [proxyAddr], 0
652
        jz      @f
653
        mov     eax, [proxyPort]
654
        xchg    al, ah
655
        mov     [server_port], ax
656
    @@:
657
 
658
        mcall   socket, AF_INET4, SOCK_STREAM, 0
659
        mov     [socketnum], eax
660
        mcall   connect, [socketnum], sockaddr1, 18
3566 hidnplayr 661
 
3561 hidnplayr 662
        ret
663
 
664
 
665
;****************************************************************************
666
;    Function
667
;       parse_url
668
;
669
;   Description
670
;       parses the full url typed in by the user into a web address ( that
671
;       can be turned into an IP address by DNS ) and the page to display
672
;       DNS will be used to translate the web address into an IP address, if
673
;       needed.
674
;       url is at document_user and will be space terminated.
675
;       web address goes to webAddr and is space terminated.
676
;       ip address goes to server_ip
677
;       page goes to document and is space terminated.
678
;
679
;       Supported formats:
680
;       address
681
;        is optional, removed and ignored - only http supported
682
;       
is required. It can be an ip address or web address
683
;        is optional and must start with a leading / character
684
;
685
;****************************************************************************
686
parse_url:
687
; First, reset destination variables
688
        mov     al, ' '
689
        mov     edi, document
690
        mov     ecx, URLMAXLEN
691
        rep     stosb
692
        mov     edi, webAddr
693
        mov     ecx, URLMAXLEN
694
        rep     stosb
695
 
696
        mov     al, '/'
697
        mov     [document], al
698
 
699
        mov     esi, document_user
700
; remove any leading protocol text
701
        mov     ecx, URLMAXLEN
702
        mov     ax, '//'
703
 
704
pu_000:
705
        cmp     [esi], byte ' '         ; end of text?
706
        je      pu_002                  ; yep, so not found
707
        cmp     [esi], ax
708
        je      pu_001                  ; Found it, so esi+2 is start
709
        inc     esi
710
        loop    pu_000
711
 
712
pu_002:
713
; not found, so reset esi to start
714
        mov     esi, document_user-2
715
 
716
pu_001:
717
        add     esi, 2
718
        mov     ebx, esi ; save address of start of web address
719
        mov     edi, document_user + URLMAXLEN   ; end of string
720
; look for page delimiter - it's a '/' character
721
pu_003:
722
        cmp     [esi], byte ' '  ; end of text?
723
        je      pu_004          ; yep, so none found
724
        cmp     esi, edi         ; end of string?
725
        je      pu_004          ; yep, so none found
726
        cmp     [esi], byte '/'  ; delimiter?
727
        je      pu_005          ; yep - process it
728
        inc     esi
729
        jmp     pu_003
730
 
731
pu_005:
732
; copy page to document address
733
; esi = delimiter
734
        push    esi
735
        mov     ecx, edi         ; end of document_user
736
        mov     edi, document
737
 
738
pu_006:
739
        movsb
740
        cmp     esi, ecx
741
        je      pu_007          ; end of string?
742
        cmp     [esi], byte ' '  ; end of text
743
;       je      pu_007          ; äçåí-àññåìáëåð
744
;       jmp     pu_006          ; íå íàäî ïëîäèòü ñóùíîñòè ïî íàïðàñíó
745
        jne     pu_006
746
 
747
pu_007:
748
        pop     esi     ; point esi to '/' delimiter
749
 
750
pu_004:
751
; copy web address to webAddr
752
; start in ebx, end in esi-1
753
        mov     ecx, esi
754
        mov     esi, ebx
755
        mov     edi, webAddr
756
  @@:
757
        movsb
758
        cmp     esi, ecx
759
        jne     @r
760
        mov     byte [edi], 0
761
 
762
pu_009:
763
; For debugging, display resulting strings
3564 hidnplayr 764
        DEBUGF  2, "Downloadng %s\n", document_user
3561 hidnplayr 765
 
766
; Look up the ip address, or was it specified?
767
        mov     al, [proxyAddr]
768
        cmp     al, 0
769
        jnz     pu_015
770
        mov     al, [webAddr]
771
pu_015:
772
        cmp     al, '0'
773
        jb      pu_010  ; Resolve address
774
        cmp     al, '9'
775
        ja      pu_010  ; Resolve address
776
 
777
        DEBUGF  1, "GotIP\n"
778
 
779
; Convert address
780
; If proxy is given, get proxy address instead of server
781
        mov     esi, proxyAddr-1
782
        cmp     byte[esi+1], 0
783
        jne     pu_020
784
        mov     esi, webAddr-1
785
 
786
pu_020:
787
        mov     edi, server_ip
788
        xor     eax, eax
789
 
790
ip1:
791
        inc     esi
792
        cmp     [esi], byte '0'
793
        jb      ip2
794
        cmp     [esi], byte '9'
795
        ja      ip2
796
        imul    eax, 10
797
        movzx   ebx, byte [esi]
798
        sub     ebx, 48
799
        add     eax, ebx
800
        jmp     ip1
801
 
802
ip2:
803
        mov     [edi], al
804
        xor     eax, eax
805
        inc     edi
806
        cmp     edi, server_ip+3
807
        jbe     ip1
808
 
3623 hidnplayr 809
        ret
810
 
3561 hidnplayr 811
pu_010:
812
        DEBUGF  1, "Resolving %s\n", webAddr
813
 
814
; resolve name
815
        push    esp     ; reserve stack place
816
        push    esp     ; fourth parameter
817
        push    0       ; third parameter
818
        push    0       ; second parameter
819
        push    webAddr
820
        call    [getaddrinfo]
821
        pop     esi
3564 hidnplayr 822
; TODO: handle error
3561 hidnplayr 823
;        test    eax, eax
824
;        jnz     .fail_dns
825
 
3564 hidnplayr 826
; fill in ip
3561 hidnplayr 827
        mov     eax, [esi + addrinfo.ai_addr]
828
        mov     eax, [eax + sockaddr_in.sin_addr]
829
        mov     [server_ip], eax
830
 
3736 hidnplayr 831
; free allocated memory
832
        push    esi
833
        call    [freeaddrinfo]
834
 
3561 hidnplayr 835
        DEBUGF  1, "Resolved to %u.%u.%u.%u\n", [server_ip]:1, [server_ip + 1]:1, [server_ip + 2]:1, [server_ip + 3]:1
836
 
837
        ret
838
 
839
;***************************************************************************
840
;   Function
841
;       append_proxy_auth_header
842
;
843
;   Description
844
;       Append header to HTTP request for proxy authentification
845
;
846
;***************************************************************************
847
append_proxy_auth_header:
848
        mov     esi, proxy_auth_basic
849
        mov     ecx, proxy_auth_basic_end - proxy_auth_basic
850
        rep     movsb
851
; base64-encode string :
852
        mov     esi, proxyUser
853
 
854
apah000:
855
        lodsb
856
        test    al, al
857
        jz      apah001
858
        call    encode_base64_byte
859
        jmp     apah000
860
 
861
apah001:
862
        mov     al, ':'
863
        call    encode_base64_byte
864
        mov     esi, proxyPassword
865
 
866
apah002:
867
        lodsb
868
        test    al, al
869
        jz      apah003
870
        call    encode_base64_byte
871
        jmp     apah002
872
 
873
apah003:
874
        call    encode_base64_final
875
        ret
876
 
877
encode_base64_byte:
878
        inc     ecx
879
        shl     edx, 8
880
        mov     dl, al
881
        cmp     ecx, 3
882
        je      ebb001
883
        ret
884
 
885
ebb001:
886
        shl     edx, 8
887
        inc     ecx
888
 
889
ebb002:
890
        rol     edx, 6
891
        xor     eax, eax
892
        xchg    al, dl
893
        mov     al, [base64_table+eax]
894
        stosb
895
        loop    ebb002
896
        ret
897
 
898
encode_base64_final:
899
        mov     al, 0
900
        test    ecx, ecx
901
        jz      ebf000
902
        call    encode_base64_byte
903
        test    ecx, ecx
904
        jz      ebf001
905
        call    encode_base64_byte
906
        mov     byte [edi-2], '='
907
 
908
ebf001:
909
        mov     byte [edi-1], '='
910
 
911
ebf000:
912
        ret
913
 
914
;   *********************************************
915
;   *******  WINDOW DEFINITIONS AND DRAW ********
916
;   *********************************************
917
 
918
draw_window:
919
 
920
        mcall   12, 1
921
 
922
        mcall   48, 3, sc, 40 ;get system colors
923
 
924
        mov     edx, [sc.work]
925
        or      edx, 0x34000000
926
        mcall   0, <50, 370>, <350, 140>, , 0, title   ;draw window
927
 
928
        mov     ecx, [sc.work_text]
929
        or      ecx, 80000000h
930
        mcall   4, <14, 14>, , type_pls ;"URL:"
931
 
932
        edit_boxes_set_sys_color edit1, editboxes_end, sc
933
        stdcall [edit_box_draw], edit1
934
 
935
; RELOAD
936
        mcall   8, <90, 68>, <54, 16>, 22, [sc.work_button]
937
; STOP
938
        mcall   , <166, 50>, <54, 16>, 24
939
; SAVE
940
        mcall   , <224, 54>, , 26
941
; BUTTON TEXT
942
        mov     ecx, [sc.work_button_text]
943
        or      ecx, 80000000h
944
        mcall   4, <102, 59>, , button_text
945
 
946
        mcall   12, 2 ; end window redraw
3623 hidnplayr 947
 
3561 hidnplayr 948
        ret
3566 hidnplayr 949
 
950
 
3561 hidnplayr 951
;-----------------------------------------------------------------------------
952
; Data area
953
;-----------------------------------------------------------------------------
954
align   4
955
@IMPORT:
956
 
957
library libini, 'libini.obj', \
958
        box_lib, 'box_lib.obj', \
959
        network, 'network.obj'
960
 
961
import  libini, \
962
        ini.get_str, 'ini_get_str', \
963
        ini.get_int, 'ini_get_int'
964
 
965
import  box_lib, \
966
        edit_box_draw, 'edit_box', \
967
        edit_box_key, 'edit_box_key', \
968
        edit_box_mouse, 'edit_box_mouse'
969
 
970
import  network,\
971
        getaddrinfo,    'getaddrinfo',\
972
        freeaddrinfo,   'freeaddrinfo',\
973
        inet_ntoa,      'inet_ntoa'
974
 
975
;---------------------------------------------------------------------
976
fileinfo        dd 2, 0, 0
977
final_size      dd 0
978
final_buffer    dd 0
979
                db '/rd/1/.download', 0
980
 
981
body_pos        dd 0
982
buf_size        dd 0
983
buf_ptr         dd 0
984
 
985
deba            dd 0
986
                db 0
987
 
988
;---------------------------------------------------------------------
989
 
990
mouse_dd        dd 0
991
edit1           edit_box 295, 48, 10, 0xffffff, 0xff, 0x80ff, 0, 0x8000, URLMAXLEN, document_user, mouse_dd, ed_focus+ed_always_focus, 7, 7
992
editboxes_end:
993
 
994
;---------------------------------------------------------------------
995
 
996
include_debug_strings
997
 
998
;---------------------------------------------------------------------
999
 
1000
type_pls        db 'URL:', 0
1001
button_text     db 'DOWNLOAD     STOP     RESAVE', 0
1002
download_complete db 'File saved as /rd/1/.download', 0
1003
title           db 'HTTP Downloader', 0
1004
 
1005
;---------------------------------------------------------------------
1006
s_contentlength db 'Content-Length:'
1007
len_contentlength = 15
1008
 
1009
s_chunked       db 'Transfer-Encoding: chunked'
1010
len_chunked     = $ - s_chunked
1011
 
1012
string0:        db 'GET '
1013
 
1014
stringh                 db ' HTTP/1.1', 13, 10, 'Host: '
1015
stringh_end:
1016
proxy_auth_basic        db 13, 10, 'Proxy-Authorization: Basic '
1017
proxy_auth_basic_end:
1018
connclose               db 13, 10, 'User-Agent: Kolibrios Downloader', 13, 10, 'Connection: Close', 13, 10, 13, 10
1019
connclose_end:
1020
 
1021
base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
1022
                db '0123456789+/'
1023
 
1024
inifile         db '/sys/network.ini', 0
1025
 
1026
sec_proxy:
1027
key_proxy       db 'proxy', 0
1028
key_proxyport   db 'port', 0
1029
key_user        db 'user', 0
1030
key_password    db 'password', 0
1031
 
1032
sockaddr1:
1033
                dw AF_INET4
1034
server_port     dw 0x5000       ; 80
1035
server_ip       dd 0
1036
                rb 10
1037
 
1038
proxyPort       dd 80
1039
 
1040
shared_name     dd 0
1041
 
1042
;---------------------------------------------------------------------
1043
document_user   db 'http://', 0
1044
;---------------------------------------------------------------------
1045
IM_END:
1046
;---------------------------------------------------------------------
1047
                rb URLMAXLEN-(IM_END - document_user)
1048
;---------------------------------------------------------------------
1049
                sc system_colors
1050
;---------------------------------------------------------------------
1051
align 4
1052
document        rb URLMAXLEN
1053
;---------------------------------------------------------------------
1054
align 4
1055
webAddr         rb URLMAXLEN+1
1056
;---------------------------------------------------------------------
3566 hidnplayr 1057
pos             dd ?
1058
socketnum       dd ?
1059
is_chunked      dd ?
1060
prev_chunk_end  dd ?
1061
cur_chunk_size  dd ?
1062
;---------------------------------------------------------------------
3561 hidnplayr 1063
 
1064
params          rb 1024
1065
 
1066
request         rb 256
1067
 
1068
proxyAddr       rb 256
1069
proxyUser       rb 256
1070
proxyPassword   rb 256
1071
 
1072
I_END:
1073