Subversion Repositories Kolibri OS

Rev

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