Subversion Repositories Kolibri OS

Rev

Rev 7009 | Rev 7101 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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