Subversion Repositories Kolibri OS

Rev

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