Subversion Repositories Kolibri OS

Rev

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