Rev 6835 | Rev 7201 | 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 | ;;================================================================================================;; |
||
647 | mov [filestruct2.subfn], 3 |
||
648 | m2m [filestruct2.offset], [logfile_offset] |
||
649 | mov [filestruct2.size], ecx |
||
650 | mov [filestruct2.ptr], eax |
||
651 | mov [filestruct2.name], log_file |
||
652 | mcall 70, filestruct2 |
||
653 | test eax, eax |
||
654 | jz @f |
||
655 | mov [logfile_offset], -1 ; disable logging |
||
656 | call error_fs |
||
657 | icall ebx, interface_addr, interface.print, str_no_logging |
||
658 | ret |
||
659 | @@: |
||
660 | mov eax, [logfile_offset] |
||
661 | add eax, ecx |
||
662 | mov [logfile_offset], eax |
||
663 | ret |
||
664 | |||
665 | ;;================================================================================================;; |
||
666 | error: ;//////////////////////////////////////////////////////////////////////////////////////////;; |
||
667 | ;;------------------------------------------------------------------------------------------------;; |
||
668 | ;? Generic error routine. Prints the error string passed to it. ;; |
||
669 | ;;------------------------------------------------------------------------------------------------;; |
||
670 | ;> eax = pointer to the error string ;; |
||
671 | ;;------------------------------------------------------------------------------------------------;; |
||
672 | ;< none ;; |
||
673 | ;;================================================================================================;; |
||
6436 | nisargshah | 674 | push eax |
6582 | nisargshah | 675 | icall ebx, interface_addr, interface.set_flags, 0x0c ; print errors in red |
6436 | nisargshah | 676 | pop eax |
6582 | nisargshah | 677 | icall ebx, interface_addr, interface.print, eax |
5011 | hidnplayr | 678 | jmp wait_for_keypress |
679 | |||
6582 | nisargshah | 680 | |
681 | ; Error handling block for filesystem errors |
||
682 | error_fs: |
||
683 | |||
684 | cmp eax, 12 |
||
685 | jne @f |
||
686 | mov ebx, str_fs_err_12 |
||
687 | @@: |
||
688 | cmp eax, 11 |
||
689 | jne @f |
||
690 | mov ebx, str_fs_err_11 |
||
691 | @@: |
||
692 | cmp eax, 10 |
||
693 | jne @f |
||
694 | mov ebx, str_fs_err_10 |
||
695 | @@: |
||
696 | cmp eax, 9 |
||
697 | jne @f |
||
698 | mov ebx, str_fs_err_9 |
||
699 | @@: |
||
700 | cmp eax, 8 |
||
701 | jne @f |
||
702 | mov ebx, str_fs_err_8 |
||
703 | @@: |
||
704 | cmp eax, 7 |
||
705 | jne @f |
||
706 | mov ebx, str_fs_err_7 |
||
707 | @@: |
||
708 | cmp eax, 6 |
||
709 | jne @f |
||
710 | mov ebx, str_fs_err_6 |
||
711 | @@: |
||
712 | cmp eax, 5 |
||
713 | jne @f |
||
714 | mov ebx, str_fs_err_5 |
||
715 | @@: |
||
716 | cmp eax, 3 |
||
717 | jne @f |
||
718 | mov ebx, str_fs_err_3 |
||
719 | @@: |
||
720 | cmp eax, 2 |
||
721 | jne @f |
||
722 | mov ebx, str_fs_err_2 |
||
723 | @@: |
||
724 | mov edi, fs_error_code |
||
725 | call dword_ascii ; convert error code in eax to ascii |
||
726 | icall eax, interface_addr, interface.set_flags, 0x0c ; print errors in red |
||
727 | icall eax, interface_addr, interface.print, str_err_fs, fs_error_code, ebx |
||
728 | mov word[fs_error_code], ' ' ; clear error code for next time |
||
729 | icall eax, interface_addr, interface.set_flags, 0x0a |
||
730 | |||
731 | ret |
||
732 | |||
4922 | ashmew2 | 733 | error_heap: |
6582 | nisargshah | 734 | icall eax, interface_addr, interface.set_flags, 0x0c ; print errors in red |
735 | icall eax, interface_addr, interface.print, str_err_heap |
||
5011 | hidnplayr | 736 | |
3813 | hidnplayr | 737 | wait_for_keypress: |
5011 | hidnplayr | 738 | mcall close, [controlsocket] |
6582 | nisargshah | 739 | icall eax, interface_addr, interface.set_flags, 0x07 ; reset color to grey |
740 | icall eax, interface_addr, interface.print, str_push |
||
741 | ijmp eax, interface_addr, interface.error |
||
3701 | hidnplayr | 742 | |
743 | exit: |
||
5011 | hidnplayr | 744 | mcall close, [controlsocket] |
745 | exit2: |
||
3701 | hidnplayr | 746 | mcall -1 |
747 | |||
748 | |||
749 | |||
750 | ; data |
||
3813 | hidnplayr | 751 | str_title db 'FTP client',0 |
4918 | hidnplayr | 752 | str_welcome db 'FTP client for KolibriOS v0.12',10 |
6582 | nisargshah | 753 | db 10,0 |
754 | str_srv_addr db 'Please enter ftp server address.',10,0 |
||
3800 | hidnplayr | 755 | |
3813 | hidnplayr | 756 | str_prompt db '> ',0 |
757 | str_resolve db 'Resolving ',0 |
||
758 | str_newline db 10,0 |
||
759 | str_err_resolve db 10,'Name resolution failed.',10,0 |
||
6436 | nisargshah | 760 | str_err_socket db 10,'[75,0 socket]: Error creating a socket',10,0 |
761 | str_err_bind db 10,'[75,2 bind]: Error binding to socket',10,0 |
||
762 | str_err_listen db 10,'[75,3 listen]: Cannot accept incoming connections',10,0 |
||
763 | str_err_accept db 10,'[75,5 accept]: Error accepting a connection',10,0 |
||
764 | str_err_recv db 10,'[75,7 recv]: Error receiving data from server',10,0 |
||
5011 | hidnplayr | 765 | str_err_heap db 10,'Cannot allocate memory from heap.',10,0 |
4918 | hidnplayr | 766 | str_err_timeout db 10,'Timeout - no response from server.',10,0 |
6436 | nisargshah | 767 | str_err_connect db 10,'[75,4 connect]: Cannot connect to the server.',10,0 |
5011 | hidnplayr | 768 | str_err_host db 10,'Invalid hostname.',10,0 |
6436 | nisargshah | 769 | str_err_params db 10,'Invalid parameters',10,0 |
6582 | nisargshah | 770 | str_err_fs db 10,'File system error: code ',0 |
771 | fs_error_code db ' ',0 ; file system error code |
||
772 | str_fs_err_2 db ' [Function is not supported for the given file system]',10,0 |
||
773 | str_fs_err_3 db ' [Unknown file system]',10,0 |
||
774 | str_fs_err_5 db ' [File/Folder not found]',10,0 |
||
775 | str_fs_err_6 db ' [End of file, EOF]',10,0 |
||
776 | str_fs_err_7 db ' [Pointer lies outside of application memory]',10,0 |
||
777 | str_fs_err_8 db ' [Disk is full]',10,0 |
||
778 | str_fs_err_9 db ' [File system error]',10,0 |
||
779 | str_fs_err_10 db ' [Access denied]',10,0 |
||
780 | str_fs_err_11 db ' [Device error]',10,0 |
||
781 | str_fs_err_12 db ' [File system requires more memory]',10,0 |
||
3813 | hidnplayr | 782 | str8 db ' (',0 |
783 | str9 db ')',10,0 |
||
784 | str_push db 'Push any key to continue.',0 |
||
785 | str_connect db 'Connecting...',10,0 |
||
786 | str_waiting db 'Waiting for welcome message.',10,0 |
||
787 | str_user db "username: ",0 |
||
788 | str_pass db "password: ",0 |
||
6582 | nisargshah | 789 | str_port db "port (default 21): ",0 |
790 | str_path db "path (optional): ",0 |
||
3813 | hidnplayr | 791 | str_unknown db "Unknown command or insufficient parameters - type help for more information.",10,0 |
792 | str_lcwd db "Local working directory is now: ",0 |
||
6582 | nisargshah | 793 | str_bytes_done db ' ',0 |
794 | str_downloaded db 'Downloaded ',0 |
||
795 | str_bytes db ' bytes',13,0 |
||
796 | str_args_err db 'Invalid arguments. USAGE: ftpc [-cli] [ftp://username:password@server:port/path]',10,0 |
||
3701 | hidnplayr | 797 | |
3813 | hidnplayr | 798 | str_open db "opening data socket",10,0 |
4922 | ashmew2 | 799 | str_close db 10,"closing data socket",10,0 |
800 | str_dot db '.',0 |
||
3701 | hidnplayr | 801 | |
3813 | hidnplayr | 802 | str_help db "available commands:",10 |
803 | db 10 |
||
804 | db "bye - close the connection",10 |
||
805 | db "cdup - change to parent of current directory on the server",10 |
||
806 | db "cwd |
||
807 | db "dele |
||
808 | db "list - list files and folders in current server directory",10 |
||
809 | db "lcwd |
||
810 | db "mkd |
||
811 | db "pwd - print server working directory",10 |
||
812 | db "retr |
||
813 | db "rmd |
||
814 | db "stor |
||
6582 | nisargshah | 815 | db "rdir - retreive all files from current server dir",10 |
3813 | hidnplayr | 816 | db 10,0 |
817 | |||
5011 | hidnplayr | 818 | str_ini db '.ini', 0 |
819 | str_active db 'active', 0 |
||
820 | str_port_start db 'port_start', 0 |
||
821 | str_port_stop db 'port_stop', 0 |
||
822 | str_ip db 'ip', 0 |
||
823 | str_dir db 'dir', 0 |
||
824 | str_general db 'general', 0 |
||
6582 | nisargshah | 825 | str_logfile db 'logfile',0 |
826 | str_no_logging db 'Error writing to log file. Logging disabled',0 |
||
3821 | hidnplayr | 827 | |
5011 | hidnplayr | 828 | queued dd 0 |
829 | mode db 0 ; passive = 0, active = 1 |
||
830 | |||
6582 | nisargshah | 831 | |
3821 | hidnplayr | 832 | ; FTP strings |
833 | |||
834 | str_PASV db 'PASV',13,10 |
||
835 | .length = $ - str_PASV |
||
836 | |||
3701 | hidnplayr | 837 | sockaddr1: |
838 | dw AF_INET4 |
||
5011 | hidnplayr | 839 | .port dw ? |
840 | .ip dd ? |
||
3701 | hidnplayr | 841 | rb 10 |
842 | |||
843 | sockaddr2: |
||
844 | dw AF_INET4 |
||
5011 | hidnplayr | 845 | .port dw ? |
846 | .ip dd ? |
||
3701 | hidnplayr | 847 | rb 10 |
848 | |||
6582 | nisargshah | 849 | struc interface |
850 | { |
||
851 | .init dd 0 |
||
852 | .server_addr dd 4 |
||
853 | .get_username dd 8 |
||
854 | .get_cmd dd 12 |
||
855 | .print dd 16 |
||
856 | .set_flags dd 20 |
||
857 | .list dd 24 |
||
858 | .progress dd 28 |
||
859 | .error dd 32 |
||
860 | } |
||
861 | interface interface |
||
862 | |||
3701 | hidnplayr | 863 | ; import |
864 | align 4 |
||
865 | @IMPORT: |
||
866 | |||
6582 | nisargshah | 867 | library network, 'network.obj', libini, 'libini.obj' |
3701 | hidnplayr | 868 | |
6582 | nisargshah | 869 | import network, \ |
870 | getaddrinfo, 'getaddrinfo', \ |
||
3701 | hidnplayr | 871 | freeaddrinfo, 'freeaddrinfo', \ |
872 | inet_ntoa, 'inet_ntoa' |
||
873 | |||
6582 | nisargshah | 874 | import libini, \ |
875 | ini.get_str, 'ini_get_str', \ |
||
5011 | hidnplayr | 876 | ini.get_int, 'ini_get_int' |
3701 | hidnplayr | 877 | |
5011 | hidnplayr | 878 | |
3701 | hidnplayr | 879 | i_end: |
880 | |||
3813 | hidnplayr | 881 | ; uninitialised data |
882 | |||
6582 | nisargshah | 883 | interface_addr rd 1 |
884 | |||
3794 | hidnplayr | 885 | status db ? |
886 | |||
6582 | nisargshah | 887 | file_size dd ? |
888 | |||
5011 | hidnplayr | 889 | controlsocket dd ? |
3701 | hidnplayr | 890 | datasocket dd ? |
3790 | hidnplayr | 891 | offset dd ? |
892 | size dd ? |
||
3800 | hidnplayr | 893 | operation dd ? |
4918 | hidnplayr | 894 | timeout dd ? |
895 | |||
5011 | hidnplayr | 896 | ptr_fname dd ? |
897 | size_fname dd ? |
||
898 | ptr_queue dd ? |
||
899 | |||
900 | acti_port_start dw ? |
||
901 | acti_port_stop dw ? |
||
902 | acti_port dw ? |
||
903 | |||
904 | str_active_ip rb 16 |
||
905 | |||
3800 | hidnplayr | 906 | filestruct: |
5011 | hidnplayr | 907 | .subfn dd ? |
908 | .offset dd ? |
||
909 | dd ? |
||
910 | .size dd ? |
||
911 | .ptr dd ? |
||
912 | .name rb 1024 |
||
3800 | hidnplayr | 913 | |
6582 | nisargshah | 914 | filestruct2: |
915 | .subfn dd ? |
||
916 | .offset dd ? |
||
917 | dd 0 |
||
918 | .size dd ? |
||
919 | .ptr dd ? |
||
920 | db 0 |
||
921 | .name dd ? |
||
922 | |||
923 | folder_buf rb 40 |
||
924 | |||
925 | |||
4922 | ashmew2 | 926 | buf_buffer1 rb BUFFERSIZE+1 |
927 | buf_buffer2 rb BUFFERSIZE+1 |
||
5011 | hidnplayr | 928 | buf_cmd rb 1024 ; buffer for holding command string |
6582 | nisargshah | 929 | log_file rb 512 ; holds log file path |
930 | logfile_offset rd 1 |
||
3794 | hidnplayr | 931 | |
5011 | hidnplayr | 932 | path rb 1024 |
933 | |||
6582 | nisargshah | 934 | initial_login rb 1 |
6394 | nisargshah | 935 | param_user rb 1024 |
936 | param_password rb 1024 |
||
937 | param_server_addr rb 1024 |
||
938 | param_path rb 1024 |
||
6582 | nisargshah | 939 | param_port rb 6 |
6394 | nisargshah | 940 | |
6582 | nisargshah | 941 | sc system_colors |
942 | rb 1024 |
||
943 | |||
3701 | hidnplayr | 944 | mem:>>>>>>> |