Subversion Repositories Kolibri OS

Rev

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