Subversion Repositories Kolibri OS

Rev

Rev 4211 | Rev 4216 | 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\n"
  109.  
  110.         xor     eax, eax
  111.         ret
  112.  
  113.   .error:
  114.         DEBUGF  1, "ERROR loading libraries\n"
  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 (final) header yet?
  456.         test    [ebp + http_msg.flags], FLAG_GOT_HEADER
  457.         jnz     .header_parsed
  458.  
  459. ; We havent found the (final) header yet, search for it..
  460.   .scan_again:
  461.         ; eax = total number of bytes received so far
  462.         mov     eax, [ebp + http_msg.write_ptr]
  463.         sub     eax, http_msg.data
  464.         sub     eax, ebp
  465.         sub     eax, [ebp + http_msg.header_length]
  466.         ; edi is ptr to begin of header
  467.         lea     edi, [ebp + http_msg.data]
  468.         add     edi, [ebp + http_msg.header_length]
  469.         ; put it in esi for next proc too
  470.         mov     esi, edi
  471.         sub     eax, 3
  472.         jle     .need_more_data
  473.   .scan_loop:
  474.         ; scan for end of header (empty line)
  475.         cmp     dword[edi], 0x0a0d0a0d                  ; end of header
  476.         je      .end_of_header
  477.         cmp     word[edi+2], 0x0a0a                     ; notice the use of offset + 2, to calculate header length correctly :)
  478.         je      .end_of_header
  479.         inc     edi
  480.         dec     eax
  481.         jnz     .scan_loop
  482.         jmp     .need_more_data
  483.  
  484.   .end_of_header:
  485.         add     edi, 4 - http_msg.data
  486.         sub     edi, ebp
  487.         mov     [ebp + http_msg.header_length], edi     ; If this isnt the final header, we'll use this as an offset to find real header.
  488.         DEBUGF  1, "Header length: %u\n", edi
  489.  
  490. ; Ok, we have found header:
  491.         cmp     dword[esi], 'HTTP'
  492.         jne     .invalid_header
  493.         cmp     dword[esi+4], '/1.0'
  494.         je      .http_1.0
  495.         cmp     dword[esi+4], '/1.1'
  496.         jne     .invalid_header
  497.         or      [ebp + http_msg.flags], FLAG_HTTP11
  498.   .http_1.0:
  499.         cmp     byte[esi+8], ' '
  500.         jne     .invalid_header
  501.  
  502.         add     esi, 9
  503.         xor     eax, eax
  504.         xor     ebx, ebx
  505.         mov     ecx, 3
  506.   .statusloop:
  507.         lodsb
  508.         sub     al, '0'
  509.         jb      .invalid_header
  510.         cmp     al, 9
  511.         ja      .invalid_header
  512.         lea     ebx, [ebx + 4*ebx]
  513.         shl     ebx, 1
  514.         add     ebx, eax
  515.         dec     ecx
  516.         jnz     .statusloop
  517.  
  518. ; Ignore "100 - Continue" headers
  519.         cmp     ebx, 100
  520.         je      .scan_again
  521.  
  522.         DEBUGF  1, "Status: %u\n", ebx
  523.         mov     [ebp + http_msg.status], ebx
  524.         or      [ebp + http_msg.flags], FLAG_GOT_HEADER
  525.  
  526. ; Now, convert all header names to lowercase.
  527. ; This way, it will be much easier to find certain header fields, later on.
  528.  
  529.         lea     esi, [ebp + http_msg.data]
  530.         mov     ecx, [ebp + http_msg.header_length]
  531.   .need_newline:
  532.         inc     esi
  533.         dec     ecx
  534.         jz      .convert_done
  535.         cmp     byte[esi], 10
  536.         jne     .need_newline
  537. ; Ok, we have a newline, a line beginning with space or tabs has no header fields.
  538.  
  539.         inc     esi
  540.         dec     ecx
  541.         jz      .convert_done
  542.         cmp     byte[esi], ' '
  543.         je      .need_newline
  544.         cmp     byte[esi], 9    ; horizontal tab
  545.         je      .need_newline
  546.         jmp     .convert_loop
  547.   .next_char:
  548.         inc     esi
  549.         dec     ecx
  550.         jz      .convert_done
  551.   .convert_loop:
  552.         cmp     byte[esi], ':'
  553.         je      .need_newline
  554.         cmp     byte[esi], 'A'
  555.         jb      .next_char
  556.         cmp     byte[esi], 'Z'
  557.         ja      .next_char
  558.         or      byte[esi], 0x20 ; convert to lowercase
  559.         jmp     .next_char
  560.   .convert_done:
  561.         mov     byte[esi-1], 0
  562.         lea     esi, [ebp + http_msg.data]
  563.         DEBUGF  1, "Header names converted to lowercase:\n%s\n", esi
  564.  
  565. ; Check for content-length header field.
  566.         stdcall find_header_field, ebp, str_cl
  567.         test    eax, eax
  568.         jz      .no_content
  569.         or      [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
  570.  
  571.         xor     edx, edx
  572.   .cl_loop:
  573.         movzx   ebx, byte[eax]
  574.         inc     eax
  575.         cmp     bl, 10
  576.         je      .cl_ok
  577.         cmp     bl, 13
  578.         je      .cl_ok
  579.         cmp     bl, ' '
  580.         je      .cl_ok
  581.         sub     bl, '0'
  582.         jb      .invalid_header
  583.         cmp     bl, 9
  584.         ja      .invalid_header
  585.         lea     edx, [edx + edx*4]      ; edx = edx*10
  586.         shl     edx, 1                  ;
  587.         add     edx, ebx
  588.         jmp     .cl_loop
  589.  
  590.   .cl_ok:
  591.         mov     [ebp + http_msg.content_length], edx
  592.         DEBUGF  1, "Content-length: %u\n", edx
  593.  
  594. ; Resize buffer according to content-length.
  595.         add     edx, [ebp + http_msg.header_length]
  596.         add     edx, http_msg.data
  597.  
  598.         mov     ecx, edx
  599.         sub     ecx, [ebp + http_msg.write_ptr]
  600.         mov     [ebp + http_msg.buffer_length], ecx
  601.  
  602.         invoke  mem.realloc, ebp, edx
  603.         or      eax, eax
  604.         jz      .no_ram
  605.  
  606.         mov     eax, [ebp + http_msg.write_ptr]
  607.         sub     eax, [ebp + http_msg.header_length]
  608.         sub     eax, http_msg.data
  609.         sub     eax, ebp
  610.         jmp     .header_parsed  ; hooray!
  611.  
  612.   .no_content:
  613.         DEBUGF  1, "Content-length not found.\n"
  614.  
  615. ; We didnt find 'content-length', maybe server is using chunked transfer encoding?
  616. ; Try to find 'transfer-encoding' header.
  617.         stdcall find_header_field, ebp, str_te
  618.         test    eax, eax
  619.         jz      .invalid_header
  620.  
  621.         mov     ebx, dword[eax]
  622.         or      ebx, 0x20202020
  623.         cmp     ebx, 'chun'
  624.         jne     .invalid_header
  625.         mov     ebx, dword[eax+4]
  626.         or      ebx, 0x00202020
  627.         and     ebx, 0x00ffffff
  628.         cmp     ebx, 'ked'
  629.         jne     .invalid_header
  630.  
  631.         or      [ebp + http_msg.flags], FLAG_CHUNKED
  632.         DEBUGF  1, "Transfer type is: chunked\n"
  633.  
  634. ; Set chunk pointer where first chunk should begin.
  635.         lea     eax, [ebp + http_msg.data]
  636.         add     eax, [ebp + http_msg.header_length]
  637.         mov     [ebp + http_msg.chunk_ptr], eax
  638.  
  639.   .chunk_loop:
  640.         mov     ecx, [ebp + http_msg.write_ptr]
  641.         sub     ecx, [ebp + http_msg.chunk_ptr]
  642.         jb      .need_more_data_chunked         ; TODO: use this ecx !!!
  643.  
  644. ; Chunkline starts here, convert the ASCII hex number into ebx
  645.         mov     esi, [ebp + http_msg.chunk_ptr]
  646.         xor     ebx, ebx
  647.   .chunk_hexloop:
  648.         lodsb
  649.         sub     al, '0'
  650.         jb      .chunk_
  651.         cmp     al, 9
  652.         jbe     .chunk_hex
  653.         sub     al, 'A' - '0' - 10
  654.         jb      .chunk_
  655.         cmp     al, 15
  656.         jbe     .chunk_hex
  657.         sub     al, 'a' - 'A'
  658.         cmp     al, 15
  659.         ja      .chunk_
  660.   .chunk_hex:
  661.         shl     ebx, 4
  662.         add     bl, al
  663.         jmp     .chunk_hexloop
  664.   .chunk_:
  665.         DEBUGF  1, "got chunk of %u bytes\n", ebx
  666. ;;        cmp     esi, [ebp + http_msg.chunk_ptr]
  667. ;;        je
  668. ; If chunk size is 0, all chunks have been received.
  669.         test    ebx, ebx
  670.         jz      .got_all_data_chunked           ; last chunk, hooray! FIXME: what if it wasnt a valid hex number???
  671.  
  672. ; Chunkline ends with a CR, LF or simply LF
  673.   .end_of_chunkline?:
  674.         cmp     al, 10
  675.         je      .end_of_chunkline
  676.         lodsb
  677.         cmp     edi, [ebp + http_msg.write_ptr]
  678.         jb      .end_of_chunkline?
  679.         jmp     .need_more_data
  680.  
  681.   .end_of_chunkline:
  682. ; Update chunk ptr, and remember old one
  683.         mov     edi, [ebp + http_msg.chunk_ptr]
  684.         add     [ebp + http_msg.chunk_ptr], ebx
  685. ; Realloc buffer, make it 'chunksize' bigger.
  686.         mov     eax, [ebp + http_msg.buffer_length]
  687.         add     eax, ebx
  688.         invoke  mem.realloc, ebp, eax
  689.         or      eax, eax
  690.         jz      .no_ram
  691.         add     [ebp + http_msg.buffer_length], ebx
  692.  
  693. ; Update write ptr
  694.         mov     eax, esi
  695.         sub     eax, edi
  696.         sub     [ebp + http_msg.write_ptr], eax
  697.  
  698. ; Now move all received data to the left (remove chunk header).
  699. ; Update content_length accordingly.
  700.         mov     ecx, [ebp + http_msg.write_ptr]
  701.         sub     ecx, esi
  702.         add     [ebp + http_msg.content_received], ecx
  703.         rep     movsb
  704.         jmp     .chunk_loop
  705.  
  706. ; Check if we got all the data.
  707.   .header_parsed:
  708.         add     [ebp + http_msg.content_received], eax
  709.         mov     eax, [ebp + http_msg.content_length]
  710.         cmp     eax, [ebp + http_msg.content_received]
  711.         jae     .got_all_data
  712.         jmp     .need_more_data
  713.  
  714.   .need_more_data:
  715.         popa
  716.         xor     eax, eax
  717.         dec     eax
  718.         ret
  719.  
  720.   .need_more_data_chunked:
  721.         add     [ebp + http_msg.content_received], eax
  722.         popa
  723.         xor     eax, eax
  724.         dec     eax
  725.         ret
  726.  
  727.   .got_all_data_chunked:
  728.         mov     eax, [ebp + http_msg.chunk_ptr]
  729.         sub     eax, [ebp + http_msg.header_length]
  730.         sub     eax, http_msg.data
  731.         sub     eax, ebp
  732.         mov     [ebp + http_msg.content_length], eax
  733.         mov     [ebp + http_msg.content_received], eax
  734.   .got_all_data:
  735.         DEBUGF  1, "We got all the data! (%u bytes)\n", [ebp + http_msg.content_length]
  736.         or      [ebp + http_msg.flags], FLAG_GOT_ALL_DATA
  737.         and     [ebp + http_msg.flags], not FLAG_CONNECTED
  738.         mcall   close, [ebp + http_msg.socket]
  739.         popa
  740.         xor     eax, eax
  741.         ret
  742.  
  743.   .check_socket:
  744.         cmp     ebx, EWOULDBLOCK
  745.         jne     .socket_error
  746.  
  747.         mcall   29, 9
  748.         sub     eax, TIMEOUT
  749.         cmp     eax, [ebp + http_msg.timestamp]
  750.         jb      .need_more_data
  751.         DEBUGF  1, "ERROR: timeout\n"
  752.         or      [ebp + http_msg.flags], FLAG_TIMEOUT_ERROR
  753.         jmp     .disconnect
  754.  
  755.   .invalid_header:
  756.         pop     eax
  757.         DEBUGF  1, "ERROR: invalid header\n"
  758.         or      [ebp + http_msg.flags], FLAG_INVALID_HEADER
  759.         jmp     .disconnect
  760.  
  761.   .no_ram:
  762.         DEBUGF  1, "ERROR: out of RAM\n"
  763.         or      [ebp + http_msg.flags], FLAG_NO_RAM
  764.         jmp     .disconnect
  765.  
  766.   .socket_error:
  767.         DEBUGF  1, "ERROR: socket error %u\n", ebx
  768.         or      [ebp + http_msg.flags], FLAG_SOCKET_ERROR
  769.   .disconnect:
  770.         and     [ebp + http_msg.flags], not FLAG_CONNECTED
  771.         mcall   close, [ebp + http_msg.socket]
  772.   .connection_closed:
  773.         popa
  774.         xor     eax, eax
  775.         ret
  776.  
  777. endp
  778.  
  779.  
  780.  
  781.  
  782. ;;================================================================================================;;
  783. proc HTTP_free identifier ;///////////////////////////////////////////////////////////////////////;;
  784. ;;------------------------------------------------------------------------------------------------;;
  785. ;? Free the http_msg structure                                                                    ;;
  786. ;;------------------------------------------------------------------------------------------------;;
  787. ;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
  788. ;;------------------------------------------------------------------------------------------------;;
  789. ;< none                                                                                           ;;
  790. ;;================================================================================================;;
  791.  
  792.         pusha
  793.         mov     ebp, [identifier]
  794.  
  795.         test    [ebp + http_msg.flags], FLAG_CONNECTED
  796.         jz      .not_connected
  797.  
  798.         and     [ebp + http_msg.flags], not FLAG_CONNECTED
  799.         mcall   close, [ebp + http_msg.socket]
  800.  
  801.   .not_connected:
  802.         invoke  mem.free, ebp
  803.  
  804.         popa
  805.         ret
  806.  
  807. endp
  808.  
  809.  
  810.  
  811. ;;================================================================================================;;
  812. proc HTTP_stop identifier ;///////////////////////////////////////////////////////////////////////;;
  813. ;;------------------------------------------------------------------------------------------------;;
  814. ;? Stops the open connection                                                                      ;;
  815. ;;------------------------------------------------------------------------------------------------;;
  816. ;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
  817. ;;------------------------------------------------------------------------------------------------;;
  818. ;< none                                                                                           ;;
  819. ;;================================================================================================;;
  820.  
  821.         pusha
  822.         mov     ebp, [identifier]
  823.  
  824.         and     [ebp + http_msg.flags], not FLAG_CONNECTED
  825.         mcall   close, [ebp + http_msg.socket]
  826.  
  827.         popa
  828.         ret
  829.  
  830. endp
  831.  
  832.  
  833.  
  834. ;;================================================================================================;;
  835. proc find_header_field identifier, headername ;///////////////////////////////////////////////////;;
  836. ;;------------------------------------------------------------------------------------------------;;
  837. ;? Find a header field in the received HTTP header                                                ;;
  838. ;;------------------------------------------------------------------------------------------------;;
  839. ;> identifier   = ptr to http_msg struct                                                          ;;
  840. ;> headername   = ptr to ASCIIZ string containg field you want to find (must be in lowercase)     ;;
  841. ;;------------------------------------------------------------------------------------------------;;
  842. ;< eax = 0 (error) / ptr to content of the HTTP header field                                      ;;
  843. ;;================================================================================================;;
  844.         push    ebx ecx edx esi edi
  845.  
  846.         DEBUGF  1, "Find header field: %s\n", [headername]
  847.  
  848.         mov     ebx, [identifier]
  849.         test    [ebx + http_msg.flags], FLAG_GOT_HEADER
  850.         jz      .fail
  851.  
  852.         lea     edx, [ebx + http_msg.data]
  853.         mov     ecx, edx
  854.         add     ecx, [ebx + http_msg.header_length]
  855.  
  856.   .restart:
  857.         mov     esi, [headername]
  858.         mov     edi, edx
  859.   .loop:
  860.         cmp     edi, ecx
  861.         jae     .fail
  862.         lodsb
  863.         scasb
  864.         je      .loop
  865.         test    al, al
  866.         jz      .done?
  867.   .next:
  868.         inc     edx
  869.         jmp     .restart
  870.  
  871.   .not_done:
  872.         inc     edi
  873.   .done?:
  874.         cmp     byte[edi-1], ':'
  875.         je      .almost_done
  876.         cmp     byte[edi-1], ' '
  877.         je      .not_done
  878.         cmp     byte[edi-1], 9  ; tab
  879.         je      .not_done
  880.  
  881.         jmp     .next
  882.  
  883.   .almost_done:                 ; FIXME: buffer overflow?
  884.         dec     edi
  885.         DEBUGF  1, "Found header field\n"
  886.   .spaceloop:
  887.         inc     edi
  888.         cmp     byte[edi], ' '
  889.         je      .spaceloop
  890.         cmp     byte[edi], 9    ; tab
  891.         je      .spaceloop
  892.  
  893.         mov     eax, edi
  894.         pop     edi esi edx ecx ebx
  895.         ret
  896.  
  897.   .fail:
  898.         pop     edi esi edx ecx ebx
  899.         xor     eax, eax
  900.         ret
  901.  
  902. endp
  903.  
  904.  
  905.  
  906. ;;================================================================================================;;
  907. proc URI_escape URI ;/////////////////////////////////////////////////////////////////////////////;;
  908. ;;------------------------------------------------------------------------------------------------;;
  909. ;?                                                                                                ;;
  910. ;;------------------------------------------------------------------------------------------------;;
  911. ;> URI = ptr to ASCIIZ URI                                                                        ;;
  912. ;;------------------------------------------------------------------------------------------------;;
  913. ;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
  914. ;;================================================================================================;;
  915.  
  916.         pusha
  917.  
  918.         invoke  mem.alloc, URLMAXLEN
  919.         test    eax, eax
  920.         jz      .error
  921.         mov     [esp + 7 * 4], eax              ; return ptr in eax
  922.         mov     esi, [URI]
  923.         mov     edi, eax
  924.         xor     ebx, ebx
  925.         xor     ecx, ecx
  926.   .loop:
  927.         lodsb
  928.         test    al, al
  929.         jz      .done
  930.  
  931.         mov     cl, al
  932.         and     cl, 0x1f
  933.         mov     bl, al
  934.         shr     bl, 5
  935.         bt      dword[bits_must_escape + ebx], ecx
  936.         jc      .escape
  937.  
  938.         stosb
  939.         jmp     .loop
  940.  
  941.   .escape:
  942.         mov     al, '%'
  943.         stosb
  944.         mov     bl, byte[esi-1]
  945.         shr     bl, 4
  946.         mov     al, byte[str_hex + ebx]
  947.         stosb
  948.         mov     bl, byte[esi-1]
  949.         and     bl, 0x0f
  950.         mov     al, byte[str_hex + ebx]
  951.         stosb
  952.         jmp     .loop
  953.  
  954.  
  955.   .done:
  956.         stosb
  957.  
  958.         popa
  959.         ret
  960.  
  961.   .error:
  962.         popa
  963.         xor     eax, eax
  964.         ret
  965.  
  966. endp
  967.  
  968.  
  969.  
  970. ;;================================================================================================;;
  971. proc URI_unescape URI ;///////////////////////////////////////////////////////////////////////////;;
  972. ;;------------------------------------------------------------------------------------------------;;
  973. ;?                                                                                                ;;
  974. ;;------------------------------------------------------------------------------------------------;;
  975. ;> URI = ptr to ASCIIZ URI                                                                        ;;
  976. ;;------------------------------------------------------------------------------------------------;;
  977. ;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
  978. ;;================================================================================================;;
  979.  
  980.         pusha
  981.  
  982.         invoke  mem.alloc, URLMAXLEN
  983.         test    eax, eax
  984.         jz      .error
  985.         mov     [esp + 7 * 4], eax              ; return ptr in eax
  986.         mov     esi, [URI]
  987.         mov     edi, eax
  988.   .loop:
  989.         lodsb
  990.         test    al, al
  991.         jz      .done
  992.  
  993.         cmp     al, '%'
  994.         je      .unescape
  995.  
  996.         stosb
  997.         jmp     .loop
  998.  
  999.   .unescape:
  1000.         xor     ebx, ebx
  1001.         xor     ecx, ecx
  1002.   .unescape_nibble:
  1003.         lodsb
  1004.         sub     al, '0'
  1005.         jb      .fail
  1006.         cmp     al, 9
  1007.         jbe     .nibble_ok
  1008.         sub     al, 'A' - '0' - 10
  1009.         jb      .fail
  1010.         cmp     al, 15
  1011.         jbe     .nibble_ok
  1012.         sub     al, 'a' - 'A'
  1013.         cmp     al, 15
  1014.         ja      .fail
  1015.   .nibble_ok:
  1016.         shl     bl, 8
  1017.         or      bl, al
  1018.         dec     ecx
  1019.         jc      .unescape_nibble
  1020.         mov     al, bl
  1021.         stosb
  1022.         jmp     .loop
  1023.  
  1024.   .fail:
  1025.         DEBUGF  1, "ERROR: invalid URI!\n"
  1026.         jmp     .loop
  1027.  
  1028.   .done:
  1029.         stosb
  1030.  
  1031.         popa
  1032.         ret
  1033.  
  1034.   .error:
  1035.         popa
  1036.         xor     eax, eax
  1037.         ret
  1038.  
  1039. endp
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045. ;;================================================================================================;;
  1046. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1047. ;;================================================================================================;;
  1048. ;! Internal procedures section                                                                    ;;
  1049. ;;================================================================================================;;
  1050. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1051. ;;================================================================================================;;
  1052.  
  1053.  
  1054.  
  1055.  
  1056. ;;================================================================================================;;
  1057. proc open_connection hostname, port ;/////////////////////////////////////////////////////////////;;
  1058. ;;------------------------------------------------------------------------------------------------;;
  1059. ;? Connects to a HTTP server                                                                      ;;
  1060. ;;------------------------------------------------------------------------------------------------;;
  1061. ;> hostname     = ptr to ASCIIZ hostname                                                          ;;
  1062. ;> port         = port (x86 byte order)                                                           ;;
  1063. ;;------------------------------------------------------------------------------------------------;;
  1064. ;< eax = 0 (error) / socketnum                                                                    ;;
  1065. ;;================================================================================================;;
  1066.  
  1067. locals
  1068.         sockaddr        dd ?
  1069.         socketnum       dd ?
  1070. endl
  1071.  
  1072. ; Resolve the hostname
  1073.         DEBUGF  1, "Resolving hostname\n"
  1074.         push    esp     ; reserve stack place
  1075.         push    esp     ; fourth parameter
  1076.         push    0       ; third parameter
  1077.         push    0       ; second parameter
  1078.         push    [hostname]
  1079.         call    [getaddrinfo]
  1080.         pop     esi
  1081.         test    eax, eax
  1082.         jnz     .error1
  1083.  
  1084. ; getaddrinfo returns addrinfo struct, make the pointer to sockaddr struct
  1085.         mov     esi, [esi + addrinfo.ai_addr]
  1086.         mov     [sockaddr], esi
  1087.         mov     eax, [esi + sockaddr_in.sin_addr]
  1088.         test    eax, eax
  1089.         jz      .error2
  1090.  
  1091.         DEBUGF  1, "Server ip=%u.%u.%u.%u\n", \
  1092.         [esi + sockaddr_in.sin_addr]:1, [esi + sockaddr_in.sin_addr + 1]:1, \
  1093.         [esi + sockaddr_in.sin_addr + 2]:1, [esi + sockaddr_in.sin_addr + 3]:1
  1094.  
  1095.         mov     [esi + sockaddr_in.sin_family], AF_INET4
  1096.         mov     eax, [port]
  1097.         xchg    al, ah
  1098.         mov     [esi + sockaddr_in.sin_port], ax
  1099.  
  1100. ; Connect to the server.
  1101.         mcall   socket, AF_INET4, SOCK_STREAM, 0
  1102.         test    eax, eax
  1103.         jz      .error2
  1104.         mov     [socketnum], eax
  1105.         DEBUGF  1, "Socket: 0x%x\n", eax
  1106.  
  1107.         mcall   connect, [socketnum], [sockaddr], 18
  1108.         test    eax, eax
  1109.         jnz     .error2
  1110.         DEBUGF  1, "Socket is now connected.\n"
  1111.  
  1112. ; free allocated memory
  1113.         push    [sockaddr]
  1114.         call    [freeaddrinfo]
  1115.  
  1116.         mov     eax, [socketnum]
  1117.         ret
  1118.  
  1119.   .error2:
  1120.  
  1121. ; free allocated memory
  1122.         push    [sockaddr]
  1123.         call    [freeaddrinfo]
  1124.  
  1125.   .error1:
  1126.         xor     eax, eax
  1127.         ret
  1128.  
  1129. endp
  1130.  
  1131.  
  1132. ;;================================================================================================;;
  1133. proc parse_url URL ;//////////////////////////////////////////////////////////////////////////////;;
  1134. ;;------------------------------------------------------------------------------------------------;;
  1135. ;? Split a given URL into hostname and pageaddr                                                   ;;
  1136. ;;------------------------------------------------------------------------------------------------;;
  1137. ;> URL = ptr to ASCIIZ URL                                                                        ;;
  1138. ;;------------------------------------------------------------------------------------------------;;
  1139. ;< eax = 0 (error) / ptr to ASCIIZ hostname                                                       ;;
  1140. ;< ebx = ptr to ASCIIZ pageaddr                                                                   ;;
  1141. ;;================================================================================================;;
  1142.  
  1143. locals
  1144.         urlsize         dd ?
  1145.         hostname        dd ?
  1146.         pageaddr        dd ?
  1147. endl
  1148.  
  1149.         DEBUGF  1, "parsing URL: %s\n", [URL]
  1150.  
  1151. ; remove any leading protocol text
  1152.         mov     esi, [URL]
  1153.         mov     ecx, URLMAXLEN
  1154.         mov     ax, '//'
  1155.   .loop1:
  1156.         cmp     byte[esi], 0            ; end of URL?
  1157.         je      .url_ok                 ; yep, so not found
  1158.         cmp     [esi], ax
  1159.         je      .skip_proto
  1160.         inc     esi
  1161.         dec     ecx
  1162.         jnz     .loop1
  1163.  
  1164.         DEBUGF  1, "Invalid URL\n"
  1165.         xor     eax, eax
  1166.         ret
  1167.  
  1168.   .skip_proto:
  1169.         inc     esi                     ; skip the two '/'
  1170.         inc     esi
  1171.         mov     [URL], esi              ; update pointer so it skips protocol
  1172.         jmp     .loop1                  ; we still need to find the length of the URL
  1173.  
  1174.   .url_ok:
  1175.         sub     esi, [URL]              ; calculate total length of URL
  1176.         mov     [urlsize], esi
  1177.  
  1178.  
  1179. ; now look for page delimiter - it's a '/' character
  1180.         mov     ecx, esi                ; URL length
  1181.         mov     edi, [URL]
  1182.         mov     al, '/'
  1183.         repne   scasb
  1184.         jne     @f
  1185.         dec     edi                     ; return one char, '/' must be part of the pageaddr
  1186.         inc     ecx                     ;
  1187.   @@:
  1188.         push    ecx edi                 ; remember the pointer and length of pageaddr
  1189.  
  1190.         mov     ecx, edi
  1191.         sub     ecx, [URL]
  1192.         inc     ecx                     ; we will add a 0 byte at the end
  1193.         invoke  mem.alloc, ecx
  1194.         or      eax, eax
  1195.         jz      .no_mem
  1196.  
  1197.         mov     [hostname], eax         ; copy hostname to buffer
  1198.         mov     edi, eax
  1199.         mov     esi, [URL]
  1200.         dec     ecx
  1201.         rep     movsb
  1202.         xor     al, al
  1203.         stosb
  1204.  
  1205.         mov     [pageaddr], str_slash   ; assume there is no pageaddr
  1206.         pop     esi ecx
  1207.         test    ecx, ecx
  1208.         jz      .no_page
  1209.         inc     ecx                     ; we will add a 0 byte at the end
  1210.         invoke  mem.alloc, ecx
  1211.         or      eax, eax
  1212.         jz      .no_mem
  1213.  
  1214.         mov     [pageaddr], eax         ; copy pageaddr to buffer
  1215.         mov     edi, eax
  1216.         dec     ecx
  1217.         rep     movsb
  1218.         xor     al, al
  1219.         stosb
  1220.   .no_page:
  1221.  
  1222.         mov     eax, [hostname]
  1223.         mov     ebx, [pageaddr]
  1224.  
  1225.         DEBUGF  1, "hostname: %s\n", eax
  1226.         DEBUGF  1, "pageaddr: %s\n", ebx
  1227.  
  1228.         ret
  1229.  
  1230.   .no_mem:
  1231.         xor     eax, eax
  1232.         ret
  1233.  
  1234. endp
  1235.  
  1236.  
  1237. ;;================================================================================================;;
  1238. proc ascii_dec ;//////////////////////////////////////////////////////////////////////////////////;;
  1239. ;;------------------------------------------------------------------------------------------------;;
  1240. ;? Convert eax to ASCII decimal number                                                            ;;
  1241. ;;------------------------------------------------------------------------------------------------;;
  1242. ;> eax = number                                                                                   ;;
  1243. ;> edi = ptr where to write ASCII decimal number                                                  ;;
  1244. ;;------------------------------------------------------------------------------------------------;;
  1245. ;< /                                                                                              ;;
  1246. ;;================================================================================================;;
  1247.  
  1248.         push    -'0'
  1249.         mov     ecx, 10
  1250.   .loop:
  1251.         xor     edx, edx
  1252.         div     ecx
  1253.         add     dl, '0'
  1254.         push    edx
  1255.         test    eax, eax
  1256.         jnz     .loop
  1257.  
  1258.   .loop2:
  1259.         pop     eax
  1260.         add     al, '0'
  1261.         jz      .done
  1262.         stosb
  1263.         jmp     .loop2
  1264.   .done:
  1265.  
  1266.         ret
  1267.  
  1268. endp
  1269.  
  1270.  
  1271. ;;================================================================================================;;
  1272. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1273. ;;================================================================================================;;
  1274. ;! Imported functions section                                                                     ;;
  1275. ;;================================================================================================;;
  1276. ;;////////////////////////////////////////////////////////////////////////////////////////////////;;
  1277. ;;================================================================================================;;
  1278.  
  1279.  
  1280. align 16
  1281. @IMPORT:
  1282.  
  1283. library \
  1284.         libini, 'libini.obj', \
  1285.         network, 'network.obj'
  1286.  
  1287. import  libini, \
  1288.         ini.get_str, 'ini_get_str', \
  1289.         ini.get_int, 'ini_get_int'
  1290.  
  1291. import  network,\
  1292.         getaddrinfo, 'getaddrinfo',\
  1293.         freeaddrinfo,  'freeaddrinfo',\
  1294.         inet_ntoa, 'inet_ntoa'
  1295.  
  1296. ;;===========================================================================;;
  1297. ;;///////////////////////////////////////////////////////////////////////////;;
  1298. ;;===========================================================================;;
  1299. ;! Exported functions section                                                ;;
  1300. ;;===========================================================================;;
  1301. ;;///////////////////////////////////////////////////////////////////////////;;
  1302. ;;===========================================================================;;
  1303.  
  1304.  
  1305. align 4
  1306. @EXPORT:
  1307. export  \
  1308.         lib_init                , 'lib_init'            , \
  1309.         0x00010001              , 'version'             , \
  1310.         HTTP_get                , 'get'                 , \
  1311.         HTTP_head               , 'head'                , \
  1312.         HTTP_post               , 'post'                , \
  1313.         find_header_field       , 'find_header_field'   , \
  1314.         HTTP_process            , 'process'             , \
  1315.         HTTP_free               , 'free'                , \
  1316.         HTTP_stop               , 'stop'                , \
  1317.         URI_escape              , 'escape'              , \
  1318.         URI_unescape            , 'unescape'
  1319.  
  1320. ;        HTTP_put                , 'put'                 , \
  1321. ;        HTTP_delete             , 'delete'              , \
  1322. ;        HTTP_trace              , 'trace'               , \
  1323. ;        HTTP_connect            , 'connect'             , \
  1324.  
  1325.  
  1326.  
  1327. section '.data' data readable writable align 16
  1328.  
  1329. inifile         db '/sys/settings/network.ini', 0
  1330.  
  1331. sec_proxy:
  1332. key_proxy       db 'proxy', 0
  1333. key_proxyport   db 'port', 0
  1334. key_user        db 'user', 0
  1335. key_password    db 'password', 0
  1336.  
  1337. str_http11      db ' HTTP/1.1', 13, 10, 'Host: '
  1338.   .length       = $ - str_http11
  1339. str_post_cl     db 13, 10, 'Content-Length: '
  1340.   .length       = $ - str_post_cl
  1341. str_post_ct     db 13, 10, 'Content-Type: '
  1342.   .length       = $ - str_post_ct
  1343. str_close       db 13, 10, 'User-Agent: KolibriOS libHTTP/1.0', 13, 10, 'Connection: Close', 13, 10, 13, 10
  1344.   .length       = $ - str_close
  1345. str_proxy_auth  db 13, 10, 'Proxy-Authorization: Basic '
  1346.   .length       = $ - str_proxy_auth
  1347.  
  1348. base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
  1349.                 db '0123456789+/'
  1350.  
  1351. str_cl          db 'content-length', 0
  1352. str_slash       db '/', 0
  1353. str_te          db 'transfer-encoding', 0
  1354. str_get         db 'GET ', 0
  1355. str_head        db 'HEAD ', 0
  1356. str_post        db 'POST ', 0
  1357.  
  1358. bits_must_escape:
  1359. dd      0xffffffff                                                      ; 00-1F
  1360. dd      1 shl 0 + 1 shl 2 + 1 shl 3 + 1 shl 5 + 1 shl 28 + 1 shl 30     ; "#%<>
  1361. dd      1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 30                       ;[\]^
  1362. dd      1 shl 0 + 1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 31             ;`{|} DEL
  1363.  
  1364. dd      0xffffffff
  1365. dd      0xffffffff
  1366. dd      0xffffffff
  1367. dd      0xffffffff
  1368.  
  1369. str_hex:
  1370. db '0123456789ABCDEF'
  1371.  
  1372. include_debug_strings
  1373.  
  1374. ; uninitialized data
  1375. mem.alloc       dd ?
  1376. mem.free        dd ?
  1377. mem.realloc     dd ?
  1378. dll.load        dd ?
  1379.  
  1380. proxyAddr       rb 256
  1381. proxyUser       rb 256
  1382. proxyPassword   rb 256
  1383. proxyPort       dd ?