Subversion Repositories Kolibri OS

Rev

Rev 4207 | Rev 4211 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  HTTP library for KolibriOS                                     ;;
  7. ;;                                                                 ;;
  8. ;;   Written by hidnplayr@kolibrios.org                            ;;
  9. ;;                                                                 ;;
  10. ;;         GNU GENERAL PUBLIC LICENSE                              ;;
  11. ;;          Version 2, June 1991                                   ;;
  12. ;;                                                                 ;;
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14.  
  15. ; references:
  16. ; "HTTP made really easy", http://www.jmarshall.com/easy/http/
  17. ; "Hypertext Transfer Protocol -- HTTP/1.1", http://tools.ietf.org/html/rfc2616
  18.  
  19.  
  20.         URLMAXLEN       = 65535
  21.         BUFFERSIZE      = 4096
  22.         TIMEOUT         = 1000  ; in 1/100 s
  23.  
  24.         __DEBUG__       = 1
  25.         __DEBUG_LEVEL__ = 1
  26.  
  27.  
  28. format MS COFF
  29.  
  30. public @EXPORT as 'EXPORTS'
  31.  
  32. include '../../../struct.inc'
  33. include '../../../proc32.inc'
  34. include '../../../macros.inc'
  35. purge section,mov,add,sub
  36. include '../../../debug-fdo.inc'
  37.  
  38. include '../../../network.inc'
  39. include 'http.inc'
  40.  
  41. virtual at 0
  42.         http_msg http_msg
  43. end virtual
  44.  
  45. macro copy_till_zero {
  46.   @@:
  47.         lodsb
  48.         test    al, al
  49.         jz      @f
  50.         stosb
  51.         jmp     @r
  52.   @@:
  53. }
  54.  
  55. macro HTTP_init_buffer buffer, socketnum {
  56.  
  57.         mov     eax, buffer
  58.         push    socketnum
  59.         popd    [eax + http_msg.socket]
  60.         lea     esi, [eax + http_msg.data]
  61.         mov     [eax + http_msg.flags], FLAG_CONNECTED
  62.         mov     [eax + http_msg.write_ptr], esi
  63.         mov     [eax + http_msg.buffer_length], BUFFERSIZE -  http_msg.data
  64.         mov     [eax + http_msg.chunk_ptr], 0
  65.  
  66.         mov     [eax + http_msg.status], 0
  67.         mov     [eax + http_msg.header_length], 0
  68.         mov     [eax + http_msg.content_length], 0
  69.         mov     [eax + http_msg.content_received], 0
  70.  
  71.         push    eax ebp
  72.         mov     ebp, eax
  73.         mcall   29, 9
  74.         mov     [ebp + http_msg.timestamp], eax
  75.         pop     ebp eax
  76. }
  77.  
  78. section '.flat' code readable align 16
  79.  
  80. ;;===========================================================================;;
  81. lib_init: ;//////////////////////////////////////////////////////////////////;;
  82. ;;---------------------------------------------------------------------------;;
  83. ;? Library entry point (called after library load)                           ;;
  84. ;;---------------------------------------------------------------------------;;
  85. ;> eax = pointer to memory allocation routine                                ;;
  86. ;> ebx = pointer to memory freeing routine                                   ;;
  87. ;> ecx = pointer to memory reallocation routine                              ;;
  88. ;> edx = pointer to library loading routine                                  ;;
  89. ;;---------------------------------------------------------------------------;;
  90. ;< eax = 1 (fail) / 0 (ok)                                                   ;;
  91. ;;===========================================================================;;
  92.         mov     [mem.alloc], eax
  93.         mov     [mem.free], ebx
  94.         mov     [mem.realloc], ecx
  95.         mov     [dll.load], edx
  96.  
  97.         invoke  dll.load, @IMPORT
  98.         test    eax, eax
  99.         jnz     .error
  100.  
  101. ; load proxy settings
  102.         invoke  ini.get_str, inifile, sec_proxy, key_proxy, proxyAddr, 256, proxyAddr
  103.         invoke  ini.get_int, inifile, sec_proxy, key_proxyport, 80
  104.         mov     [proxyPort], eax
  105.         invoke  ini.get_str, inifile, sec_proxy, key_user, proxyUser, 256, proxyUser
  106.         invoke  ini.get_str, inifile, sec_proxy, key_password, proxyPassword, 256, proxyPassword
  107.  
  108.         xor     eax, eax
  109.         ret
  110.  
  111.   .error:
  112.         xor     eax, eax
  113.         inc     eax
  114.  
  115.         ret
  116.  
  117.  
  118.  
  119.  
  120. ;;================================================================================================;;
  121. proc HTTP_get URL ;///////////////////////////////////////////////////////////////////////////////;;
  122. ;;------------------------------------------------------------------------------------------------;;
  123. ;? Initiates a HTTP connection, using 'GET' method.                                               ;;
  124. ;;------------------------------------------------------------------------------------------------;;
  125. ;> URL = pointer to ASCIIZ URL                                                                    ;;
  126. ;;------------------------------------------------------------------------------------------------;;
  127. ;< eax = 0 (error) / buffer ptr                                                                   ;;
  128. ;;================================================================================================;;
  129. locals
  130.         hostname        dd ?
  131.         pageaddr        dd ?
  132.         sockaddr        dd ?
  133.         socketnum       dd ?
  134.         buffer          dd ?
  135.         port            dd ?
  136. endl
  137.  
  138. ; split the URL into hostname and pageaddr
  139.         stdcall parse_url, [URL]
  140.         test    eax, eax
  141.         jz      .error
  142.         mov     [hostname], eax
  143.         mov     [pageaddr], ebx
  144.  
  145. ; Do we need to use a proxy?
  146.         cmp     [proxyAddr], 0
  147.         jne     .proxy_done
  148.  
  149.   .proxy_done:
  150.  
  151. ;;;;
  152.         mov     [port], 80      ;;;; FIXME
  153.  
  154. ; Connect to the other side.
  155.         stdcall open_connection, [hostname], [port]
  156.         test    eax, eax
  157.         jz      .error
  158.         mov     [socketnum], eax
  159.  
  160. ; Create the HTTP request.
  161.         invoke  mem.alloc, BUFFERSIZE
  162.         test    eax, eax
  163.         jz      .error
  164.         mov     [buffer], eax
  165.         mov     edi, eax
  166.         DEBUGF  1, "Buffer has been allocated.\n"
  167.  
  168.         mov     esi, str_get
  169.         copy_till_zero
  170.  
  171.         mov     esi, [pageaddr]
  172.         copy_till_zero
  173.  
  174.         mov     esi, str_http11
  175.         mov     ecx, str_http11.length
  176.         rep     movsb
  177.  
  178.         mov     esi, [hostname]
  179.         copy_till_zero
  180.  
  181.         mov     esi, str_close
  182.         mov     ecx, str_close.length
  183.         rep     movsb
  184.  
  185.         mov     byte[edi], 0
  186.         DEBUGF  1, "Request:\n%s", [buffer]
  187.  
  188. ; Send the request
  189.         mov     esi, edi
  190.         sub     esi, [buffer]   ; length
  191.         xor     edi, edi        ; flags
  192.  
  193.         mcall   send, [socketnum], [buffer]
  194.         test    eax, eax
  195.         jz      .error
  196.         DEBUGF  1, "Request has been sent to server.\n"
  197.  
  198.         HTTP_init_buffer [buffer], [socketnum]
  199.  
  200.         ret                     ; return buffer ptr
  201.  
  202.   .error:
  203.         DEBUGF  1, "Error!\n"
  204.         xor     eax, eax        ; return 0 = error
  205.         ret
  206.  
  207. endp
  208.  
  209.  
  210.  
  211. ;;================================================================================================;;
  212. proc HTTP_head URL ;//////////////////////////////////////////////////////////////////////////////;;
  213. ;;------------------------------------------------------------------------------------------------;;
  214. ;? Initiates a HTTP connection, using 'HEAD' method.                                              ;;
  215. ;;------------------------------------------------------------------------------------------------;;
  216. ;> URL = pointer to ASCIIZ URL                                                                    ;;
  217. ;;------------------------------------------------------------------------------------------------;;
  218. ;< eax = 0 (error) / buffer ptr                                                                   ;;
  219. ;;================================================================================================;;
  220. locals
  221.         hostname        dd ?
  222.         pageaddr        dd ?
  223.         sockaddr        dd ?
  224.         socketnum       dd ?
  225.         buffer          dd ?
  226.         port            dd ?
  227. endl
  228.  
  229. ; split the URL into hostname and pageaddr
  230.         stdcall parse_url, [URL]
  231.         test    eax, eax
  232.         jz      .error
  233.         mov     [hostname], eax
  234.         mov     [pageaddr], ebx
  235.  
  236. ; Do we need to use a proxy?
  237.         cmp     [proxyAddr], 0
  238.         jne     .proxy_done
  239.  
  240.         ; TODO: set hostname to that of the
  241.   .proxy_done:
  242.  
  243. ;;;;
  244.         mov     [port], 80      ;;;; FIXME
  245.  
  246. ; Connect to the other side.
  247.         stdcall open_connection, [hostname], [port]
  248.         test    eax, eax
  249.         jz      .error
  250.         mov     [socketnum], eax
  251.  
  252. ; Create the HTTP request.
  253.         invoke  mem.alloc, BUFFERSIZE
  254.         test    eax, eax
  255.         jz      .error
  256.         mov     [buffer], eax
  257.         mov     edi, eax
  258.         DEBUGF  1, "Buffer has been allocated.\n"
  259.  
  260.         mov     esi, str_head
  261.         copy_till_zero
  262.  
  263.         mov     esi, [pageaddr]
  264.         copy_till_zero
  265.  
  266.         mov     esi, str_http11
  267.         mov     ecx, str_http11.length
  268.         rep     movsb
  269.  
  270.         mov     esi, [hostname]
  271.         copy_till_zero
  272.  
  273.         mov     esi, str_close
  274.         mov     ecx, str_close.length
  275.         rep     movsb
  276.  
  277.         mov     byte[edi], 0
  278.         DEBUGF  1, "Request:\n%s", [buffer]
  279.  
  280. ; Send the request
  281.         mov     esi, edi
  282.         sub     esi, [buffer]   ; length
  283.         xor     edi, edi        ; flags
  284.  
  285.         mcall   send, [socketnum], [buffer]
  286.         test    eax, eax
  287.         jz      .error
  288.         DEBUGF  1, "Request has been sent to server.\n"
  289.  
  290.         HTTP_init_buffer [buffer], [socketnum]
  291.  
  292.         ret                     ; return buffer ptr
  293.  
  294.   .error:
  295.         DEBUGF  1, "Error!\n"
  296.         xor     eax, eax        ; return 0 = error
  297.         ret
  298.  
  299. endp
  300.  
  301.  
  302. ;;================================================================================================;;
  303. proc HTTP_post URL, content_type, content_length ;////////////////////////////////////////////////;;
  304. ;;------------------------------------------------------------------------------------------------;;
  305. ;? Initiates a HTTP connection, using 'GET' method.                                               ;;
  306. ;;------------------------------------------------------------------------------------------------;;
  307. ;> URL                  = pointer to ASCIIZ URL                                                   ;;
  308. ;> content_type         = pointer to ASCIIZ string containing content type                        ;;
  309. ;> content_length       = length of content (in bytes)                                            ;;
  310. ;;------------------------------------------------------------------------------------------------;;
  311. ;< eax = 0 (error) / buffer ptr                                                                   ;;
  312. ;;================================================================================================;;
  313. locals
  314.         hostname        dd ?
  315.         pageaddr        dd ?
  316.         sockaddr        dd ?
  317.         socketnum       dd ?
  318.         buffer          dd ?
  319.         port            dd ?
  320. endl
  321.  
  322. ; split the URL into hostname and pageaddr
  323.         stdcall parse_url, [URL]
  324.         test    eax, eax
  325.         jz      .error
  326.         mov     [hostname], eax
  327.         mov     [pageaddr], ebx
  328.  
  329. ; Do we need to use a proxy?
  330.         cmp     [proxyAddr], 0
  331.         jne     .proxy_done
  332.  
  333.         ; TODO: set hostname to that of the
  334.   .proxy_done:
  335.  
  336. ;;;;
  337.         mov     [port], 80      ;;;; FIXME
  338.  
  339. ; Connect to the other side.
  340.         stdcall open_connection, [hostname], [port]
  341.         test    eax, eax
  342.         jz      .error
  343.         mov     [socketnum], eax
  344.  
  345. ; Create the HTTP request.
  346.         invoke  mem.alloc, BUFFERSIZE
  347.         test    eax, eax
  348.         jz      .error
  349.         mov     [buffer], eax
  350.         mov     edi, eax
  351.         DEBUGF  1, "Buffer has been allocated.\n"
  352.  
  353.         mov     esi, str_post
  354.         copy_till_zero
  355.  
  356.         mov     esi, [pageaddr]
  357.         copy_till_zero
  358.  
  359.         mov     esi, str_http11
  360.         mov     ecx, str_http11.length
  361.         rep     movsb
  362.  
  363.         mov     esi, [hostname]
  364.         copy_till_zero
  365.  
  366.         mov     esi, str_post_cl
  367.         mov     ecx, str_post_cl.length
  368.         rep     movsb
  369.  
  370.         mov     eax, [content_length]
  371.         call    ascii_dec
  372.  
  373.         mov     esi, str_post_ct
  374.         mov     ecx, str_post_ct.length
  375.         rep     movsb
  376.  
  377.         mov     esi, [content_type]
  378.         rep     movsb
  379.  
  380.         mov     esi, str_close
  381.         mov     ecx, str_close.length
  382.         rep     movsb
  383.  
  384.         mov     byte[edi], 0
  385.         DEBUGF  1, "Request:\n%s", [buffer]
  386.  
  387. ; Send the request
  388.         mov     esi, edi
  389.         sub     esi, [buffer]   ; length
  390.         xor     edi, edi        ; flags
  391.         mcall   send, [socketnum], [buffer]
  392.         test    eax, eax
  393.         jz      .error
  394.         DEBUGF  1, "Request has been sent to server.\n"
  395.  
  396.         HTTP_init_buffer [buffer], [socketnum]
  397.  
  398. ;        mov     eax, [buffer]
  399.  
  400.         ret                     ; return buffer ptr
  401.  
  402.   .error:
  403.         DEBUGF  1, "Error!\n"
  404.         xor     eax, eax        ; return 0 = error
  405.         ret
  406.  
  407. endp
  408.  
  409.  
  410.  
  411. ;;================================================================================================;;
  412. proc HTTP_process identifier ;////////////////////////////////////////////////////////////////////;;
  413. ;;------------------------------------------------------------------------------------------------;;
  414. ;? Receive data from the server, parse headers and put data in receive buffer.                    ;;
  415. ;? To complete a transfer, this procedure must be called over and over again untill it returns 0. ;;
  416. ;;------------------------------------------------------------------------------------------------;;
  417. ;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
  418. ;;------------------------------------------------------------------------------------------------;;
  419. ;< eax = -1 (not finished) / 0 finished                                                           ;;
  420. ;;================================================================================================;;
  421.         pusha
  422.         mov     ebp, [identifier]
  423.  
  424. ; If the connection is closed, return immediately
  425.         test    [ebp + http_msg.flags], FLAG_CONNECTED
  426.         jz      .connection_closed
  427.  
  428. ; Receive some data
  429.         mcall   recv, [ebp + http_msg.socket], [ebp + http_msg.write_ptr], \
  430.                       [ebp + http_msg.buffer_length], MSG_DONTWAIT
  431.         cmp     eax, 0xffffffff
  432.         je      .check_socket
  433.         DEBUGF  1, "Received %u bytes\n", eax
  434.  
  435. ; Update timestamp
  436.         push    eax
  437.         mcall   29, 9
  438.         mov     [ebp + http_msg.timestamp], eax
  439.         pop     eax
  440.  
  441. ; Update pointers
  442.         mov     edi, [ebp + http_msg.write_ptr]
  443.         add     [ebp + http_msg.write_ptr], eax
  444.         sub     [ebp + http_msg.buffer_length], eax
  445.         jz      .got_all_data
  446.  
  447. ; If data is chunked, combine chunks into contiguous data.
  448.         test    [ebp + http_msg.flags], FLAG_CHUNKED
  449.         jnz     .chunk_loop
  450.  
  451. ; Did we detect the header yet?
  452.         test    [ebp + http_msg.flags], FLAG_GOT_HEADER
  453.         jnz     .header_parsed
  454.  
  455.         push    eax
  456.  
  457. ; We havent found the header yet, search for it..
  458.         sub     eax, 4
  459.         jl      .need_more_data_pop
  460.         inc     eax
  461.   .scan:
  462.         ; scan for end of header (empty line)
  463.         cmp     dword[edi], 0x0a0d0a0d                  ; end of header
  464.         je      .end_of_header
  465.         cmp     word[edi+2], 0x0a0a
  466.         je      .end_of_header
  467.         inc     edi
  468.         dec     eax
  469.         jnz     .scan
  470.         jmp     .need_more_data_pop
  471.  
  472.   .end_of_header:
  473.         add     edi, 4 - http_msg.data
  474.         sub     edi, ebp
  475.         mov     [ebp + http_msg.header_length], edi
  476.         or      [ebp + http_msg.flags], FLAG_GOT_HEADER
  477.         DEBUGF  1, "Header length: %u\n", edi
  478.  
  479. ; Ok, we have found header:
  480.         cmp     dword[ebp + http_msg.data], 'HTTP'
  481.         jne     .invalid_header
  482.         cmp     dword[ebp + http_msg.data+4], '/1.0'
  483.         je      .http_1.0
  484.         cmp     dword[ebp + http_msg.data+4], '/1.1'
  485.         jne     .invalid_header
  486.         or      [ebp + http_msg.flags], FLAG_HTTP11
  487.   .http_1.0:
  488.         cmp     byte[ebp + http_msg.data+8], ' '
  489.         jne     .invalid_header
  490.         DEBUGF  1, "Header seems valid.\n"
  491.  
  492.         lea     esi, [ebp + http_msg.data+9]
  493.         xor     eax, eax
  494.         xor     ebx, ebx
  495.         mov     ecx, 3
  496.   .statusloop:
  497.         lodsb
  498.         sub     al, '0'
  499.         jb      .invalid_header
  500.         cmp     al, 9
  501.         ja      .invalid_header
  502.         lea     ebx, [ebx + 4*ebx]
  503.         shl     ebx, 1
  504.         add     ebx, eax
  505.         dec     ecx
  506.         jnz     .statusloop
  507.         mov     [ebp + http_msg.status], ebx
  508.         DEBUGF  1, "Status: %u\n", ebx
  509.  
  510. ; Now, convert all header names to lowercase.
  511. ; This way, it will be much easier to find certain header fields, later on.
  512.  
  513.         lea     esi, [ebp + http_msg.data]
  514.         mov     ecx, [ebp + http_msg.header_length]
  515.   .need_newline:
  516.         inc     esi
  517.         dec     ecx
  518.         jz      .convert_done
  519.         cmp     byte[esi], 10
  520.         jne     .need_newline
  521. ; Ok, we have a newline, a line beginning with space or tabs has no header fields.
  522.  
  523.         inc     esi
  524.         dec     ecx
  525.         jz      .convert_done
  526.         cmp     byte[esi], ' '
  527.         je      .need_newline
  528.         cmp     byte[esi], 9    ; horizontal tab
  529.         je      .need_newline
  530.         jmp     .convert_loop
  531.   .next_char:
  532.         inc     esi
  533.         dec     ecx
  534.         jz      .convert_done
  535.   .convert_loop:
  536.         cmp     byte[esi], ':'
  537.         je      .need_newline
  538.         cmp     byte[esi], 'A'
  539.         jb      .next_char
  540.         cmp     byte[esi], 'Z'
  541.         ja      .next_char
  542.         or      byte[esi], 0x20 ; convert to lowercase
  543.         jmp     .next_char
  544.   .convert_done:
  545.         mov     byte[esi-1], 0
  546.         lea     esi, [ebp + http_msg.data]
  547.         DEBUGF  1, "Header names converted to lowercase:\n%s\n", esi
  548.  
  549. ; Check for content-length header field.
  550.         stdcall find_header_field, ebp, str_cl
  551.         test    eax, eax
  552.         jz      .no_content
  553.         or      [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
  554.  
  555.         xor     edx, edx
  556.   .cl_loop:
  557.         movzx   ebx, byte[eax]
  558.         inc     eax
  559.         cmp     bl, 10
  560.         je      .cl_ok
  561.         cmp     bl, 13
  562.         je      .cl_ok
  563.         cmp     bl, ' '
  564.         je      .cl_ok
  565.         sub     bl, '0'
  566.         jb      .invalid_header
  567.         cmp     bl, 9
  568.         ja      .invalid_header
  569.         lea     edx, [edx + edx*4]      ; edx = edx*10
  570.         shl     edx, 1                  ;
  571.         add     edx, ebx
  572.         jmp     .cl_loop
  573.  
  574.   .cl_ok:
  575.         mov     [ebp + http_msg.content_length], edx
  576.         DEBUGF  1, "Content-length: %u\n", edx
  577.  
  578. ; Resize buffer according to content-length.
  579.         add     edx, [ebp + http_msg.header_length]
  580.         add     edx, http_msg.data
  581.  
  582.         mov     ecx, edx
  583.         sub     ecx, [ebp + http_msg.write_ptr]
  584.         mov     [ebp + http_msg.buffer_length], ecx
  585.  
  586.         invoke  mem.realloc, ebp, edx
  587.         or      eax, eax
  588.         jz      .no_ram_pop
  589.  
  590.         pop     eax
  591.         sub     eax, [ebp + http_msg.header_length]
  592.         jmp     .header_parsed  ; hooray!
  593.  
  594.   .no_content:
  595.         DEBUGF  1, "Content-length not found.\n"
  596.  
  597. ; We didnt find 'content-length', maybe server is using chunked transfer encoding?
  598. ; Try to find 'transfer-encoding' header.
  599.         stdcall find_header_field, ebp, str_te
  600.         test    eax, eax
  601.         jz      .invalid_header
  602.  
  603.         mov     ebx, dword[eax]
  604.         or      ebx, 0x20202020
  605.         cmp     ebx, 'chun'
  606.         jne     .invalid_header
  607.         mov     ebx, dword[eax+4]
  608.         or      ebx, 0x00202020
  609.         and     ebx, 0x00ffffff
  610.         cmp     ebx, 'ked'
  611.         jne     .invalid_header
  612.  
  613.         or      [ebp + http_msg.flags], FLAG_CHUNKED
  614.         DEBUGF  1, "Transfer type is: chunked\n"
  615.  
  616.         pop     eax
  617.  
  618. ; Set chunk pointer where first chunk should begin.
  619.         lea     eax, [ebp + http_msg.data]
  620.         add     eax, [ebp + http_msg.header_length]
  621.         mov     [ebp + http_msg.chunk_ptr], eax
  622.  
  623.   .chunk_loop:
  624.         mov     ecx, [ebp + http_msg.write_ptr]
  625.         sub     ecx, [ebp + http_msg.chunk_ptr]
  626.         jb      .need_more_data_chunked         ; TODO: use this ecx !!!
  627.  
  628. ; Chunkline starts here, convert the ASCII hex number into ebx
  629.         mov     esi, [ebp + http_msg.chunk_ptr]
  630.         xor     ebx, ebx
  631.   .chunk_hexloop:
  632.         lodsb
  633.         sub     al, '0'
  634.         jb      .chunk_
  635.         cmp     al, 9
  636.         jbe     .chunk_hex
  637.         sub     al, 'A' - '0' - 10
  638.         jb      .chunk_
  639.         cmp     al, 15
  640.         jbe     .chunk_hex
  641.         sub     al, 'a' - 'A'
  642.         cmp     al, 15
  643.         ja      .chunk_
  644.   .chunk_hex:
  645.         shl     ebx, 4
  646.         add     bl, al
  647.         jmp     .chunk_hexloop
  648.   .chunk_:
  649.         DEBUGF  1, "got chunk of %u bytes\n", ebx
  650. ;;        cmp     esi, [ebp + http_msg.chunk_ptr]
  651. ;;        je
  652. ; If chunk size is 0, all chunks have been received.
  653.         test    ebx, ebx
  654.         jz      .got_all_data_chunked           ; last chunk, hooray! FIXME: what if it wasnt a valid hex number???
  655.  
  656. ; Chunkline ends with a CR, LF or simply LF
  657.   .end_of_chunkline?:
  658.         cmp     al, 10
  659.         je      .end_of_chunkline
  660.         lodsb
  661.         cmp     edi, [ebp + http_msg.write_ptr]
  662.         jb      .end_of_chunkline?
  663.         jmp     .need_more_data
  664.  
  665.   .end_of_chunkline:
  666. ; Update chunk ptr, and remember old one
  667.         mov     edi, [ebp + http_msg.chunk_ptr]
  668.         add     [ebp + http_msg.chunk_ptr], ebx
  669. ; Realloc buffer, make it 'chunksize' bigger.
  670.         mov     eax, [ebp + http_msg.buffer_length]
  671.         add     eax, ebx
  672.         invoke  mem.realloc, ebp, eax
  673.         or      eax, eax
  674.         jz      .no_ram
  675.         add     [ebp + http_msg.buffer_length], ebx
  676.  
  677. ; Update write ptr
  678.         mov     eax, esi
  679.         sub     eax, edi
  680.         sub     [ebp + http_msg.write_ptr], eax
  681.  
  682. ; Now move all received data to the left (remove chunk header).
  683. ; Update content_length accordingly.
  684.         mov     ecx, [ebp + http_msg.write_ptr]
  685.         sub     ecx, esi
  686.         add     [ebp + http_msg.content_received], ecx
  687.         rep     movsb
  688.         jmp     .chunk_loop
  689.  
  690. ; Check if we got all the data.
  691.   .header_parsed:
  692.         add     [ebp + http_msg.content_received], eax
  693.         mov     eax, [ebp + http_msg.content_length]
  694.         cmp     eax, [ebp + http_msg.content_received]
  695.         jae     .got_all_data
  696.         jmp     .need_more_data
  697.   .need_more_data_pop:
  698.         pop     eax
  699.   .need_more_data:
  700.         popa
  701.         xor     eax, eax
  702.         dec     eax
  703.         ret
  704.  
  705.   .need_more_data_chunked:
  706.         add     [ebp + http_msg.content_received], eax
  707.         popa
  708.         xor     eax, eax
  709.         dec     eax
  710.         ret
  711.  
  712.   .got_all_data_chunked:
  713.         mov     eax, [ebp + http_msg.chunk_ptr]
  714.         sub     eax, [ebp + http_msg.header_length]
  715.         sub     eax, http_msg.data
  716.         sub     eax, ebp
  717.         mov     [ebp + http_msg.content_length], eax
  718.         mov     [ebp + http_msg.content_received], eax
  719.   .got_all_data:
  720.         DEBUGF  1, "We got all the data! (%u bytes)\n", [ebp + http_msg.content_length]
  721.         or      [ebp + http_msg.flags], FLAG_GOT_ALL_DATA
  722.         and     [ebp + http_msg.flags], not FLAG_CONNECTED
  723.         mcall   close, [ebp + http_msg.socket]
  724.         popa
  725.         xor     eax, eax
  726.         ret
  727.  
  728.   .check_socket:
  729.         cmp     ebx, EWOULDBLOCK
  730.         jne     .socket_error
  731.  
  732.         mcall   29, 9
  733.         sub     eax, TIMEOUT
  734.         cmp     eax, [ebp + http_msg.timestamp]
  735.         jb      .need_more_data
  736.         DEBUGF  1, "ERROR: timeout\n"
  737.         or      [ebp + http_msg.flags], FLAG_TIMEOUT_ERROR
  738.         jmp     .disconnect
  739.  
  740.   .invalid_header:
  741.         pop     eax
  742.         DEBUGF  1, "ERROR: invalid header\n"
  743.         or      [ebp + http_msg.flags], FLAG_INVALID_HEADER
  744.         jmp     .disconnect
  745.  
  746.   .no_ram_pop:
  747.         pop     eax
  748.   .no_ram:
  749.         DEBUGF  1, "ERROR: out of RAM\n"
  750.         or      [ebp + http_msg.flags], FLAG_NO_RAM
  751.         jmp     .disconnect
  752.  
  753.   .socket_error:
  754.         DEBUGF  1, "ERROR: socket error %u\n", ebx
  755.         or      [ebp + http_msg.flags], FLAG_SOCKET_ERROR
  756.   .disconnect:
  757.         and     [ebp + http_msg.flags], not FLAG_CONNECTED
  758.         mcall   close, [ebp + http_msg.socket]
  759.   .connection_closed:
  760.         popa
  761.         xor     eax, eax
  762.         ret
  763.  
  764. endp
  765.  
  766.  
  767.  
  768.  
  769. ;;================================================================================================;;
  770. proc HTTP_free identifier ;///////////////////////////////////////////////////////////////////////;;
  771. ;;------------------------------------------------------------------------------------------------;;
  772. ;? Free the http_msg structure                                                                    ;;
  773. ;;------------------------------------------------------------------------------------------------;;
  774. ;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
  775. ;;------------------------------------------------------------------------------------------------;;
  776. ;< none                                                                                           ;;
  777. ;;================================================================================================;;
  778.  
  779.         pusha
  780.         mov     ebp, [identifier]
  781.  
  782.         test    [ebp + http_msg.flags], FLAG_CONNECTED
  783.         jz      .not_connected
  784.  
  785.         and     [ebp + http_msg.flags], not FLAG_CONNECTED
  786.         mcall   close, [ebp + http_msg.socket]
  787.  
  788.   .not_connected:
  789.         invoke  mem.free, ebp
  790.  
  791.         popa
  792.         ret
  793.  
  794. endp
  795.  
  796.  
  797.  
  798. ;;================================================================================================;;
  799. proc HTTP_stop identifier ;///////////////////////////////////////////////////////////////////////;;
  800. ;;------------------------------------------------------------------------------------------------;;
  801. ;? Stops the open connection                                                                      ;;
  802. ;;------------------------------------------------------------------------------------------------;;
  803. ;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
  804. ;;------------------------------------------------------------------------------------------------;;
  805. ;< none                                                                                           ;;
  806. ;;================================================================================================;;
  807.  
  808.         pusha
  809.         mov     ebp, [identifier]
  810.  
  811.         and     [ebp + http_msg.flags], not FLAG_CONNECTED
  812.         mcall   close, [ebp + http_msg.socket]
  813.  
  814.         popa
  815.         ret
  816.  
  817. endp
  818.  
  819.  
  820.  
  821. ;;================================================================================================;;
  822. proc find_header_field identifier, headername ;///////////////////////////////////////////////////;;
  823. ;;------------------------------------------------------------------------------------------------;;
  824. ;? Find a header field in the received HTTP header                                                ;;
  825. ;;------------------------------------------------------------------------------------------------;;
  826. ;> identifier   = ptr to http_msg struct                                                          ;;
  827. ;> headername   = ptr to ASCIIZ string containg field you want to find (must be in lowercase)     ;;
  828. ;;------------------------------------------------------------------------------------------------;;
  829. ;< eax = 0 (error) / ptr to content of the HTTP header field                                      ;;
  830. ;;================================================================================================;;
  831.         push    ebx ecx edx esi edi
  832.  
  833.         DEBUGF  1, "Find header field: %s\n", [headername]
  834.  
  835.         mov     ebx, [identifier]
  836.         test    [ebx + http_msg.flags], FLAG_GOT_HEADER
  837.         jz      .fail
  838.  
  839.         lea     edx, [ebx + http_msg.data]
  840.         mov     ecx, edx
  841.         add     ecx, [ebx + http_msg.header_length]
  842.  
  843.   .restart:
  844.         mov     esi, [headername]
  845.         mov     edi, edx
  846.   .loop:
  847.         cmp     edi, ecx
  848.         jae     .fail
  849.         lodsb
  850.         scasb
  851.         je      .loop
  852.         test    al, al
  853.         jz      .done?
  854.   .next:
  855.         inc     edx
  856.         jmp     .restart
  857.  
  858.   .not_done:
  859.         inc     edi
  860.   .done?:
  861.         cmp     byte[edi-1], ':'
  862.         je      .almost_done
  863.         cmp     byte[edi-1], ' '
  864.         je      .not_done
  865.         cmp     byte[edi-1], 9  ; tab
  866.         je      .not_done
  867.  
  868.         jmp     .next
  869.  
  870.   .almost_done:                 ; FIXME: buffer overflow?
  871.         dec     edi
  872.         DEBUGF  1, "Found header field\n"
  873.   .spaceloop:
  874.         inc     edi
  875.         cmp     byte[edi], ' '
  876.         je      .spaceloop
  877.         cmp     byte[edi], 9    ; tab
  878.         je      .spaceloop
  879.  
  880.         mov     eax, edi
  881.         pop     edi esi edx ecx ebx
  882.         ret
  883.  
  884.   .fail:
  885.         pop     edi esi edx ecx ebx
  886.         xor     eax, eax
  887.         ret
  888.  
  889. endp
  890.  
  891.  
  892.  
  893. ;;================================================================================================;;
  894. proc URI_escape URI ;/////////////////////////////////////////////////////////////////////////////;;
  895. ;;------------------------------------------------------------------------------------------------;;
  896. ;?                                                                                                ;;
  897. ;;------------------------------------------------------------------------------------------------;;
  898. ;> URI = ptr to ASCIIZ URI                                                                        ;;
  899. ;;------------------------------------------------------------------------------------------------;;
  900. ;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
  901. ;;================================================================================================;;
  902.  
  903.         pusha
  904.  
  905.         invoke  mem.alloc, URLMAXLEN
  906.         test    eax, eax
  907.         jz      .error
  908.         mov     [esp + 7 * 4], eax              ; return ptr in eax
  909.         mov     esi, [URI]
  910.         mov     edi, eax
  911.         xor     ebx, ebx
  912.         xor     ecx, ecx
  913.   .loop:
  914.         lodsb
  915.         test    al, al
  916.         jz      .done
  917.  
  918.         mov     cl, al
  919.         and     cl, 0x1f
  920.         mov     bl, al
  921.         shr     bl, 5
  922.         bt      dword[bits_must_escape + ebx], ecx
  923.         jc      .escape
  924.  
  925.         stosb
  926.         jmp     .loop
  927.  
  928.   .escape:
  929.         mov     al, '%'
  930.         stosb
  931.         mov     bl, byte[esi-1]
  932.         shr     bl, 4
  933.         mov     al, byte[str_hex + ebx]
  934.         stosb
  935.         mov     bl, byte[esi-1]
  936.         and     bl, 0x0f
  937.         mov     al, byte[str_hex + ebx]
  938.         stosb
  939.         jmp     .loop
  940.  
  941.  
  942.   .done:
  943.         stosb
  944.  
  945.         popa
  946.         ret
  947.  
  948.   .error:
  949.         popa
  950.         xor     eax, eax
  951.         ret
  952.  
  953. endp
  954.  
  955.  
  956.  
  957. ;;================================================================================================;;
  958. proc URI_unescape URI ;///////////////////////////////////////////////////////////////////////////;;
  959. ;;------------------------------------------------------------------------------------------------;;
  960. ;?                                                                                                ;;
  961. ;;------------------------------------------------------------------------------------------------;;
  962. ;> URI = ptr to ASCIIZ URI                                                                        ;;
  963. ;;------------------------------------------------------------------------------------------------;;
  964. ;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
  965. ;;================================================================================================;;
  966.  
  967.         pusha
  968.  
  969.         invoke  mem.alloc, URLMAXLEN
  970.         test    eax, eax
  971.         jz      .error
  972.         mov     [esp + 7 * 4], eax              ; return ptr in eax
  973.         mov     esi, [URI]
  974.         mov     edi, eax
  975.   .loop:
  976.         lodsb
  977.         test    al, al
  978.         jz      .done
  979.  
  980.         cmp     al, '%'
  981.         je      .unescape
  982.  
  983.         stosb
  984.         jmp     .loop
  985.  
  986.   .unescape:
  987.         xor     ebx, ebx
  988.         xor     ecx, ecx
  989.   .unescape_nibble:
  990.         lodsb
  991.         sub     al, '0'
  992.         jb      .fail
  993.         cmp     al, 9
  994.         jbe     .nibble_ok
  995.         sub     al, 'A' - '0' - 10
  996.         jb      .fail
  997.         cmp     al, 15
  998.         jbe     .nibble_ok
  999.         sub     al, 'a' - 'A'
  1000.         cmp     al, 15
  1001.         ja      .fail
  1002.   .nibble_ok:
  1003.         shl     bl, 8
  1004.         or      bl, al
  1005.         dec     ecx
  1006.         jc      .unescape_nibble
  1007.         mov     al, bl
  1008.         stosb
  1009.         jmp     .loop
  1010.  
  1011.   .fail:
  1012.         DEBUGF  1, "ERROR: invalid URI!\n"
  1013.         jmp     .loop
  1014.  
  1015.   .done:
  1016.         stosb
  1017.  
  1018.         popa
  1019.         ret
  1020.  
  1021.   .error:
  1022.         popa
  1023.         xor     eax, eax
  1024.         ret
  1025.  
  1026. endp
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032. ;;================================================================================================;;
  1033. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1034. ;;================================================================================================;;
  1035. ;! Internal procedures section                                                                    ;;
  1036. ;;================================================================================================;;
  1037. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1038. ;;================================================================================================;;
  1039.  
  1040.  
  1041.  
  1042.  
  1043. ;;================================================================================================;;
  1044. proc open_connection hostname, port ;/////////////////////////////////////////////////////////////;;
  1045. ;;------------------------------------------------------------------------------------------------;;
  1046. ;? Connects to a HTTP server                                                                      ;;
  1047. ;;------------------------------------------------------------------------------------------------;;
  1048. ;> hostname     = ptr to ASCIIZ hostname                                                          ;;
  1049. ;> port         = port (x86 byte order)                                                           ;;
  1050. ;;------------------------------------------------------------------------------------------------;;
  1051. ;< eax = 0 (error) / socketnum                                                                    ;;
  1052. ;;================================================================================================;;
  1053.  
  1054. locals
  1055.         sockaddr        dd ?
  1056.         socketnum       dd ?
  1057. endl
  1058.  
  1059. ; Resolve the hostname
  1060.         DEBUGF  1, "Resolving hostname\n"
  1061.         push    esp     ; reserve stack place
  1062.         push    esp     ; fourth parameter
  1063.         push    0       ; third parameter
  1064.         push    0       ; second parameter
  1065.         push    [hostname]
  1066.         call    [getaddrinfo]
  1067.         pop     esi
  1068.         test    eax, eax
  1069.         jnz     .error1
  1070.  
  1071. ; getaddrinfo returns addrinfo struct, make the pointer to sockaddr struct
  1072.         mov     esi, [esi + addrinfo.ai_addr]
  1073.         mov     [sockaddr], esi
  1074.         mov     eax, [esi + sockaddr_in.sin_addr]
  1075.         test    eax, eax
  1076.         jz      .error2
  1077.  
  1078.         DEBUGF  1, "Server ip=%u.%u.%u.%u\n", \
  1079.         [esi + sockaddr_in.sin_addr]:1, [esi + sockaddr_in.sin_addr + 1]:1, \
  1080.         [esi + sockaddr_in.sin_addr + 2]:1, [esi + sockaddr_in.sin_addr + 3]:1
  1081.  
  1082.         mov     [esi + sockaddr_in.sin_family], AF_INET4
  1083.         mov     eax, [port]
  1084.         xchg    al, ah
  1085.         mov     [esi + sockaddr_in.sin_port], ax
  1086.  
  1087. ; Connect to the server.
  1088.         mcall   socket, AF_INET4, SOCK_STREAM, 0
  1089.         test    eax, eax
  1090.         jz      .error2
  1091.         mov     [socketnum], eax
  1092.         DEBUGF  1, "Socket: 0x%x\n", eax
  1093.  
  1094.         mcall   connect, [socketnum], [sockaddr], 18
  1095.         test    eax, eax
  1096.         jnz     .error2
  1097.         DEBUGF  1, "Socket is now connected.\n"
  1098.  
  1099. ; free allocated memory
  1100.         push    [sockaddr]
  1101.         call    [freeaddrinfo]
  1102.  
  1103.         mov     eax, [socketnum]
  1104.         ret
  1105.  
  1106.   .error2:
  1107.  
  1108. ; free allocated memory
  1109.         push    [sockaddr]
  1110.         call    [freeaddrinfo]
  1111.  
  1112.   .error1:
  1113.         xor     eax, eax
  1114.         ret
  1115.  
  1116. endp
  1117.  
  1118.  
  1119. ;;================================================================================================;;
  1120. proc parse_url URL ;//////////////////////////////////////////////////////////////////////////////;;
  1121. ;;------------------------------------------------------------------------------------------------;;
  1122. ;? Split a given URL into hostname and pageaddr                                                   ;;
  1123. ;;------------------------------------------------------------------------------------------------;;
  1124. ;> URL = ptr to ASCIIZ URL                                                                        ;;
  1125. ;;------------------------------------------------------------------------------------------------;;
  1126. ;< eax = 0 (error) / ptr to ASCIIZ hostname                                                       ;;
  1127. ;< ebx = ptr to ASCIIZ pageaddr                                                                   ;;
  1128. ;;================================================================================================;;
  1129.  
  1130. locals
  1131.         urlsize         dd ?
  1132.         hostname        dd ?
  1133.         pageaddr        dd ?
  1134. endl
  1135.  
  1136.         DEBUGF  1, "parsing URL: %s\n", [URL]
  1137.  
  1138. ; remove any leading protocol text
  1139.         mov     esi, [URL]
  1140.         mov     ecx, URLMAXLEN
  1141.         mov     ax, '//'
  1142.   .loop1:
  1143.         cmp     byte[esi], 0            ; end of URL?
  1144.         je      .url_ok                 ; yep, so not found
  1145.         cmp     [esi], ax
  1146.         je      .skip_proto
  1147.         inc     esi
  1148.         dec     ecx
  1149.         jnz     .loop1
  1150.  
  1151.         DEBUGF  1, "Invalid URL\n"
  1152.         xor     eax, eax
  1153.         ret
  1154.  
  1155.   .skip_proto:
  1156.         inc     esi                     ; skip the two '/'
  1157.         inc     esi
  1158.         mov     [URL], esi              ; update pointer so it skips protocol
  1159.         jmp     .loop1                  ; we still need to find the length of the URL
  1160.  
  1161.   .url_ok:
  1162.         sub     esi, [URL]              ; calculate total length of URL
  1163.         mov     [urlsize], esi
  1164.  
  1165.  
  1166. ; now look for page delimiter - it's a '/' character
  1167.         mov     ecx, esi                ; URL length
  1168.         mov     edi, [URL]
  1169.         mov     al, '/'
  1170.         repne   scasb
  1171.         jne     @f
  1172.         dec     edi                     ; return one char, '/' must be part of the pageaddr
  1173.         inc     ecx                     ;
  1174.   @@:
  1175.         push    ecx edi                 ; remember the pointer and length of pageaddr
  1176.  
  1177.         mov     ecx, edi
  1178.         sub     ecx, [URL]
  1179.         inc     ecx                     ; we will add a 0 byte at the end
  1180.         invoke  mem.alloc, ecx
  1181.         or      eax, eax
  1182.         jz      .no_mem
  1183.  
  1184.         mov     [hostname], eax         ; copy hostname to buffer
  1185.         mov     edi, eax
  1186.         mov     esi, [URL]
  1187.         dec     ecx
  1188.         rep     movsb
  1189.         xor     al, al
  1190.         stosb
  1191.  
  1192.         mov     [pageaddr], str_slash   ; assume there is no pageaddr
  1193.         pop     esi ecx
  1194.         test    ecx, ecx
  1195.         jz      .no_page
  1196.         inc     ecx                     ; we will add a 0 byte at the end
  1197.         invoke  mem.alloc, ecx
  1198.         or      eax, eax
  1199.         jz      .no_mem
  1200.  
  1201.         mov     [pageaddr], eax         ; copy pageaddr to buffer
  1202.         mov     edi, eax
  1203.         dec     ecx
  1204.         rep     movsb
  1205.         xor     al, al
  1206.         stosb
  1207.   .no_page:
  1208.  
  1209.         mov     eax, [hostname]
  1210.         mov     ebx, [pageaddr]
  1211.  
  1212.         DEBUGF  1, "hostname: %s\n", eax
  1213.         DEBUGF  1, "pageaddr: %s\n", ebx
  1214.  
  1215.         ret
  1216.  
  1217.   .no_mem:
  1218.         xor     eax, eax
  1219.         ret
  1220.  
  1221. endp
  1222.  
  1223.  
  1224. ;;================================================================================================;;
  1225. proc ascii_dec ;//////////////////////////////////////////////////////////////////////////////////;;
  1226. ;;------------------------------------------------------------------------------------------------;;
  1227. ;? Convert eax to ASCII decimal number                                                            ;;
  1228. ;;------------------------------------------------------------------------------------------------;;
  1229. ;> eax = number                                                                                   ;;
  1230. ;> edi = ptr where to write ASCII decimal number                                                  ;;
  1231. ;;------------------------------------------------------------------------------------------------;;
  1232. ;< /                                                                                              ;;
  1233. ;;================================================================================================;;
  1234.  
  1235.         push    -'0'
  1236.         mov     ecx, 10
  1237.   .loop:
  1238.         xor     edx, edx
  1239.         div     ecx
  1240.         add     dl, '0'
  1241.         push    edx
  1242.         test    eax, eax
  1243.         jnz     .loop
  1244.  
  1245.   .loop2:
  1246.         pop     eax
  1247.         add     al, '0'
  1248.         jz      .done
  1249.         stosb
  1250.         jmp     .loop2
  1251.   .done:
  1252.  
  1253.         ret
  1254.  
  1255. endp
  1256.  
  1257.  
  1258. ;;================================================================================================;;
  1259. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1260. ;;================================================================================================;;
  1261. ;! Imported functions section                                                                     ;;
  1262. ;;================================================================================================;;
  1263. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1264. ;;================================================================================================;;
  1265.  
  1266.  
  1267. align 16
  1268. @IMPORT:
  1269.  
  1270. library \
  1271.         libini, 'libini.obj', \
  1272.         network, 'network.obj'
  1273.  
  1274. import  libini, \
  1275.         ini.get_str, 'ini_get_str', \
  1276.         ini.get_int, 'ini_get_int'
  1277.  
  1278. import  network,\
  1279.         getaddrinfo, 'getaddrinfo',\
  1280.         freeaddrinfo,  'freeaddrinfo',\
  1281.         inet_ntoa, 'inet_ntoa'
  1282.  
  1283. ;;===========================================================================;;
  1284. ;;///////////////////////////////////////////////////////////////////////////;;
  1285. ;;===========================================================================;;
  1286. ;! Exported functions section                                                ;;
  1287. ;;===========================================================================;;
  1288. ;;///////////////////////////////////////////////////////////////////////////;;
  1289. ;;===========================================================================;;
  1290.  
  1291.  
  1292. align 4
  1293. @EXPORT:
  1294. export  \
  1295.         lib_init                , 'lib_init'            , \
  1296.         0x00010001              , 'version'             , \
  1297.         HTTP_get                , 'get'                 , \
  1298.         HTTP_head               , 'head'                , \
  1299.         HTTP_post               , 'post'                , \
  1300.         find_header_field       , 'find_header_field'   , \
  1301.         HTTP_process            , 'process'             , \
  1302.         HTTP_free               , 'free'                , \
  1303.         HTTP_stop               , 'stop'                , \
  1304.         URI_escape              , 'escape'              , \
  1305.         URI_unescape            , 'unescape'
  1306.  
  1307. ;        HTTP_put                , 'put'                 , \
  1308. ;        HTTP_delete             , 'delete'              , \
  1309. ;        HTTP_trace              , 'trace'               , \
  1310. ;        HTTP_connect            , 'connect'             , \
  1311.  
  1312.  
  1313.  
  1314. section '.data' data readable writable align 16
  1315.  
  1316. inifile         db '/sys/settings/network.ini', 0
  1317.  
  1318. sec_proxy:
  1319. key_proxy       db 'proxy', 0
  1320. key_proxyport   db 'port', 0
  1321. key_user        db 'user', 0
  1322. key_password    db 'password', 0
  1323.  
  1324. str_http11      db ' HTTP/1.1', 13, 10, 'Host: '
  1325.   .length       = $ - str_http11
  1326. str_post_cl     db 13, 10, 'Content-Length: '
  1327.   .length       = $ - str_post_cl
  1328. str_post_ct     db 13, 10, 'Content-Type: '
  1329.   .length       = $ - str_post_ct
  1330. str_close       db 13, 10, 'User-Agent: KolibriOS libHTTP/1.0', 13, 10, 'Connection: Close', 13, 10, 13, 10
  1331.   .length       = $ - str_close
  1332. str_proxy_auth  db 13, 10, 'Proxy-Authorization: Basic '
  1333.   .length       = $ - str_proxy_auth
  1334.  
  1335. base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
  1336.                 db '0123456789+/'
  1337.  
  1338. str_cl          db 'content-length', 0
  1339. str_slash       db '/', 0
  1340. str_te          db 'transfer-encoding', 0
  1341. str_get         db 'GET ', 0
  1342. str_head        db 'HEAD ', 0
  1343. str_post        db 'POST ', 0
  1344.  
  1345. bits_must_escape:
  1346. dd      0xffffffff                                                      ; 00-1F
  1347. dd      1 shl 0 + 1 shl 2 + 1 shl 3 + 1 shl 5 + 1 shl 28 + 1 shl 30     ; "#%<>
  1348. dd      1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 30                       ;[\]^
  1349. dd      1 shl 0 + 1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 31             ;`{|} DEL
  1350.  
  1351. dd      0xffffffff
  1352. dd      0xffffffff
  1353. dd      0xffffffff
  1354. dd      0xffffffff
  1355.  
  1356. str_hex:
  1357. db '0123456789ABCDEF'
  1358.  
  1359. include_debug_strings
  1360.  
  1361. ; uninitialized data
  1362. mem.alloc       dd ?
  1363. mem.free        dd ?
  1364. mem.realloc     dd ?
  1365. dll.load        dd ?
  1366.  
  1367. proxyAddr       rb 256
  1368. proxyUser       rb 256
  1369. proxyPassword   rb 256
  1370. proxyPort       dd ?