Subversion Repositories Kolibri OS

Rev

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