Subversion Repositories Kolibri OS

Rev

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