Subversion Repositories Kolibri OS

Rev

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