Subversion Repositories Kolibri OS

Rev

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

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