Subversion Repositories Kolibri OS

Rev

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