Subversion Repositories Kolibri OS

Rev

Rev 8571 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 8571 Rev 8575
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2020. All rights reserved.    ;;
3
;; Copyright (C) KolibriOS team 2004-2020. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
5
;;                                                                 ;;
6
;;  HTTP library for KolibriOS                                     ;;
6
;;  HTTP library for KolibriOS                                     ;;
7
;;                                                                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
9
;;   Proxy code written by CleverMouse                             ;;
9
;;   Proxy code written by CleverMouse                             ;;
10
;;                                                                 ;;
10
;;                                                                 ;;
11
;;         GNU GENERAL PUBLIC LICENSE                              ;;
11
;;         GNU GENERAL PUBLIC LICENSE                              ;;
12
;;          Version 2, June 1991                                   ;;
12
;;          Version 2, June 1991                                   ;;
13
;;                                                                 ;;
13
;;                                                                 ;;
14
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
 
15
 
16
; references:
16
; references:
17
; "HTTP made really easy", http://www.jmarshall.com/easy/http/
17
; "HTTP made really easy", http://www.jmarshall.com/easy/http/
18
; "Hypertext Transfer Protocol -- HTTP/1.1", http://tools.ietf.org/html/rfc2616
18
; "Hypertext Transfer Protocol -- HTTP/1.1", http://tools.ietf.org/html/rfc2616
19
 
19
 
20
 
20
 
21
        URLMAXLEN       = 65535
21
        URLMAXLEN       = 65535
22
        BUFFERSIZE      = 512*1024
22
        BUFFERSIZE      = 512*1024
23
        TIMEOUT         = 500  ; in 1/100 s
23
        TIMEOUT         = 500  ; in 1/100 s
24
 
24
 
25
        __DEBUG__       = 1
25
        __DEBUG__       = 1
26
        __DEBUG_LEVEL__ = 2
26
        __DEBUG_LEVEL__ = 2
27
 
27
 
28
 
28
 
29
format MS COFF
29
format MS COFF
30
 
30
 
31
public @EXPORT as 'EXPORTS'
31
public @EXPORT as 'EXPORTS'
32
 
32
 
33
include '../../../struct.inc'
33
include '../../../struct.inc'
34
include '../../../proc32.inc'
34
include '../../../proc32.inc'
35
include '../../../macros.inc'
35
include '../../../macros.inc'
36
purge section,mov,add,sub
36
purge section,mov,add,sub
37
include '../../../debug-fdo.inc'
37
include '../../../debug-fdo.inc'
38
 
38
 
39
include '../../../network.inc'
39
include '../../../network.inc'
40
include 'http.inc'
40
include 'http.inc'
41
 
41
 
42
virtual at 0
42
virtual at 0
43
        http_msg http_msg
43
        http_msg http_msg
44
end virtual
44
end virtual
45
 
45
 
46
macro copy_till_zero {
46
macro copy_till_zero {
47
local   .copyloop, .copydone
47
local   .copyloop, .copydone
48
  .copyloop:
48
  .copyloop:
49
        lodsb
49
        lodsb
50
        test    al, al
50
        test    al, al
51
        jz      .copydone
51
        jz      .copydone
52
        stosb
52
        stosb
53
        jmp     .copyloop
53
        jmp     .copyloop
54
  .copydone:
54
  .copydone:
55
}
55
}
56
 
56
 
57
macro HTTP_init_buffer buffer, socketnum, flags {
57
macro HTTP_init_buffer buffer, socketnum, flags {
58
 
58
 
59
        mov     eax, buffer
59
        mov     eax, buffer
60
        push    socketnum
60
        push    socketnum
61
        popd    [eax + http_msg.socket]
61
        popd    [eax + http_msg.socket]
62
        lea     esi, [eax + http_msg.http_header]
62
        lea     esi, [eax + http_msg.http_header]
63
        push    flags
63
        push    flags
64
        pop     [eax + http_msg.flags]
64
        pop     [eax + http_msg.flags]
65
        or      [eax + http_msg.flags], FLAG_CONNECTED
65
        or      [eax + http_msg.flags], FLAG_CONNECTED
66
        mov     [eax + http_msg.write_ptr], esi
66
        mov     [eax + http_msg.write_ptr], esi
67
 
67
 
68
        mov     ebx, [buffersize]
68
        mov     ebx, [buffersize]
69
        sub     ebx, http_msg.http_header
69
        sub     ebx, http_msg.http_header
70
        mov     [eax + http_msg.buffer_length], ebx
70
        mov     [eax + http_msg.buffer_length], ebx
71
        mov     [eax + http_msg.chunk_ptr], 0
71
        mov     [eax + http_msg.chunk_ptr], 0
72
 
72
 
73
        mov     [eax + http_msg.status], 0
73
        mov     [eax + http_msg.status], 0
74
        mov     [eax + http_msg.header_length], 0
74
        mov     [eax + http_msg.header_length], 0
75
        mov     [eax + http_msg.content_ptr], 0
75
        mov     [eax + http_msg.content_ptr], 0
76
        mov     [eax + http_msg.content_length], 0
76
        mov     [eax + http_msg.content_length], 0
77
        mov     [eax + http_msg.content_received], 0
77
        mov     [eax + http_msg.content_received], 0
78
 
78
 
79
        push    eax ebp
79
        push    eax ebp
80
        mov     ebp, eax
80
        mov     ebp, eax
81
        mcall   26, 9
81
        mcall   26, 9
82
        mov     [ebp + http_msg.timestamp], eax
82
        mov     [ebp + http_msg.timestamp], eax
83
        pop     ebp eax
83
        pop     ebp eax
84
}
84
}
85
 
85
 
86
section '.flat' code readable align 16
86
section '.flat' code readable align 16
87
 
87
 
88
;;===========================================================================;;
88
;;===========================================================================;;
89
lib_init: ;//////////////////////////////////////////////////////////////////;;
89
lib_init: ;//////////////////////////////////////////////////////////////////;;
90
;;---------------------------------------------------------------------------;;
90
;;---------------------------------------------------------------------------;;
91
;? Library entry point (called after library load)                           ;;
91
;? Library entry point (called after library load)                           ;;
92
;;---------------------------------------------------------------------------;;
92
;;---------------------------------------------------------------------------;;
93
;> eax = pointer to memory allocation routine                                ;;
93
;> eax = pointer to memory allocation routine                                ;;
94
;> ebx = pointer to memory freeing routine                                   ;;
94
;> ebx = pointer to memory freeing routine                                   ;;
95
;> ecx = pointer to memory reallocation routine                              ;;
95
;> ecx = pointer to memory reallocation routine                              ;;
96
;> edx = pointer to library loading routine                                  ;;
96
;> edx = pointer to library loading routine                                  ;;
97
;;---------------------------------------------------------------------------;;
97
;;---------------------------------------------------------------------------;;
98
;< eax = 1 (fail) / 0 (ok)                                                   ;;
98
;< eax = 1 (fail) / 0 (ok)                                                   ;;
99
;;===========================================================================;;
99
;;===========================================================================;;
100
        mov     [mem.alloc], eax
100
        mov     [mem.alloc], eax
101
        mov     [mem.free], ebx
101
        mov     [mem.free], ebx
102
        mov     [mem.realloc], ecx
102
        mov     [mem.realloc], ecx
103
        mov     [dll.load], edx
103
        mov     [dll.load], edx
104
 
104
 
105
        invoke  dll.load, @IMPORT
105
        invoke  dll.load, @IMPORT
106
        test    eax, eax
106
        test    eax, eax
107
        jnz     .error
107
        jnz     .error
108
 
108
 
109
; load proxy settings
109
; load proxy settings
110
        pusha
110
        pusha
111
        invoke  ini.get_str, inifile, sec_proxy, key_proxy, proxyAddr, 256, proxyAddr
111
        invoke  ini.get_str, inifile, sec_proxy, key_proxy, proxyAddr, 256, proxyAddr
112
        invoke  ini.get_int, inifile, sec_proxy, key_proxyport, 80
112
        invoke  ini.get_int, inifile, sec_proxy, key_proxyport, 80
113
        mov     [proxyPort], eax
113
        mov     [proxyPort], eax
114
        invoke  ini.get_str, inifile, sec_proxy, key_user, proxyUser, 256, proxyUser
114
        invoke  ini.get_str, inifile, sec_proxy, key_user, proxyUser, 256, proxyUser
115
        invoke  ini.get_str, inifile, sec_proxy, key_password, proxyPassword, 256, proxyPassword
115
        invoke  ini.get_str, inifile, sec_proxy, key_password, proxyPassword, 256, proxyPassword
116
        popa
116
        popa
117
 
117
 
118
        DEBUGF  1, "HTTP library: init OK\n"
118
        DEBUGF  1, "HTTP library: init OK\n"
119
        xor     eax, eax
119
        xor     eax, eax
120
        ret
120
        ret
121
 
121
 
122
  .error:
122
  .error:
123
        DEBUGF  2, "ERROR loading http.obj dependencies\n"
123
        DEBUGF  2, "ERROR loading http.obj dependencies\n"
124
        xor     eax, eax
124
        xor     eax, eax
125
        inc     eax
125
        inc     eax
126
        ret
126
        ret
127
 
127
 
128
 
128
 
129
;;================================================================================================;;
129
;;================================================================================================;;
130
proc HTTP_buffersize_get ;////////////////////////////////////////////////////////////////////////;;
130
proc HTTP_buffersize_get ;////////////////////////////////////////////////////////////////////////;;
131
;;------------------------------------------------------------------------------------------------;;
131
;;------------------------------------------------------------------------------------------------;;
132
;? Get HTTP buffer size                                                                           ;;
132
;? Get HTTP buffer size                                                                           ;;
133
;;------------------------------------------------------------------------------------------------;;
133
;;------------------------------------------------------------------------------------------------;;
134
;< eax = buffer size in bytes                                                                     ;;
134
;< eax = buffer size in bytes                                                                     ;;
135
;;================================================================================================;;
135
;;================================================================================================;;
136
 
136
 
137
        mov     eax, [buffersize]
137
        mov     eax, [buffersize]
138
        ret
138
        ret
139
 
139
 
140
endp
140
endp
141
 
141
 
142
;;================================================================================================;;
142
;;================================================================================================;;
143
proc HTTP_buffersize_set ;////////////////////////////////////////////////////////////////////////;;
143
proc HTTP_buffersize_set ;////////////////////////////////////////////////////////////////////////;;
144
;;------------------------------------------------------------------------------------------------;;
144
;;------------------------------------------------------------------------------------------------;;
145
;? Set HTTP buffer size                                                                           ;;
145
;? Set HTTP buffer size                                                                           ;;
146
;;------------------------------------------------------------------------------------------------;;
146
;;------------------------------------------------------------------------------------------------;;
147
;> eax = buffer size in bytes                                                                     ;;
147
;> eax = buffer size in bytes                                                                     ;;
148
;;================================================================================================;;
148
;;================================================================================================;;
149
 
149
 
150
        mov     [buffersize], eax
150
        mov     [buffersize], eax
151
        ret
151
        ret
152
 
152
 
153
endp
153
endp
154
 
154
 
155
 
155
 
156
;;================================================================================================;;
156
;;================================================================================================;;
157
proc HTTP_disconnect identifier ;/////////////////////////////////////////////////////////////////;;
157
proc HTTP_disconnect identifier ;/////////////////////////////////////////////////////////////////;;
158
;;------------------------------------------------------------------------------------------------;;
158
;;------------------------------------------------------------------------------------------------;;
159
;? Stops the open connection                                                                      ;;
159
;? Stops the open connection                                                                      ;;
160
;;------------------------------------------------------------------------------------------------;;
160
;;------------------------------------------------------------------------------------------------;;
161
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
161
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
162
;;------------------------------------------------------------------------------------------------;;
162
;;------------------------------------------------------------------------------------------------;;
163
;< none                                                                                           ;;
163
;< none                                                                                           ;;
164
;;================================================================================================;;
164
;;================================================================================================;;
165
 
165
 
166
        pusha
166
        pusha
167
        mov     ebp, [identifier]
167
        mov     ebp, [identifier]
168
 
168
 
169
        test    [ebp + http_msg.flags], FLAG_CONNECTED
169
        test    [ebp + http_msg.flags], FLAG_CONNECTED
170
        jz      .error
170
        jz      .error
171
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
171
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
172
        mcall   close, [ebp + http_msg.socket]
172
        mcall   close, [ebp + http_msg.socket]
173
 
173
 
174
        popa
174
        popa
175
        ret
175
        ret
176
 
176
 
177
  .error:
177
  .error:
178
        DEBUGF  1, "Cannot close already closed connection!\n"
178
        DEBUGF  1, "Cannot close already closed connection!\n"
179
        popa
179
        popa
180
        ret
180
        ret
181
 
181
 
182
endp
182
endp
183
 
183
 
184
 
184
 
185
;;================================================================================================;;
185
;;================================================================================================;;
186
proc HTTP_free identifier ;///////////////////////////////////////////////////////////////////////;;
186
proc HTTP_free identifier ;///////////////////////////////////////////////////////////////////////;;
187
;;------------------------------------------------------------------------------------------------;;
187
;;------------------------------------------------------------------------------------------------;;
188
;? Free the http_msg structure                                                                    ;;
188
;? Free the http_msg structure                                                                    ;;
189
;;------------------------------------------------------------------------------------------------;;
189
;;------------------------------------------------------------------------------------------------;;
190
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
190
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
191
;;------------------------------------------------------------------------------------------------;;
191
;;------------------------------------------------------------------------------------------------;;
192
;< none                                                                                           ;;
192
;< none                                                                                           ;;
193
;;================================================================================================;;
193
;;================================================================================================;;
194
        DEBUGF  1, "HTTP_free: 0x%x\n", [identifier]
194
        DEBUGF  1, "HTTP_free: 0x%x\n", [identifier]
195
        pusha
195
        pusha
196
        mov     ebp, [identifier]
196
        mov     ebp, [identifier]
197
 
197
 
198
        test    [ebp + http_msg.flags], FLAG_CONNECTED
198
        test    [ebp + http_msg.flags], FLAG_CONNECTED
199
        jz      .not_connected
199
        jz      .not_connected
200
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
200
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
201
        mcall   close, [ebp + http_msg.socket]
201
        mcall   close, [ebp + http_msg.socket]
202
 
202
 
203
  .not_connected:
203
  .not_connected:
-
 
204
        invoke  mem.free, [ebp + http_msg.content_ptr]
204
        invoke  mem.free, ebp
205
        invoke  mem.free, ebp
205
 
-
 
206
        popa
206
        popa
207
        ret
207
        ret
208
 
208
 
209
endp
209
endp
210
 
210
 
211
 
211
 
212
 
212
 
213
;;================================================================================================;;
213
;;================================================================================================;;
214
proc HTTP_get URL, identifier, flags, add_header ;////////////////////////////////////////////////;;
214
proc HTTP_get URL, identifier, flags, add_header ;////////////////////////////////////////////////;;
215
;;------------------------------------------------------------------------------------------------;;
215
;;------------------------------------------------------------------------------------------------;;
216
;? Initiates a HTTP connection, using 'GET' method.                                               ;;
216
;? Initiates a HTTP connection, using 'GET' method.                                               ;;
217
;;------------------------------------------------------------------------------------------------;;
217
;;------------------------------------------------------------------------------------------------;;
218
;> URL                  = pointer to ASCIIZ URL                                                   ;;
218
;> URL                  = pointer to ASCIIZ URL                                                   ;;
219
;> identifier           = Identifier of an already open connection, or NULL to create a new one.  ;;
219
;> identifier           = Identifier of an already open connection, or NULL to create a new one.  ;;
220
;> flags                = Flags indicating how to threat the connection.                          ;;
220
;> flags                = Flags indicating how to threat the connection.                          ;;
221
;> add_header           = pointer to additional header parameters (ASCIIZ), or NULL for none.     ;;
221
;> add_header           = pointer to additional header parameters (ASCIIZ), or NULL for none.     ;;
222
;;------------------------------------------------------------------------------------------------;;
222
;;------------------------------------------------------------------------------------------------;;
223
;< eax = 0 (error) / buffer ptr                                                                   ;;
223
;< eax = 0 (error) / buffer ptr                                                                   ;;
224
;;================================================================================================;;
224
;;================================================================================================;;
225
locals
225
locals
226
        hostname        dd ?
226
        hostname        dd ?
227
        pageaddr        dd ?
227
        pageaddr        dd ?
228
        socketnum       dd ?
228
        socketnum       dd ?
229
        buffer          dd ?
229
        buffer          dd ?
230
        port            dd ?
230
        port            dd ?
231
endl
231
endl
232
 
232
 
233
        and     [flags], 0xff00       ; filter out invalid flags
233
        and     [flags], 0xff00       ; filter out invalid flags
234
 
234
 
235
        pusha
235
        pusha
236
 
236
 
237
; split the URL into hostname and pageaddr
237
; split the URL into hostname and pageaddr
238
        stdcall parse_url, [URL]
238
        stdcall parse_url, [URL]
239
        test    eax, eax
239
        test    eax, eax
240
        jz      .error
240
        jz      .error
241
        mov     [hostname], eax
241
        mov     [hostname], eax
242
        mov     [pageaddr], ebx
242
        mov     [pageaddr], ebx
243
        mov     [port], ecx
243
        mov     [port], ecx
244
 
244
 
245
        mov     eax, [identifier]
245
        mov     eax, [identifier]
246
        test    eax, eax
246
        test    eax, eax
247
        jz      .open_new
247
        jz      .open_new
248
        test    [eax + http_msg.flags], FLAG_CONNECTED
248
        test    [eax + http_msg.flags], FLAG_CONNECTED
249
        jz      .error
249
        jz      .error
250
        mov     eax, [eax + http_msg.socket]
250
        mov     eax, [eax + http_msg.socket]
251
        mov     [socketnum], eax
251
        mov     [socketnum], eax
252
        jmp     .send_request
252
        jmp     .send_request
253
 
253
 
254
; Connect to the other side.
254
; Connect to the other side.
255
  .open_new:
255
  .open_new:
256
        stdcall open_connection, [hostname], [port]
256
        stdcall open_connection, [hostname], [port]
257
        test    eax, eax
257
        test    eax, eax
258
        jz      .error
258
        jz      .error
259
        mov     [socketnum], eax
259
        mov     [socketnum], eax
260
 
260
 
261
; Create the HTTP request.
261
; Create the HTTP request.
262
  .send_request:
262
  .send_request:
263
        invoke  mem.alloc, [buffersize]
263
        invoke  mem.alloc, [buffersize]
264
        test    eax, eax
264
        test    eax, eax
265
        jz      .error
265
        jz      .error
266
        mov     [buffer], eax
266
        mov     [buffer], eax
267
        mov     edi, eax
267
        mov     edi, eax
268
        DEBUGF  1, "Buffer allocated: 0x%x\n", eax
268
        DEBUGF  1, "Buffer allocated: 0x%x\n", eax
269
 
269
 
270
        mov     esi, str_get
270
        mov     esi, str_get
271
        copy_till_zero
271
        copy_till_zero
272
 
272
 
273
; If we are using a proxy, send complete URL, otherwise send only page address.
273
; If we are using a proxy, send complete URL, otherwise send only page address.
274
        cmp     [proxyAddr], 0
274
        cmp     [proxyAddr], 0
275
        je      .no_proxy
275
        je      .no_proxy
276
        mov     esi, str_http           ; prepend 'http://'
276
        mov     esi, str_http           ; prepend 'http://'
277
        copy_till_zero
277
        copy_till_zero
278
        mov     esi, [hostname]
278
        mov     esi, [hostname]
279
        copy_till_zero
279
        copy_till_zero
280
  .no_proxy:
280
  .no_proxy:
281
        mov     esi, [pageaddr]
281
        mov     esi, [pageaddr]
282
        copy_till_zero
282
        copy_till_zero
283
 
283
 
284
        mov     esi, str_http11
284
        mov     esi, str_http11
285
        mov     ecx, str_http11.length
285
        mov     ecx, str_http11.length
286
        rep     movsb
286
        rep     movsb
287
 
287
 
288
        mov     esi, [hostname]
288
        mov     esi, [hostname]
289
        copy_till_zero
289
        copy_till_zero
290
 
290
 
291
        cmp     byte[proxyUser], 0
291
        cmp     byte[proxyUser], 0
292
        je      @f
292
        je      @f
293
        call    append_proxy_auth_header
293
        call    append_proxy_auth_header
294
  @@:
294
  @@:
295
 
295
 
296
        mov     ax, 0x0a0d
296
        mov     ax, 0x0a0d
297
        stosw
297
        stosw
298
 
298
 
299
        mov     esi, [add_header]
299
        mov     esi, [add_header]
300
        test    esi, esi
300
        test    esi, esi
301
        jz      @f
301
        jz      @f
302
        copy_till_zero
302
        copy_till_zero
303
  @@:
303
  @@:
304
 
304
 
305
        mov     esi, str_close
305
        mov     esi, str_close
306
        mov     ecx, str_close.length
306
        mov     ecx, str_close.length
307
        test    [flags], FLAG_KEEPALIVE
307
        test    [flags], FLAG_KEEPALIVE
308
        jz      @f
308
        jz      @f
309
        mov     esi, str_keep
309
        mov     esi, str_keep
310
        mov     ecx, str_keep.length
310
        mov     ecx, str_keep.length
311
  @@:
311
  @@:
312
        rep     movsb
312
        rep     movsb
313
 
313
 
314
        mov     byte[edi], 0
314
        mov     byte[edi], 0
315
        DEBUGF  1, "Request:\n%s", [buffer]
315
        DEBUGF  1, "Request:\n%s", [buffer]
316
 
316
 
317
; Free unused memory
317
; Free unused memory
318
        push    edi
318
        push    edi
319
        invoke  mem.free, [pageaddr]
319
        invoke  mem.free, [pageaddr]
320
        invoke  mem.free, [hostname]
320
        invoke  mem.free, [hostname]
321
        pop     esi
321
        pop     esi
322
 
322
 
323
; Send the request
323
; Send the request
324
        sub     esi, [buffer]   ; length
324
        sub     esi, [buffer]   ; length
325
        xor     edi, edi        ; flags
325
        xor     edi, edi        ; flags
326
        mcall   send, [socketnum], [buffer]
326
        mcall   send, [socketnum], [buffer]
327
        test    eax, eax
327
        test    eax, eax
328
        jz      .error
328
        jz      .error
329
        DEBUGF  1, "Request has been sent to server.\n"
329
        DEBUGF  1, "Request has been sent to server.\n"
330
 
330
 
331
        cmp     [identifier], 0
331
        cmp     [identifier], 0
332
        je      .new_connection
332
        je      .new_connection
333
        invoke  mem.free, [buffer]
333
        invoke  mem.free, [buffer]
334
        mov     eax, [identifier]
334
        mov     eax, [identifier]
335
        mov     [buffer], eax
335
        mov     [buffer], eax
336
  .new_connection:
336
  .new_connection:
337
        HTTP_init_buffer [buffer], [socketnum], [flags]
337
        HTTP_init_buffer [buffer], [socketnum], [flags]
338
        popa
338
        popa
339
        mov     eax, [buffer]   ; return buffer ptr
339
        mov     eax, [buffer]   ; return buffer ptr
340
        ret
340
        ret
341
 
341
 
342
  .error:
342
  .error:
343
        DEBUGF  2, "HTTP GET error!\n"
343
        DEBUGF  2, "HTTP GET error!\n"
344
        popa
344
        popa
345
        xor     eax, eax        ; return 0 = error
345
        xor     eax, eax        ; return 0 = error
346
        ret
346
        ret
347
 
347
 
348
endp
348
endp
349
 
349
 
350
 
350
 
351
 
351
 
352
;;================================================================================================;;
352
;;================================================================================================;;
353
proc HTTP_head URL, identifier, flags, add_header ;///////////////////////////////////////////////;;
353
proc HTTP_head URL, identifier, flags, add_header ;///////////////////////////////////////////////;;
354
;;------------------------------------------------------------------------------------------------;;
354
;;------------------------------------------------------------------------------------------------;;
355
;? Initiates a HTTP connection, using 'HEAD' method.                                              ;;
355
;? Initiates a HTTP connection, using 'HEAD' method.                                              ;;
356
;? This will only return HTTP header and status, no content                                       ;;
356
;? This will only return HTTP header and status, no content                                       ;;
357
;;------------------------------------------------------------------------------------------------;;
357
;;------------------------------------------------------------------------------------------------;;
358
;> URL                  = pointer to ASCIIZ URL                                                   ;;
358
;> URL                  = pointer to ASCIIZ URL                                                   ;;
359
;> identifier           = Identifier of an already open connection, or NULL to create a new one.  ;;
359
;> identifier           = Identifier of an already open connection, or NULL to create a new one.  ;;
360
;> flags                = Flags indicating how to threat the connection.                          ;;
360
;> flags                = Flags indicating how to threat the connection.                          ;;
361
;> add_header           = pointer to additional header parameters (ASCIIZ), or NULL for none.     ;;
361
;> add_header           = pointer to additional header parameters (ASCIIZ), or NULL for none.     ;;
362
;;------------------------------------------------------------------------------------------------;;
362
;;------------------------------------------------------------------------------------------------;;
363
;< eax = 0 (error) / buffer ptr                                                                   ;;
363
;< eax = 0 (error) / buffer ptr                                                                   ;;
364
;;================================================================================================;;
364
;;================================================================================================;;
365
locals
365
locals
366
        hostname        dd ?
366
        hostname        dd ?
367
        pageaddr        dd ?
367
        pageaddr        dd ?
368
        socketnum       dd ?
368
        socketnum       dd ?
369
        buffer          dd ?
369
        buffer          dd ?
370
        port            dd ?
370
        port            dd ?
371
endl
371
endl
372
 
372
 
373
        and     [flags], 0xff00         ; filter out invalid flags
373
        and     [flags], 0xff00         ; filter out invalid flags
374
 
374
 
375
        pusha
375
        pusha
376
; split the URL into hostname and pageaddr
376
; split the URL into hostname and pageaddr
377
        stdcall parse_url, [URL]
377
        stdcall parse_url, [URL]
378
        test    eax, eax
378
        test    eax, eax
379
        jz      .error
379
        jz      .error
380
        mov     [hostname], eax
380
        mov     [hostname], eax
381
        mov     [pageaddr], ebx
381
        mov     [pageaddr], ebx
382
        mov     [port], ecx
382
        mov     [port], ecx
383
 
383
 
384
        mov     eax, [identifier]
384
        mov     eax, [identifier]
385
        test    eax, eax
385
        test    eax, eax
386
        jz      .open_new
386
        jz      .open_new
387
        test    [eax + http_msg.flags], FLAG_CONNECTED
387
        test    [eax + http_msg.flags], FLAG_CONNECTED
388
        jz      .error
388
        jz      .error
389
        mov     eax, [eax + http_msg.socket]
389
        mov     eax, [eax + http_msg.socket]
390
        mov     [socketnum], eax
390
        mov     [socketnum], eax
391
        jmp     .send_request
391
        jmp     .send_request
392
 
392
 
393
; Connect to the other side.
393
; Connect to the other side.
394
  .open_new:
394
  .open_new:
395
        stdcall open_connection, [hostname], [port]
395
        stdcall open_connection, [hostname], [port]
396
        test    eax, eax
396
        test    eax, eax
397
        jz      .error
397
        jz      .error
398
        mov     [socketnum], eax
398
        mov     [socketnum], eax
399
 
399
 
400
; Create the HTTP request.
400
; Create the HTTP request.
401
  .send_request:
401
  .send_request:
402
        invoke  mem.alloc, [buffersize]
402
        invoke  mem.alloc, [buffersize]
403
        test    eax, eax
403
        test    eax, eax
404
        jz      .error
404
        jz      .error
405
        mov     [buffer], eax
405
        mov     [buffer], eax
406
        mov     edi, eax
406
        mov     edi, eax
407
        DEBUGF  1, "Buffer has been allocated.\n"
407
        DEBUGF  1, "Buffer has been allocated.\n"
408
 
408
 
409
        mov     esi, str_head
409
        mov     esi, str_head
410
        copy_till_zero
410
        copy_till_zero
411
 
411
 
412
; If we are using a proxy, send complete URL, otherwise send only page address.
412
; If we are using a proxy, send complete URL, otherwise send only page address.
413
        cmp     [proxyAddr], 0
413
        cmp     [proxyAddr], 0
414
        je      .no_proxy
414
        je      .no_proxy
415
        mov     esi, str_http           ; prepend 'http://'
415
        mov     esi, str_http           ; prepend 'http://'
416
        copy_till_zero
416
        copy_till_zero
417
        mov     esi, [hostname]
417
        mov     esi, [hostname]
418
        copy_till_zero
418
        copy_till_zero
419
  .no_proxy:
419
  .no_proxy:
420
        mov     esi, [pageaddr]
420
        mov     esi, [pageaddr]
421
        copy_till_zero
421
        copy_till_zero
422
 
422
 
423
        mov     esi, str_http11
423
        mov     esi, str_http11
424
        mov     ecx, str_http11.length
424
        mov     ecx, str_http11.length
425
        rep     movsb
425
        rep     movsb
426
 
426
 
427
        mov     esi, [hostname]
427
        mov     esi, [hostname]
428
        copy_till_zero
428
        copy_till_zero
429
 
429
 
430
        cmp     byte[proxyUser], 0
430
        cmp     byte[proxyUser], 0
431
        je      @f
431
        je      @f
432
        call    append_proxy_auth_header
432
        call    append_proxy_auth_header
433
  @@:
433
  @@:
434
 
434
 
435
        mov     ax, 0x0a0d
435
        mov     ax, 0x0a0d
436
        stosw
436
        stosw
437
 
437
 
438
        mov     esi, [add_header]
438
        mov     esi, [add_header]
439
        test    esi, esi
439
        test    esi, esi
440
        jz      @f
440
        jz      @f
441
        copy_till_zero
441
        copy_till_zero
442
  @@:
442
  @@:
443
 
443
 
444
        mov     esi, str_close
444
        mov     esi, str_close
445
        mov     ecx, str_close.length
445
        mov     ecx, str_close.length
446
        test    [flags], FLAG_KEEPALIVE
446
        test    [flags], FLAG_KEEPALIVE
447
        jz      @f
447
        jz      @f
448
        mov     esi, str_keep
448
        mov     esi, str_keep
449
        mov     ecx, str_keep.length
449
        mov     ecx, str_keep.length
450
  @@:
450
  @@:
451
        rep     movsb
451
        rep     movsb
452
 
452
 
453
        mov     byte[edi], 0
453
        mov     byte[edi], 0
454
        DEBUGF  1, "Request:\n%s", [buffer]
454
        DEBUGF  1, "Request:\n%s", [buffer]
455
 
455
 
456
; Free unused memory
456
; Free unused memory
457
        push    edi
457
        push    edi
458
        invoke  mem.free, [pageaddr]
458
        invoke  mem.free, [pageaddr]
459
        invoke  mem.free, [hostname]
459
        invoke  mem.free, [hostname]
460
        pop     esi
460
        pop     esi
461
 
461
 
462
; Send the request
462
; Send the request
463
        sub     esi, [buffer]   ; length
463
        sub     esi, [buffer]   ; length
464
        xor     edi, edi        ; flags
464
        xor     edi, edi        ; flags
465
        mcall   send, [socketnum], [buffer]
465
        mcall   send, [socketnum], [buffer]
466
        test    eax, eax
466
        test    eax, eax
467
        jz      .error
467
        jz      .error
468
        DEBUGF  1, "Request has been sent to server.\n"
468
        DEBUGF  1, "Request has been sent to server.\n"
469
 
469
 
470
        cmp     [identifier], 0
470
        cmp     [identifier], 0
471
        je      .new_connection
471
        je      .new_connection
472
        invoke  mem.free, [buffer]
472
        invoke  mem.free, [buffer]
473
        mov     eax, [identifier]
473
        mov     eax, [identifier]
474
        mov     [buffer], eax
474
        mov     [buffer], eax
475
  .new_connection:
475
  .new_connection:
476
        HTTP_init_buffer [buffer], [socketnum], [flags]
476
        HTTP_init_buffer [buffer], [socketnum], [flags]
477
        popa
477
        popa
478
        mov     eax, [buffer]   ; return buffer ptr
478
        mov     eax, [buffer]   ; return buffer ptr
479
        ret
479
        ret
480
 
480
 
481
  .error:
481
  .error:
482
        DEBUGF  2, "HTTP HEAD error!\n"
482
        DEBUGF  2, "HTTP HEAD error!\n"
483
        popa
483
        popa
484
        xor     eax, eax        ; return 0 = error
484
        xor     eax, eax        ; return 0 = error
485
        ret
485
        ret
486
 
486
 
487
endp
487
endp
488
 
488
 
489
 
489
 
490
;;================================================================================================;;
490
;;================================================================================================;;
491
proc HTTP_post URL, identifier, flags, add_header, content_type, content_length ;/////////////////;;
491
proc HTTP_post URL, identifier, flags, add_header, content_type, content_length ;/////////////////;;
492
;;------------------------------------------------------------------------------------------------;;
492
;;------------------------------------------------------------------------------------------------;;
493
;? Initiates a HTTP connection, using 'POST' method.                                              ;;
493
;? Initiates a HTTP connection, using 'POST' method.                                              ;;
494
;? This method is used to send data to the HTTP server                                            ;;
494
;? This method is used to send data to the HTTP server                                            ;;
495
;;------------------------------------------------------------------------------------------------;;
495
;;------------------------------------------------------------------------------------------------;;
496
;> URL                  = pointer to ASCIIZ URL                                                   ;;
496
;> URL                  = pointer to ASCIIZ URL                                                   ;;
497
;> identifier           = Identifier of an already open connection, or NULL to create a new one.  ;;
497
;> identifier           = Identifier of an already open connection, or NULL to create a new one.  ;;
498
;> flags                = Flags indicating how to threat the connection.                          ;;
498
;> flags                = Flags indicating how to threat the connection.                          ;;
499
;> add_header           = pointer to additional header parameters (ASCIIZ), or NULL for none.     ;;
499
;> add_header           = pointer to additional header parameters (ASCIIZ), or NULL for none.     ;;
500
;> content_type         = pointer to ASCIIZ string containing content type                        ;;
500
;> content_type         = pointer to ASCIIZ string containing content type                        ;;
501
;> content_length       = length of content (in bytes)                                            ;;
501
;> content_length       = length of content (in bytes)                                            ;;
502
;;------------------------------------------------------------------------------------------------;;
502
;;------------------------------------------------------------------------------------------------;;
503
;< eax = 0 (error) / buffer ptr (aka Identifier)                                                  ;;
503
;< eax = 0 (error) / buffer ptr (aka Identifier)                                                  ;;
504
;;================================================================================================;;
504
;;================================================================================================;;
505
locals
505
locals
506
        hostname        dd ?
506
        hostname        dd ?
507
        pageaddr        dd ?
507
        pageaddr        dd ?
508
        socketnum       dd ?
508
        socketnum       dd ?
509
        buffer          dd ?
509
        buffer          dd ?
510
        port            dd ?
510
        port            dd ?
511
endl
511
endl
512
 
512
 
513
        DEBUGF  1, "HTTP POST (%s).\n", [URL]
513
        DEBUGF  1, "HTTP POST (%s).\n", [URL]
514
 
514
 
515
        and     [flags], 0xff00       ; filter out invalid flags
515
        and     [flags], 0xff00       ; filter out invalid flags
516
 
516
 
517
        pusha
517
        pusha
518
; split the URL into hostname and pageaddr
518
; split the URL into hostname and pageaddr
519
        stdcall parse_url, [URL]
519
        stdcall parse_url, [URL]
520
        test    eax, eax
520
        test    eax, eax
521
        jz      .error
521
        jz      .error
522
        mov     [hostname], eax
522
        mov     [hostname], eax
523
        mov     [pageaddr], ebx
523
        mov     [pageaddr], ebx
524
        mov     [port], ecx
524
        mov     [port], ecx
525
 
525
 
526
        mov     eax, [identifier]
526
        mov     eax, [identifier]
527
        test    eax, eax
527
        test    eax, eax
528
        jz      .open_new
528
        jz      .open_new
529
        test    [eax + http_msg.flags], FLAG_CONNECTED
529
        test    [eax + http_msg.flags], FLAG_CONNECTED
530
        jz      .error
530
        jz      .error
531
        mov     eax, [eax + http_msg.socket]
531
        mov     eax, [eax + http_msg.socket]
532
        mov     [socketnum], eax
532
        mov     [socketnum], eax
533
        jmp     .send_request
533
        jmp     .send_request
534
 
534
 
535
; Connect to the other side.
535
; Connect to the other side.
536
  .open_new:
536
  .open_new:
537
        DEBUGF  1, "Opening new connection.\n"
537
        DEBUGF  1, "Opening new connection.\n"
538
        stdcall open_connection, [hostname], [port]
538
        stdcall open_connection, [hostname], [port]
539
        test    eax, eax
539
        test    eax, eax
540
        jz      .error
540
        jz      .error
541
        mov     [socketnum], eax
541
        mov     [socketnum], eax
542
 
542
 
543
; Create the HTTP request.
543
; Create the HTTP request.
544
  .send_request:
544
  .send_request:
545
        invoke  mem.alloc, [buffersize]
545
        invoke  mem.alloc, [buffersize]
546
        test    eax, eax
546
        test    eax, eax
547
        jz      .error
547
        jz      .error
548
        mov     [buffer], eax
548
        mov     [buffer], eax
549
        mov     edi, eax
549
        mov     edi, eax
550
        DEBUGF  1, "Buffer has been allocated.\n"
550
        DEBUGF  1, "Buffer has been allocated.\n"
551
 
551
 
552
        mov     esi, str_post
552
        mov     esi, str_post
553
        copy_till_zero
553
        copy_till_zero
554
 
554
 
555
; If we are using a proxy, send complete URL, otherwise send only page address.
555
; If we are using a proxy, send complete URL, otherwise send only page address.
556
        cmp     [proxyAddr], 0
556
        cmp     [proxyAddr], 0
557
        je      .no_proxy
557
        je      .no_proxy
558
        mov     esi, str_http           ; prepend 'http://'
558
        mov     esi, str_http           ; prepend 'http://'
559
        copy_till_zero
559
        copy_till_zero
560
        mov     esi, [hostname]
560
        mov     esi, [hostname]
561
        copy_till_zero
561
        copy_till_zero
562
  .no_proxy:
562
  .no_proxy:
563
        mov     esi, [pageaddr]
563
        mov     esi, [pageaddr]
564
        copy_till_zero
564
        copy_till_zero
565
 
565
 
566
        mov     esi, str_http11
566
        mov     esi, str_http11
567
        mov     ecx, str_http11.length
567
        mov     ecx, str_http11.length
568
        rep     movsb
568
        rep     movsb
569
 
569
 
570
        mov     esi, [hostname]
570
        mov     esi, [hostname]
571
        copy_till_zero
571
        copy_till_zero
572
 
572
 
573
        mov     esi, str_post_cl
573
        mov     esi, str_post_cl
574
        mov     ecx, str_post_cl.length
574
        mov     ecx, str_post_cl.length
575
        rep     movsb
575
        rep     movsb
576
 
576
 
577
        mov     eax, [content_length]
577
        mov     eax, [content_length]
578
        call    eax_ascii_dec
578
        call    eax_ascii_dec
579
 
579
 
580
        mov     esi, str_post_ct
580
        mov     esi, str_post_ct
581
        mov     ecx, str_post_ct.length
581
        mov     ecx, str_post_ct.length
582
        rep     movsb
582
        rep     movsb
583
 
583
 
584
        mov     esi, [content_type]
584
        mov     esi, [content_type]
585
        copy_till_zero
585
        copy_till_zero
586
 
586
 
587
        cmp     byte[proxyUser], 0
587
        cmp     byte[proxyUser], 0
588
        je      @f
588
        je      @f
589
        call    append_proxy_auth_header
589
        call    append_proxy_auth_header
590
  @@:
590
  @@:
591
 
591
 
592
        mov     ax, 0x0a0d
592
        mov     ax, 0x0a0d
593
        stosw
593
        stosw
594
 
594
 
595
        mov     esi, [add_header]
595
        mov     esi, [add_header]
596
        test    esi, esi
596
        test    esi, esi
597
        jz      @f
597
        jz      @f
598
        copy_till_zero
598
        copy_till_zero
599
  @@:
599
  @@:
600
 
600
 
601
        mov     esi, str_close
601
        mov     esi, str_close
602
        mov     ecx, str_close.length
602
        mov     ecx, str_close.length
603
        test    [flags], FLAG_KEEPALIVE
603
        test    [flags], FLAG_KEEPALIVE
604
        jz      @f
604
        jz      @f
605
        mov     esi, str_keep
605
        mov     esi, str_keep
606
        mov     ecx, str_keep.length
606
        mov     ecx, str_keep.length
607
  @@:
607
  @@:
608
        rep     movsb
608
        rep     movsb
609
 
609
 
610
        mov     byte[edi], 0
610
        mov     byte[edi], 0
611
        DEBUGF  1, "Request:\n%s", [buffer]
611
        DEBUGF  1, "Request:\n%s", [buffer]
612
 
612
 
613
; Free unused memory
613
; Free unused memory
614
        push    edi
614
        push    edi
615
        invoke  mem.free, [pageaddr]
615
        invoke  mem.free, [pageaddr]
616
        invoke  mem.free, [hostname]
616
        invoke  mem.free, [hostname]
617
        pop     esi
617
        pop     esi
618
 
618
 
619
; Send the request
619
; Send the request
620
        sub     esi, [buffer]   ; length
620
        sub     esi, [buffer]   ; length
621
        xor     edi, edi        ; flags
621
        xor     edi, edi        ; flags
622
        mcall   send, [socketnum], [buffer]
622
        mcall   send, [socketnum], [buffer]
623
        test    eax, eax
623
        test    eax, eax
624
        jz      .error
624
        jz      .error
625
        DEBUGF  1, "Request has been sent to server.\n"
625
        DEBUGF  1, "Request has been sent to server.\n"
626
 
626
 
627
        cmp     [identifier], 0
627
        cmp     [identifier], 0
628
        je      .new_connection
628
        je      .new_connection
629
        invoke  mem.free, [buffer]
629
        invoke  mem.free, [buffer]
630
        mov     eax, [identifier]
630
        mov     eax, [identifier]
631
        mov     [buffer], eax
631
        mov     [buffer], eax
632
  .new_connection:
632
  .new_connection:
633
        HTTP_init_buffer [buffer], [socketnum], [flags]
633
        HTTP_init_buffer [buffer], [socketnum], [flags]
634
        popa
634
        popa
635
        mov     eax, [buffer]   ; return buffer ptr
635
        mov     eax, [buffer]   ; return buffer ptr
636
        DEBUGF  1, "HTTP POST complete.\n"
636
        DEBUGF  1, "HTTP POST complete.\n"
637
        ret
637
        ret
638
 
638
 
639
  .error:
639
  .error:
640
        DEBUGF  2, "HTTP POST error!\n"
640
        DEBUGF  2, "HTTP POST error!\n"
641
        popa
641
        popa
642
        xor     eax, eax        ; return 0 = error
642
        xor     eax, eax        ; return 0 = error
643
        ret
643
        ret
644
 
644
 
645
endp
645
endp
646
 
646
 
647
 
647
 
648
 
648
 
649
;;================================================================================================;;
649
;;================================================================================================;;
650
proc HTTP_receive identifier ;////////////////////////////////////////////////////////////////////;;
650
proc HTTP_receive identifier ;////////////////////////////////////////////////////////////////////;;
651
;;------------------------------------------------------------------------------------------------;;
651
;;------------------------------------------------------------------------------------------------;;
652
;? Receive data from the server, parse headers and put data in receive buffer(s).                 ;;
652
;? Receive data from the server, parse headers and put data in receive buffer(s).                 ;;
653
;? To complete a transfer, this procedure must be called over and over again untill it returns 0. ;;
653
;? To complete a transfer, this procedure must be called over and over again untill it returns 0. ;;
654
;;------------------------------------------------------------------------------------------------;;
654
;;------------------------------------------------------------------------------------------------;;
655
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
655
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
656
;;------------------------------------------------------------------------------------------------;;
656
;;------------------------------------------------------------------------------------------------;;
657
;< eax = -1 (not finished) / 0 finished                                                           ;;
657
;< eax = -1 (not finished) / 0 finished                                                           ;;
658
;;================================================================================================;;
658
;;================================================================================================;;
659
 
659
 
660
        pusha
660
        pusha
661
        mov     ebp, [identifier]
661
        mov     ebp, [identifier]
662
 
662
 
663
; If the connection is closed, return immediately
663
; If the connection is closed, return immediately
664
        test    [ebp + http_msg.flags], FLAG_CONNECTED
664
        test    [ebp + http_msg.flags], FLAG_CONNECTED
665
        jz      .connection_closed
665
        jz      .connection_closed
666
 
666
 
667
; Check if our receive buffer still has space
667
; Check if our receive buffer still has space
668
        cmp     [ebp + http_msg.buffer_length], 0
668
        cmp     [ebp + http_msg.buffer_length], 0
669
        jne     .receive
669
        jne     .receive
670
 
670
 
671
        test    [ebp + http_msg.flags], FLAG_RING
671
        test    [ebp + http_msg.flags], FLAG_RING
672
        jnz     .need_more_space
672
        jnz     .need_more_space
673
 
673
 
674
        test    [ebp + http_msg.flags], FLAG_STREAM
674
        test    [ebp + http_msg.flags], FLAG_STREAM
675
        jz      .err_header
675
        jz      .err_header
676
 
676
 
677
        test    [ebp + http_msg.flags], FLAG_REUSE_BUFFER
677
        test    [ebp + http_msg.flags], FLAG_REUSE_BUFFER
678
        jz      .new_buffer
678
        jz      .new_buffer
679
 
679
 
680
        mov     eax, [ebp + http_msg.content_ptr]
680
        mov     eax, [ebp + http_msg.content_ptr]
681
        mov     [ebp + http_msg.write_ptr], eax
681
        mov     [ebp + http_msg.write_ptr], eax
682
        push    [buffersize]
682
        push    [buffersize]
683
        pop     [ebp + http_msg.buffer_length]
683
        pop     [ebp + http_msg.buffer_length]
684
        jmp     .receive
684
        jmp     .receive
685
 
685
 
686
  .new_buffer:
686
  .new_buffer:
687
        invoke  mem.alloc, [buffersize]
687
        invoke  mem.alloc, [buffersize]
688
        test    eax, eax
688
        test    eax, eax
689
        jz      .err_no_ram
689
        jz      .err_no_ram
690
        mov     [ebp + http_msg.content_ptr], eax
690
        mov     [ebp + http_msg.content_ptr], eax
691
        mov     [ebp + http_msg.write_ptr], eax
691
        mov     [ebp + http_msg.write_ptr], eax
692
        push    [buffersize]
692
        push    [buffersize]
693
        pop     [ebp + http_msg.buffer_length]
693
        pop     [ebp + http_msg.buffer_length]
694
        DEBUGF  1, "New buffer: 0x%x\n", eax
694
        DEBUGF  1, "New buffer: 0x%x\n", eax
695
 
695
 
696
; Receive some data
696
; Receive some data
697
  .receive:
697
  .receive:
698
        mov     edi, MSG_DONTWAIT
698
        mov     edi, MSG_DONTWAIT
699
        test    [ebp + http_msg.flags], FLAG_BLOCK
699
        test    [ebp + http_msg.flags], FLAG_BLOCK
700
        jz      @f
700
        jz      @f
701
        xor     edi, edi
701
        xor     edi, edi
702
  @@:
702
  @@:
703
        mcall   recv, [ebp + http_msg.socket], [ebp + http_msg.write_ptr], \
703
        mcall   recv, [ebp + http_msg.socket], [ebp + http_msg.write_ptr], \
704
                      [ebp + http_msg.buffer_length]
704
                      [ebp + http_msg.buffer_length]
705
        cmp     eax, 0xffffffff
705
        cmp     eax, 0xffffffff
706
        je      .check_socket
706
        je      .check_socket
707
 
707
 
708
        test    eax, eax
708
        test    eax, eax
709
        jz      .server_closed
709
        jz      .server_closed
710
        DEBUGF  1, "Received %u bytes ", eax
710
        DEBUGF  1, "Received %u bytes ", eax
711
 
711
 
712
; Update timestamp
712
; Update timestamp
713
        push    eax
713
        push    eax
714
        mcall   26, 9
714
        mcall   26, 9
715
        mov     [ebp + http_msg.timestamp], eax
715
        mov     [ebp + http_msg.timestamp], eax
716
        pop     eax
716
        pop     eax
717
 
717
 
718
; Update pointers
718
; Update pointers
719
        mov     edi, [ebp + http_msg.write_ptr]
719
        mov     edi, [ebp + http_msg.write_ptr]
720
        add     [ebp + http_msg.write_ptr], eax
720
        add     [ebp + http_msg.write_ptr], eax
721
        sub     [ebp + http_msg.buffer_length], eax
721
        sub     [ebp + http_msg.buffer_length], eax
722
        DEBUGF  1, "buffer length = %d\n", [ebp + http_msg.buffer_length]
722
        DEBUGF  1, "buffer length = %d\n", [ebp + http_msg.buffer_length]
723
 
723
 
724
; If data is chunked, combine chunks into contiguous data.
724
; If data is chunked, combine chunks into contiguous data.
725
        test    [ebp + http_msg.flags], FLAG_CHUNKED
725
        test    [ebp + http_msg.flags], FLAG_CHUNKED
726
        jnz     .chunk_loop
726
        jnz     .chunk_loop
727
 
727
 
728
; Did we detect the (final) header yet?
728
; Did we detect the (final) header yet?
729
        test    [ebp + http_msg.flags], FLAG_GOT_HEADER
729
        test    [ebp + http_msg.flags], FLAG_GOT_HEADER
730
        jnz     .header_parsed
730
        jnz     .header_parsed
731
 
731
 
732
;--------------------------------------------------------------
732
;--------------------------------------------------------------
733
;
733
;
734
; Header parsing code begins here
734
; Header parsing code begins here
735
;
735
;
736
 
736
 
737
; We havent found the (final) header yet, search for it..
737
; We havent found the (final) header yet, search for it..
738
  .scan_again:
738
  .scan_again:
739
        ; eax = total number of bytes received so far
739
        ; eax = total number of bytes received so far
740
        mov     eax, [ebp + http_msg.write_ptr]
740
        mov     eax, [ebp + http_msg.write_ptr]
741
        sub     eax, http_msg.http_header
741
        sub     eax, http_msg.http_header
742
        sub     eax, ebp
742
        sub     eax, ebp
743
        sub     eax, [ebp + http_msg.header_length]
743
        sub     eax, [ebp + http_msg.header_length]
744
        ; edi is ptr to begin of header
744
        ; edi is ptr to begin of header
745
        lea     edi, [ebp + http_msg.http_header]
745
        lea     edi, [ebp + http_msg.http_header]
746
        add     edi, [ebp + http_msg.header_length]
746
        add     edi, [ebp + http_msg.header_length]
747
        ; put it in esi for next proc too
747
        ; put it in esi for next proc too
748
        mov     esi, edi
748
        mov     esi, edi
749
        sub     eax, 3
749
        sub     eax, 3
750
        jle     .need_more_data_for_header
750
        jle     .need_more_data_for_header
751
  .scan_loop:
751
  .scan_loop:
752
        ; scan for end of header (empty line)
752
        ; scan for end of header (empty line)
753
        cmp     dword[edi], 0x0a0d0a0d                  ; end of header
753
        cmp     dword[edi], 0x0a0d0a0d                  ; end of header
754
        je      .end_of_header
754
        je      .end_of_header
755
        cmp     word[edi+2], 0x0a0a                     ; notice the use of offset + 2, to calculate header length correctly :)
755
        cmp     word[edi+2], 0x0a0a                     ; notice the use of offset + 2, to calculate header length correctly :)
756
        je      .end_of_header
756
        je      .end_of_header
757
        inc     edi
757
        inc     edi
758
        dec     eax
758
        dec     eax
759
        jnz     .scan_loop
759
        jnz     .scan_loop
760
        jmp     .need_more_data_for_header
760
        jmp     .need_more_data_for_header
761
 
761
 
762
  .end_of_header:
762
  .end_of_header:
763
        add     edi, 4 - http_msg.http_header
763
        add     edi, 4 - http_msg.http_header
764
        sub     edi, ebp
764
        sub     edi, ebp
765
        mov     [ebp + http_msg.header_length], edi     ; If this isnt the final header, we'll use this as an offset to find real header.
765
        mov     [ebp + http_msg.header_length], edi     ; If this isnt the final header, we'll use this as an offset to find real header.
766
        DEBUGF  1, "Header length: %u\n", edi
766
        DEBUGF  1, "Header length: %u\n", edi
767
 
767
 
768
; Ok, we have found the header
768
; Ok, we have found the header
769
        cmp     dword[esi], 'HTTP'
769
        cmp     dword[esi], 'HTTP'
770
        jne     .err_header
770
        jne     .err_header
771
        cmp     dword[esi+4], '/1.0'
771
        cmp     dword[esi+4], '/1.0'
772
        je      .http_1.0
772
        je      .http_1.0
773
        cmp     dword[esi+4], '/1.1'
773
        cmp     dword[esi+4], '/1.1'
774
        jne     .err_header
774
        jne     .err_header
775
        or      [ebp + http_msg.flags], FLAG_HTTP11
775
        or      [ebp + http_msg.flags], FLAG_HTTP11
776
  .http_1.0:
776
  .http_1.0:
777
        cmp     byte[esi+8], ' '
777
        cmp     byte[esi+8], ' '
778
        jne     .err_header
778
        jne     .err_header
779
 
779
 
780
        add     esi, 9
780
        add     esi, 9
781
        xor     eax, eax
781
        xor     eax, eax
782
        xor     ebx, ebx
782
        xor     ebx, ebx
783
        mov     ecx, 3
783
        mov     ecx, 3
784
  .statusloop:
784
  .statusloop:
785
        lodsb
785
        lodsb
786
        sub     al, '0'
786
        sub     al, '0'
787
        jb      .err_header
787
        jb      .err_header
788
        cmp     al, 9
788
        cmp     al, 9
789
        ja      .err_header
789
        ja      .err_header
790
        lea     ebx, [ebx + 4*ebx]
790
        lea     ebx, [ebx + 4*ebx]
791
        shl     ebx, 1
791
        shl     ebx, 1
792
        add     ebx, eax
792
        add     ebx, eax
793
        dec     ecx
793
        dec     ecx
794
        jnz     .statusloop
794
        jnz     .statusloop
795
 
795
 
796
; Ignore "100 - Continue" lines
796
; Ignore "100 - Continue" lines
797
        cmp     ebx, 100
797
        cmp     ebx, 100
798
        je      .scan_again
798
        je      .scan_again
799
 
799
 
800
        DEBUGF  1, "Status: %u\n", ebx
800
        DEBUGF  1, "Status: %u\n", ebx
801
        mov     [ebp + http_msg.status], ebx
801
        mov     [ebp + http_msg.status], ebx
802
        or      [ebp + http_msg.flags], FLAG_GOT_HEADER
802
        or      [ebp + http_msg.flags], FLAG_GOT_HEADER
803
 
803
 
804
; Now, convert all header names to lowercase.
804
; Now, convert all header names to lowercase.
805
; This way, it will be much easier to find certain header fields, later on.
805
; This way, it will be much easier to find certain header fields, later on.
806
        lea     esi, [ebp + http_msg.http_header]
806
        lea     esi, [ebp + http_msg.http_header]
807
        mov     ecx, [ebp + http_msg.header_length]
807
        mov     ecx, [ebp + http_msg.header_length]
808
  .need_newline:
808
  .need_newline:
809
        inc     esi
809
        inc     esi
810
        dec     ecx
810
        dec     ecx
811
        jz      .convert_done
811
        jz      .convert_done
812
        cmp     byte[esi], 10
812
        cmp     byte[esi], 10
813
        jne     .need_newline
813
        jne     .need_newline
814
; We have found a newline
814
; We have found a newline
815
; A line beginning with space or tabs has no header fields.
815
; A line beginning with space or tabs has no header fields.
816
        inc     esi
816
        inc     esi
817
        dec     ecx
817
        dec     ecx
818
        jz      .convert_done
818
        jz      .convert_done
819
        cmp     byte[esi], ' '
819
        cmp     byte[esi], ' '
820
        je      .need_newline
820
        je      .need_newline
821
        cmp     byte[esi], 9    ; horizontal tab
821
        cmp     byte[esi], 9    ; horizontal tab
822
        je      .need_newline
822
        je      .need_newline
823
        jmp     .convert_loop
823
        jmp     .convert_loop
824
  .next_char:
824
  .next_char:
825
        inc     esi
825
        inc     esi
826
        dec     ecx
826
        dec     ecx
827
        jz      .convert_done
827
        jz      .convert_done
828
  .convert_loop:
828
  .convert_loop:
829
        cmp     byte[esi], ':'
829
        cmp     byte[esi], ':'
830
        je      .need_newline
830
        je      .need_newline
831
        cmp     byte[esi], 'A'
831
        cmp     byte[esi], 'A'
832
        jb      .next_char
832
        jb      .next_char
833
        cmp     byte[esi], 'Z'
833
        cmp     byte[esi], 'Z'
834
        ja      .next_char
834
        ja      .next_char
835
        or      byte[esi], 0x20 ; convert to lowercase
835
        or      byte[esi], 0x20 ; convert to lowercase
836
        jmp     .next_char
836
        jmp     .next_char
837
  .convert_done:
837
  .convert_done:
838
        mov     byte[esi-1], 0
838
        mov     byte[esi-1], 0
839
        lea     esi, [ebp + http_msg.http_header]
839
        lea     esi, [ebp + http_msg.http_header]
840
        DEBUGF  1, "Header names converted to lowercase:\n%s\n", esi
840
        DEBUGF  1, "Header names converted to lowercase:\n%s\n", esi
841
 
841
 
842
; Check for content-length header field.
842
; Check for content-length header field.
843
        stdcall HTTP_find_header_field, ebp, str_cl
843
        stdcall HTTP_find_header_field, ebp, str_cl
844
        test    eax, eax
844
        test    eax, eax
845
        jz      .no_content
845
        jz      .no_content
846
        or      [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
846
        or      [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
847
 
847
 
848
        xor     edx, edx
848
        xor     edx, edx
849
  .cl_loop:
849
  .cl_loop:
850
        movzx   ebx, byte[eax]
850
        movzx   ebx, byte[eax]
851
        inc     eax
851
        inc     eax
852
        cmp     bl, 10
852
        cmp     bl, 10
853
        je      .cl_ok
853
        je      .cl_ok
854
        cmp     bl, 13
854
        cmp     bl, 13
855
        je      .cl_ok
855
        je      .cl_ok
856
        cmp     bl, ' '
856
        cmp     bl, ' '
857
        je      .cl_ok
857
        je      .cl_ok
858
        sub     bl, '0'
858
        sub     bl, '0'
859
        jb      .err_header
859
        jb      .err_header
860
        cmp     bl, 9
860
        cmp     bl, 9
861
        ja      .err_header
861
        ja      .err_header
862
        lea     edx, [edx + edx*4]      ; edx = edx*10
862
        lea     edx, [edx + edx*4]      ; edx = edx*10
863
        shl     edx, 1                  ;
863
        shl     edx, 1                  ;
864
        add     edx, ebx
864
        add     edx, ebx
865
        jmp     .cl_loop
865
        jmp     .cl_loop
866
 
866
 
867
  .cl_ok:
867
  .cl_ok:
868
        mov     [ebp + http_msg.content_length], edx
868
        mov     [ebp + http_msg.content_length], edx
869
        DEBUGF  1, "Content-length: %u\n", edx
869
        DEBUGF  1, "Content-length: %u\n", edx
870
 
870
 
871
        test    edx, edx
871
        test    edx, edx
872
        jz      .got_all_data
872
        jz      .got_all_data
873
 
873
 
874
        call    alloc_contentbuff
874
        call    alloc_contentbuff
875
        test    eax, eax
875
        test    eax, eax
876
        jz      .err_no_ram
876
        jz      .err_no_ram
877
        xor     eax, eax
877
        xor     eax, eax
878
        jmp     .header_parsed
878
        jmp     .header_parsed
879
 
879
 
880
  .no_content:
880
  .no_content:
881
        DEBUGF  1, "Content-length not found.\n"
881
        DEBUGF  1, "Content-length not found.\n"
882
; We didnt find 'content-length', maybe server is using chunked transfer encoding?
882
; We didnt find 'content-length', maybe server is using chunked transfer encoding?
883
  .multibuffer:
883
  .multibuffer:
884
; Try to find 'transfer-encoding' header.
884
; Try to find 'transfer-encoding' header.
885
        stdcall HTTP_find_header_field, ebp, str_te
885
        stdcall HTTP_find_header_field, ebp, str_te
886
        test    eax, eax
886
        test    eax, eax
887
        jnz     .ct_hdr_found
887
        jnz     .ct_hdr_found
888
 
888
 
889
  .not_chunked:
889
  .not_chunked:
890
        mov     edx, [buffersize]
890
        mov     edx, [buffersize]
891
        call    alloc_contentbuff
891
        call    alloc_contentbuff
892
        test    eax, eax
892
        test    eax, eax
893
        jz      .err_no_ram
893
        jz      .err_no_ram
894
        xor     eax, eax
894
        xor     eax, eax
895
        jmp     .header_parsed
895
        jmp     .header_parsed
896
 
896
 
897
  .ct_hdr_found:
897
  .ct_hdr_found:
898
        mov     ebx, dword[eax]
898
        mov     ebx, dword[eax]
899
        or      ebx, 0x20202020
899
        or      ebx, 0x20202020
900
        cmp     ebx, 'chun'
900
        cmp     ebx, 'chun'
901
        jne     .not_chunked
901
        jne     .not_chunked
902
        mov     ebx, dword[eax+4]
902
        mov     ebx, dword[eax+4]
903
        or      ebx, 0x00202020
903
        or      ebx, 0x00202020
904
        and     ebx, 0x00ffffff
904
        and     ebx, 0x00ffffff
905
        cmp     ebx, 'ked'
905
        cmp     ebx, 'ked'
906
        jne     .not_chunked
906
        jne     .not_chunked
907
 
907
 
908
        or      [ebp + http_msg.flags], FLAG_CHUNKED
908
        or      [ebp + http_msg.flags], FLAG_CHUNKED
909
        DEBUGF  1, "Transfer type is: chunked\n"
909
        DEBUGF  1, "Transfer type is: chunked\n"
910
 
910
 
911
        mov     edx, [buffersize]
911
        mov     edx, [buffersize]
912
        call    alloc_contentbuff
912
        call    alloc_contentbuff
913
        test    eax, eax
913
        test    eax, eax
914
        jz      .err_no_ram
914
        jz      .err_no_ram
915
 
915
 
916
; Set chunk pointer where first chunk should begin.
916
; Set chunk pointer where first chunk should begin.
917
        mov     eax, [ebp + http_msg.content_ptr]
917
        mov     eax, [ebp + http_msg.content_ptr]
918
        mov     [ebp + http_msg.chunk_ptr], eax
918
        mov     [ebp + http_msg.chunk_ptr], eax
919
 
919
 
920
;--------------------------------------------------------------
920
;--------------------------------------------------------------
921
;
921
;
922
; Chunk parsing code begins here
922
; Chunk parsing code begins here
923
;
923
;
924
 
924
 
925
  .chunk_loop:
925
  .chunk_loop:
926
        DEBUGF  1, "chunk_loop write_ptr=0x%x chunk_ptr=0x%x\n", [ebp + http_msg.write_ptr], [ebp + http_msg.chunk_ptr]
926
        DEBUGF  1, "chunk_loop write_ptr=0x%x chunk_ptr=0x%x\n", [ebp + http_msg.write_ptr], [ebp + http_msg.chunk_ptr]
927
        mov     ecx, [ebp + http_msg.write_ptr]
927
        mov     ecx, [ebp + http_msg.write_ptr]
928
        sub     ecx, [ebp + http_msg.chunk_ptr]
928
        sub     ecx, [ebp + http_msg.chunk_ptr]
929
        jbe     .need_more_data_chunked                 ; amount of available bytes after chunkline start
929
        jbe     .need_more_data_chunked                 ; amount of available bytes after chunkline start
930
 
930
 
931
; Chunkline starts here, convert the ASCII hex number into ebx
931
; Chunkline starts here, convert the ASCII hex number into ebx
932
        mov     esi, [ebp + http_msg.chunk_ptr]
932
        mov     esi, [ebp + http_msg.chunk_ptr]
933
 
933
 
934
        xor     ebx, ebx
934
        xor     ebx, ebx
935
        cmp     byte[esi], 0x0d
935
        cmp     byte[esi], 0x0d
936
        jne     .chunk_hex_loop
936
        jne     .chunk_hex_loop
937
        dec     ecx
937
        dec     ecx
938
        jz      .need_more_data_chunked
938
        jz      .need_more_data_chunked
939
        inc     esi
939
        inc     esi
940
        cmp     byte[esi], 0x0a
940
        cmp     byte[esi], 0x0a
941
        jne     .chunk_hex_loop
941
        jne     .chunk_hex_loop
942
        dec     ecx
942
        dec     ecx
943
        jz      .need_more_data_chunked
943
        jz      .need_more_data_chunked
944
        inc     esi
944
        inc     esi
945
  .chunk_hex_loop:
945
  .chunk_hex_loop:
946
        lodsb
946
        lodsb
947
        sub     al, '0'
947
        sub     al, '0'
948
        jb      .chunk_hex_end
948
        jb      .chunk_hex_end
949
        cmp     al, 9
949
        cmp     al, 9
950
        jbe     .chunk_hex
950
        jbe     .chunk_hex
951
        sub     al, 'A' - '0' - 10
951
        sub     al, 'A' - '0' - 10
952
        jb      .chunk_hex_end
952
        jb      .chunk_hex_end
953
        cmp     al, 15
953
        cmp     al, 15
954
        jbe     .chunk_hex
954
        jbe     .chunk_hex
955
        sub     al, 'a' - 'A'
955
        sub     al, 'a' - 'A'
956
        cmp     al, 15
956
        cmp     al, 15
957
        ja      .chunk_hex_end
957
        ja      .chunk_hex_end
958
  .chunk_hex:
958
  .chunk_hex:
959
        shl     ebx, 4
959
        shl     ebx, 4
960
        add     bl, al
960
        add     bl, al
961
        dec     ecx
961
        dec     ecx
962
        jnz     .chunk_hex_loop
962
        jnz     .chunk_hex_loop
963
        jmp     .need_more_data_chunked
963
        jmp     .need_more_data_chunked
964
  .chunk_hex_end:
964
  .chunk_hex_end:
965
; Chunkline ends with a CR LF or simply LF
965
; Chunkline ends with a CR LF or simply LF
966
        dec     esi
966
        dec     esi
967
  .end_of_chunkline?:
967
  .end_of_chunkline?:
968
        lodsb
968
        lodsb
969
        cmp     al, 10                                  ; chunkline must always end with LF
969
        cmp     al, 10                                  ; chunkline must always end with LF
970
        je      .end_of_chunkline
970
        je      .end_of_chunkline
971
        dec     ecx
971
        dec     ecx
972
        jnz     .end_of_chunkline?
972
        jnz     .end_of_chunkline?
973
        xor     eax, eax
973
        xor     eax, eax
974
        jmp     .need_more_data_chunked                 ; chunkline is incomplete, request more data
974
        jmp     .need_more_data_chunked                 ; chunkline is incomplete, request more data
975
  .end_of_chunkline:
975
  .end_of_chunkline:
976
        DEBUGF  1, "Chunk of 0x%x bytes\n", ebx
976
        DEBUGF  1, "Chunk of 0x%x bytes\n", ebx
977
; If chunk size is 0, all chunks have been received.
977
; If chunk size is 0, all chunks have been received.
978
        test    ebx, ebx
978
        test    ebx, ebx
979
        jz      .got_all_data_chunked
979
        jz      .got_all_data_chunked
980
; Calculate chunkline length
980
; Calculate chunkline length
981
        mov     edx, esi
981
        mov     edx, esi
982
        sub     edx, [ebp + http_msg.chunk_ptr]         ; edx is now length of chunkline
982
        sub     edx, [ebp + http_msg.chunk_ptr]         ; edx is now length of chunkline
983
        DEBUGF  1, "Chunkline is %u bytes long\n", edx
983
        DEBUGF  1, "Chunkline is %u bytes long\n", edx
984
; Calculate how many data bytes we have received already
984
; Calculate how many data bytes we have received already
985
        mov     ecx, [ebp + http_msg.write_ptr]
985
        mov     ecx, [ebp + http_msg.write_ptr]
986
        sub     ecx, [ebp + http_msg.chunk_ptr]
986
        sub     ecx, [ebp + http_msg.chunk_ptr]
987
        sub     ecx, edx                                ; ecx is now number of received data bytes (without chunkline)
987
        sub     ecx, edx                                ; ecx is now number of received data bytes (without chunkline)
988
; Update content_received counter
988
; Update content_received counter
989
        add     [ebp + http_msg.content_received], ecx
989
        add     [ebp + http_msg.content_received], ecx
990
; Calculate new write ptr
990
; Calculate new write ptr
991
        sub     [ebp + http_msg.write_ptr], edx
991
        sub     [ebp + http_msg.write_ptr], edx
992
        test    [ebp + http_msg.flags], FLAG_STREAM
992
        test    [ebp + http_msg.flags], FLAG_STREAM
993
        jnz     .dont_resize
993
        jnz     .dont_resize
994
; Realloc buffer, make it 'chunksize' bigger.
994
; Realloc buffer, make it 'chunksize' bigger.
995
        mov     edx, ebx
995
        mov     edx, ebx
996
        add     edx, [buffersize]
996
        add     edx, [buffersize]
997
        mov     [ebp + http_msg.buffer_length], edx     ; remaining space in new buffer
997
        mov     [ebp + http_msg.buffer_length], edx     ; remaining space in new buffer
998
        add     edx, [ebp + http_msg.write_ptr]
998
        add     edx, [ebp + http_msg.write_ptr]
999
        sub     edx, [ebp + http_msg.content_ptr]
999
        sub     edx, [ebp + http_msg.content_ptr]
1000
        DEBUGF  1, "Resizing buffer 0x%x, it will now be %u bytes\n", [ebp + http_msg.content_ptr], edx
1000
        DEBUGF  1, "Resizing buffer 0x%x, it will now be %u bytes\n", [ebp + http_msg.content_ptr], edx
1001
        invoke  mem.realloc, [ebp + http_msg.content_ptr], edx
1001
        invoke  mem.realloc, [ebp + http_msg.content_ptr], edx
1002
        DEBUGF  1, "New buffer = 0x%x\n", eax
1002
        DEBUGF  1, "New buffer = 0x%x\n", eax
1003
        or      eax, eax
1003
        or      eax, eax
1004
        jz      .err_no_ram
1004
        jz      .err_no_ram
1005
        call    recalculate_pointers                    ; Because it's possible that buffer begins on another address now
1005
        call    recalculate_pointers                    ; Because it's possible that buffer begins on another address now
1006
        add     esi, eax                                ; recalculate esi too!
1006
        add     esi, eax                                ; recalculate esi too!
1007
  .dont_resize:
1007
  .dont_resize:
1008
; Remove chunk header (aka chunkline) from the buffer by shifting all received data after chunkt_ptr to the left
1008
; Remove chunk header (aka chunkline) from the buffer by shifting all received data after chunkt_ptr to the left
1009
        mov     edi, [ebp + http_msg.chunk_ptr]
1009
        mov     edi, [ebp + http_msg.chunk_ptr]
1010
        DEBUGF  1, "Removing chunkline esi=0x%x edi=0x%x ecx=%u\n", esi, edi, ecx
1010
        DEBUGF  1, "Removing chunkline esi=0x%x edi=0x%x ecx=%u\n", esi, edi, ecx
1011
        rep movsb
1011
        rep movsb
1012
; Update chunk ptr to point to next chunk
1012
; Update chunk ptr to point to next chunk
1013
        add     [ebp + http_msg.chunk_ptr], ebx
1013
        add     [ebp + http_msg.chunk_ptr], ebx
1014
; Set number of received bytes to 0, we already updated content_received
1014
; Set number of received bytes to 0, we already updated content_received
1015
        xor     eax, eax
1015
        xor     eax, eax
1016
        jmp     .chunk_loop
1016
        jmp     .chunk_loop
1017
 
1017
 
1018
;--------------------------------------------------------------
1018
;--------------------------------------------------------------
1019
;
1019
;
1020
; end of proc code begins here
1020
; end of proc code begins here
1021
;
1021
;
1022
 
1022
 
1023
  .header_parsed:
1023
  .header_parsed:
1024
        ; If we're using ring buffer, check we crossed the boundary
1024
        ; If we're using ring buffer, check we crossed the boundary
1025
        test    [ebp + http_msg.flags], FLAG_RING
1025
        test    [ebp + http_msg.flags], FLAG_RING
1026
        jz      @f
1026
        jz      @f
1027
        mov     ebx, [ebp + http_msg.content_ptr]
1027
        mov     ebx, [ebp + http_msg.content_ptr]
1028
        add     ebx, [buffersize]
1028
        add     ebx, [buffersize]
1029
        cmp     [ebp + http_msg.write_ptr], ebx
1029
        cmp     [ebp + http_msg.write_ptr], ebx
1030
        jb      @f
1030
        jb      @f
1031
        DEBUGF  1, "Restarting at beginning of ring buffer\n"
1031
        DEBUGF  1, "Restarting at beginning of ring buffer\n"
1032
        mov     ebx, [buffersize]
1032
        mov     ebx, [buffersize]
1033
        sub     [ebp + http_msg.write_ptr], ebx
1033
        sub     [ebp + http_msg.write_ptr], ebx
1034
  @@:
1034
  @@:
1035
        ; Header was already parsed and connection isnt chunked.
1035
        ; Header was already parsed and connection isnt chunked.
1036
        ; Update content_received
1036
        ; Update content_received
1037
        add     [ebp + http_msg.content_received], eax
1037
        add     [ebp + http_msg.content_received], eax
1038
        ; If we received content-length parameter, check if we received all the data
1038
        ; If we received content-length parameter, check if we received all the data
1039
        test    [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
1039
        test    [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
1040
        jz      @f
1040
        jz      @f
1041
        mov     eax, [ebp + http_msg.content_received]
1041
        mov     eax, [ebp + http_msg.content_received]
1042
        cmp     eax, [ebp + http_msg.content_length]
1042
        cmp     eax, [ebp + http_msg.content_length]
1043
        jae     .got_all_data
1043
        jae     .got_all_data
1044
  @@:
1044
  @@:
1045
        cmp     [ebp + http_msg.buffer_length], 0
1045
        cmp     [ebp + http_msg.buffer_length], 0
1046
        je      .buffer_full
1046
        je      .buffer_full
1047
        ; Need more data
1047
        ; Need more data
1048
        popa
1048
        popa
1049
        xor     eax, eax
1049
        xor     eax, eax
1050
        dec     eax
1050
        dec     eax
1051
        ret
1051
        ret
1052
 
1052
 
1053
  .buffer_full:
1053
  .buffer_full:
1054
        test    [ebp + http_msg.flags], FLAG_STREAM
1054
        test    [ebp + http_msg.flags], FLAG_STREAM
1055
        jnz     .multibuff
1055
        jnz     .multibuff
1056
        mov     eax, [ebp + http_msg.write_ptr]
1056
        mov     eax, [ebp + http_msg.write_ptr]
1057
        add     eax, [buffersize]
1057
        add     eax, [buffersize]
1058
        sub     eax, [ebp + http_msg.content_ptr]
1058
        sub     eax, [ebp + http_msg.content_ptr]
1059
        invoke  mem.realloc, [ebp + http_msg.content_ptr], eax
1059
        invoke  mem.realloc, [ebp + http_msg.content_ptr], eax
1060
        or      eax, eax
1060
        or      eax, eax
1061
        jz      .err_no_ram
1061
        jz      .err_no_ram
1062
        call    recalculate_pointers
1062
        call    recalculate_pointers
1063
        push    [buffersize]
1063
        push    [buffersize]
1064
        pop     [ebp + http_msg.buffer_length]
1064
        pop     [ebp + http_msg.buffer_length]
1065
        ; Need more data
1065
        ; Need more data
1066
        popa
1066
        popa
1067
        xor     eax, eax
1067
        xor     eax, eax
1068
        dec     eax
1068
        dec     eax
1069
        ret
1069
        ret
1070
 
1070
 
1071
  .multibuff:
1071
  .multibuff:
1072
        ; This buffer is full
1072
        ; This buffer is full
1073
        popa
1073
        popa
1074
        xor     eax, eax
1074
        xor     eax, eax
1075
        ret
1075
        ret
1076
 
1076
 
1077
  .need_more_data_for_header:
1077
  .need_more_data_for_header:
1078
        cmp     [ebp + http_msg.buffer_length], 0
1078
        cmp     [ebp + http_msg.buffer_length], 0
1079
        je      .err_header                     ; It's just too damn long!
1079
        je      .err_header                     ; It's just too damn long!
1080
        ; Need more data
1080
        ; Need more data
1081
        popa
1081
        popa
1082
        xor     eax, eax
1082
        xor     eax, eax
1083
        dec     eax
1083
        dec     eax
1084
        ret
1084
        ret
1085
 
1085
 
1086
  .need_more_data_chunked:
1086
  .need_more_data_chunked:
1087
; If we're using ring buffer, check we crossed the boundary
1087
; If we're using ring buffer, check we crossed the boundary
1088
        test    [ebp + http_msg.flags], FLAG_RING
1088
        test    [ebp + http_msg.flags], FLAG_RING
1089
        jz      @f
1089
        jz      @f
1090
        mov     ebx, [ebp + http_msg.content_ptr]
1090
        mov     ebx, [ebp + http_msg.content_ptr]
1091
        add     ebx, [buffersize]
1091
        add     ebx, [buffersize]
1092
        cmp     [ebp + http_msg.write_ptr], ebx
1092
        cmp     [ebp + http_msg.write_ptr], ebx
1093
        jb      @f
1093
        jb      @f
1094
        DEBUGF  1, "Restarting at beginning of ring buffer\n"
1094
        DEBUGF  1, "Restarting at beginning of ring buffer\n"
1095
        mov     ebx, [buffersize]
1095
        mov     ebx, [buffersize]
1096
        sub     [ebp + http_msg.write_ptr], ebx
1096
        sub     [ebp + http_msg.write_ptr], ebx
1097
  @@:
1097
  @@:
1098
        ; We only got a partial chunk, or need more chunks, update content_received and request more data
1098
        ; We only got a partial chunk, or need more chunks, update content_received and request more data
1099
        add     [ebp + http_msg.content_received], eax
1099
        add     [ebp + http_msg.content_received], eax
1100
        popa
1100
        popa
1101
        xor     eax, eax
1101
        xor     eax, eax
1102
        dec     eax
1102
        dec     eax
1103
        ret
1103
        ret
1104
 
1104
 
1105
  .got_all_data_chunked:
1105
  .got_all_data_chunked:
1106
        ; Woohoo, we got all the chunked data, calculate total number of bytes received.
1106
        ; Woohoo, we got all the chunked data, calculate total number of bytes received.
1107
        mov     eax, [ebp + http_msg.chunk_ptr]
1107
        mov     eax, [ebp + http_msg.chunk_ptr]
1108
        sub     eax, [ebp + http_msg.content_ptr]
1108
        sub     eax, [ebp + http_msg.content_ptr]
1109
        mov     [ebp + http_msg.content_length], eax
1109
        mov     [ebp + http_msg.content_length], eax
1110
        mov     [ebp + http_msg.content_received], eax
1110
        mov     [ebp + http_msg.content_received], eax
1111
  .got_all_data:
1111
  .got_all_data:
1112
        DEBUGF  1, "We got all the data! (%u bytes)\n", [ebp + http_msg.content_received]
1112
        DEBUGF  1, "We got all the data! (%u bytes)\n", [ebp + http_msg.content_received]
1113
        or      [ebp + http_msg.flags], FLAG_GOT_ALL_DATA
1113
        or      [ebp + http_msg.flags], FLAG_GOT_ALL_DATA
1114
        test    [ebp + http_msg.flags], FLAG_KEEPALIVE
1114
        test    [ebp + http_msg.flags], FLAG_KEEPALIVE
1115
        jnz     @f
1115
        jnz     @f
1116
        mcall   close, [ebp + http_msg.socket]
1116
        mcall   close, [ebp + http_msg.socket]
1117
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
1117
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
1118
  @@:
1118
  @@:
1119
        popa
1119
        popa
1120
        xor     eax, eax
1120
        xor     eax, eax
1121
        ret
1121
        ret
1122
 
1122
 
1123
;--------------------------------------------------------------
1123
;--------------------------------------------------------------
1124
;
1124
;
1125
; error handeling code begins here
1125
; error handeling code begins here
1126
;
1126
;
1127
 
1127
 
1128
  .check_socket:
1128
  .check_socket:
1129
        cmp     ebx, EWOULDBLOCK
1129
        cmp     ebx, EWOULDBLOCK
1130
        jne     .err_socket
1130
        jne     .err_socket
1131
        mcall   26, 9
1131
        mcall   26, 9
1132
        sub     eax, [ebp + http_msg.timestamp]
1132
        sub     eax, [ebp + http_msg.timestamp]
1133
        cmp     eax, TIMEOUT
1133
        cmp     eax, TIMEOUT
1134
        ja      .err_timeout
1134
        ja      .err_timeout
1135
        ; Need more data
1135
        ; Need more data
1136
        popa
1136
        popa
1137
        xor     eax, eax
1137
        xor     eax, eax
1138
        dec     eax
1138
        dec     eax
1139
        ret
1139
        ret
1140
 
1140
 
1141
  .server_closed:
1141
  .server_closed:
1142
        DEBUGF  1, "server closed connection, transfer complete?\n"
1142
        DEBUGF  1, "server closed connection, transfer complete?\n"
1143
        mcall   close, [ebp + http_msg.socket]
1143
        mcall   close, [ebp + http_msg.socket]
1144
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
1144
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
1145
        test    [ebp + http_msg.flags], FLAG_GOT_HEADER
1145
        test    [ebp + http_msg.flags], FLAG_GOT_HEADER
1146
        jz      .err_server_closed
1146
        jz      .err_server_closed
1147
        test    [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
1147
        test    [ebp + http_msg.flags], FLAG_CONTENT_LENGTH
1148
        jz      .got_all_data
1148
        jz      .got_all_data
1149
  .err_server_closed:
1149
  .err_server_closed:
1150
        pop     eax
1150
        pop     eax
1151
        DEBUGF  2, "ERROR: server closed connection unexpectedly\n"
1151
        DEBUGF  2, "ERROR: server closed connection unexpectedly\n"
1152
        or      [ebp + http_msg.flags], FLAG_TRANSFER_FAILED
1152
        or      [ebp + http_msg.flags], FLAG_TRANSFER_FAILED
1153
        jmp     .abort
1153
        jmp     .abort
1154
 
1154
 
1155
  .err_header:
1155
  .err_header:
1156
        pop     eax
1156
        pop     eax
1157
        DEBUGF  2, "ERROR: invalid header\n"
1157
        DEBUGF  2, "ERROR: invalid header\n"
1158
        or      [ebp + http_msg.flags], FLAG_INVALID_HEADER
1158
        or      [ebp + http_msg.flags], FLAG_INVALID_HEADER
1159
        jmp     .abort
1159
        jmp     .abort
1160
 
1160
 
1161
  .err_no_ram:
1161
  .err_no_ram:
1162
        DEBUGF  2, "ERROR: out of RAM\n"
1162
        DEBUGF  2, "ERROR: out of RAM\n"
1163
        or      [ebp + http_msg.flags], FLAG_NO_RAM
1163
        or      [ebp + http_msg.flags], FLAG_NO_RAM
1164
        jmp     .abort  ; TODO: dont abort connection (requires rechecking all codepaths..)
1164
        jmp     .abort  ; TODO: dont abort connection (requires rechecking all codepaths..)
1165
 
1165
 
1166
  .err_timeout:
1166
  .err_timeout:
1167
        DEBUGF  2, "ERROR: timeout\n"
1167
        DEBUGF  2, "ERROR: timeout\n"
1168
        or      [ebp + http_msg.flags], FLAG_TIMEOUT_ERROR
1168
        or      [ebp + http_msg.flags], FLAG_TIMEOUT_ERROR
1169
        jmp     .abort
1169
        jmp     .abort
1170
 
1170
 
1171
  .err_socket:
1171
  .err_socket:
1172
        DEBUGF  2, "ERROR: socket error %u\n", ebx
1172
        DEBUGF  2, "ERROR: socket error %u\n", ebx
1173
        or      [ebp + http_msg.flags], FLAG_SOCKET_ERROR
1173
        or      [ebp + http_msg.flags], FLAG_SOCKET_ERROR
1174
  .abort:
1174
  .abort:
1175
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
1175
        and     [ebp + http_msg.flags], not FLAG_CONNECTED
1176
        mcall   close, [ebp + http_msg.socket]
1176
        mcall   close, [ebp + http_msg.socket]
1177
  .connection_closed:
1177
  .connection_closed:
1178
  .continue:
1178
  .continue:
1179
        popa
1179
        popa
1180
        xor     eax, eax
1180
        xor     eax, eax
1181
        ret
1181
        ret
1182
 
1182
 
1183
  .need_more_space:
1183
  .need_more_space:
1184
        DEBUGF  1, "Buffer is full!\n"
1184
        DEBUGF  1, "Buffer is full!\n"
1185
        and     [ebp + http_msg.flags], not FLAG_NEED_MORE_SPACE
1185
        and     [ebp + http_msg.flags], not FLAG_NEED_MORE_SPACE
1186
        popa
1186
        popa
1187
        xor     eax, eax
1187
        xor     eax, eax
1188
        ret
1188
        ret
1189
 
1189
 
1190
endp
1190
endp
1191
 
1191
 
1192
 
1192
 
1193
alloc_contentbuff:
1193
alloc_contentbuff:
1194
 
1194
 
1195
        test    [ebp + http_msg.flags], FLAG_RING
1195
        test    [ebp + http_msg.flags], FLAG_RING
1196
        jz      @f
1196
        jz      @f
1197
 
1197
 
1198
        DEBUGF  1, "Allocating ring buffer\n"
1198
        DEBUGF  1, "Allocating ring buffer\n"
1199
        mcall   68, 29, [buffersize]
1199
        mcall   68, 29, [buffersize]
1200
        or      eax, eax
1200
        or      eax, eax
1201
        jz      .no_ram
1201
        jz      .no_ram
1202
        jmp     .allocated
1202
        jmp     .allocated
1203
  @@:
1203
  @@:
1204
 
1204
 
1205
        test    [ebp + http_msg.flags], FLAG_STREAM
1205
        test    [ebp + http_msg.flags], FLAG_STREAM
1206
        jz      @f
1206
        jz      @f
1207
        mov     edx, [buffersize]
1207
        mov     edx, [buffersize]
1208
  @@:
1208
  @@:
1209
 
1209
 
1210
; Allocate content buffer
1210
; Allocate content buffer
1211
        invoke  mem.alloc, edx
1211
        invoke  mem.alloc, edx
1212
        or      eax, eax
1212
        or      eax, eax
1213
        jz      .no_ram
1213
        jz      .no_ram
1214
 
1214
 
1215
  .allocated:
1215
  .allocated:
1216
        DEBUGF  1, "Content buffer allocated: 0x%x\n", eax
1216
        DEBUGF  1, "Content buffer allocated: 0x%x\n", eax
1217
 
1217
 
1218
; Copy already received content into content buffer
1218
; Copy already received content into content buffer
1219
        mov     edi, eax
1219
        mov     edi, eax
1220
        lea     esi, [ebp + http_msg.http_header]
1220
        lea     esi, [ebp + http_msg.http_header]
1221
        add     esi, [ebp + http_msg.header_length]
1221
        add     esi, [ebp + http_msg.header_length]
1222
        mov     ecx, [ebp + http_msg.write_ptr]
1222
        mov     ecx, [ebp + http_msg.write_ptr]
1223
        sub     ecx, esi
1223
        sub     ecx, esi
1224
        mov     ebx, ecx
1224
        mov     ebx, ecx
1225
        rep movsb
1225
        rep movsb
1226
 
1226
 
1227
; Update pointers to point to new buffer
1227
; Update pointers to point to new buffer
1228
        mov     [ebp + http_msg.content_ptr], eax
1228
        mov     [ebp + http_msg.content_ptr], eax
1229
        mov     [ebp + http_msg.content_received], ebx
1229
        mov     [ebp + http_msg.content_received], ebx
1230
        sub     edx, ebx
1230
        sub     edx, ebx
1231
        mov     [ebp + http_msg.buffer_length], edx
1231
        mov     [ebp + http_msg.buffer_length], edx
1232
        add     eax, ebx
1232
        add     eax, ebx
1233
        mov     [ebp + http_msg.write_ptr], eax
1233
        mov     [ebp + http_msg.write_ptr], eax
1234
 
1234
 
1235
; Shrink header buffer
1235
; Shrink header buffer
1236
        mov     eax, http_msg.http_header
1236
        mov     eax, http_msg.http_header
1237
        add     eax, [ebp + http_msg.header_length]
1237
        add     eax, [ebp + http_msg.header_length]
1238
        invoke  mem.realloc, ebp, eax
1238
        invoke  mem.realloc, ebp, eax
1239
        or      eax, eax
1239
        or      eax, eax
1240
        ret
1240
        ret
1241
 
1241
 
1242
  .no_ram:
1242
  .no_ram:
1243
        DEBUGF  2, "Error allocating content buffer!\n"
1243
        DEBUGF  2, "Error allocating content buffer!\n"
1244
        mov     [ebp + http_msg.buffer_length], 0       ;;;
1244
        mov     [ebp + http_msg.buffer_length], 0       ;;;
1245
        ret
1245
        ret
1246
 
1246
 
1247
 
1247
 
1248
 
1248
 
1249
recalculate_pointers:
1249
recalculate_pointers:
1250
 
1250
 
1251
        sub     eax, [ebp + http_msg.content_ptr]
1251
        sub     eax, [ebp + http_msg.content_ptr]
1252
        jz      .done
1252
        jz      .done
1253
        add     [ebp + http_msg.content_ptr], eax
1253
        add     [ebp + http_msg.content_ptr], eax
1254
        add     [ebp + http_msg.write_ptr], eax
1254
        add     [ebp + http_msg.write_ptr], eax
1255
        add     [ebp + http_msg.chunk_ptr], eax
1255
        add     [ebp + http_msg.chunk_ptr], eax
1256
 
1256
 
1257
  .done:
1257
  .done:
1258
        ret
1258
        ret
1259
 
1259
 
1260
 
1260
 
1261
 
1261
 
1262
;;================================================================================================;;
1262
;;================================================================================================;;
1263
proc HTTP_send identifier, dataptr, datalength ;//////////////////////////////////////////////////;;
1263
proc HTTP_send identifier, dataptr, datalength ;//////////////////////////////////////////////////;;
1264
;;------------------------------------------------------------------------------------------------;;
1264
;;------------------------------------------------------------------------------------------------;;
1265
;? Send data to the server                                                                        ;;
1265
;? Send data to the server                                                                        ;;
1266
;;------------------------------------------------------------------------------------------------;;
1266
;;------------------------------------------------------------------------------------------------;;
1267
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
1267
;> identifier   = pointer to buffer containing http_msg struct.                                   ;;
1268
;> dataptr      = pointer to data to be sent.                                                     ;;
1268
;> dataptr      = pointer to data to be sent.                                                     ;;
1269
;> datalength   = length of data (in bytes) to be sent                                            ;;
1269
;> datalength   = length of data (in bytes) to be sent                                            ;;
1270
;;------------------------------------------------------------------------------------------------;;
1270
;;------------------------------------------------------------------------------------------------;;
1271
;< eax = number of bytes sent, -1 on error                                                        ;;
1271
;< eax = number of bytes sent, -1 on error                                                        ;;
1272
;;================================================================================================;;
1272
;;================================================================================================;;
1273
 
1273
 
1274
        push    ebx ecx edx esi edi
1274
        push    ebx ecx edx esi edi
1275
        mov     edx, [identifier]
1275
        mov     edx, [identifier]
1276
        test    [edx + http_msg.flags], FLAG_CONNECTED
1276
        test    [edx + http_msg.flags], FLAG_CONNECTED
1277
        jz      .fail
1277
        jz      .fail
1278
        mcall   send, [edx + http_msg.socket], [dataptr], [datalength], 0
1278
        mcall   send, [edx + http_msg.socket], [dataptr], [datalength], 0
1279
        pop     edi esi edx ecx ebx
1279
        pop     edi esi edx ecx ebx
1280
        ret
1280
        ret
1281
 
1281
 
1282
  .fail:
1282
  .fail:
1283
        pop     edi esi edx ecx ebx
1283
        pop     edi esi edx ecx ebx
1284
        xor     eax, eax
1284
        xor     eax, eax
1285
        dec     eax
1285
        dec     eax
1286
        ret
1286
        ret
1287
 
1287
 
1288
endp
1288
endp
1289
 
1289
 
1290
 
1290
 
1291
;;================================================================================================;;
1291
;;================================================================================================;;
1292
proc HTTP_find_header_field identifier, headername ;//////////////////////////////////////////////;;
1292
proc HTTP_find_header_field identifier, headername ;//////////////////////////////////////////////;;
1293
;;------------------------------------------------------------------------------------------------;;
1293
;;------------------------------------------------------------------------------------------------;;
1294
;? Find a header field in the received HTTP header                                                ;;
1294
;? Find a header field in the received HTTP header                                                ;;
1295
;?                                                                                                ;;
1295
;?                                                                                                ;;
1296
;? NOTE: this function returns a pointer which points into the original header data.              ;;
1296
;? NOTE: this function returns a pointer which points into the original header data.              ;;
1297
;? The header field is terminated by a CR, LF, space or maybe even tab.                           ;;
1297
;? The header field is terminated by a CR, LF, space or maybe even tab.                           ;;
1298
;? A free operation should not be operated on this pointer!                                       ;;
1298
;? A free operation should not be operated on this pointer!                                       ;;
1299
;;------------------------------------------------------------------------------------------------;;
1299
;;------------------------------------------------------------------------------------------------;;
1300
;> identifier   = ptr to http_msg struct                                                          ;;
1300
;> identifier   = ptr to http_msg struct                                                          ;;
1301
;> headername   = ptr to ASCIIZ string containing field you want to find (must be in lowercase)   ;;
1301
;> headername   = ptr to ASCIIZ string containing field you want to find (must be in lowercase)   ;;
1302
;;------------------------------------------------------------------------------------------------;;
1302
;;------------------------------------------------------------------------------------------------;;
1303
;< eax = 0 (error) / ptr to content of the HTTP header field                                      ;;
1303
;< eax = 0 (error) / ptr to content of the HTTP header field                                      ;;
1304
;;================================================================================================;;
1304
;;================================================================================================;;
1305
        push    ebx ecx edx esi edi
1305
        push    ebx ecx edx esi edi
1306
 
1306
 
1307
        DEBUGF  1, "Find header field: %s\n", [headername]
1307
        DEBUGF  1, "Find header field: %s\n", [headername]
1308
 
1308
 
1309
        mov     ebx, [identifier]
1309
        mov     ebx, [identifier]
1310
        test    [ebx + http_msg.flags], FLAG_GOT_HEADER
1310
        test    [ebx + http_msg.flags], FLAG_GOT_HEADER
1311
        jz      .fail
1311
        jz      .fail
1312
 
1312
 
1313
        lea     edx, [ebx + http_msg.http_header]
1313
        lea     edx, [ebx + http_msg.http_header]
1314
        mov     ecx, edx
1314
        mov     ecx, edx
1315
        add     ecx, [ebx + http_msg.header_length]
1315
        add     ecx, [ebx + http_msg.header_length]
1316
 
1316
 
1317
  .restart:
1317
  .restart:
1318
        mov     esi, [headername]
1318
        mov     esi, [headername]
1319
        mov     edi, edx
1319
        mov     edi, edx
1320
  .loop:
1320
  .loop:
1321
        cmp     edi, ecx
1321
        cmp     edi, ecx
1322
        jae     .fail
1322
        jae     .fail
1323
        lodsb
1323
        lodsb
1324
        scasb
1324
        scasb
1325
        je      .loop
1325
        je      .loop
1326
        test    al, al
1326
        test    al, al
1327
        jz      .done?
1327
        jz      .done?
1328
  .next:
1328
  .next:
1329
        inc     edx
1329
        inc     edx
1330
        jmp     .restart
1330
        jmp     .restart
1331
 
1331
 
1332
  .not_done:
1332
  .not_done:
1333
        inc     edi
1333
        inc     edi
1334
  .done?:
1334
  .done?:
1335
        cmp     byte[edi-1], ':'
1335
        cmp     byte[edi-1], ':'
1336
        je      .almost_done
1336
        je      .almost_done
1337
        cmp     byte[edi-1], ' '
1337
        cmp     byte[edi-1], ' '
1338
        je      .not_done
1338
        je      .not_done
1339
        cmp     byte[edi-1], 9  ; tab
1339
        cmp     byte[edi-1], 9  ; tab
1340
        je      .not_done
1340
        je      .not_done
1341
 
1341
 
1342
        jmp     .next
1342
        jmp     .next
1343
 
1343
 
1344
  .almost_done:                 ; FIXME: buffer overflow?
1344
  .almost_done:                 ; FIXME: buffer overflow?
1345
        dec     edi
1345
        dec     edi
1346
        DEBUGF  1, "Found header field\n"
1346
        DEBUGF  1, "Found header field\n"
1347
  .spaceloop:
1347
  .spaceloop:
1348
        inc     edi
1348
        inc     edi
1349
        cmp     byte[edi], ' '
1349
        cmp     byte[edi], ' '
1350
        je      .spaceloop
1350
        je      .spaceloop
1351
        cmp     byte[edi], 9    ; tab
1351
        cmp     byte[edi], 9    ; tab
1352
        je      .spaceloop
1352
        je      .spaceloop
1353
 
1353
 
1354
        mov     eax, edi
1354
        mov     eax, edi
1355
        pop     edi esi edx ecx ebx
1355
        pop     edi esi edx ecx ebx
1356
        ret
1356
        ret
1357
 
1357
 
1358
  .fail:
1358
  .fail:
1359
        DEBUGF  1, "Header field not found\n"
1359
        DEBUGF  1, "Header field not found\n"
1360
        pop     edi esi edx ecx ebx
1360
        pop     edi esi edx ecx ebx
1361
        xor     eax, eax
1361
        xor     eax, eax
1362
        ret
1362
        ret
1363
 
1363
 
1364
endp
1364
endp
1365
 
1365
 
1366
 
1366
 
1367
 
1367
 
1368
;;================================================================================================;;
1368
;;================================================================================================;;
1369
proc HTTP_escape URI, length ;////////////////////////////////////////////////////////////////////;;
1369
proc HTTP_escape URI, length ;////////////////////////////////////////////////////////////////////;;
1370
;;------------------------------------------------------------------------------------------------;;
1370
;;------------------------------------------------------------------------------------------------;;
1371
;?                                                                                                ;;
1371
;?                                                                                                ;;
1372
;;------------------------------------------------------------------------------------------------;;
1372
;;------------------------------------------------------------------------------------------------;;
1373
;> URI = ptr to ASCIIZ URI/data                                                                   ;;
1373
;> URI = ptr to ASCIIZ URI/data                                                                   ;;
1374
;> length = length of URI/data                                                                    ;;
1374
;> length = length of URI/data                                                                    ;;
1375
;;------------------------------------------------------------------------------------------------;;
1375
;;------------------------------------------------------------------------------------------------;;
1376
;< eax = 0 (error) / ptr to ASCIIZ URI/data                                                       ;;
1376
;< eax = 0 (error) / ptr to ASCIIZ URI/data                                                       ;;
1377
;< ebx = length of escaped URI/data                                                               ;;
1377
;< ebx = length of escaped URI/data                                                               ;;
1378
;;================================================================================================;;
1378
;;================================================================================================;;
1379
 
1379
 
1380
        DEBUGF  1, "HTTP_escape: %s\n", [URI]
1380
        DEBUGF  1, "HTTP_escape: %s\n", [URI]
1381
 
1381
 
1382
        pusha
1382
        pusha
1383
 
1383
 
1384
        invoke  mem.alloc, URLMAXLEN            ; FIXME: use length provided by caller to guess final size.
1384
        invoke  mem.alloc, URLMAXLEN            ; FIXME: use length provided by caller to guess final size.
1385
        test    eax, eax
1385
        test    eax, eax
1386
        jz      .error
1386
        jz      .error
1387
        mov     edx, URLMAXLEN-1                ; Remaining space in temp buffer minus one for 0 byte
1387
        mov     edx, URLMAXLEN-1                ; Remaining space in temp buffer minus one for 0 byte
1388
        mov     [esp + 7 * 4], eax              ; return ptr in eax
1388
        mov     [esp + 7 * 4], eax              ; return ptr in eax
1389
        mov     esi, [URI]
1389
        mov     esi, [URI]
1390
        mov     edi, eax
1390
        mov     edi, eax
1391
        xor     ebx, ebx
1391
        xor     ebx, ebx
1392
        xor     ecx, ecx
1392
        xor     ecx, ecx
1393
  .loop:
1393
  .loop:
1394
        lodsb
1394
        lodsb
1395
        test    al, al
1395
        test    al, al
1396
        jz      .done
1396
        jz      .done
1397
 
1397
 
1398
        mov     cl, al
1398
        mov     cl, al
1399
        and     cl, 0x1f
1399
        and     cl, 0x1f
1400
        mov     bl, al
1400
        mov     bl, al
1401
        shr     bl, 3
1401
        shr     bl, 3
1402
        and     bl, not 3
1402
        and     bl, not 3
1403
        bt      dword[bits_must_escape + ebx], ecx
1403
        bt      dword[bits_must_escape + ebx], ecx
1404
        jc      .escape
1404
        jc      .escape
1405
 
1405
 
1406
        stosb
1406
        stosb
1407
        dec     edx
1407
        dec     edx
1408
        jnz     .loop
1408
        jnz     .loop
1409
        jmp     .out_of_space
1409
        jmp     .out_of_space
1410
 
1410
 
1411
  .escape:
1411
  .escape:
1412
        sub     edx, 3
1412
        sub     edx, 3
1413
        jbe     .out_of_space
1413
        jbe     .out_of_space
1414
        mov     al, '%'
1414
        mov     al, '%'
1415
        stosb
1415
        stosb
1416
        mov     bl, byte[esi-1]
1416
        mov     bl, byte[esi-1]
1417
        shr     bl, 4
1417
        shr     bl, 4
1418
        mov     al, byte[str_hex + ebx]
1418
        mov     al, byte[str_hex + ebx]
1419
        stosb
1419
        stosb
1420
        mov     bl, byte[esi-1]
1420
        mov     bl, byte[esi-1]
1421
        and     bl, 0x0f
1421
        and     bl, 0x0f
1422
        mov     al, byte[str_hex + ebx]
1422
        mov     al, byte[str_hex + ebx]
1423
        stosb
1423
        stosb
1424
        jmp     .loop
1424
        jmp     .loop
1425
 
1425
 
1426
 
1426
 
1427
  .out_of_space:
1427
  .out_of_space:
1428
        DEBUGF  2, "ERROR: buffer too small!\n"
1428
        DEBUGF  2, "ERROR: buffer too small!\n"
1429
 
1429
 
1430
  .done:
1430
  .done:
1431
        xor     al, al
1431
        xor     al, al
1432
        stosb
1432
        stosb
1433
        sub     edi, [esp + 7 * 4]
1433
        sub     edi, [esp + 7 * 4]
1434
        dec     edi
1434
        dec     edi
1435
        mov     [esp + 4 * 4], edi
1435
        mov     [esp + 4 * 4], edi
1436
 
1436
 
1437
        popa
1437
        popa
1438
        DEBUGF  1, "escaped URL: %s\n", eax
1438
        DEBUGF  1, "escaped URL: %s\n", eax
1439
        ret
1439
        ret
1440
 
1440
 
1441
  .error:
1441
  .error:
1442
        DEBUGF  2, "ERROR: out of RAM!\n"
1442
        DEBUGF  2, "ERROR: out of RAM!\n"
1443
        popa
1443
        popa
1444
        xor     eax, eax
1444
        xor     eax, eax
1445
        ret
1445
        ret
1446
 
1446
 
1447
endp
1447
endp
1448
 
1448
 
1449
 
1449
 
1450
 
1450
 
1451
;;================================================================================================;;
1451
;;================================================================================================;;
1452
proc HTTP_unescape URI, length ;//////////////////////////////////////////////////////////////////;;
1452
proc HTTP_unescape URI, length ;//////////////////////////////////////////////////////////////////;;
1453
;;------------------------------------------------------------------------------------------------;;
1453
;;------------------------------------------------------------------------------------------------;;
1454
;?                                                                                                ;;
1454
;?                                                                                                ;;
1455
;;------------------------------------------------------------------------------------------------;;
1455
;;------------------------------------------------------------------------------------------------;;
1456
;> URI = ptr to ASCIIZ URI                                                                        ;;
1456
;> URI = ptr to ASCIIZ URI                                                                        ;;
1457
;;------------------------------------------------------------------------------------------------;;
1457
;;------------------------------------------------------------------------------------------------;;
1458
;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
1458
;< eax = 0 (error) / ptr to ASCIIZ URI                                                            ;;
1459
;;================================================================================================;;
1459
;;================================================================================================;;
1460
 
1460
 
1461
        DEBUGF  1, "HTTP_unescape: %s\n", [URI]
1461
        DEBUGF  1, "HTTP_unescape: %s\n", [URI]
1462
        pusha
1462
        pusha
1463
 
1463
 
1464
        invoke  mem.alloc, URLMAXLEN            ; FIXME: use length provided by caller
1464
        invoke  mem.alloc, URLMAXLEN            ; FIXME: use length provided by caller
1465
        test    eax, eax
1465
        test    eax, eax
1466
        jz      .error
1466
        jz      .error
1467
        mov     edx, URLMAXLEN-1                ; Remaining space in temp buffer minus one for 0 byte
1467
        mov     edx, URLMAXLEN-1                ; Remaining space in temp buffer minus one for 0 byte
1468
        mov     [esp + 7 * 4], eax              ; return ptr in eax
1468
        mov     [esp + 7 * 4], eax              ; return ptr in eax
1469
        mov     esi, [URI]
1469
        mov     esi, [URI]
1470
        mov     edi, eax
1470
        mov     edi, eax
1471
  .loop:
1471
  .loop:
1472
        lodsb
1472
        lodsb
1473
        test    al, al
1473
        test    al, al
1474
        jz      .done
1474
        jz      .done
1475
        cmp     al, '%'
1475
        cmp     al, '%'
1476
        je      .unescape
1476
        je      .unescape
1477
        stosb
1477
        stosb
1478
        dec     edx
1478
        dec     edx
1479
        jnz     .loop
1479
        jnz     .loop
1480
        jmp     .out_of_space
1480
        jmp     .out_of_space
1481
 
1481
 
1482
  .unescape:
1482
  .unescape:
1483
        xor     ebx, ebx
1483
        xor     ebx, ebx
1484
        xor     ecx, ecx
1484
        xor     ecx, ecx
1485
  .unescape_nibble:
1485
  .unescape_nibble:
1486
        lodsb
1486
        lodsb
1487
        sub     al, '0'
1487
        sub     al, '0'
1488
        jb      .fail
1488
        jb      .fail
1489
        cmp     al, 9
1489
        cmp     al, 9
1490
        jbe     .nibble_ok
1490
        jbe     .nibble_ok
1491
        sub     al, 'A' - '0' - 10
1491
        sub     al, 'A' - '0' - 10
1492
        jb      .fail
1492
        jb      .fail
1493
        cmp     al, 15
1493
        cmp     al, 15
1494
        jbe     .nibble_ok
1494
        jbe     .nibble_ok
1495
        sub     al, 'a' - 'A'
1495
        sub     al, 'a' - 'A'
1496
        cmp     al, 15
1496
        cmp     al, 15
1497
        ja      .fail
1497
        ja      .fail
1498
  .nibble_ok:
1498
  .nibble_ok:
1499
        shl     bl, 8
1499
        shl     bl, 8
1500
        or      bl, al
1500
        or      bl, al
1501
        dec     ecx
1501
        dec     ecx
1502
        jc      .unescape_nibble
1502
        jc      .unescape_nibble
1503
        mov     al, bl
1503
        mov     al, bl
1504
        stosb
1504
        stosb
1505
        dec     edx
1505
        dec     edx
1506
        jnz     .loop
1506
        jnz     .loop
1507
        jmp     .out_of_space
1507
        jmp     .out_of_space
1508
 
1508
 
1509
  .fail:
1509
  .fail:
1510
        DEBUGF  2, "ERROR: invalid URI!\n"
1510
        DEBUGF  2, "ERROR: invalid URI!\n"
1511
        jmp     .loop
1511
        jmp     .loop
1512
 
1512
 
1513
  .out_of_space:
1513
  .out_of_space:
1514
        DEBUGF  2, "ERROR: buffer too small!\n"
1514
        DEBUGF  2, "ERROR: buffer too small!\n"
1515
 
1515
 
1516
  .done:
1516
  .done:
1517
        xor     al, al
1517
        xor     al, al
1518
        stosb
1518
        stosb
1519
        popa
1519
        popa
1520
        DEBUGF  1, "unescaped URL: %s\n", eax
1520
        DEBUGF  1, "unescaped URL: %s\n", eax
1521
        ret
1521
        ret
1522
 
1522
 
1523
  .error:
1523
  .error:
1524
        DEBUGF  2, "ERROR: out of RAM!\n"
1524
        DEBUGF  2, "ERROR: out of RAM!\n"
1525
        popa
1525
        popa
1526
        xor     eax, eax
1526
        xor     eax, eax
1527
        ret
1527
        ret
1528
 
1528
 
1529
endp
1529
endp
1530
 
1530
 
1531
 
1531
 
1532
 
1532
 
1533
 
1533
 
1534
 
1534
 
1535
;;================================================================================================;;
1535
;;================================================================================================;;
1536
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1536
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1537
;;================================================================================================;;
1537
;;================================================================================================;;
1538
;! Internal procedures section                                                                    ;;
1538
;! Internal procedures section                                                                    ;;
1539
;;                                                                                                ;;
1539
;;                                                                                                ;;
1540
;; NOTICE: These procedures do not follow stdcall conventions and thus may destroy any register.  ;;
1540
;; NOTICE: These procedures do not follow stdcall conventions and thus may destroy any register.  ;;
1541
;;================================================================================================;;
1541
;;================================================================================================;;
1542
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1542
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1543
;;================================================================================================;;
1543
;;================================================================================================;;
1544
 
1544
 
1545
 
1545
 
1546
 
1546
 
1547
 
1547
 
1548
;;================================================================================================;;
1548
;;================================================================================================;;
1549
proc open_connection hostname, port ;/////////////////////////////////////////////////////////////;;
1549
proc open_connection hostname, port ;/////////////////////////////////////////////////////////////;;
1550
;;------------------------------------------------------------------------------------------------;;
1550
;;------------------------------------------------------------------------------------------------;;
1551
;? Connects to a HTTP server                                                                      ;;
1551
;? Connects to a HTTP server                                                                      ;;
1552
;;------------------------------------------------------------------------------------------------;;
1552
;;------------------------------------------------------------------------------------------------;;
1553
;> hostname     = ptr to ASCIIZ hostname                                                          ;;
1553
;> hostname     = ptr to ASCIIZ hostname                                                          ;;
1554
;> port         = port (x86 byte order)                                                           ;;
1554
;> port         = port (x86 byte order)                                                           ;;
1555
;;------------------------------------------------------------------------------------------------;;
1555
;;------------------------------------------------------------------------------------------------;;
1556
;< eax = 0 (error) / socketnum                                                                    ;;
1556
;< eax = 0 (error) / socketnum                                                                    ;;
1557
;;================================================================================================;;
1557
;;================================================================================================;;
1558
 
1558
 
1559
locals
1559
locals
1560
        sockaddr        dd ?
1560
        sockaddr        dd ?
1561
        socketnum       dd ?
1561
        socketnum       dd ?
1562
endl
1562
endl
1563
 
1563
 
1564
        cmp     [proxyAddr], 0
1564
        cmp     [proxyAddr], 0
1565
        je      .no_proxy
1565
        je      .no_proxy
1566
 
1566
 
1567
        mov     [hostname], proxyAddr
1567
        mov     [hostname], proxyAddr
1568
 
1568
 
1569
        push    [proxyPort]
1569
        push    [proxyPort]
1570
        pop     [port]
1570
        pop     [port]
1571
  .no_proxy:
1571
  .no_proxy:
1572
 
1572
 
1573
; Resolve the hostname
1573
; Resolve the hostname
1574
        DEBUGF  1, "Resolving hostname\n"
1574
        DEBUGF  1, "Resolving hostname\n"
1575
        push    esp     ; reserve stack place
1575
        push    esp     ; reserve stack place
1576
        invoke  getaddrinfo, [hostname], 0, 0, esp
1576
        invoke  getaddrinfo, [hostname], 0, 0, esp
1577
        pop     esi
1577
        pop     esi
1578
        test    eax, eax
1578
        test    eax, eax
1579
        jnz     .error1
1579
        jnz     .error1
1580
 
1580
 
1581
; getaddrinfo returns addrinfo struct, make the pointer to sockaddr struct
1581
; getaddrinfo returns addrinfo struct, make the pointer to sockaddr struct
1582
        push    esi     ; for freeaddrinfo
1582
        push    esi     ; for freeaddrinfo
1583
        mov     esi, [esi + addrinfo.ai_addr]
1583
        mov     esi, [esi + addrinfo.ai_addr]
1584
        mov     [sockaddr], esi
1584
        mov     [sockaddr], esi
1585
        mov     eax, [esi + sockaddr_in.sin_addr]
1585
        mov     eax, [esi + sockaddr_in.sin_addr]
1586
        test    eax, eax
1586
        test    eax, eax
1587
        jz      .error2
1587
        jz      .error2
1588
 
1588
 
1589
        DEBUGF  1, "Server ip=%u.%u.%u.%u\n", \
1589
        DEBUGF  1, "Server ip=%u.%u.%u.%u\n", \
1590
        [esi + sockaddr_in.sin_addr]:1, [esi + sockaddr_in.sin_addr + 1]:1, \
1590
        [esi + sockaddr_in.sin_addr]:1, [esi + sockaddr_in.sin_addr + 1]:1, \
1591
        [esi + sockaddr_in.sin_addr + 2]:1, [esi + sockaddr_in.sin_addr + 3]:1
1591
        [esi + sockaddr_in.sin_addr + 2]:1, [esi + sockaddr_in.sin_addr + 3]:1
1592
 
1592
 
1593
        mov     [esi + sockaddr_in.sin_family], AF_INET4
1593
        mov     [esi + sockaddr_in.sin_family], AF_INET4
1594
        mov     eax, [port]
1594
        mov     eax, [port]
1595
        xchg    al, ah
1595
        xchg    al, ah
1596
        mov     [esi + sockaddr_in.sin_port], ax
1596
        mov     [esi + sockaddr_in.sin_port], ax
1597
 
1597
 
1598
; Open a new TCP socket
1598
; Open a new TCP socket
1599
        mcall   socket, AF_INET4, SOCK_STREAM, 0
1599
        mcall   socket, AF_INET4, SOCK_STREAM, 0
1600
        test    eax, eax
1600
        test    eax, eax
1601
        jz      .error3
1601
        jz      .error3
1602
        mov     [socketnum], eax
1602
        mov     [socketnum], eax
1603
        DEBUGF  1, "Socket: 0x%x\n", eax
1603
        DEBUGF  1, "Socket: 0x%x\n", eax
1604
 
1604
 
1605
; Connect to the server
1605
; Connect to the server
1606
        mcall   connect, [socketnum], [sockaddr], 18
1606
        mcall   connect, [socketnum], [sockaddr], 18
1607
        test    eax, eax
1607
        test    eax, eax
1608
        jnz     .error3
1608
        jnz     .error3
1609
        DEBUGF  1, "Socket is now connected.\n"
1609
        DEBUGF  1, "Socket is now connected.\n"
1610
 
1610
 
1611
        invoke  freeaddrinfo            ; Free allocated memory
1611
        invoke  freeaddrinfo            ; Free allocated memory
1612
        mov     eax, [socketnum]
1612
        mov     eax, [socketnum]
1613
        ret
1613
        ret
1614
 
1614
 
1615
  .error3:
1615
  .error3:
1616
        DEBUGF  2, "Could not connect to the remote server\n"
1616
        DEBUGF  2, "Could not connect to the remote server\n"
1617
        invoke  freeaddrinfo            ; Free allocated memory
1617
        invoke  freeaddrinfo            ; Free allocated memory
1618
        xor     eax, eax
1618
        xor     eax, eax
1619
        ret
1619
        ret
1620
 
1620
 
1621
  .error2:
1621
  .error2:
1622
        DEBUGF  2, "Resolving hostname failed\n"
1622
        DEBUGF  2, "Resolving hostname failed\n"
1623
        invoke  freeaddrinfo            ; Free allocated memory
1623
        invoke  freeaddrinfo            ; Free allocated memory
1624
        xor     eax, eax
1624
        xor     eax, eax
1625
        ret
1625
        ret
1626
 
1626
 
1627
  .error1:
1627
  .error1:
1628
        DEBUGF  2, "Contacting DNS server failed with EAI code: %x\n", eax
1628
        DEBUGF  2, "Contacting DNS server failed with EAI code: %x\n", eax
1629
        xor     eax, eax
1629
        xor     eax, eax
1630
        ret
1630
        ret
1631
 
1631
 
1632
endp
1632
endp
1633
 
1633
 
1634
 
1634
 
1635
;;================================================================================================;;
1635
;;================================================================================================;;
1636
proc parse_url URL ;//////////////////////////////////////////////////////////////////////////////;;
1636
proc parse_url URL ;//////////////////////////////////////////////////////////////////////////////;;
1637
;;------------------------------------------------------------------------------------------------;;
1637
;;------------------------------------------------------------------------------------------------;;
1638
;? Split a given URL into hostname and pageaddr                                                   ;;
1638
;? Split a given URL into hostname and pageaddr                                                   ;;
1639
;;------------------------------------------------------------------------------------------------;;
1639
;;------------------------------------------------------------------------------------------------;;
1640
;> URL = ptr to ASCIIZ URL                                                                        ;;
1640
;> URL = ptr to ASCIIZ URL                                                                        ;;
1641
;;------------------------------------------------------------------------------------------------;;
1641
;;------------------------------------------------------------------------------------------------;;
1642
;< eax = 0 (error) / ptr to ASCIIZ hostname                                                       ;;
1642
;< eax = 0 (error) / ptr to ASCIIZ hostname                                                       ;;
1643
;< ebx = ptr to ASCIIZ pageaddr                                                                   ;;
1643
;< ebx = ptr to ASCIIZ pageaddr                                                                   ;;
1644
;< ecx = port number                                                                              ;;
1644
;< ecx = port number                                                                              ;;
1645
;;================================================================================================;;
1645
;;================================================================================================;;
1646
 
1646
 
1647
locals
1647
locals
1648
        urlsize         dd ?
1648
        urlsize         dd ?
1649
        hostname        dd ?
1649
        hostname        dd ?
1650
        pageaddr        dd ?
1650
        pageaddr        dd ?
1651
        port            dd ?
1651
        port            dd ?
1652
endl
1652
endl
1653
 
1653
 
1654
        DEBUGF  1, "parsing URL: %s\n", [URL]
1654
        DEBUGF  1, "parsing URL: %s\n", [URL]
1655
 
1655
 
1656
; remove any leading protocol text
1656
; remove any leading protocol text
1657
        mov     edi, [URL]
1657
        mov     edi, [URL]
1658
        mov     ecx, URLMAXLEN
1658
        mov     ecx, URLMAXLEN
1659
        mov     ax, '//'
1659
        mov     ax, '//'
1660
  .loop1:
1660
  .loop1:
1661
        cmp     byte[edi], 0            ; end of URL?
1661
        cmp     byte[edi], 0            ; end of URL?
1662
        je      .url_ok                 ; yep, so not found
1662
        je      .url_ok                 ; yep, so not found
1663
        cmp     [edi], ax
1663
        cmp     [edi], ax
1664
        je      .skip_proto
1664
        je      .skip_proto
1665
        inc     edi
1665
        inc     edi
1666
        dec     ecx
1666
        dec     ecx
1667
        jnz     .loop1
1667
        jnz     .loop1
1668
        jmp     .invalid
1668
        jmp     .invalid
1669
 
1669
 
1670
  .skip_proto:
1670
  .skip_proto:
1671
        inc     edi                     ; skip the two '/'
1671
        inc     edi                     ; skip the two '/'
1672
        inc     edi
1672
        inc     edi
1673
        mov     [URL], edi              ; update pointer so it skips protocol
1673
        mov     [URL], edi              ; update pointer so it skips protocol
1674
 
1674
 
1675
; Find the trailing 0 byte
1675
; Find the trailing 0 byte
1676
        xor     al, al
1676
        xor     al, al
1677
        repne   scasb
1677
        repne   scasb
1678
        jne     .invalid                ; ecx reached 0 before we reached end of string
1678
        jne     .invalid                ; ecx reached 0 before we reached end of string
1679
 
1679
 
1680
  .url_ok:
1680
  .url_ok:
1681
        sub     edi, [URL]              ; calculate total length of URL
1681
        sub     edi, [URL]              ; calculate total length of URL
1682
        mov     [urlsize], edi
1682
        mov     [urlsize], edi
1683
 
1683
 
1684
; now look for page delimiter - it's a '/' character
1684
; now look for page delimiter - it's a '/' character
1685
        mov     ecx, edi                ; URL length
1685
        mov     ecx, edi                ; URL length
1686
        mov     edi, [URL]
1686
        mov     edi, [URL]
1687
        mov     al, '/'
1687
        mov     al, '/'
1688
        repne   scasb
1688
        repne   scasb
1689
        jne     @f
1689
        jne     @f
1690
        dec     edi                     ; return one char, '/' must be part of the pageaddr
1690
        dec     edi                     ; return one char, '/' must be part of the pageaddr
1691
        inc     ecx                     ;
1691
        inc     ecx                     ;
1692
  @@:
1692
  @@:
1693
        push    ecx edi                 ; remember the pointer and length of pageaddr
1693
        push    ecx edi                 ; remember the pointer and length of pageaddr
1694
 
1694
 
1695
 
1695
 
1696
; Create new buffer and put hostname in it.
1696
; Create new buffer and put hostname in it.
1697
        mov     ecx, edi
1697
        mov     ecx, edi
1698
        sub     ecx, [URL]
1698
        sub     ecx, [URL]
1699
        inc     ecx                     ; we will add a 0 byte at the end
1699
        inc     ecx                     ; we will add a 0 byte at the end
1700
        invoke  mem.alloc, ecx
1700
        invoke  mem.alloc, ecx
1701
        or      eax, eax
1701
        or      eax, eax
1702
        jz      .no_mem
1702
        jz      .no_mem
1703
 
1703
 
1704
        mov     [hostname], eax         ; copy hostname to buffer
1704
        mov     [hostname], eax         ; copy hostname to buffer
1705
        mov     edi, eax
1705
        mov     edi, eax
1706
        mov     esi, [URL]
1706
        mov     esi, [URL]
1707
        dec     ecx
1707
        dec     ecx
1708
        rep     movsb
1708
        rep     movsb
1709
        xor     al, al
1709
        xor     al, al
1710
        stosb
1710
        stosb
1711
 
1711
 
1712
; Check if user provided a port, and convert it if so.
1712
; Check if user provided a port, and convert it if so.
1713
        mov     esi, [hostname]
1713
        mov     esi, [hostname]
1714
        mov     [port], 80              ; default port if user didnt provide one
1714
        mov     [port], 80              ; default port if user didnt provide one
1715
  .portloop:
1715
  .portloop:
1716
        lodsb
1716
        lodsb
1717
        test    al, al
1717
        test    al, al
1718
        jz      .no_port
1718
        jz      .no_port
1719
        cmp     al, ':'
1719
        cmp     al, ':'
1720
        jne     .portloop
1720
        jne     .portloop
1721
 
1721
 
1722
        push    esi
1722
        push    esi
1723
        call    ascii_dec_ebx
1723
        call    ascii_dec_ebx
1724
        pop     edi
1724
        pop     edi
1725
        cmp     byte[esi-1], 0
1725
        cmp     byte[esi-1], 0
1726
        jne     .invalid
1726
        jne     .invalid
1727
        cmp     [proxyAddr], 0          ; remove port number from hostname
1727
        cmp     [proxyAddr], 0          ; remove port number from hostname
1728
        jne     @f                      ; unless when we are using proxy
1728
        jne     @f                      ; unless when we are using proxy
1729
        mov     byte[edi-1], 0
1729
        mov     byte[edi-1], 0
1730
  @@:
1730
  @@:
1731
        test    ebx, ebx
1731
        test    ebx, ebx
1732
        je      .invalid
1732
        je      .invalid
1733
        cmp     ebx, 0xffff
1733
        cmp     ebx, 0xffff
1734
        ja      .invalid
1734
        ja      .invalid
1735
        mov     [port], ebx
1735
        mov     [port], ebx
1736
  .no_port:
1736
  .no_port:
1737
 
1737
 
1738
 
1738
 
1739
; Did user provide a pageaddr?
1739
; Did user provide a pageaddr?
1740
        mov     [pageaddr], str_slash   ; assume there is no pageaddr
1740
        mov     [pageaddr], str_slash   ; assume there is no pageaddr
1741
        pop     esi ecx
1741
        pop     esi ecx
1742
        test    ecx, ecx
1742
        test    ecx, ecx
1743
        jz      .no_page
1743
        jz      .no_page
1744
 
1744
 
1745
; Create new buffer and put pageaddr into it.
1745
; Create new buffer and put pageaddr into it.
1746
        inc     ecx                     ; we will add a 0 byte at the end
1746
        inc     ecx                     ; we will add a 0 byte at the end
1747
        invoke  mem.alloc, ecx
1747
        invoke  mem.alloc, ecx
1748
        or      eax, eax
1748
        or      eax, eax
1749
        jz      .no_mem
1749
        jz      .no_mem
1750
 
1750
 
1751
        mov     [pageaddr], eax         ; copy pageaddr to buffer
1751
        mov     [pageaddr], eax         ; copy pageaddr to buffer
1752
        mov     edi, eax
1752
        mov     edi, eax
1753
        dec     ecx
1753
        dec     ecx
1754
        rep     movsb
1754
        rep     movsb
1755
        xor     al, al
1755
        xor     al, al
1756
        stosb
1756
        stosb
1757
 
1757
 
1758
  .no_page:
1758
  .no_page:
1759
        mov     eax, [hostname]
1759
        mov     eax, [hostname]
1760
        mov     ebx, [pageaddr]
1760
        mov     ebx, [pageaddr]
1761
        mov     ecx, [port]
1761
        mov     ecx, [port]
1762
 
1762
 
1763
        DEBUGF  1, "hostname: %s\n", eax
1763
        DEBUGF  1, "hostname: %s\n", eax
1764
        DEBUGF  1, "pageaddr: %s\n", ebx
1764
        DEBUGF  1, "pageaddr: %s\n", ebx
1765
        DEBUGF  1, "port: %u\n", ecx
1765
        DEBUGF  1, "port: %u\n", ecx
1766
 
1766
 
1767
        ret
1767
        ret
1768
 
1768
 
1769
  .no_mem:
1769
  .no_mem:
1770
        DEBUGF  2, "Out of memory!\n"
1770
        DEBUGF  2, "Out of memory!\n"
1771
        xor     eax, eax
1771
        xor     eax, eax
1772
        ret
1772
        ret
1773
 
1773
 
1774
  .invalid:
1774
  .invalid:
1775
        DEBUGF  2, "Invalid URL!\n"
1775
        DEBUGF  2, "Invalid URL!\n"
1776
        xor     eax, eax
1776
        xor     eax, eax
1777
        ret
1777
        ret
1778
 
1778
 
1779
endp
1779
endp
1780
 
1780
 
1781
 
1781
 
1782
 
1782
 
1783
 
1783
 
1784
 
1784
 
1785
;;================================================================================================;;
1785
;;================================================================================================;;
1786
proc append_proxy_auth_header ;///////////////////////////////////////////////////////////////////;;
1786
proc append_proxy_auth_header ;///////////////////////////////////////////////////////////////////;;
1787
;;------------------------------------------------------------------------------------------------;;
1787
;;------------------------------------------------------------------------------------------------;;
1788
;? Appends the proxy authentication header                                                        ;;
1788
;? Appends the proxy authentication header                                                        ;;
1789
;;------------------------------------------------------------------------------------------------;;
1789
;;------------------------------------------------------------------------------------------------;;
1790
;> /                                                                                              ;;
1790
;> /                                                                                              ;;
1791
;;------------------------------------------------------------------------------------------------;;
1791
;;------------------------------------------------------------------------------------------------;;
1792
;< /                                                                                              ;;
1792
;< /                                                                                              ;;
1793
;;================================================================================================;;
1793
;;================================================================================================;;
1794
        mov     esi, str_proxy_auth
1794
        mov     esi, str_proxy_auth
1795
        mov     ecx, str_proxy_auth.length
1795
        mov     ecx, str_proxy_auth.length
1796
        rep     movsb
1796
        rep     movsb
1797
; base64-encode string :
1797
; base64-encode string :
1798
        mov     esi, proxyUser
1798
        mov     esi, proxyUser
1799
 
1799
 
1800
apah000:
1800
apah000:
1801
        lodsb
1801
        lodsb
1802
        test    al, al
1802
        test    al, al
1803
        jz      apah001
1803
        jz      apah001
1804
        call    encode_base64_byte
1804
        call    encode_base64_byte
1805
        jmp     apah000
1805
        jmp     apah000
1806
 
1806
 
1807
apah001:
1807
apah001:
1808
        mov     al, ':'
1808
        mov     al, ':'
1809
        call    encode_base64_byte
1809
        call    encode_base64_byte
1810
        mov     esi, proxyPassword
1810
        mov     esi, proxyPassword
1811
 
1811
 
1812
apah002:
1812
apah002:
1813
        lodsb
1813
        lodsb
1814
        test    al, al
1814
        test    al, al
1815
        jz      apah003
1815
        jz      apah003
1816
        call    encode_base64_byte
1816
        call    encode_base64_byte
1817
        jmp     apah002
1817
        jmp     apah002
1818
 
1818
 
1819
apah003:
1819
apah003:
1820
        call    encode_base64_final
1820
        call    encode_base64_final
1821
        ret
1821
        ret
1822
 
1822
 
1823
encode_base64_byte:
1823
encode_base64_byte:
1824
        inc     ecx
1824
        inc     ecx
1825
        shl     edx, 8
1825
        shl     edx, 8
1826
        mov     dl, al
1826
        mov     dl, al
1827
        cmp     ecx, 3
1827
        cmp     ecx, 3
1828
        je      ebb001
1828
        je      ebb001
1829
        ret
1829
        ret
1830
 
1830
 
1831
ebb001:
1831
ebb001:
1832
        shl     edx, 8
1832
        shl     edx, 8
1833
        inc     ecx
1833
        inc     ecx
1834
 
1834
 
1835
ebb002:
1835
ebb002:
1836
        rol     edx, 6
1836
        rol     edx, 6
1837
        xor     eax, eax
1837
        xor     eax, eax
1838
        xchg    al, dl
1838
        xchg    al, dl
1839
        mov     al, [base64_table+eax]
1839
        mov     al, [base64_table+eax]
1840
        stosb
1840
        stosb
1841
        loop    ebb002
1841
        loop    ebb002
1842
        ret
1842
        ret
1843
 
1843
 
1844
encode_base64_final:
1844
encode_base64_final:
1845
        mov     al, 0
1845
        mov     al, 0
1846
        test    ecx, ecx
1846
        test    ecx, ecx
1847
        jz      ebf000
1847
        jz      ebf000
1848
        call    encode_base64_byte
1848
        call    encode_base64_byte
1849
        test    ecx, ecx
1849
        test    ecx, ecx
1850
        jz      ebf001
1850
        jz      ebf001
1851
        call    encode_base64_byte
1851
        call    encode_base64_byte
1852
        mov     byte [edi-2], '='
1852
        mov     byte [edi-2], '='
1853
 
1853
 
1854
ebf001:
1854
ebf001:
1855
        mov     byte [edi-1], '='
1855
        mov     byte [edi-1], '='
1856
 
1856
 
1857
ebf000:
1857
ebf000:
1858
        ret
1858
        ret
1859
 
1859
 
1860
endp
1860
endp
1861
 
1861
 
1862
 
1862
 
1863
;;================================================================================================;;
1863
;;================================================================================================;;
1864
proc eax_ascii_dec ;//////////////////////////////////////////////////////////////////////////////;;
1864
proc eax_ascii_dec ;//////////////////////////////////////////////////////////////////////////////;;
1865
;;------------------------------------------------------------------------------------------------;;
1865
;;------------------------------------------------------------------------------------------------;;
1866
;? Convert eax to ASCII decimal number                                                            ;;
1866
;? Convert eax to ASCII decimal number                                                            ;;
1867
;;------------------------------------------------------------------------------------------------;;
1867
;;------------------------------------------------------------------------------------------------;;
1868
;> eax = number                                                                                   ;;
1868
;> eax = number                                                                                   ;;
1869
;> edi = ptr where to write ASCII decimal number                                                  ;;
1869
;> edi = ptr where to write ASCII decimal number                                                  ;;
1870
;;------------------------------------------------------------------------------------------------;;
1870
;;------------------------------------------------------------------------------------------------;;
1871
;< /                                                                                              ;;
1871
;< /                                                                                              ;;
1872
;;================================================================================================;;
1872
;;================================================================================================;;
1873
 
1873
 
1874
        push    -'0'
1874
        push    -'0'
1875
        mov     ecx, 10
1875
        mov     ecx, 10
1876
  .loop:
1876
  .loop:
1877
        xor     edx, edx
1877
        xor     edx, edx
1878
        div     ecx
1878
        div     ecx
1879
        push    edx
1879
        push    edx
1880
        test    eax, eax
1880
        test    eax, eax
1881
        jnz     .loop
1881
        jnz     .loop
1882
 
1882
 
1883
  .loop2:
1883
  .loop2:
1884
        pop     eax
1884
        pop     eax
1885
        add     al, '0'
1885
        add     al, '0'
1886
        jz      .done
1886
        jz      .done
1887
        stosb
1887
        stosb
1888
        jmp     .loop2
1888
        jmp     .loop2
1889
  .done:
1889
  .done:
1890
 
1890
 
1891
        ret
1891
        ret
1892
 
1892
 
1893
endp
1893
endp
1894
 
1894
 
1895
 
1895
 
1896
;;================================================================================================;;
1896
;;================================================================================================;;
1897
proc ascii_dec_ebx ;//////////////////////////////////////////////////////////////////////////////;;
1897
proc ascii_dec_ebx ;//////////////////////////////////////////////////////////////////////////////;;
1898
;;------------------------------------------------------------------------------------------------;;
1898
;;------------------------------------------------------------------------------------------------;;
1899
;? Convert ASCII decimal number to ebx                                                            ;;
1899
;? Convert ASCII decimal number to ebx                                                            ;;
1900
;;------------------------------------------------------------------------------------------------;;
1900
;;------------------------------------------------------------------------------------------------;;
1901
;> esi = ptr where to read ASCII decimal number                                                   ;;
1901
;> esi = ptr where to read ASCII decimal number                                                   ;;
1902
;;------------------------------------------------------------------------------------------------;;
1902
;;------------------------------------------------------------------------------------------------;;
1903
;> ebx = number                                                                                   ;;
1903
;> ebx = number                                                                                   ;;
1904
;;================================================================================================;;
1904
;;================================================================================================;;
1905
 
1905
 
1906
        xor     eax, eax
1906
        xor     eax, eax
1907
        xor     ebx, ebx
1907
        xor     ebx, ebx
1908
  .loop:
1908
  .loop:
1909
        lodsb
1909
        lodsb
1910
        sub     al, '0'
1910
        sub     al, '0'
1911
        jb      .done
1911
        jb      .done
1912
        cmp     al, 9
1912
        cmp     al, 9
1913
        ja      .done
1913
        ja      .done
1914
        lea     ebx, [ebx + 4*ebx]
1914
        lea     ebx, [ebx + 4*ebx]
1915
        shl     ebx, 1
1915
        shl     ebx, 1
1916
        add     ebx, eax
1916
        add     ebx, eax
1917
        jmp     .loop
1917
        jmp     .loop
1918
  .done:
1918
  .done:
1919
 
1919
 
1920
        ret
1920
        ret
1921
 
1921
 
1922
endp
1922
endp
1923
 
1923
 
1924
 
1924
 
1925
;;================================================================================================;;
1925
;;================================================================================================;;
1926
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1926
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1927
;;================================================================================================;;
1927
;;================================================================================================;;
1928
;! Imported functions section                                                                     ;;
1928
;! Imported functions section                                                                     ;;
1929
;;================================================================================================;;
1929
;;================================================================================================;;
1930
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1930
;;////////////////////////////////////////////////////////////////////////////////////////////////;;
1931
;;================================================================================================;;
1931
;;================================================================================================;;
1932
 
1932
 
1933
 
1933
 
1934
align 16
1934
align 16
1935
@IMPORT:
1935
@IMPORT:
1936
 
1936
 
1937
library \
1937
library \
1938
        libini, 'libini.obj', \
1938
        libini, 'libini.obj', \
1939
        network, 'network.obj'
1939
        network, 'network.obj'
1940
 
1940
 
1941
import  libini, \
1941
import  libini, \
1942
        ini.get_str, 'ini_get_str', \
1942
        ini.get_str, 'ini_get_str', \
1943
        ini.get_int, 'ini_get_int'
1943
        ini.get_int, 'ini_get_int'
1944
 
1944
 
1945
import  network,\
1945
import  network,\
1946
        getaddrinfo, 'getaddrinfo',\
1946
        getaddrinfo, 'getaddrinfo',\
1947
        freeaddrinfo,  'freeaddrinfo',\
1947
        freeaddrinfo,  'freeaddrinfo',\
1948
        inet_ntoa, 'inet_ntoa'
1948
        inet_ntoa, 'inet_ntoa'
1949
 
1949
 
1950
;;===========================================================================;;
1950
;;===========================================================================;;
1951
;;///////////////////////////////////////////////////////////////////////////;;
1951
;;///////////////////////////////////////////////////////////////////////////;;
1952
;;===========================================================================;;
1952
;;===========================================================================;;
1953
;! Exported functions section                                                ;;
1953
;! Exported functions section                                                ;;
1954
;;===========================================================================;;
1954
;;===========================================================================;;
1955
;;///////////////////////////////////////////////////////////////////////////;;
1955
;;///////////////////////////////////////////////////////////////////////////;;
1956
;;===========================================================================;;
1956
;;===========================================================================;;
1957
 
1957
 
1958
 
1958
 
1959
HTTP_stop = HTTP_disconnect
1959
HTTP_stop = HTTP_disconnect
1960
HTTP_process = HTTP_receive
1960
HTTP_process = HTTP_receive
1961
 
1961
 
1962
align 4
1962
align 4
1963
@EXPORT:
1963
@EXPORT:
1964
export  \
1964
export  \
1965
        lib_init                , 'lib_init'            , \
1965
        lib_init                , 'lib_init'            , \
1966
        0x00010001              , 'version'             , \
1966
        0x00010001              , 'version'             , \
1967
        HTTP_buffersize_get     , 'buffersize_get'      , \
1967
        HTTP_buffersize_get     , 'buffersize_get'      , \
1968
        HTTP_buffersize_set     , 'buffersize_set'      , \
1968
        HTTP_buffersize_set     , 'buffersize_set'      , \
1969
        HTTP_get                , 'get'                 , \
1969
        HTTP_get                , 'get'                 , \
1970
        HTTP_head               , 'head'                , \
1970
        HTTP_head               , 'head'                , \
1971
        HTTP_post               , 'post'                , \
1971
        HTTP_post               , 'post'                , \
1972
        HTTP_find_header_field  , 'find_header_field'   , \
1972
        HTTP_find_header_field  , 'find_header_field'   , \
1973
        HTTP_process            , 'process'             , \    ; To be removed
1973
        HTTP_process            , 'process'             , \    ; To be removed
1974
        HTTP_send               , 'send'                , \
1974
        HTTP_send               , 'send'                , \
1975
        HTTP_receive            , 'receive'             , \
1975
        HTTP_receive            , 'receive'             , \
1976
        HTTP_disconnect         , 'disconnect'          , \
1976
        HTTP_disconnect         , 'disconnect'          , \
1977
        HTTP_free               , 'free'                , \
1977
        HTTP_free               , 'free'                , \
1978
        HTTP_stop               , 'stop'                , \    ; To be removed
1978
        HTTP_stop               , 'stop'                , \    ; To be removed
1979
        HTTP_escape             , 'escape'              , \
1979
        HTTP_escape             , 'escape'              , \
1980
        HTTP_unescape           , 'unescape'
1980
        HTTP_unescape           , 'unescape'
1981
;        HTTP_put                , 'put'                 , \
1981
;        HTTP_put                , 'put'                 , \
1982
;        HTTP_delete             , 'delete'              , \
1982
;        HTTP_delete             , 'delete'              , \
1983
;        HTTP_trace              , 'trace'               , \
1983
;        HTTP_trace              , 'trace'               , \
1984
;        HTTP_connect            , 'connect'             , \
1984
;        HTTP_connect            , 'connect'             , \
1985
 
1985
 
1986
 
1986
 
1987
 
1987
 
1988
section '.data' data readable writable align 16
1988
section '.data' data readable writable align 16
1989
 
1989
 
1990
inifile         db '/sys/settings/network.ini', 0
1990
inifile         db '/sys/settings/network.ini', 0
1991
 
1991
 
1992
sec_proxy:
1992
sec_proxy:
1993
key_proxy       db 'proxy', 0
1993
key_proxy       db 'proxy', 0
1994
key_proxyport   db 'port', 0
1994
key_proxyport   db 'port', 0
1995
key_user        db 'user', 0
1995
key_user        db 'user', 0
1996
key_password    db 'password', 0
1996
key_password    db 'password', 0
1997
 
1997
 
1998
str_http11      db ' HTTP/1.1', 13, 10, 'Host: '
1998
str_http11      db ' HTTP/1.1', 13, 10, 'Host: '
1999
  .length       = $ - str_http11
1999
  .length       = $ - str_http11
2000
str_post_cl     db 13, 10, 'Content-Length: '
2000
str_post_cl     db 13, 10, 'Content-Length: '
2001
  .length       = $ - str_post_cl
2001
  .length       = $ - str_post_cl
2002
str_post_ct     db 13, 10, 'Content-Type: '
2002
str_post_ct     db 13, 10, 'Content-Type: '
2003
  .length       = $ - str_post_ct
2003
  .length       = $ - str_post_ct
2004
str_proxy_auth  db 13, 10, 'Proxy-Authorization: Basic '
2004
str_proxy_auth  db 13, 10, 'Proxy-Authorization: Basic '
2005
  .length       = $ - str_proxy_auth
2005
  .length       = $ - str_proxy_auth
2006
str_close       db 'User-Agent: KolibriOS libHTTP/1.1', 13, 10, 'Connection: close', 13, 10, 13, 10
2006
str_close       db 'User-Agent: KolibriOS libHTTP/1.1', 13, 10, 'Connection: close', 13, 10, 13, 10
2007
  .length       = $ - str_close
2007
  .length       = $ - str_close
2008
str_keep        db 'User-Agent: KolibriOS libHTTP/1.1', 13, 10, 'Connection: keep-alive', 13, 10, 13, 10
2008
str_keep        db 'User-Agent: KolibriOS libHTTP/1.1', 13, 10, 'Connection: keep-alive', 13, 10, 13, 10
2009
  .length       = $ - str_keep
2009
  .length       = $ - str_keep
2010
 
2010
 
2011
str_http        db 'http://', 0
2011
str_http        db 'http://', 0
2012
 
2012
 
2013
base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
2013
base64_table    db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
2014
                db '0123456789+/'
2014
                db '0123456789+/'
2015
 
2015
 
2016
str_cl          db 'content-length', 0
2016
str_cl          db 'content-length', 0
2017
str_slash       db '/', 0
2017
str_slash       db '/', 0
2018
str_te          db 'transfer-encoding', 0
2018
str_te          db 'transfer-encoding', 0
2019
str_get         db 'GET ', 0
2019
str_get         db 'GET ', 0
2020
str_head        db 'HEAD ', 0
2020
str_head        db 'HEAD ', 0
2021
str_post        db 'POST ', 0
2021
str_post        db 'POST ', 0
2022
 
2022
 
2023
bits_must_escape:
2023
bits_must_escape:
2024
dd      0xffffffff                                                      ; 00-1F
2024
dd      0xffffffff                                                      ; 00-1F
2025
dd      1 shl 0 + 1 shl 2 + 1 shl 3 + 1 shl 5 + 1 shl 28 + 1 shl 30     ; "#%<>
2025
dd      1 shl 0 + 1 shl 2 + 1 shl 3 + 1 shl 5 + 1 shl 28 + 1 shl 30     ; "#%<>
2026
dd      1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 30                       ;[\]^
2026
dd      1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 30                       ;[\]^
2027
dd      1 shl 0 + 1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 31             ;`{|} DEL
2027
dd      1 shl 0 + 1 shl 27 + 1 shl 28 + 1 shl 29 + 1 shl 31             ;`{|} DEL
2028
 
2028
 
2029
dd      0xffffffff
2029
dd      0xffffffff
2030
dd      0xffffffff
2030
dd      0xffffffff
2031
dd      0xffffffff
2031
dd      0xffffffff
2032
dd      0xffffffff
2032
dd      0xffffffff
2033
 
2033
 
2034
str_hex:
2034
str_hex:
2035
db '0123456789ABCDEF'
2035
db '0123456789ABCDEF'
2036
 
2036
 
2037
buffersize      dd BUFFERSIZE
2037
buffersize      dd BUFFERSIZE
2038
 
2038
 
2039
include_debug_strings
2039
include_debug_strings
2040
 
2040
 
2041
; uninitialized data
2041
; uninitialized data
2042
mem.alloc       dd ?
2042
mem.alloc       dd ?
2043
mem.free        dd ?
2043
mem.free        dd ?
2044
mem.realloc     dd ?
2044
mem.realloc     dd ?
2045
dll.load        dd ?
2045
dll.load        dd ?
2046
 
2046
 
2047
proxyAddr       rb 256
2047
proxyAddr       rb 256
2048
proxyUser       rb 256
2048
proxyUser       rb 256
2049
proxyPassword   rb 256
2049
proxyPassword   rb 256
2050
proxyPort       dd ?
2050
proxyPort       dd ?