Subversion Repositories Kolibri OS

Rev

Rev 3564 | Rev 3572 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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