Subversion Repositories Kolibri OS

Rev

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