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