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