Subversion Repositories Kolibri OS

Rev

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