Subversion Repositories Kolibri OS

Rev

Rev 3561 | Rev 3566 | 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
19
primary_buffer_size     = 4096
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
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:
3564 hidnplayr 193
        DEBUGF  2, "File saved\n"
3561 hidnplayr 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
3564 hidnplayr 366
        DEBUGF  1, "Reading incoming data\n"
3561 hidnplayr 367
 
368
  .read:
3564 hidnplayr 369
        ; TODO: implement timeout !
3561 hidnplayr 370
        mcall   recv, [socketnum], primary_buf, primary_buffer_size, 0
371
        inc     eax             ; -1 = error (socket closed?)
372
        jz      .no_more_data
373
        dec     eax             ; 0 bytes...
374
        jz      .read
3564 hidnplayr 375
 
376
        DEBUGF  1, "Got chunk of %u bytes\n", eax
3561 hidnplayr 377
 
378
        mov     edi, [pos]
379
        add     [pos], eax
380
        push    eax
381
        mcall   68, 20, [pos], [buf_ptr]
382
        mov     [buf_ptr], eax
383
        add     edi, eax
384
        mov     esi, primary_buf
385
        pop     ecx             ; number of recently read bytes
386
        lea     edx, [ecx - 3]
387
        rep     movsb
388
 
389
  .no_more_data:
390
 
3564 hidnplayr 391
        DEBUGF  1, "No more data\n"
392
 
3561 hidnplayr 393
;        mov     [status], 4     ; connection closed by server
394
 
395
        call    parse_result
3564 hidnplayr 396
 
397
        DEBUGF  1, "Parsing complete\n"
398
 
3561 hidnplayr 399
        mov     ecx, [shared_name]
400
        test    ecx, ecx
401
        jz      @f
402
        cmp     [ecx], byte 0
403
        jnz     save_in_shared
404
    @@:
405
 
406
        mcall   70, fileinfo
3564 hidnplayr 407
 
408
        DEBUGF  2, "File saved\n"
3561 hidnplayr 409
 
410
        mov     ecx, [sc.work_text]
411
        or      ecx, 0x80000000
412
        mcall   4, <10, 93>, , download_complete
413
 
414
        pop     edi
415
        pop     esi
416
 
417
; if called from command line, then exit
418
        cmp     byte[params], 0
419
        jne     exit
420
 
421
        ret
422
 
423
save_in_shared:
424
 
425
        mov     esi, 1   ; SHM_OPEN+SHM_WRITE
426
        mcall   68, 22
427
        test    eax, eax
428
        jz      save_in_shared_done
429
 
430
        sub     edx, 4
431
        jbe     save_in_shared_done
432
 
433
        mov     ecx, [final_size]
434
        cmp     ecx, edx
435
        jb      @f
436
 
437
        mov     ecx, edx
438
    @@:
439
        mov     [eax], ecx
440
        lea     edi, [eax+4]
441
        mov     esi, [final_buffer]
442
        mov     edx, ecx
443
        shr     ecx, 2
444
        rep     movsd
445
        mov     ecx, edx
446
        and     ecx, 3
447
        rep     movsb
448
 
449
save_in_shared_done:
450
        pop     edi
451
        pop     esi
452
        jmp     exit
453
 
454
; this function cuts header, and removes chunk sizes if doc is chunked
455
; in: buf_ptr, pos; out: buf_ptr, pos.
456
 
457
parse_result:
458
; close socket
459
        mcall   close, [socketnum]
460
 
461
        mov     edi, [buf_ptr]
462
        mov     edx, [pos]
463
        mov     [buf_size], edx
464
;       mcall   70, fileinfo_tmp
3564 hidnplayr 465
        DEBUGF  1, "Parsing result (%u bytes)\n", edx
3561 hidnplayr 466
 
467
; first, find end of headers
468
  .next_byte:
469
        cmp     dword[edi], 0x0d0a0d0a  ; ìíå ëåíü ÷èòàòü ñòàíäàðò, ïóñòü áóäóò îáà âàðèàíòà
470
        je      .end_of_headers
471
        cmp     dword[edi], 0x0a0d0a0d
472
        je      .end_of_headers
473
        inc     edi
474
        dec     edx
475
        jne     .next_byte
3564 hidnplayr 476
        DEBUGF  1, "Uh-oh, there's no end of header!\n"
3561 hidnplayr 477
; no end of headers. it's an error. let client see all those headers.
478
        ret
479
 
480
  .end_of_headers:
481
; here we look at headers and search content-length or transfer-encoding headers
3564 hidnplayr 482
        DEBUGF  1, "Found end of header\n"
3561 hidnplayr 483
 
484
        sub     edi, [buf_ptr]
485
        add     edi, 4
486
        mov     [body_pos], edi  ; store position where document body starts
487
        mov     [is_chunked], 0
488
; find content-length in headers
489
; not good method, but should work for 'Content-Length:'
490
        mov     esi, [buf_ptr]
491
        mov     edi, s_contentlength
492
        mov     ebx, [body_pos]
493
        xor     edx, edx ; 0
494
  .cl_next:
495
        mov     al, [esi]
496
        cmp     al, [edi + edx]
497
        jne     .cl_fail
498
        inc     edx
499
        cmp     edx, len_contentlength
500
        je      .cl_found
501
        jmp     .cl_incr
502
  .cl_fail:
503
        xor     edx, edx ; 0
504
  .cl_incr:
505
        inc     esi
506
        dec     ebx
507
        je      .cl_error
508
        jmp     .cl_next
509
  .cl_error:
3564 hidnplayr 510
        DEBUGF  1, "content-length not found\n"
3561 hidnplayr 511
 
512
; find 'chunked'
513
; äà, ÿ êîïèðóþ êîä, ýòî óæàñíî, íî ìíå õî÷åòñÿ, ÷òîáû ïîñêîðåå çàðàáîòàëî
514
; à òàì óæ îòðåôàêòîðþ
515
        mov     esi, [buf_ptr]
516
        mov     edi, s_chunked
517
        mov     ebx, [body_pos]
518
        xor     edx, edx ; 0
519
 
520
  .ch_next:
521
        mov     al, [esi]
522
        cmp     al, [edi + edx]
523
        jne     .ch_fail
524
        inc     edx
525
        cmp     edx, len_chunked
526
        je      .ch_found
527
        jmp     .ch_incr
528
 
529
  .ch_fail:
530
        xor     edx, edx ; 0
531
 
532
  .ch_incr:
533
        inc     esi
534
        dec     ebx
535
        je      .ch_error
536
        jmp     .ch_next
537
 
538
  .ch_error:
539
; if neither of the 2 headers is found, it's an error
540
;       DEBUGF  1, "transfer-encoding: chunked not found\n"
541
        mov     eax, [pos]
542
        sub     eax, [body_pos]
543
        jmp     .write_final_size
544
 
545
  .ch_found:
546
        mov     [is_chunked], 1
547
        mov     eax, [body_pos]
548
        add     eax, [buf_ptr]
549
        sub     eax, 2
550
        mov     [prev_chunk_end], eax
551
        jmp     parse_chunks
552
 
553
  .cl_found:
554
        call    read_number     ; eax = number from *esi
3564 hidnplayr 555
        DEBUGF  1, "Content length: %u\n", eax
3561 hidnplayr 556
 
557
  .write_final_size:
558
 
3564 hidnplayr 559
        mov     ebx, [buf_size]
3561 hidnplayr 560
        sub     ebx, [body_pos]
3564 hidnplayr 561
        cmp     eax, ebx
562
        jbe     .size_ok
563
        DEBUGF  2, "Not all data was received!\n"
564
        mov     eax, ebx
565
  .size_ok:
566
        mov     [final_size], eax
3561 hidnplayr 567
 
3564 hidnplayr 568
        mov     ebx, [body_pos]
569
        add     ebx, [buf_ptr]
3561 hidnplayr 570
        mov     [final_buffer], ebx
3564 hidnplayr 571
 
3561 hidnplayr 572
        ret
573
 
574
parse_chunks:
3564 hidnplayr 575
        DEBUGF  1, "parse chunks\n"
3561 hidnplayr 576
        ; we have to look through the data and remove sizes of chunks we see
577
        ; 1. read size of next chunk
578
        ; 2. if 0, it's end. if not, continue.
579
        ; 3. make a good buffer and copy a chunk there
580
        xor     eax, eax
581
        mov     [final_buffer], eax      ; 0
582
        mov     [final_size], eax        ; 0
583
 
584
.read_size:
585
        mov     eax, [prev_chunk_end]
586
        mov     ebx, eax
587
        sub     ebx, [buf_ptr]
588
        mov     edx, eax
3564 hidnplayr 589
        DEBUGF  1, "rs "
3561 hidnplayr 590
        cmp     ebx, [pos]
591
        jae     chunks_end      ; not good
592
 
593
        call    read_hex        ; in: eax=pointer to text. out:eax=hex number, ebx=end of text.
594
        cmp     eax, 0
595
        jz      chunks_end
596
 
597
        add     ebx, 1
598
        mov     edx, ebx ; edx = size of size of chunk
599
 
600
        add     ebx, eax
601
        mov     [prev_chunk_end], ebx
602
 
3564 hidnplayr 603
        DEBUGF  1, "sz "
3561 hidnplayr 604
 
605
; do copying: from buf_ptr+edx to final_buffer+prev_final_size count eax
606
; realloc final buffer
607
        push    eax
608
        push    edx
609
        push    dword [final_size]
610
        add     [final_size], eax
611
        mcall   68, 20, [final_size], [final_buffer]
612
        mov     [final_buffer], eax
3564 hidnplayr 613
        DEBUGF  1, "re "
3561 hidnplayr 614
        pop     edi
615
        pop     esi
616
        pop     ecx
617
;       add     [pos], ecx
618
        add     edi, [final_buffer]
3564 hidnplayr 619
        DEBUGF  1, "cp "
3561 hidnplayr 620
 
621
        rep     movsb
622
        jmp     .read_size
623
 
624
chunks_end:
625
; free old buffer
626
        DEBUGF  1, "chunks end\n"
627
 
628
        mcall   68, 13, [buf_ptr]
629
; done!
630
        ret
631
 
632
; reads content-length from [edi+ecx], result in eax
633
read_number:
634
        push    ebx
635
        xor     eax, eax
636
        xor     ebx, ebx
637
 
638
  .next:
639
        mov     bl, [esi]
640
 
641
        cmp     bl, '0'
642
        jb      .not_number
643
        cmp     bl, '9'
644
        ja      .not_number
645
        sub     bl, '0'
646
        shl     eax, 1
647
        lea     eax, [eax + eax * 4]     ; eax *= 10
648
        add     eax, ebx
649
 
650
  .not_number:
651
        cmp     bl, 13
652
        je      .done
653
        inc     esi
654
        jmp     .next
655
 
656
  .done:
657
        pop     ebx
658
        ret
659
 
660
; reads hex from eax, result in eax, end of text in ebx
661
read_hex:
662
        add     eax, 2
663
        mov     ebx, eax
664
        mov     eax, [ebx]
665
        mov     [deba], eax
666
 
667
        xor     eax, eax
668
        xor     ecx, ecx
669
.next:
670
        mov     cl, [ebx]
671
        inc     ebx
672
 
673
        cmp     cl, 0x0d
674
        jz      .done
675
 
676
        or      cl, 0x20
677
        sub     cl, '0'
678
        jb      .bad
679
 
680
        cmp     cl, 0x9
681
        jbe     .adding
682
 
683
        sub     cl, 'a'-'0'-10
684
        cmp     cl, 0x0a
685
        jb      .bad
686
 
687
        cmp     cl, 0x0f
688
        ja      .bad
689
 
690
.adding:
691
        shl     eax, 4
692
        or      eax, ecx
693
;       jmp     .not_number
694
;.bad:
695
.bad:
696
        jmp     .next
697
.done:
698
 
699
        ret
700
 
701
;****************************************************************************
702
;    Function
703
;       socket_commands
704
;
705
;   Description
706
;       opens or closes the socket
707
;
708
;****************************************************************************
709
socket_commands:
710
        cmp     ah, 22   ; open socket
711
        jne     tst3
712
 
713
        DEBUGF  1, "opening socket\n"
714
 
715
; Clear all page memory
716
        xor     eax, eax
717
        mov     [prev_chunk_end], eax    ; 0
718
        cmp     [buf_ptr], eax   ; 0
719
        jz      no_free
720
 
721
        mcall   68, 13, [buf_ptr] ; free  buffer
722
 
723
no_free:
724
        xor     eax, eax
725
        mov     [buf_size], eax  ; 0
726
; Parse the entered url
727
        call    parse_url
728
 
729
        mov     edx, 80
730
        cmp     byte [proxyAddr], 0
731
        jz      @f
732
        mov     eax, [proxyPort]
733
        xchg    al, ah
734
        mov     [server_port], ax
735
    @@:
736
 
737
        mcall   socket, AF_INET4, SOCK_STREAM, 0
738
        mov     [socketnum], eax
739
        mcall   connect, [socketnum], sockaddr1, 18
740
        mov     [pagexs], 80
741
 
742
        push    eax
743
        xor     eax, eax ; 0
744
        mov     [pos], eax
745
        mov     [pagex], eax
746
        mov     [pagey], eax
747
        mov     [command_on_off], eax
748
        mov     [is_body], eax
749
        pop     eax
750
        ret
751
 
752
tst3:
753
        cmp     ah, 24   ; close socket
754
        jne     no_24
755
 
756
        mcall   close, [socketnum]
757
no_24:
758
        ret
759
 
760
;****************************************************************************
761
;    Function
762
;       parse_url
763
;
764
;   Description
765
;       parses the full url typed in by the user into a web address ( that
766
;       can be turned into an IP address by DNS ) and the page to display
767
;       DNS will be used to translate the web address into an IP address, if
768
;       needed.
769
;       url is at document_user and will be space terminated.
770
;       web address goes to webAddr and is space terminated.
771
;       ip address goes to server_ip
772
;       page goes to document and is space terminated.
773
;
774
;       Supported formats:
775
;       address
776
;        is optional, removed and ignored - only http supported
777
;       
is required. It can be an ip address or web address
778
;        is optional and must start with a leading / character
779
;
780
;****************************************************************************
781
parse_url:
782
; First, reset destination variables
783
        mov     al, ' '
784
        mov     edi, document
785
        mov     ecx, URLMAXLEN
786
        rep     stosb
787
        mov     edi, webAddr
788
        mov     ecx, URLMAXLEN
789
        rep     stosb
790
 
791
        mov     al, '/'
792
        mov     [document], al
793
 
794
        mov     esi, document_user
795
; remove any leading protocol text
796
        mov     ecx, URLMAXLEN
797
        mov     ax, '//'
798
 
799
pu_000:
800
        cmp     [esi], byte ' '         ; end of text?
801
        je      pu_002                  ; yep, so not found
802
        cmp     [esi], ax
803
        je      pu_001                  ; Found it, so esi+2 is start
804
        inc     esi
805
        loop    pu_000
806
 
807
pu_002:
808
; not found, so reset esi to start
809
        mov     esi, document_user-2
810
 
811
pu_001:
812
        add     esi, 2
813
        mov     ebx, esi ; save address of start of web address
814
        mov     edi, document_user + URLMAXLEN   ; end of string
815
; look for page delimiter - it's a '/' character
816
pu_003:
817
        cmp     [esi], byte ' '  ; end of text?
818
        je      pu_004          ; yep, so none found
819
        cmp     esi, edi         ; end of string?
820
        je      pu_004          ; yep, so none found
821
        cmp     [esi], byte '/'  ; delimiter?
822
        je      pu_005          ; yep - process it
823
        inc     esi
824
        jmp     pu_003
825
 
826
pu_005:
827
; copy page to document address
828
; esi = delimiter
829
        push    esi
830
        mov     ecx, edi         ; end of document_user
831
        mov     edi, document
832
 
833
pu_006:
834
        movsb
835
        cmp     esi, ecx
836
        je      pu_007          ; end of string?
837
        cmp     [esi], byte ' '  ; end of text
838
;       je      pu_007          ; äçåí-àññåìáëåð
839
;       jmp     pu_006          ; íå íàäî ïëîäèòü ñóùíîñòè ïî íàïðàñíó
840
        jne     pu_006
841
 
842
pu_007:
843
        pop     esi     ; point esi to '/' delimiter
844
 
845
pu_004:
846
; copy web address to webAddr
847
; start in ebx, end in esi-1
848
        mov     ecx, esi
849
        mov     esi, ebx
850
        mov     edi, webAddr
851
  @@:
852
        movsb
853
        cmp     esi, ecx
854
        jne     @r
855
        mov     byte [edi], 0
856
 
857
pu_009:
858
; For debugging, display resulting strings
3564 hidnplayr 859
        DEBUGF  2, "Downloadng %s\n", document_user
3561 hidnplayr 860
 
861
; Look up the ip address, or was it specified?
862
        mov     al, [proxyAddr]
863
        cmp     al, 0
864
        jnz     pu_015
865
        mov     al, [webAddr]
866
pu_015:
867
        cmp     al, '0'
868
        jb      pu_010  ; Resolve address
869
        cmp     al, '9'
870
        ja      pu_010  ; Resolve address
871
 
872
        DEBUGF  1, "GotIP\n"
873
 
874
; Convert address
875
; If proxy is given, get proxy address instead of server
876
        mov     esi, proxyAddr-1
877
        cmp     byte[esi+1], 0
878
        jne     pu_020
879
        mov     esi, webAddr-1
880
 
881
pu_020:
882
        mov     edi, server_ip
883
        xor     eax, eax
884
 
885
ip1:
886
        inc     esi
887
        cmp     [esi], byte '0'
888
        jb      ip2
889
        cmp     [esi], byte '9'
890
        ja      ip2
891
        imul    eax, 10
892
        movzx   ebx, byte [esi]
893
        sub     ebx, 48
894
        add     eax, ebx
895
        jmp     ip1
896
 
897
ip2:
898
        mov     [edi], al
899
        xor     eax, eax
900
        inc     edi
901
        cmp     edi, server_ip+3
902
        jbe     ip1
903
        jmp     pu_011
904
 
905
pu_010:
906
        DEBUGF  1, "Resolving %s\n", webAddr
907
 
908
; resolve name
909
        push    esp     ; reserve stack place
910
        push    esp     ; fourth parameter
911
        push    0       ; third parameter
912
        push    0       ; second parameter
913
        push    webAddr
914
        call    [getaddrinfo]
915
        pop     esi
3564 hidnplayr 916
; TODO: handle error
3561 hidnplayr 917
;        test    eax, eax
918
;        jnz     .fail_dns
919
 
3564 hidnplayr 920
; fill in ip
3561 hidnplayr 921
        mov     eax, [esi + addrinfo.ai_addr]
922
        mov     eax, [eax + sockaddr_in.sin_addr]
923
        mov     [server_ip], eax
924
 
925
        DEBUGF  1, "Resolved to %u.%u.%u.%u\n", [server_ip]:1, [server_ip + 1]:1, [server_ip + 2]:1, [server_ip + 3]:1
926
 
927
pu_011:
928
 
929
        ret
930
 
931
;***************************************************************************
932
;   Function
933
;       load_settings
934
;
935
;   Description
936
;       Load settings from configuration file network.ini
937
;
938
;***************************************************************************
939
load_settings:
940
 
941
        invoke  ini.get_str, inifile, sec_proxy, key_proxy, proxyAddr, 256, proxyAddr
942
        invoke  ini.get_int, inifile, sec_proxy, key_proxyport, 80
943
        mov     [proxyPort], eax
944
        invoke  ini.get_str, inifile, sec_proxy, key_user, proxyUser, 256, proxyUser
945
        invoke  ini.get_str, inifile, sec_proxy, key_password, proxyPassword, 256, proxyPassword
946
 
947
        ret
948
 
949
;***************************************************************************
950
;   Function
951
;       append_proxy_auth_header
952
;
953
;   Description
954
;       Append header to HTTP request for proxy authentification
955
;
956
;***************************************************************************
957
append_proxy_auth_header:
958
        mov     esi, proxy_auth_basic
959
        mov     ecx, proxy_auth_basic_end - proxy_auth_basic
960
        rep     movsb
961
; base64-encode string :
962
        mov     esi, proxyUser
963
 
964
apah000:
965
        lodsb
966
        test    al, al
967
        jz      apah001
968
        call    encode_base64_byte
969
        jmp     apah000
970
 
971
apah001:
972
        mov     al, ':'
973
        call    encode_base64_byte
974
        mov     esi, proxyPassword
975
 
976
apah002:
977
        lodsb
978
        test    al, al
979
        jz      apah003
980
        call    encode_base64_byte
981
        jmp     apah002
982
 
983
apah003:
984
        call    encode_base64_final
985
        ret
986
 
987
encode_base64_byte:
988
        inc     ecx
989
        shl     edx, 8
990
        mov     dl, al
991
        cmp     ecx, 3
992
        je      ebb001
993
        ret
994
 
995
ebb001:
996
        shl     edx, 8
997
        inc     ecx
998
 
999
ebb002:
1000
        rol     edx, 6
1001
        xor     eax, eax
1002
        xchg    al, dl
1003
        mov     al, [base64_table+eax]
1004
        stosb
1005
        loop    ebb002
1006
        ret
1007
 
1008
encode_base64_final:
1009
        mov     al, 0
1010
        test    ecx, ecx
1011
        jz      ebf000
1012
        call    encode_base64_byte
1013
        test    ecx, ecx
1014
        jz      ebf001
1015
        call    encode_base64_byte
1016
        mov     byte [edi-2], '='
1017
 
1018
ebf001:
1019
        mov     byte [edi-1], '='
1020
 
1021
ebf000:
1022
        ret
1023
 
1024
;   *********************************************
1025
;   *******  WINDOW DEFINITIONS AND DRAW ********
1026
;   *********************************************
1027
 
1028
draw_window:
1029
 
1030
        mcall   12, 1
1031
 
1032
        mcall   48, 3, sc, 40 ;get system colors
1033
 
1034
        mov     edx, [sc.work]
1035
        or      edx, 0x34000000
1036
        mcall   0, <50, 370>, <350, 140>, , 0, title   ;draw window
1037
 
1038
        mov     ecx, [sc.work_text]
1039
        or      ecx, 80000000h
1040
        mcall   4, <14, 14>, , type_pls ;"URL:"
1041
 
1042
        edit_boxes_set_sys_color edit1, editboxes_end, sc
1043
        stdcall [edit_box_draw], edit1
1044
 
1045
; RELOAD
1046
        mcall   8, <90, 68>, <54, 16>, 22, [sc.work_button]
1047
; STOP
1048
        mcall   , <166, 50>, <54, 16>, 24
1049
; SAVE
1050
        mcall   , <224, 54>, , 26
1051
; BUTTON TEXT
1052
        mov     ecx, [sc.work_button_text]
1053
        or      ecx, 80000000h
1054
        mcall   4, <102, 59>, , button_text
1055
 
1056
        mcall   12, 2 ; end window redraw
1057
        ret
1058
;-----------------------------------------------------------------------------
1059
; Data area
1060
;-----------------------------------------------------------------------------
1061
align   4
1062
@IMPORT:
1063
 
1064
library libini, 'libini.obj', \
1065
        box_lib, 'box_lib.obj', \
1066
        network, 'network.obj'
1067
 
1068
import  libini, \
1069
        ini.get_str, 'ini_get_str', \
1070
        ini.get_int, 'ini_get_int'
1071
 
1072
import  box_lib, \
1073
        edit_box_draw, 'edit_box', \
1074
        edit_box_key, 'edit_box_key', \
1075
        edit_box_mouse, 'edit_box_mouse'
1076
 
1077
import  network,\
1078
        getaddrinfo,    'getaddrinfo',\
1079
        freeaddrinfo,   'freeaddrinfo',\
1080
        inet_ntoa,      'inet_ntoa'
1081
 
1082
;---------------------------------------------------------------------
1083
fileinfo        dd 2, 0, 0
1084
final_size      dd 0
1085
final_buffer    dd 0
1086
                db '/rd/1/.download', 0
1087
 
1088
body_pos        dd 0
1089
 
1090
buf_size        dd 0
1091
buf_ptr         dd 0
1092
 
1093
deba            dd 0
1094
                db 0
1095
 
1096
;---------------------------------------------------------------------
1097
 
1098
mouse_dd        dd 0
1099
edit1           edit_box 295, 48, 10, 0xffffff, 0xff, 0x80ff, 0, 0x8000, URLMAXLEN, document_user, mouse_dd, ed_focus+ed_always_focus, 7, 7
1100
editboxes_end:
1101
 
1102
;---------------------------------------------------------------------
1103
 
1104
include_debug_strings
1105
 
1106
;---------------------------------------------------------------------
1107
 
1108
type_pls        db 'URL:', 0
1109
button_text     db 'DOWNLOAD     STOP     RESAVE', 0
1110
download_complete db 'File saved as /rd/1/.download', 0
1111
display_from    dd 20
1112
pos             dd 0
1113
pagex           dd 0
1114
pagey           dd 0
1115
pagexs          dd 80
1116
command_on_off  dd 0
1117
text_type       db 1
1118
com2            dd 0
1119
script          dd 0
1120
socketnum       dd 0
1121
 
1122
addr            dd 0
1123
ya              dd 0
1124
len             dd 0
1125
 
1126
title           db 'HTTP Downloader', 0
1127
 
1128
;---------------------------------------------------------------------
1129
s_contentlength db 'Content-Length:'
1130
len_contentlength = 15
1131
 
1132
s_chunked       db 'Transfer-Encoding: chunked'
1133
len_chunked     = $ - s_chunked
1134
 
1135
is_body         dd 0    ; 0 if headers, 1 if content
1136
is_chunked      dd 0
1137
prev_chunk_end  dd 0
1138
cur_chunk_size  dd 0
1139
 
1140
string0:        db 'GET '
1141
 
1142
stringh                 db ' HTTP/1.1', 13, 10, 'Host: '
1143
stringh_end:
1144
proxy_auth_basic        db 13, 10, 'Proxy-Authorization: Basic '
1145
proxy_auth_basic_end:
1146
connclose               db 13, 10, 'User-Agent: Kolibrios Downloader', 13, 10, 'Connection: Close', 13, 10, 13, 10
1147
connclose_end:
1148
 
1149
base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
1150
                db '0123456789+/'
1151
 
1152
inifile         db '/sys/network.ini', 0
1153
 
1154
sec_proxy:
1155
key_proxy       db 'proxy', 0
1156
key_proxyport   db 'port', 0
1157
key_user        db 'user', 0
1158
key_password    db 'password', 0
1159
 
1160
sockaddr1:
1161
                dw AF_INET4
1162
server_port     dw 0x5000       ; 80
1163
server_ip       dd 0
1164
                rb 10
1165
 
1166
proxyPort       dd 80
1167
 
1168
shared_name     dd 0
1169
 
1170
status          dd 0x0
1171
prev_status     dd 0x0
1172
 
1173
onoff           dd 0x0
1174
 
1175
nextupdate      dd 0
1176
winys           dd 400
1177
 
1178
;---------------------------------------------------------------------
1179
document_user   db 'http://', 0
1180
;---------------------------------------------------------------------
1181
IM_END:
1182
;---------------------------------------------------------------------
1183
                rb URLMAXLEN-(IM_END - document_user)
1184
;---------------------------------------------------------------------
1185
                sc system_colors
1186
;---------------------------------------------------------------------
1187
align 4
1188
document        rb URLMAXLEN
1189
;---------------------------------------------------------------------
1190
align 4
1191
webAddr         rb URLMAXLEN+1
1192
;---------------------------------------------------------------------
1193
 
1194
align 4
1195
primary_buf     rb primary_buffer_size
1196
 
1197
params          rb 1024
1198
 
1199
request         rb 256
1200
 
1201
proxyAddr       rb 256
1202
proxyUser       rb 256
1203
proxyPassword   rb 256
1204
 
1205
                rb 4096         ; stack
1206
 
1207
I_END:
1208