Rev 8442 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 8442 | Rev 9164 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2013-2018. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2013-2021. 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 | ;; ftpc.asm - FTP client for KolibriOS ;; |
6 | ;; ftpc.asm - FTP client for KolibriOS ;; |
7 | ;; ;; |
7 | ;; ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
9 | ;; Modified by nisargshah323@gmail.com (2016) ;; |
9 | ;; Modified by nisargshah323@gmail.com (2016) ;; |
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 | format binary as "" |
16 | format binary as "" |
17 | 17 | ||
18 | TIMEOUT = 3 ; seconds |
18 | TIMEOUT = 3 ; seconds |
19 | 19 | ||
20 | BUFFERSIZE = 4096 |
20 | BUFFERSIZE = 4096 |
21 | 21 | ||
22 | STATUS_CONNECTING = 0 |
22 | STATUS_CONNECTING = 0 |
23 | STATUS_CONNECTED = 1 |
23 | STATUS_CONNECTED = 1 |
24 | STATUS_NEEDPASSWORD = 2 |
24 | STATUS_NEEDPASSWORD = 2 |
25 | STATUS_LOGGED_IN = 3 |
25 | STATUS_LOGGED_IN = 3 |
26 | 26 | ||
27 | OPERATION_NONE = 0 |
27 | OPERATION_NONE = 0 |
28 | OPERATION_LIST = 1 |
28 | OPERATION_LIST = 1 |
29 | OPERATION_RETR = 2 |
29 | OPERATION_RETR = 2 |
30 | OPERATION_STOR = 3 |
30 | OPERATION_STOR = 3 |
31 | OPERATION_RDIR = 4 |
31 | OPERATION_RDIR = 4 |
32 | 32 | ||
33 | use32 |
33 | use32 |
34 | ; standard header |
34 | ; standard header |
35 | db 'MENUET01' ; signature |
35 | db 'MENUET01' ; signature |
36 | dd 1 ; header version |
36 | dd 1 ; header version |
37 | dd start ; entry point |
37 | dd start ; entry point |
38 | dd i_end ; initialized size |
38 | dd i_end ; initialized size |
39 | dd mem+0x1000 ; required memory |
39 | dd mem+0x1000 ; required memory |
40 | dd mem+0x1000 ; stack pointer |
40 | dd mem+0x1000 ; stack pointer |
41 | dd buf_cmd ; parameters |
41 | dd buf_cmd ; parameters |
42 | dd path ; path |
42 | dd path ; path |
43 | 43 | ||
44 | include '../../macros.inc' |
44 | include '../../macros.inc' |
45 | macro ijmp reg, addr, method |
45 | macro ijmp reg, addr, method |
46 | { |
46 | { |
47 | mov reg, [addr] |
47 | mov reg, [addr] |
48 | add reg, [method] |
48 | add reg, [method] |
49 | jmp dword[reg] |
49 | jmp dword[reg] |
50 | } |
50 | } |
51 | macro icall reg, addr, method, [arg] |
51 | macro icall reg, addr, method, [arg] |
52 | { |
52 | { |
53 | mov reg, [addr] |
53 | mov reg, [addr] |
54 | add reg, [method] |
54 | add reg, [method] |
55 | if ~ arg eq |
55 | if ~ arg eq |
56 | pushd arg |
56 | pushd arg |
57 | end if |
57 | end if |
58 | call dword[reg] |
58 | call dword[reg] |
59 | } |
59 | } |
60 | 60 | ||
61 | purge mov,add,sub |
61 | purge mov,add,sub |
62 | 62 | ||
63 | include '../../proc32.inc' |
63 | include '../../proc32.inc' |
64 | include '../../network.inc' |
64 | include '../../network.inc' |
65 | include '../../KOSfuncs.inc' |
65 | include '../../KOSfuncs.inc' |
66 | 66 | ||
67 | include 'console.inc' |
67 | include 'console.inc' |
68 | include 'gui.inc' |
68 | include 'gui.inc' |
69 | include 'login_gui.inc' |
69 | include 'login_gui.inc' |
70 | include 'usercommands.inc' |
70 | include 'usercommands.inc' |
71 | include 'servercommands.inc' |
71 | include 'servercommands.inc' |
72 | include 'parser.inc' |
72 | include 'parser.inc' |
73 | 73 | ||
74 | ; TODO: Add Pasta support to FTPC |
74 | ; TODO: Add Pasta support to FTPC |
75 | 75 | ||
76 | ;;================================================================================================;; |
76 | ;;================================================================================================;; |
77 | start: ;//////////////////////////////////////////////////////////////////////////////////////////;; |
77 | start: ;//////////////////////////////////////////////////////////////////////////////////////////;; |
78 | ;;------------------------------------------------------------------------------------------------;; |
78 | ;;------------------------------------------------------------------------------------------------;; |
79 | ;? Program entry point - initialize heap, load libraries and settings ;; |
79 | ;? Program entry point - initialize heap, load libraries and settings ;; |
80 | ;;------------------------------------------------------------------------------------------------;; |
80 | ;;------------------------------------------------------------------------------------------------;; |
81 | ;> ;; |
81 | ;> ;; |
82 | ;;------------------------------------------------------------------------------------------------;; |
82 | ;;------------------------------------------------------------------------------------------------;; |
83 | ;< none ;; |
83 | ;< none ;; |
84 | ;;================================================================================================;; |
84 | ;;================================================================================================;; |
85 | ; initialize heap for using dynamic blocks |
85 | ; initialize heap for using dynamic blocks |
86 | mcall 68, 11 |
86 | mcall 68, 11 |
87 | test eax, eax |
87 | test eax, eax |
88 | je exit2 |
88 | je exit2 |
89 | 89 | ||
90 | ; disable all events except network event |
90 | ; disable all events except network event |
91 | mcall 40, EV_STACK |
91 | mcall 40, EV_STACK |
92 | ; load libraries |
92 | ; load libraries |
93 | stdcall dll.Load, @IMPORT |
93 | stdcall dll.Load, @IMPORT |
94 | test eax, eax |
94 | test eax, eax |
95 | jnz exit |
95 | jnz exit |
96 | ; find path to main settings file (ftpc.ini) |
96 | ; find path to main settings file (ftpc.ini) |
97 | mov edi, path ; Calculate the length of zero-terminated string |
97 | mov edi, path ; Calculate the length of zero-terminated string |
98 | xor al, al |
98 | xor al, al |
99 | mov ecx, 1024 |
99 | mov ecx, 1024 |
100 | repne scasb |
100 | repne scasb |
101 | dec edi |
101 | dec edi |
102 | mov esi, str_ini ; append it with '.ini', 0 |
102 | mov esi, str_ini ; append it with '.ini', 0 |
103 | movsd |
103 | movsd |
104 | movsb |
104 | movsb |
105 | ; get settings from ini |
105 | ; get settings from ini |
106 | invoke ini.get_str, path, str_active, str_ip, str_active_ip, 16, 0 |
106 | invoke ini.get_str, path, str_active, str_ip, str_active_ip, 16, 0 |
107 | mov esi, str_active_ip |
107 | mov esi, str_active_ip |
108 | .ip_loop: |
108 | .ip_loop: |
109 | lodsb |
109 | lodsb |
110 | test al, al |
110 | test al, al |
111 | jz .ip_ok |
111 | jz .ip_ok |
112 | cmp al, ' ' |
112 | cmp al, ' ' |
113 | je .ip_ok |
113 | je .ip_ok |
114 | cmp al, '.' |
114 | cmp al, '.' |
115 | jne .ip_loop |
115 | jne .ip_loop |
116 | mov byte[esi-1], ',' |
116 | mov byte[esi-1], ',' |
117 | jmp .ip_loop |
117 | jmp .ip_loop |
118 | .ip_ok: |
118 | .ip_ok: |
119 | mov byte[esi-1], 0 |
119 | mov byte[esi-1], 0 |
120 | 120 | ||
121 | invoke ini.get_int, path, str_active, str_port_start, 64000 |
121 | invoke ini.get_int, path, str_active, str_port_start, 64000 |
122 | mov [acti_port_start], ax |
122 | mov [acti_port_start], ax |
123 | 123 | ||
124 | invoke ini.get_int, path, str_active, str_port_stop, 65000 |
124 | invoke ini.get_int, path, str_active, str_port_stop, 65000 |
125 | mov [acti_port_stop], ax |
125 | mov [acti_port_stop], ax |
126 | 126 | ||
127 | invoke ini.get_str, path, str_general, str_dir, buf_buffer1, BUFFERSIZE, 0 |
127 | invoke ini.get_str, path, str_general, str_dir, buf_buffer1, BUFFERSIZE, 0 |
128 | mcall 30, 1, buf_buffer1 ; set working directory |
128 | mcall 30, 1, buf_buffer1 ; set working directory |
129 | 129 | ||
130 | ; initialize log file |
130 | ; initialize log file |
131 | invoke ini.get_str, path, str_general, str_logfile, log_file, 512, 0 |
131 | invoke ini.get_str, path, str_general, str_logfile, log_file, 512, 0 |
132 | mov [filestruct2.subfn], 2 |
132 | mov [filestruct2.subfn], 2 |
133 | mov [filestruct2.offset], 0 |
133 | mov [filestruct2.offset], 0 |
134 | mov [filestruct2.size], 0 |
134 | mov [filestruct2.size], 0 |
135 | mov [filestruct2.ptr], 0 |
135 | mov [filestruct2.ptr], 0 |
136 | mov [filestruct2.name], log_file |
136 | mov [filestruct2.name], log_file |
137 | mcall 70, filestruct2 |
137 | mcall 70, filestruct2 |
138 | 138 | ||
139 | ; Usage: ftpc [-cli] [ftp://username:password@server:port/path] |
139 | ; Usage: ftpc [-cli] [ftp://username:password@server:port/path] |
140 | 140 | ||
141 | ; mov dword[buf_cmd], '-cli' ;;;; to test CLI ;;;;; |
141 | ; mov dword[buf_cmd], '-cli' ;;;; to test CLI ;;;;; |
142 | 142 | ||
143 | cmp byte[buf_cmd], 0 |
143 | cmp byte[buf_cmd], 0 |
144 | jne @f |
144 | jne @f |
145 | mov [interface_addr], gui |
145 | mov [interface_addr], gui |
146 | jmp .args_ok |
146 | jmp .args_ok |
147 | @@: cmp dword[buf_cmd], '-cli' |
147 | @@: cmp dword[buf_cmd], '-cli' |
148 | jne .error |
148 | jne .error |
149 | mov [interface_addr], console |
149 | mov [interface_addr], console |
150 | jmp .args_ok |
150 | jmp .args_ok |
151 | 151 | ||
152 | .args_ok: |
152 | .args_ok: |
153 | 153 | ||
154 | icall eax, interface_addr, interface.init |
154 | icall eax, interface_addr, interface.init |
155 | ; check for ftp://username:pass@server:port/path urls |
155 | ; check for ftp://username:pass@server:port/path urls |
156 | cmp dword[buf_cmd], 'ftp:' |
156 | cmp dword[buf_cmd], 'ftp:' |
157 | je parse_args |
157 | je parse_args |
158 | cmp dword[buf_cmd+5], 'ftp:' |
158 | cmp dword[buf_cmd+5], 'ftp:' |
159 | je parse_args |
159 | je parse_args |
160 | ijmp eax, interface_addr, interface.server_addr |
160 | ijmp eax, interface_addr, interface.server_addr |
161 | 161 | ||
162 | .error: |
162 | .error: |
163 | call console.init |
163 | call console.init |
164 | invoke con_write_asciiz, str_args_err |
164 | invoke con_write_asciiz, str_args_err |
165 | invoke con_getch2 |
165 | invoke con_getch2 |
166 | call console.exit |
166 | call console.exit |
167 | jmp exit |
167 | jmp exit |
168 | 168 | ||
169 | ;;================================================================================================;; |
169 | ;;================================================================================================;; |
170 | arg_handler: ;////////////////////////////////////////////////////////////////////////////////////;; |
170 | arg_handler: ;////////////////////////////////////////////////////////////////////////////////////;; |
171 | ;;------------------------------------------------------------------------------------------------;; |
171 | ;;------------------------------------------------------------------------------------------------;; |
172 | ;? Passes initial connection info from console/GUI to FTP core and the other way around ;; |
172 | ;? Passes initial connection info from console/GUI to FTP core and the other way around ;; |
173 | ;;------------------------------------------------------------------------------------------------;; |
173 | ;;------------------------------------------------------------------------------------------------;; |
174 | ;> esp+4 = pointer to the argument passed to the function ;; |
174 | ;> esp+4 = pointer to the argument passed to the function ;; |
175 | ;;------------------------------------------------------------------------------------------------;; |
175 | ;;------------------------------------------------------------------------------------------------;; |
176 | ;< none ;; |
176 | ;< none ;; |
177 | ;;================================================================================================;; |
177 | ;;================================================================================================;; |
178 | 178 | ||
179 | .get_username: |
179 | .get_username: |
180 | ; request username |
180 | ; request username |
181 | ijmp eax, interface_addr, interface.get_username |
181 | ijmp eax, interface_addr, interface.get_username |
182 | 182 | ||
183 | .copy_user: |
183 | .copy_user: |
184 | mov dword[buf_cmd], "USER" |
184 | mov dword[buf_cmd], "USER" |
185 | mov byte[buf_cmd+4], " " |
185 | mov byte[buf_cmd+4], " " |
186 | ; copy user name to buf_cmd (for command line args) |
186 | ; copy user name to buf_cmd (for command line args) |
187 | mov edi, buf_cmd+5 |
187 | mov edi, buf_cmd+5 |
188 | mov esi, param_user |
188 | mov esi, param_user |
189 | @@: |
189 | @@: |
190 | movsb |
190 | movsb |
191 | cmp byte [esi-1], 0 |
191 | cmp byte [esi-1], 0 |
192 | jne @b |
192 | jne @b |
193 | mov word[edi-1], 0x0a0d |
193 | mov word[edi-1], 0x0a0d |
194 | 194 | ||
195 | lea esi, [edi+1-buf_cmd] |
195 | lea esi, [edi+1-buf_cmd] |
196 | jmp server_connect.send |
196 | jmp server_connect.send |
197 | 197 | ||
198 | .get_pass: |
198 | .get_pass: |
199 | mov dword[buf_cmd], "PASS" |
199 | mov dword[buf_cmd], "PASS" |
200 | mov byte[buf_cmd+4], " " |
200 | mov byte[buf_cmd+4], " " |
201 | ; copy password to buf_cmd (for command line args) |
201 | ; copy password to buf_cmd (for command line args) |
202 | mov edi, buf_cmd+5 |
202 | mov edi, buf_cmd+5 |
203 | mov esi, param_password |
203 | mov esi, param_password |
204 | @@: |
204 | @@: |
205 | movsb |
205 | movsb |
206 | cmp byte[esi-1], 0 |
206 | cmp byte[esi-1], 0 |
207 | jne @b |
207 | jne @b |
208 | mov word[edi-1], 0x0a0d |
208 | mov word[edi-1], 0x0a0d |
209 | 209 | ||
210 | lea esi, [edi+1-buf_cmd] |
210 | lea esi, [edi+1-buf_cmd] |
211 | jmp server_connect.send |
211 | jmp server_connect.send |
212 | 212 | ||
213 | .get_path: |
213 | .get_path: |
214 | ; copy path from param_path to buf_cmd |
214 | ; copy path from param_path to buf_cmd |
215 | mov dword[buf_cmd], "CWD " |
215 | mov dword[buf_cmd], "CWD " |
216 | mov edi, buf_cmd+4 |
216 | mov edi, buf_cmd+4 |
217 | mov esi, param_path |
217 | mov esi, param_path |
218 | @@: |
218 | @@: |
219 | lodsb |
219 | lodsb |
220 | stosb |
220 | stosb |
221 | cmp al, 0x20 |
221 | cmp al, 0x20 |
222 | ja @b |
222 | ja @b |
223 | mov word[edi-1], 0x0a0d |
223 | mov word[edi-1], 0x0a0d |
224 | 224 | ||
225 | lea esi, [edi+1-buf_cmd] |
225 | lea esi, [edi+1-buf_cmd] |
226 | jmp server_connect.send |
226 | jmp server_connect.send |
227 | 227 | ||
228 | .connect: |
228 | .connect: |
229 | ; copy server address to buf_cmd |
229 | ; copy server address to buf_cmd |
230 | mov esi, param_server_addr |
230 | mov esi, param_server_addr |
231 | mov edi, buf_cmd |
231 | mov edi, buf_cmd |
232 | @@: |
232 | @@: |
233 | lodsb |
233 | lodsb |
234 | stosb |
234 | stosb |
235 | cmp al, 0x20 |
235 | cmp al, 0x20 |
236 | ja @r |
236 | ja @r |
237 | mov byte[edi-1], 0 ; delete terminating '\n' |
237 | mov byte[edi-1], 0 ; delete terminating '\n' |
238 | 238 | ||
239 | cmp [param_port], 0x20 |
239 | cmp [param_port], 0x20 |
240 | jbe server_connect.default_port |
240 | jbe server_connect.default_port |
241 | mov esi, param_port |
241 | mov esi, param_port |
242 | jmp server_connect.do_port |
242 | jmp server_connect.do_port |
243 | 243 | ||
244 | 244 | ||
245 | ;;================================================================================================;; |
245 | ;;================================================================================================;; |
246 | server_connect: ;/////////////////////////////////////////////////////////////////////////////////;; |
246 | server_connect: ;/////////////////////////////////////////////////////////////////////////////////;; |
247 | ;;------------------------------------------------------------------------------------------------;; |
247 | ;;------------------------------------------------------------------------------------------------;; |
248 | ;? Establishes a connection to the FTP server (common block for all interfaces) ;; |
248 | ;? Establishes a connection to the FTP server (common block for all interfaces) ;; |
249 | ;? .do_port - Port is specified by the user and needs to be converted from ASCII ;; |
249 | ;? .do_port - Port is specified by the user and needs to be converted from ASCII ;; |
250 | ;;------------------------------------------------------------------------------------------------;; |
250 | ;;------------------------------------------------------------------------------------------------;; |
251 | ;> esi = pointer to port no. ;; |
251 | ;> esi = pointer to port no. ;; |
252 | ;;------------------------------------------------------------------------------------------------;; |
252 | ;;------------------------------------------------------------------------------------------------;; |
253 | ;< none ;; |
253 | ;< none ;; |
254 | ;;================================================================================================;; |
254 | ;;================================================================================================;; |
255 | 255 | ||
256 | .send: |
256 | .send: |
257 | ; send username/password/path to the server |
257 | ; send username/password/path to the server |
258 | mcall send, [controlsocket], buf_cmd, , 0 |
258 | mcall send, [controlsocket], buf_cmd, , 0 |
259 | icall eax, interface_addr, interface.print, str_newline |
259 | icall eax, interface_addr, interface.print, str_newline |
260 | icall eax, interface_addr, interface.set_flags, 0x07 ; reset color |
260 | icall eax, interface_addr, interface.set_flags, 0x07 ; reset color |
261 | 261 | ||
262 | jmp wait_for_servercommand |
262 | jmp wait_for_servercommand |
263 | 263 | ||
264 | ; resolve port if specified |
264 | ; resolve port if specified |
265 | .do_port: |
265 | .do_port: |
266 | xor eax, eax |
266 | xor eax, eax |
267 | xor ebx, ebx |
267 | xor ebx, ebx |
268 | .portloop: |
268 | .portloop: |
269 | lodsb |
269 | lodsb |
270 | cmp al, 0x20 |
270 | cmp al, 0x20 |
271 | jbe .port_done |
271 | jbe .port_done |
272 | sub al, '0' |
272 | sub al, '0' |
273 | jnb @f |
273 | jnb @f |
274 | mov eax, str_err_host |
274 | mov eax, str_err_host |
275 | jmp error |
275 | jmp error |
276 | @@: cmp al, 9 |
276 | @@: cmp al, 9 |
277 | jna @f |
277 | jna @f |
278 | mov eax, str_err_host |
278 | mov eax, str_err_host |
279 | jmp error |
279 | jmp error |
280 | @@: lea ebx, [ebx*4 + ebx] |
280 | @@: lea ebx, [ebx*4 + ebx] |
281 | shl ebx, 1 |
281 | shl ebx, 1 |
282 | add ebx, eax |
282 | add ebx, eax |
283 | jmp .portloop |
283 | jmp .portloop |
284 | 284 | ||
285 | .port_done: |
285 | .port_done: |
286 | xchg bl, bh |
286 | xchg bl, bh |
287 | mov [sockaddr1.port], bx |
287 | mov [sockaddr1.port], bx |
288 | jmp .done |
288 | jmp .done |
289 | 289 | ||
290 | .default_port: |
290 | .default_port: |
291 | mov [sockaddr1.port], 21 shl 8 |
291 | mov [sockaddr1.port], 21 shl 8 |
292 | 292 | ||
293 | .done: |
293 | .done: |
294 | ; Say to the user that we're resolving |
294 | ; Say to the user that we're resolving |
295 | icall eax, interface_addr, interface.set_flags, 0x07 ; reset color |
295 | icall eax, interface_addr, interface.set_flags, 0x07 ; reset color |
296 | icall eax, interface_addr, interface.print, str_resolve, buf_cmd |
296 | icall eax, interface_addr, interface.print, str_resolve, buf_cmd |
297 | ; resolve name |
297 | ; resolve name |
298 | push esp ; reserve stack place |
298 | push esp ; reserve stack place |
299 | invoke getaddrinfo, buf_cmd, 0, 0, esp |
299 | invoke getaddrinfo, buf_cmd, 0, 0, esp |
300 | pop esi |
300 | pop esi |
301 | ; test for error |
301 | ; test for error |
302 | test eax, eax |
302 | test eax, eax |
303 | jz @f |
303 | jz @f |
304 | mov eax, str_err_resolve |
304 | mov eax, str_err_resolve |
305 | jmp error |
305 | jmp error |
306 | @@: |
306 | @@: |
307 | ; write results |
307 | ; write results |
308 | icall eax, interface_addr, interface.print, str8 ; ' (',0 |
308 | icall eax, interface_addr, interface.print, str8 ; ' (',0 |
309 | mov eax, [esi+addrinfo.ai_addr] ; convert IP address to decimal notation |
309 | mov eax, [esi+addrinfo.ai_addr] ; convert IP address to decimal notation |
310 | mov eax, [eax+sockaddr_in.sin_addr] ; |
310 | mov eax, [eax+sockaddr_in.sin_addr] ; |
311 | mov [sockaddr1.ip], eax ; |
311 | mov [sockaddr1.ip], eax ; |
312 | invoke inet_ntoa, eax ; |
312 | invoke inet_ntoa, eax ; |
313 | icall ebx, interface_addr, interface.print, eax, str9 ; |
313 | icall ebx, interface_addr, interface.print, eax, str9 ; |
314 | invoke freeaddrinfo, esi ; free allocated memory |
314 | invoke freeaddrinfo, esi ; free allocated memory |
315 | ; open the socket |
315 | ; open the socket |
316 | mcall socket, AF_INET4, SOCK_STREAM, 0 |
316 | mcall socket, AF_INET4, SOCK_STREAM, 0 |
317 | cmp eax, -1 |
317 | cmp eax, -1 |
318 | jne @f |
318 | jne @f |
319 | mov eax, str_err_socket |
319 | mov eax, str_err_socket |
320 | jmp error |
320 | jmp error |
321 | @@: mov [controlsocket], eax |
321 | @@: mov [controlsocket], eax |
322 | ; connect to the server |
322 | ; connect to the server |
323 | icall eax, interface_addr, interface.print, str_connect |
323 | icall eax, interface_addr, interface.print, str_connect |
324 | mcall connect, [controlsocket], sockaddr1, 18 |
324 | mcall connect, [controlsocket], sockaddr1, 18 |
325 | cmp eax, -1 |
325 | cmp eax, -1 |
326 | jne @f |
326 | jne @f |
327 | mov eax, str_err_connect |
327 | mov eax, str_err_connect |
328 | jmp error |
328 | jmp error |
329 | @@: mov [status], STATUS_CONNECTING |
329 | @@: mov [status], STATUS_CONNECTING |
330 | ; Tell the user we're waiting for the server now. |
330 | ; Tell the user we're waiting for the server now. |
331 | icall eax, interface_addr, interface.print, str_waiting |
331 | icall eax, interface_addr, interface.print, str_waiting |
332 | 332 | ||
333 | ; Reset 'offset' variable, it's used by the data receiver |
333 | ; Reset 'offset' variable, it's used by the data receiver |
334 | mov [offset], 0 |
334 | mov [offset], 0 |
335 | 335 | ||
336 | 336 | ||
337 | ;;================================================================================================;; |
337 | ;;================================================================================================;; |
338 | wait_for_servercommand: ;/////////////////////////////////////////////////////////////////////////;; |
338 | wait_for_servercommand: ;/////////////////////////////////////////////////////////////////////////;; |
339 | ;;------------------------------------------------------------------------------------------------;; |
339 | ;;------------------------------------------------------------------------------------------------;; |
340 | ;? Checks if any data received from the server is present in buffer. ;; |
340 | ;? Checks if any data received from the server is present in buffer. ;; |
341 | ;? If not, receives and processes it ;; |
341 | ;? If not, receives and processes it ;; |
342 | ;;------------------------------------------------------------------------------------------------;; |
342 | ;;------------------------------------------------------------------------------------------------;; |
343 | ;> ;; |
343 | ;> ;; |
344 | ;;------------------------------------------------------------------------------------------------;; |
344 | ;;------------------------------------------------------------------------------------------------;; |
345 | ;< none ;; |
345 | ;< none ;; |
346 | ;;================================================================================================;; |
346 | ;;================================================================================================;; |
347 | ; Any commands still in our buffer? |
347 | ; Any commands still in our buffer? |
348 | cmp [offset], 0 |
348 | cmp [offset], 0 |
349 | je .receive ; nope, receive some more |
349 | je .receive ; nope, receive some more |
350 | mov esi, [offset] |
350 | mov esi, [offset] |
351 | mov edi, buf_cmd |
351 | mov edi, buf_cmd |
352 | mov ecx, [size] |
352 | mov ecx, [size] |
353 | add ecx, esi |
353 | add ecx, esi |
354 | jmp .byteloop |
354 | jmp .byteloop |
355 | 355 | ||
356 | ; receive socket data |
356 | ; receive socket data with timeout |
357 | .receive: |
357 | .receive: |
358 | mcall 26, 9 |
358 | mcall 26, 9 |
359 | add eax, TIMEOUT*100 |
359 | add eax, TIMEOUT*100 |
360 | mov [timeout], eax |
360 | mov [timeout], eax |
361 | .receive_loop: |
361 | .again: |
362 | mcall 23, 50 ; Wait for event with timeout |
362 | mcall recv, [controlsocket], buf_buffer1, BUFFERSIZE, MSG_DONTWAIT |
363 | mcall 26, 9 |
- | |
364 | cmp eax, [timeout] |
- | |
365 | jl @f |
- | |
366 | mov eax, str_err_timeout |
- | |
367 | jmp error |
363 | cmp eax, 0 |
368 | @@: mcall recv, [controlsocket], buf_buffer1, BUFFERSIZE, MSG_DONTWAIT |
- | |
369 | test eax, eax |
364 | jg .got_data |
370 | jnz .got_data |
365 | je .closed |
371 | cmp ebx, EWOULDBLOCK |
366 | cmp ebx, EWOULDBLOCK |
- | 367 | jne .sock_err |
|
- | 368 | mcall 26, 9 |
|
- | 369 | mov ebx, [timeout] |
|
- | 370 | sub ebx, eax |
|
- | 371 | jle .timeout |
|
- | 372 | mcall 23 ; Wait for event with timeout |
|
372 | je @f |
373 | jmp .again |
- | 374 | ||
- | 375 | .sock_err: |
|
373 | mov eax, str_err_recv |
376 | mov eax, str_err_recv |
374 | jmp error |
377 | jmp error |
- | 378 | ||
- | 379 | .closed: |
|
- | 380 | mov eax, str_err_closed |
|
375 | @@: jmp .receive_loop |
381 | jmp error |
- | 382 | ||
- | 383 | .timeout: |
|
- | 384 | mov eax, str_err_timeout |
|
- | 385 | jmp error |
|
376 | 386 | ||
377 | .got_data: |
387 | .got_data: |
378 | mov [offset], 0 |
388 | mov [offset], 0 |
379 | 389 | ||
380 | ; extract commands, copy them to "buf_cmd" buffer |
390 | ; extract commands, copy them to "buf_cmd" buffer |
381 | lea ecx, [eax + buf_buffer1] ; ecx = end pointer |
391 | lea ecx, [eax + buf_buffer1] ; ecx = end pointer |
382 | mov esi, buf_buffer1 ; esi = current pointer |
392 | mov esi, buf_buffer1 ; esi = current pointer |
383 | mov edi, buf_cmd |
393 | mov edi, buf_cmd |
384 | .byteloop: |
394 | .byteloop: |
385 | cmp esi, ecx |
395 | cmp esi, ecx |
386 | jae wait_for_servercommand |
396 | jae wait_for_servercommand |
387 | lodsb |
397 | lodsb |
388 | cmp al, 10 ; excellent, we might have a command |
398 | cmp al, 10 ; excellent, we might have a command |
389 | je .got_command |
399 | je .got_command |
390 | cmp al, 13 ; just ignore this byte |
400 | cmp al, 13 ; just ignore this byte |
391 | je .byteloop |
401 | je .byteloop |
392 | stosb |
402 | stosb |
393 | jmp .byteloop |
403 | jmp .byteloop |
394 | .got_command: ; we have a newline check if its a command |
404 | .got_command: ; we have a newline check if its a command |
395 | cmp esi, ecx |
405 | cmp esi, ecx |
396 | je .no_more_data |
406 | je .no_more_data |
397 | mov [offset], esi |
407 | mov [offset], esi |
398 | sub ecx, esi |
408 | sub ecx, esi |
399 | mov [size], ecx |
409 | mov [size], ecx |
400 | jmp .go_cmd |
410 | jmp .go_cmd |
401 | .no_more_data: |
411 | .no_more_data: |
402 | mov [offset], 0 |
412 | mov [offset], 0 |
403 | .go_cmd: |
413 | .go_cmd: |
404 | lea ecx, [edi - buf_cmd] ; length of command |
414 | lea ecx, [edi - buf_cmd] ; length of command |
405 | xor al, al |
415 | xor al, al |
406 | stosb |
416 | stosb |
407 | 417 | ||
408 | icall eax, interface_addr, interface.set_flags, 0x03 ; change color |
418 | icall eax, interface_addr, interface.set_flags, 0x03 ; change color |
409 | icall eax, interface_addr, interface.print, buf_cmd, str_newline |
419 | icall eax, interface_addr, interface.print, buf_cmd, str_newline |
410 | icall eax, interface_addr, interface.set_flags, 0x07 ; reset color |
420 | icall eax, interface_addr, interface.set_flags, 0x07 ; reset color |
411 | 421 | ||
412 | jmp server_parser ; parse command |
422 | jmp server_parser ; parse command |
413 | 423 | ||
414 | 424 | ||
415 | 425 | ||
416 | ;;================================================================================================;; |
426 | ;;================================================================================================;; |
417 | wait_for_usercommand: ;///////////////////////////////////////////////////////////////////////////;; |
427 | wait_for_usercommand: ;///////////////////////////////////////////////////////////////////////////;; |
418 | ;;------------------------------------------------------------------------------------------------;; |
428 | ;;------------------------------------------------------------------------------------------------;; |
419 | ;? Reads the FTP command entered by the user and compares it with valid FTP commands. ;; |
429 | ;? Reads the FTP command entered by the user and compares it with valid FTP commands. ;; |
420 | ;? Jumps to appropriate handling routine in usercommands.inc ;; |
430 | ;? Jumps to appropriate handling routine in usercommands.inc ;; |
421 | ;;------------------------------------------------------------------------------------------------;; |
431 | ;;------------------------------------------------------------------------------------------------;; |
422 | ;> status = socket connection status ;; |
432 | ;> status = socket connection status ;; |
423 | ;> buf_cmd = command entered by the user ;; |
433 | ;> buf_cmd = command entered by the user ;; |
424 | ;;------------------------------------------------------------------------------------------------;; |
434 | ;;------------------------------------------------------------------------------------------------;; |
425 | ;< none ;; |
435 | ;< none ;; |
426 | ;;================================================================================================;; |
436 | ;;================================================================================================;; |
427 | 437 | ||
428 | ; Are there any files in the transfer queue? |
438 | ; Are there any files in the transfer queue? |
429 | 439 | ||
430 | cmp [queued], 0 |
440 | cmp [queued], 0 |
431 | ja transfer_queued ; Yes, transfer those first. |
441 | ja transfer_queued ; Yes, transfer those first. |
432 | 442 | ||
433 | ; change color to green for user input |
443 | ; change color to green for user input |
434 | icall eax, interface_addr, interface.set_flags, 0x0a |
444 | icall eax, interface_addr, interface.set_flags, 0x0a |
435 | 445 | ||
436 | ; If we are not yet connected, request username/password |
446 | ; If we are not yet connected, request username/password |
437 | 447 | ||
438 | cmp [status], STATUS_CONNECTED |
448 | cmp [status], STATUS_CONNECTED |
439 | je arg_handler.get_username |
449 | je arg_handler.get_username |
440 | 450 | ||
441 | cmp [status], STATUS_NEEDPASSWORD |
451 | cmp [status], STATUS_NEEDPASSWORD |
442 | je arg_handler.get_pass |
452 | je arg_handler.get_pass |
443 | 453 | ||
444 | ijmp eax, interface_addr, interface.get_cmd |
454 | ijmp eax, interface_addr, interface.get_cmd |
445 | 455 | ||
446 | .parse_cmd: |
456 | .parse_cmd: |
447 | cmp dword[buf_cmd], "cwd " |
457 | cmp dword[buf_cmd], "cwd " |
448 | je cmd_cwd |
458 | je cmd_cwd |
449 | 459 | ||
450 | cmp dword[buf_cmd], "mkd " |
460 | cmp dword[buf_cmd], "mkd " |
451 | je cmd_mkd |
461 | je cmd_mkd |
452 | 462 | ||
453 | cmp dword[buf_cmd], "rmd " |
463 | cmp dword[buf_cmd], "rmd " |
454 | je cmd_rmd |
464 | je cmd_rmd |
455 | 465 | ||
456 | cmp dword[buf_cmd], "pwd" + 10 shl 24 |
466 | cmp dword[buf_cmd], "pwd" + 10 shl 24 |
457 | je cmd_pwd |
467 | je cmd_pwd |
458 | 468 | ||
459 | cmp dword[buf_cmd], "bye" + 10 shl 24 |
469 | cmp dword[buf_cmd], "bye" + 10 shl 24 |
460 | je cmd_bye |
470 | je cmd_bye |
461 | 471 | ||
462 | cmp dword[buf_cmd], "rdir" |
472 | cmp dword[buf_cmd], "rdir" |
463 | je cmd_rdir |
473 | je cmd_rdir |
464 | 474 | ||
465 | cmp byte[buf_cmd+4], " " |
475 | cmp byte[buf_cmd+4], " " |
466 | jne @f |
476 | jne @f |
467 | 477 | ||
468 | cmp dword[buf_cmd], "lcwd" |
478 | cmp dword[buf_cmd], "lcwd" |
469 | je cmd_lcwd |
479 | je cmd_lcwd |
470 | 480 | ||
471 | cmp dword[buf_cmd], "retr" |
481 | cmp dword[buf_cmd], "retr" |
472 | je cmd_retr |
482 | je cmd_retr |
473 | 483 | ||
474 | cmp dword[buf_cmd], "stor" |
484 | cmp dword[buf_cmd], "stor" |
475 | je cmd_stor |
485 | je cmd_stor |
476 | 486 | ||
477 | cmp dword[buf_cmd], "dele" |
487 | cmp dword[buf_cmd], "dele" |
478 | je cmd_dele |
488 | je cmd_dele |
479 | 489 | ||
480 | @@: |
490 | @@: |
481 | cmp byte[buf_cmd+4], 10 |
491 | cmp byte[buf_cmd+4], 10 |
482 | jne @f |
492 | jne @f |
483 | 493 | ||
484 | cmp dword[buf_cmd], "list" |
494 | cmp dword[buf_cmd], "list" |
485 | je cmd_list |
495 | je cmd_list |
486 | 496 | ||
487 | cmp dword[buf_cmd], "help" |
497 | cmp dword[buf_cmd], "help" |
488 | je cmd_help |
498 | je cmd_help |
489 | 499 | ||
490 | cmp dword[buf_cmd], "cdup" |
500 | cmp dword[buf_cmd], "cdup" |
491 | je cmd_cdup |
501 | je cmd_cdup |
492 | 502 | ||
493 | cmp dword[buf_cmd], "abor" |
503 | cmp dword[buf_cmd], "abor" |
494 | je cmd_abor |
504 | je cmd_abor |
495 | 505 | ||
496 | @@: |
506 | @@: |
497 | ; Uh oh.. unknown command, tell the user and wait for new input |
507 | ; Uh oh.. unknown command, tell the user and wait for new input |
498 | icall eax, interface_addr, interface.print, str_unknown |
508 | icall eax, interface_addr, interface.print, str_unknown |
499 | jmp wait_for_usercommand |
509 | jmp wait_for_usercommand |
500 | 510 | ||
501 | 511 | ||
502 | ; files for rdir operation are queued |
512 | ; files for rdir operation are queued |
503 | transfer_queued: |
513 | transfer_queued: |
504 | 514 | ||
505 | mov esi, [ptr_queue] ; always pointing to current part of ptr_fname_start |
515 | mov esi, [ptr_queue] ; always pointing to current part of ptr_fname_start |
506 | mov edi, buf_cmd+5 ; always point to filename for retr command |
516 | mov edi, buf_cmd+5 ; always point to filename for retr command |
507 | .build_filename: |
517 | .build_filename: |
508 | lodsb |
518 | lodsb |
509 | stosb |
519 | stosb |
510 | cmp al, 10 |
520 | cmp al, 10 |
511 | je .get_file ; filename ends with character 10 |
521 | je .get_file ; filename ends with character 10 |
512 | test al, al |
522 | test al, al |
513 | jnz .build_filename |
523 | jnz .build_filename |
514 | 524 | ||
515 | ; Error occured, we reached the end of the buffer before [queued] reached 0 |
525 | ; Error occured, we reached the end of the buffer before [queued] reached 0 |
516 | mov [queued], 0 |
526 | mov [queued], 0 |
517 | mcall 68, 13, [ptr_fname] ; free buffer |
527 | mcall 68, 13, [ptr_fname] ; free buffer |
518 | test eax, eax |
528 | test eax, eax |
519 | jz error_heap |
529 | jz error_heap |
520 | jmp wait_for_usercommand |
530 | jmp wait_for_usercommand |
521 | 531 | ||
522 | .get_file: |
532 | .get_file: |
523 | mov byte[edi], 0 ; end filename with 0 byte |
533 | mov byte[edi], 0 ; end filename with 0 byte |
524 | mov [ptr_queue], esi |
534 | mov [ptr_queue], esi |
525 | dec [queued] |
535 | dec [queued] |
526 | jnz cmd_retr |
536 | jnz cmd_retr |
527 | 537 | ||
528 | mcall 68, 13, [ptr_fname] ; free buffer |
538 | mcall 68, 13, [ptr_fname] ; free buffer |
529 | test eax, eax |
539 | test eax, eax |
530 | jz error_heap |
540 | jz error_heap |
531 | jmp cmd_retr |
541 | jmp cmd_retr |
532 | 542 | ||
533 | 543 | ||
534 | 544 | ||
535 | open_dataconnection: |
545 | open_dataconnection: |
536 | 546 | ||
537 | test [mode], 1 |
547 | test [mode], 1 |
538 | jnz .active |
548 | jnz .active |
539 | 549 | ||
540 | mcall send, [controlsocket], str_PASV, str_PASV.length, 0 |
550 | mcall send, [controlsocket], str_PASV, str_PASV.length, 0 |
541 | ret |
551 | ret |
542 | 552 | ||
543 | .active: |
553 | .active: |
544 | mcall socket, AF_INET4, SOCK_STREAM, 0 |
554 | mcall socket, AF_INET4, SOCK_STREAM, 0 |
545 | cmp eax, -1 |
555 | cmp eax, -1 |
546 | jne @f |
556 | jne @f |
547 | mov eax, str_err_socket |
557 | mov eax, str_err_socket |
548 | jmp error |
558 | jmp error |
549 | @@: mov [datasocket], eax |
559 | @@: mov [datasocket], eax |
550 | 560 | ||
551 | mov ax, [acti_port_start] |
561 | mov ax, [acti_port_start] |
552 | xchg al, ah |
562 | xchg al, ah |
553 | mov [sockaddr2.port], ax |
563 | mov [sockaddr2.port], ax |
554 | 564 | ||
555 | mcall bind, [datasocket], sockaddr2, 18 |
565 | mcall bind, [datasocket], sockaddr2, 18 |
556 | cmp eax, -1 |
566 | cmp eax, -1 |
557 | jne @f |
567 | jne @f |
558 | mov eax, str_err_bind |
568 | mov eax, str_err_bind |
559 | jmp error |
569 | jmp error |
560 | @@: |
570 | @@: |
561 | 571 | ||
562 | mcall listen, [datasocket], 1 |
572 | mcall listen, [datasocket], 1 |
563 | cmp eax, -1 |
573 | cmp eax, -1 |
564 | jne @f |
574 | jne @f |
565 | mov eax, str_err_listen |
575 | mov eax, str_err_listen |
566 | jmp error |
576 | jmp error |
567 | @@: |
577 | @@: |
568 | 578 | ||
569 | mov dword[buf_buffer1], 'PORT' |
579 | mov dword[buf_buffer1], 'PORT' |
570 | mov byte[buf_buffer1+4], ' ' |
580 | mov byte[buf_buffer1+4], ' ' |
571 | mov edi, buf_buffer1+5 |
581 | mov edi, buf_buffer1+5 |
572 | mov esi, str_active_ip |
582 | mov esi, str_active_ip |
573 | .loop: |
583 | .loop: |
574 | lodsb |
584 | lodsb |
575 | test al, al |
585 | test al, al |
576 | jz .ip_ok |
586 | jz .ip_ok |
577 | stosb |
587 | stosb |
578 | jmp .loop |
588 | jmp .loop |
579 | .ip_ok: |
589 | .ip_ok: |
580 | mov al, ',' |
590 | mov al, ',' |
581 | stosb |
591 | stosb |
582 | movzx eax, byte[sockaddr2.port+0] |
592 | movzx eax, byte[sockaddr2.port+0] |
583 | call dword_ascii |
593 | call dword_ascii |
584 | mov al, ',' |
594 | mov al, ',' |
585 | stosb |
595 | stosb |
586 | movzx eax, byte[sockaddr2.port+1] |
596 | movzx eax, byte[sockaddr2.port+1] |
587 | call dword_ascii |
597 | call dword_ascii |
588 | mov ax, 0x0a0d |
598 | mov ax, 0x0a0d |
589 | stosw |
599 | stosw |
590 | lea esi, [edi - buf_buffer1] |
600 | lea esi, [edi - buf_buffer1] |
591 | mcall send, [controlsocket], buf_buffer1, , 0 |
601 | mcall send, [controlsocket], buf_buffer1, , 0 |
592 | 602 | ||
593 | mcall accept, [datasocket], sockaddr2, 18 ; time to accept the awaiting connection.. |
603 | mcall accept, [datasocket], sockaddr2, 18 ; time to accept the awaiting connection.. |
594 | cmp eax, -1 |
604 | cmp eax, -1 |
595 | jne @f |
605 | jne @f |
596 | mov eax, str_err_accept |
606 | mov eax, str_err_accept |
597 | jmp error |
607 | jmp error |
598 | @@: push eax |
608 | @@: push eax |
599 | mcall close, [datasocket] |
609 | mcall close, [datasocket] |
600 | pop [datasocket] |
610 | pop [datasocket] |
601 | 611 | ||
602 | mcall recv, [controlsocket], buf_buffer1, BUFFERSIZE, 0 |
612 | mcall recv, [controlsocket], buf_buffer1, BUFFERSIZE, 0 |
603 | 613 | ||
604 | ret |
614 | ret |
605 | 615 | ||
606 | ; eax = input |
616 | ; eax = input |
607 | ; edi = ptr where to write |
617 | ; edi = ptr where to write |
608 | dword_ascii: |
618 | dword_ascii: |
609 | 619 | ||
610 | push edx ebx ecx |
620 | push edx ebx ecx |
611 | mov ebx, 10 |
621 | mov ebx, 10 |
612 | xor ecx, ecx |
622 | xor ecx, ecx |
613 | 623 | ||
614 | @@: |
624 | @@: |
615 | xor edx, edx |
625 | xor edx, edx |
616 | div ebx |
626 | div ebx |
617 | add edx, '0' |
627 | add edx, '0' |
618 | push dx |
628 | push dx |
619 | inc ecx |
629 | inc ecx |
620 | test eax, eax |
630 | test eax, eax |
621 | jnz @r |
631 | jnz @r |
622 | 632 | ||
623 | @@: |
633 | @@: |
624 | pop ax |
634 | pop ax |
625 | stosb |
635 | stosb |
626 | dec ecx |
636 | dec ecx |
627 | jnz @r |
637 | jnz @r |
628 | 638 | ||
629 | pop ecx ebx edx |
639 | pop ecx ebx edx |
630 | ret |
640 | ret |
631 | 641 | ||
632 | 642 | ||
633 | ;;================================================================================================;; |
643 | ;;================================================================================================;; |
634 | write_to_file: ;//////////////////////////////////////////////////////////////////////////////////;; |
644 | write_to_file: ;//////////////////////////////////////////////////////////////////////////////////;; |
635 | ;;------------------------------------------------------------------------------------------------;; |
645 | ;;------------------------------------------------------------------------------------------------;; |
636 | ;? Writes input buffer to log file ;; |
646 | ;? Writes input buffer to log file ;; |
637 | ;;------------------------------------------------------------------------------------------------;; |
647 | ;;------------------------------------------------------------------------------------------------;; |
638 | ;> eax = pointer to buffer ;; |
648 | ;> eax = pointer to buffer ;; |
639 | ;> ecx = size of buffer ;; |
649 | ;> ecx = size of buffer ;; |
640 | ;;------------------------------------------------------------------------------------------------;; |
650 | ;;------------------------------------------------------------------------------------------------;; |
641 | ;< eax = status of SF 70.3 ;; |
651 | ;< eax = status of SF 70.3 ;; |
642 | ;;================================================================================================;; |
652 | ;;================================================================================================;; |
643 | cmp [logfile_offset], -1 ; if offset == -1 => logging disabled |
653 | cmp [logfile_offset], -1 ; if offset == -1 => logging disabled |
644 | jne @f |
654 | jne @f |
645 | mov eax, 0 |
655 | mov eax, 0 |
646 | ret |
656 | ret |
647 | @@: |
657 | @@: |
648 | mov [filestruct2.subfn], 3 |
658 | mov [filestruct2.subfn], 3 |
649 | m2m [filestruct2.offset], [logfile_offset] |
659 | m2m [filestruct2.offset], [logfile_offset] |
650 | mov [filestruct2.size], ecx |
660 | mov [filestruct2.size], ecx |
651 | mov [filestruct2.ptr], eax |
661 | mov [filestruct2.ptr], eax |
652 | mov [filestruct2.name], log_file |
662 | mov [filestruct2.name], log_file |
653 | mcall 70, filestruct2 |
663 | mcall 70, filestruct2 |
654 | test eax, eax |
664 | test eax, eax |
655 | jz @f |
665 | jz @f |
656 | mov [logfile_offset], -1 ; disable logging |
666 | mov [logfile_offset], -1 ; disable logging |
657 | call error_fs |
667 | call error_fs |
658 | icall ebx, interface_addr, interface.print, str_no_logging |
668 | icall ebx, interface_addr, interface.print, str_no_logging |
659 | ret |
669 | ret |
660 | @@: |
670 | @@: |
661 | mov eax, [logfile_offset] |
671 | mov eax, [logfile_offset] |
662 | add eax, ecx |
672 | add eax, ecx |
663 | mov [logfile_offset], eax |
673 | mov [logfile_offset], eax |
664 | ret |
674 | ret |
665 | 675 | ||
666 | ;;================================================================================================;; |
676 | ;;================================================================================================;; |
667 | error: ;//////////////////////////////////////////////////////////////////////////////////////////;; |
677 | error: ;//////////////////////////////////////////////////////////////////////////////////////////;; |
668 | ;;------------------------------------------------------------------------------------------------;; |
678 | ;;------------------------------------------------------------------------------------------------;; |
669 | ;? Generic error routine. Prints the error string passed to it. ;; |
679 | ;? Generic error routine. Prints the error string passed to it. ;; |
670 | ;;------------------------------------------------------------------------------------------------;; |
680 | ;;------------------------------------------------------------------------------------------------;; |
671 | ;> eax = pointer to the error string ;; |
681 | ;> eax = pointer to the error string ;; |
672 | ;;------------------------------------------------------------------------------------------------;; |
682 | ;;------------------------------------------------------------------------------------------------;; |
673 | ;< none ;; |
683 | ;< none ;; |
674 | ;;================================================================================================;; |
684 | ;;================================================================================================;; |
675 | push eax |
685 | push eax |
676 | icall ebx, interface_addr, interface.set_flags, 0x0c ; print errors in red |
686 | icall ebx, interface_addr, interface.set_flags, 0x0c ; print errors in red |
677 | pop eax |
687 | pop eax |
678 | icall ebx, interface_addr, interface.print, eax |
688 | icall ebx, interface_addr, interface.print, eax |
679 | jmp wait_for_keypress |
689 | jmp wait_for_keypress |
680 | 690 | ||
681 | 691 | ||
682 | ; Error handling block for filesystem errors |
692 | ; Error handling block for filesystem errors |
683 | error_fs: |
693 | error_fs: |
684 | 694 | ||
685 | cmp eax, 12 |
695 | cmp eax, 12 |
686 | jne @f |
696 | jne @f |
687 | mov ebx, str_fs_err_12 |
697 | mov ebx, str_fs_err_12 |
688 | @@: |
698 | @@: |
689 | cmp eax, 11 |
699 | cmp eax, 11 |
690 | jne @f |
700 | jne @f |
691 | mov ebx, str_fs_err_11 |
701 | mov ebx, str_fs_err_11 |
692 | @@: |
702 | @@: |
693 | cmp eax, 10 |
703 | cmp eax, 10 |
694 | jne @f |
704 | jne @f |
695 | mov ebx, str_fs_err_10 |
705 | mov ebx, str_fs_err_10 |
696 | @@: |
706 | @@: |
697 | cmp eax, 9 |
707 | cmp eax, 9 |
698 | jne @f |
708 | jne @f |
699 | mov ebx, str_fs_err_9 |
709 | mov ebx, str_fs_err_9 |
700 | @@: |
710 | @@: |
701 | cmp eax, 8 |
711 | cmp eax, 8 |
702 | jne @f |
712 | jne @f |
703 | mov ebx, str_fs_err_8 |
713 | mov ebx, str_fs_err_8 |
704 | @@: |
714 | @@: |
705 | cmp eax, 7 |
715 | cmp eax, 7 |
706 | jne @f |
716 | jne @f |
707 | mov ebx, str_fs_err_7 |
717 | mov ebx, str_fs_err_7 |
708 | @@: |
718 | @@: |
709 | cmp eax, 6 |
719 | cmp eax, 6 |
710 | jne @f |
720 | jne @f |
711 | mov ebx, str_fs_err_6 |
721 | mov ebx, str_fs_err_6 |
712 | @@: |
722 | @@: |
713 | cmp eax, 5 |
723 | cmp eax, 5 |
714 | jne @f |
724 | jne @f |
715 | mov ebx, str_fs_err_5 |
725 | mov ebx, str_fs_err_5 |
716 | @@: |
726 | @@: |
717 | cmp eax, 3 |
727 | cmp eax, 3 |
718 | jne @f |
728 | jne @f |
719 | mov ebx, str_fs_err_3 |
729 | mov ebx, str_fs_err_3 |
720 | @@: |
730 | @@: |
721 | cmp eax, 2 |
731 | cmp eax, 2 |
722 | jne @f |
732 | jne @f |
723 | mov ebx, str_fs_err_2 |
733 | mov ebx, str_fs_err_2 |
724 | @@: |
734 | @@: |
725 | mov edi, fs_error_code |
735 | mov edi, fs_error_code |
726 | call dword_ascii ; convert error code in eax to ascii |
736 | call dword_ascii ; convert error code in eax to ascii |
727 | icall eax, interface_addr, interface.set_flags, 0x0c ; print errors in red |
737 | icall eax, interface_addr, interface.set_flags, 0x0c ; print errors in red |
728 | icall eax, interface_addr, interface.print, str_err_fs, fs_error_code, ebx |
738 | icall eax, interface_addr, interface.print, str_err_fs, fs_error_code, ebx |
729 | mov word[fs_error_code], ' ' ; clear error code for next time |
739 | mov word[fs_error_code], ' ' ; clear error code for next time |
730 | icall eax, interface_addr, interface.set_flags, 0x0a |
740 | icall eax, interface_addr, interface.set_flags, 0x0a |
731 | 741 | ||
732 | ret |
742 | ret |
733 | 743 | ||
734 | error_heap: |
744 | error_heap: |
735 | icall eax, interface_addr, interface.set_flags, 0x0c ; print errors in red |
745 | icall eax, interface_addr, interface.set_flags, 0x0c ; print errors in red |
736 | icall eax, interface_addr, interface.print, str_err_heap |
746 | icall eax, interface_addr, interface.print, str_err_heap |
737 | 747 | ||
738 | wait_for_keypress: |
748 | wait_for_keypress: |
739 | mcall close, [controlsocket] |
749 | mcall close, [controlsocket] |
740 | icall eax, interface_addr, interface.set_flags, 0x07 ; reset color to grey |
750 | icall eax, interface_addr, interface.set_flags, 0x07 ; reset color to grey |
741 | icall eax, interface_addr, interface.print, str_push |
751 | icall eax, interface_addr, interface.print, str_push |
742 | ijmp eax, interface_addr, interface.error |
752 | ijmp eax, interface_addr, interface.error |
743 | 753 | ||
744 | exit: |
754 | exit: |
745 | mcall close, [controlsocket] |
755 | mcall close, [controlsocket] |
746 | exit2: |
756 | exit2: |
747 | mcall -1 |
757 | mcall -1 |
748 | 758 | ||
749 | 759 | ||
750 | 760 | ||
751 | ; data |
761 | ; data |
752 | str_title db 'FTP client for KolibriOS',0 |
762 | str_title db 'FTP client for KolibriOS',0 |
753 | str_welcome db 'FTP client for KolibriOS v0.15b',10 |
763 | str_welcome db 'FTP client for KolibriOS v0.16',10 |
754 | db 10,0 |
764 | db 10,0 |
755 | str_srv_addr db 'Please enter ftp server address.',10,0 |
765 | str_srv_addr db 'Please enter ftp server address.',10,0 |
756 | 766 | ||
757 | str_prompt db '> ',0 |
767 | str_prompt db '> ',0 |
758 | str_resolve db 'Resolving ',0 |
768 | str_resolve db 'Resolving ',0 |
759 | str_newline db 10,0 |
769 | str_newline db 10,0 |
760 | str_err_resolve db 10,'Name resolution failed.',10,0 |
770 | str_err_resolve db 10,'Name resolution failed.',10,0 |
- | 771 | str_err_closed db 10,'The connection was closed by the remote end',10,0 |
|
761 | str_err_socket db 10,'[75,0 socket]: Error creating a socket',10,0 |
772 | str_err_socket db 10,'[75,0 socket]: Error creating a socket',10,0 |
762 | str_err_bind db 10,'[75,2 bind]: Error binding to socket',10,0 |
773 | str_err_bind db 10,'[75,2 bind]: Error binding to socket',10,0 |
763 | str_err_listen db 10,'[75,3 listen]: Cannot accept incoming connections',10,0 |
774 | str_err_listen db 10,'[75,3 listen]: Cannot accept incoming connections',10,0 |
764 | str_err_accept db 10,'[75,5 accept]: Error accepting a connection',10,0 |
775 | str_err_accept db 10,'[75,5 accept]: Error accepting a connection',10,0 |
765 | str_err_recv db 10,'[75,7 recv]: Error receiving data from server',10,0 |
776 | str_err_recv db 10,'[75,7 recv]: Error receiving data from server',10,0 |
766 | str_err_heap db 10,'Cannot allocate memory from heap.',10,0 |
777 | str_err_heap db 10,'Cannot allocate memory from heap.',10,0 |
767 | str_err_timeout db 10,'Timeout - no response from server.',10,0 |
778 | str_err_timeout db 10,'Timeout - no response from server.',10,0 |
768 | str_err_connect db 10,'[75,4 connect]: Cannot connect to the server.',10,0 |
779 | str_err_connect db 10,'[75,4 connect]: Cannot connect to the server.',10,0 |
769 | str_err_host db 10,'Invalid hostname.',10,0 |
780 | str_err_host db 10,'Invalid hostname.',10,0 |
770 | str_err_params db 10,'Invalid parameters',10,0 |
781 | str_err_params db 10,'Invalid parameters',10,0 |
771 | str_err_fs db 10,'File system error: code ',0 |
782 | str_err_fs db 10,'File system error: code ',0 |
772 | fs_error_code db ' ',0 ; file system error code |
783 | fs_error_code db ' ',0 ; file system error code |
773 | str_fs_err_2 db ' [Function is not supported for the given file system]',10,0 |
784 | str_fs_err_2 db ' [Function is not supported for the given file system]',10,0 |
774 | str_fs_err_3 db ' [Unknown file system]',10,0 |
785 | str_fs_err_3 db ' [Unknown file system]',10,0 |
775 | str_fs_err_5 db ' [File/Folder not found]',10,0 |
786 | str_fs_err_5 db ' [File/Folder not found]',10,0 |
776 | str_fs_err_6 db ' [End of file, EOF]',10,0 |
787 | str_fs_err_6 db ' [End of file, EOF]',10,0 |
777 | str_fs_err_7 db ' [Pointer lies outside of application memory]',10,0 |
788 | str_fs_err_7 db ' [Pointer lies outside of application memory]',10,0 |
778 | str_fs_err_8 db ' [Disk is full]',10,0 |
789 | str_fs_err_8 db ' [Disk is full]',10,0 |
779 | str_fs_err_9 db ' [File system error]',10,0 |
790 | str_fs_err_9 db ' [File system error]',10,0 |
780 | str_fs_err_10 db ' [Access denied]',10,0 |
791 | str_fs_err_10 db ' [Access denied]',10,0 |
781 | str_fs_err_11 db ' [Device error]',10,0 |
792 | str_fs_err_11 db ' [Device error]',10,0 |
782 | str_fs_err_12 db ' [File system requires more memory]',10,0 |
793 | str_fs_err_12 db ' [File system requires more memory]',10,0 |
783 | str8 db ' (',0 |
794 | str8 db ' (',0 |
784 | str9 db ')',10,0 |
795 | str9 db ')',10,0 |
785 | str_push db 'Push any key to continue.',0 |
796 | str_push db 'Push any key to continue.',0 |
786 | str_connect db 'Connecting...',10,0 |
797 | str_connect db 'Connecting...',10,0 |
787 | str_waiting db 'Waiting for welcome message.',10,0 |
798 | str_waiting db 'Waiting for welcome message.',10,0 |
788 | str_user db "username: ",0 |
799 | str_user db "username: ",0 |
789 | str_pass db "password: ",0 |
800 | str_pass db "password: ",0 |
790 | str_port db "port (default 21): ",0 |
801 | str_port db "port (default 21): ",0 |
791 | str_path db "path (optional): ",0 |
802 | str_path db "path (optional): ",0 |
792 | str_unknown db "Unknown command or insufficient parameters - type help for more information.",10,0 |
803 | str_unknown db "Unknown command or insufficient parameters - type help for more information.",10,0 |
793 | str_lcwd db "Local working directory is now: ",0 |
804 | str_lcwd db "Local working directory is now: ",0 |
794 | str_bytes_done db ' ',0 |
805 | str_bytes_done db ' ',0 |
795 | str_downloaded db 'Downloaded ',0 |
806 | str_downloaded db 'Downloaded ',0 |
796 | str_bytes db ' bytes',13,0 |
807 | str_bytes db ' bytes',13,0 |
797 | str_args_err db 'Invalid arguments. USAGE: ftpc [-cli] [ftp://username:password@server:port/path]',10,0 |
808 | str_args_err db 'Invalid arguments. USAGE: ftpc [-cli] [ftp://username:password@server:port/path]',10,0 |
798 | 809 | ||
799 | str_open db "opening data socket",10,0 |
810 | str_open db "opening data socket",10,0 |
800 | str_close db 10,"closing data socket",10,0 |
811 | str_close db 10,"closing data socket",10,0 |
801 | str_dot db '.',0 |
812 | str_dot db '.',0 |
802 | 813 | ||
803 | str_help db "available commands:",10 |
814 | str_help db "available commands:",10 |
804 | db 10 |
815 | db 10 |
805 | db "bye - close the connection",10 |
816 | db "bye - close the connection",10 |
806 | db "cdup - change to parent of current directory on the server",10 |
817 | db "cdup - change to parent of current directory on the server",10 |
807 | db "cwd |
818 | db "cwd |
808 | db "dele |
819 | db "dele |
809 | db "list - list files and folders in current server directory",10 |
820 | db "list - list files and folders in current server directory",10 |
810 | db "lcwd |
821 | db "lcwd |
811 | db "mkd |
822 | db "mkd |
812 | db "pwd - print server working directory",10 |
823 | db "pwd - print server working directory",10 |
813 | db "retr |
824 | db "retr |
814 | db "rmd |
825 | db "rmd |
815 | db "stor |
826 | db "stor |
816 | db "rdir - retreive all files from current server dir",10 |
827 | db "rdir - retreive all files from current server dir",10 |
817 | db 10,0 |
828 | db 10,0 |
818 | 829 | ||
819 | str_ini db '.ini', 0 |
830 | str_ini db '.ini', 0 |
820 | str_active db 'active', 0 |
831 | str_active db 'active', 0 |
821 | str_port_start db 'port_start', 0 |
832 | str_port_start db 'port_start', 0 |
822 | str_port_stop db 'port_stop', 0 |
833 | str_port_stop db 'port_stop', 0 |
823 | str_ip db 'ip', 0 |
834 | str_ip db 'ip', 0 |
824 | str_dir db 'dir', 0 |
835 | str_dir db 'dir', 0 |
825 | str_general db 'general', 0 |
836 | str_general db 'general', 0 |
826 | str_logfile db 'logfile',0 |
837 | str_logfile db 'logfile',0 |
827 | str_no_logging db 'Error writing to log file. Logging disabled',0 |
838 | str_no_logging db 'Error writing to log file. Logging disabled',0 |
828 | 839 | ||
829 | queued dd 0 |
840 | queued dd 0 |
830 | mode db 0 ; passive = 0, active = 1 |
841 | mode db 0 ; passive = 0, active = 1 |
831 | 842 | ||
832 | 843 | ||
833 | ; FTP strings |
844 | ; FTP strings |
834 | 845 | ||
835 | str_PASV db 'PASV',13,10 |
846 | str_PASV db 'PASV',13,10 |
836 | .length = $ - str_PASV |
847 | .length = $ - str_PASV |
837 | 848 | ||
838 | sockaddr1: |
849 | sockaddr1: |
839 | dw AF_INET4 |
850 | dw AF_INET4 |
840 | .port dw ? |
851 | .port dw ? |
841 | .ip dd ? |
852 | .ip dd ? |
842 | rb 10 |
853 | rb 10 |
843 | 854 | ||
844 | sockaddr2: |
855 | sockaddr2: |
845 | dw AF_INET4 |
856 | dw AF_INET4 |
846 | .port dw ? |
857 | .port dw ? |
847 | .ip dd ? |
858 | .ip dd ? |
848 | rb 10 |
859 | rb 10 |
849 | 860 | ||
850 | struc interface |
861 | struc interface |
851 | { |
862 | { |
852 | .init dd 0 |
863 | .init dd 0 |
853 | .server_addr dd 4 |
864 | .server_addr dd 4 |
854 | .get_username dd 8 |
865 | .get_username dd 8 |
855 | .get_cmd dd 12 |
866 | .get_cmd dd 12 |
856 | .print dd 16 |
867 | .print dd 16 |
857 | .set_flags dd 20 |
868 | .set_flags dd 20 |
858 | .list dd 24 |
869 | .list dd 24 |
859 | .progress dd 28 |
870 | .progress dd 28 |
860 | .error dd 32 |
871 | .error dd 32 |
861 | } |
872 | } |
862 | interface interface |
873 | interface interface |
863 | 874 | ||
864 | ; import |
875 | ; import |
865 | align 4 |
876 | align 4 |
866 | @IMPORT: |
877 | @IMPORT: |
867 | 878 | ||
868 | library network, 'network.obj', libini, 'libini.obj' |
879 | library network, 'network.obj', libini, 'libini.obj' |
869 | 880 | ||
870 | import network, \ |
881 | import network, \ |
871 | getaddrinfo, 'getaddrinfo', \ |
882 | getaddrinfo, 'getaddrinfo', \ |
872 | freeaddrinfo, 'freeaddrinfo', \ |
883 | freeaddrinfo, 'freeaddrinfo', \ |
873 | inet_ntoa, 'inet_ntoa' |
884 | inet_ntoa, 'inet_ntoa' |
874 | 885 | ||
875 | import libini, \ |
886 | import libini, \ |
876 | ini.get_str, 'ini_get_str', \ |
887 | ini.get_str, 'ini_get_str', \ |
877 | ini.get_int, 'ini_get_int' |
888 | ini.get_int, 'ini_get_int' |
878 | 889 | ||
879 | param_user: db 'anonymous',0 |
890 | param_user: db 'anonymous',0 |
880 | rb 60 |
891 | rb 60 |
881 | 892 | ||
882 | param_server_addr db 'kolibrios.org' |
893 | param_server_addr db 'kolibrios.org' |
883 | rb 1024 |
894 | rb 1024 |
884 | 895 | ||
885 | align 4 |
896 | align 4 |
886 | i_end: |
897 | i_end: |
887 | ; uninitialised data |
898 | ; uninitialised data |
888 | 899 | ||
889 | run_file_70 FileInfoBlock ; required for libimg |
900 | run_file_70 FileInfoBlock ; required for libimg |
890 | 901 | ||
891 | new_dir_buf rb 64 |
902 | new_dir_buf rb 64 |
892 | folder_data rb 32+32*304 |
903 | folder_data rb 32+32*304 |
893 | 904 | ||
894 | remote_list_buf rb 1024 |
905 | remote_list_buf rb 1024 |
895 | file_name rb 4096 ; required for libimg |
906 | file_name rb 4096 ; required for libimg |
896 | conv_tabl rb 128 |
907 | conv_tabl rb 128 |
897 | ed_buffer rb 100 |
908 | ed_buffer rb 100 |
898 | tedit_buffer rb 1024 |
909 | tedit_buffer rb 1024 |
899 | el_focus dd ? |
910 | el_focus dd ? |
900 | ;----------------------- |
911 | ;----------------------- |
901 | 912 | ||
902 | procinfo process_information |
913 | procinfo process_information |
903 | 914 | ||
904 | interface_addr rd 1 |
915 | interface_addr rd 1 |
905 | 916 | ||
906 | status db ? |
917 | status db ? |
907 | 918 | ||
908 | file_size dd ? |
919 | file_size dd ? |
909 | 920 | ||
910 | controlsocket dd ? |
921 | controlsocket dd ? |
911 | datasocket dd ? |
922 | datasocket dd ? |
912 | offset dd ? |
923 | offset dd ? |
913 | size dd ? |
924 | size dd ? |
914 | operation dd ? |
925 | operation dd ? |
915 | timeout dd ? |
926 | timeout dd ? |
916 | 927 | ||
917 | ptr_fname dd ? |
928 | ptr_fname dd ? |
918 | size_fname dd ? |
929 | size_fname dd ? |
919 | ptr_queue dd ? |
930 | ptr_queue dd ? |
920 | 931 | ||
921 | acti_port_start dw ? |
932 | acti_port_start dw ? |
922 | acti_port_stop dw ? |
933 | acti_port_stop dw ? |
923 | acti_port dw ? |
934 | acti_port dw ? |
924 | 935 | ||
925 | str_active_ip rb 16 |
936 | str_active_ip rb 16 |
926 | 937 | ||
927 | filestruct: |
938 | filestruct: |
928 | .subfn dd ? |
939 | .subfn dd ? |
929 | .offset dd ? |
940 | .offset dd ? |
930 | dd ? |
941 | dd ? |
931 | .size dd ? |
942 | .size dd ? |
932 | .ptr dd ? |
943 | .ptr dd ? |
933 | .name rb 1024 |
944 | .name rb 1024 |
934 | 945 | ||
935 | filestruct2: |
946 | filestruct2: |
936 | .subfn dd ? |
947 | .subfn dd ? |
937 | .offset dd ? |
948 | .offset dd ? |
938 | dd ? |
949 | dd ? |
939 | .size dd ? |
950 | .size dd ? |
940 | .ptr dd ? |
951 | .ptr dd ? |
941 | db ? |
952 | db ? |
942 | .name dd ? |
953 | .name dd ? |
943 | 954 | ||
944 | folder_buf rb 40 |
955 | folder_buf rb 40 |
945 | 956 | ||
946 | 957 | ||
947 | buf_buffer1 rb BUFFERSIZE+1 |
958 | buf_buffer1 rb BUFFERSIZE+1 |
948 | buf_buffer2 rb BUFFERSIZE+1 |
959 | buf_buffer2 rb BUFFERSIZE+1 |
949 | buf_cmd rb 1024 ; buffer for holding command string |
960 | buf_cmd rb 1024 ; buffer for holding command string |
950 | log_file rb 512 ; holds log file path |
961 | log_file rb 512 ; holds log file path |
951 | logfile_offset rd 1 |
962 | logfile_offset rd 1 |
952 | 963 | ||
953 | path rb 1024 |
964 | path rb 1024 |
954 | 965 | ||
955 | initial_login rb 1 |
966 | initial_login rb 1 |
956 | 967 | ||
957 | param_password rb 1024 |
968 | param_password rb 1024 |
958 | 969 | ||
959 | param_path rb 1024 |
970 | param_path rb 1024 |
960 | param_port rb 6 |
971 | param_port rb 6 |
961 | 972 | ||
962 | sc system_colors |
973 | sc system_colors |
963 | rb 1024 |
974 | rb 1024 |
964 | 975 | ||
965 | mem:>>>>>>> |
976 | mem:>>>>>>> |