Subversion Repositories Kolibri OS

Rev

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