Subversion Repositories Kolibri OS

Rev

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