Subversion Repositories Kolibri OS

Rev

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

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