Subversion Repositories Kolibri OS

Rev

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