Subversion Repositories Kolibri OS

Rev

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