Subversion Repositories Kolibri OS

Rev

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

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