Rev 5011 | Rev 6436 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3701 | hidnplayr | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
||
4729 | hidnplayr | 3 | ;; Copyright (C) KolibriOS team 2013-2014. 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 ;; |
||
9 | ;; ;; |
||
10 | ;; GNU GENERAL PUBLIC LICENSE ;; |
||
11 | ;; Version 2, June 1991 ;; |
||
12 | ;; ;; |
||
13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
14 | |||
15 | format binary as "" |
||
16 | |||
4918 | hidnplayr | 17 | TIMEOUT = 3 ; seconds |
18 | |||
3800 | hidnplayr | 19 | BUFFERSIZE = 4096 |
3701 | hidnplayr | 20 | |
21 | STATUS_CONNECTING = 0 |
||
22 | STATUS_CONNECTED = 1 |
||
23 | STATUS_NEEDPASSWORD = 2 |
||
24 | STATUS_LOGGED_IN = 3 |
||
25 | |||
3821 | hidnplayr | 26 | OPERATION_NONE = 0 |
27 | OPERATION_LIST = 1 |
||
28 | OPERATION_RETR = 2 |
||
29 | OPERATION_STOR = 3 |
||
5011 | hidnplayr | 30 | OPERATION_RDIR = 4 |
31 | |||
3701 | hidnplayr | 32 | use32 |
33 | ; standard header |
||
34 | db 'MENUET01' ; signature |
||
35 | dd 1 ; header version |
||
36 | dd start ; entry point |
||
37 | dd i_end ; initialized size |
||
38 | dd mem+0x1000 ; required memory |
||
39 | dd mem+0x1000 ; stack pointer |
||
4922 | ashmew2 | 40 | dd buf_cmd ; parameters |
5011 | hidnplayr | 41 | dd path ; path |
3701 | hidnplayr | 42 | |
43 | include '../../macros.inc' |
||
44 | purge mov,add,sub |
||
45 | include '../../proc32.inc' |
||
46 | include '../../dll.inc' |
||
47 | include '../../network.inc' |
||
48 | |||
49 | include 'usercommands.inc' |
||
50 | include 'servercommands.inc' |
||
6394 | nisargshah | 51 | include 'parser.inc' |
3701 | hidnplayr | 52 | |
53 | start: |
||
4922 | ashmew2 | 54 | ; initialize heap for using dynamic blocks |
5011 | hidnplayr | 55 | mcall 68,11 |
56 | test eax,eax |
||
57 | je exit2 |
||
58 | |||
4918 | hidnplayr | 59 | ; disable all events except network event |
60 | mcall 40, EV_STACK |
||
3701 | hidnplayr | 61 | ; load libraries |
62 | stdcall dll.Load, @IMPORT |
||
63 | test eax, eax |
||
64 | jnz exit |
||
65 | ; initialize console |
||
3789 | hidnplayr | 66 | invoke con_start, 1 |
3813 | hidnplayr | 67 | invoke con_init, 80, 25, 80, 250, str_title |
5011 | hidnplayr | 68 | ; find path to main settings file (ftpc.ini) |
69 | mov edi, path ; Calculate the length of zero-terminated string |
||
70 | xor al, al |
||
71 | mov ecx, 1024 |
||
72 | repne scasb |
||
73 | dec edi |
||
74 | mov esi, str_ini ; append it with '.ini', 0 |
||
75 | movsd |
||
76 | movsb |
||
77 | ; get settings from ini |
||
78 | invoke ini.get_str, path, str_active, str_ip, str_active_ip, 16, 0 |
||
79 | mov esi, str_active_ip |
||
80 | .ip_loop: |
||
81 | lodsb |
||
82 | test al, al |
||
83 | jz .ip_ok |
||
84 | cmp al, ' ' |
||
85 | je .ip_ok |
||
86 | cmp al, '.' |
||
87 | jne .ip_loop |
||
88 | mov byte[esi-1], ',' |
||
89 | jmp .ip_loop |
||
90 | .ip_ok: |
||
91 | mov byte[esi-1], 0 |
||
92 | |||
93 | invoke ini.get_int, path, str_active, str_port_start, 64000 |
||
94 | mov [acti_port_start], ax |
||
95 | |||
96 | invoke ini.get_int, path, str_active, str_port_stop, 65000 |
||
97 | mov [acti_port_stop], ax |
||
98 | |||
99 | invoke ini.get_str, path, str_general, str_dir, buf_buffer1, BUFFERSIZE, 0 |
||
100 | mcall 30, 1, buf_buffer1 ; set working directory |
||
101 | |||
3813 | hidnplayr | 102 | ; Check for parameters, if there are some, resolve the address right away |
5011 | hidnplayr | 103 | ; TODO: parse ftp://user:password@server.com:port/folder/subfolder type urls. |
4922 | ashmew2 | 104 | cmp byte [buf_cmd], 0 |
3701 | hidnplayr | 105 | jne resolve |
106 | |||
107 | main: |
||
3813 | hidnplayr | 108 | ; Clear screen |
3789 | hidnplayr | 109 | invoke con_cls |
3701 | hidnplayr | 110 | ; Welcome user |
3813 | hidnplayr | 111 | invoke con_write_asciiz, str_welcome |
112 | ; write prompt (in green color) |
||
3789 | hidnplayr | 113 | invoke con_set_flags, 0x0a |
3813 | hidnplayr | 114 | invoke con_write_asciiz, str_prompt |
3701 | hidnplayr | 115 | ; read string |
4922 | ashmew2 | 116 | invoke con_gets, buf_cmd, 256 |
3701 | hidnplayr | 117 | ; check for exit |
118 | test eax, eax |
||
119 | jz done |
||
4922 | ashmew2 | 120 | cmp byte [buf_cmd], 10 |
3701 | hidnplayr | 121 | jz done |
3813 | hidnplayr | 122 | ; reset color back to grey and print newline |
123 | invoke con_set_flags, 0x07 |
||
124 | invoke con_write_asciiz, str_newline |
||
3701 | hidnplayr | 125 | |
6394 | nisargshah | 126 | no_resolve: |
5011 | hidnplayr | 127 | mov [sockaddr1.port], 21 shl 8 |
128 | |||
3701 | hidnplayr | 129 | ; delete terminating '\n' |
4922 | ashmew2 | 130 | mov esi, buf_cmd |
3701 | hidnplayr | 131 | @@: |
132 | lodsb |
||
5011 | hidnplayr | 133 | cmp al, ':' |
134 | je .do_port |
||
3701 | hidnplayr | 135 | cmp al, 0x20 |
136 | ja @r |
||
137 | mov byte [esi-1], 0 |
||
5011 | hidnplayr | 138 | jmp .done |
139 | |||
140 | .do_port: |
||
141 | xor eax, eax |
||
142 | xor ebx, ebx |
||
143 | mov byte [esi-1], 0 |
||
144 | .portloop: |
||
145 | lodsb |
||
146 | cmp al, 0x20 |
||
147 | jbe .port_done |
||
148 | sub al, '0' |
||
149 | jb error_hostname |
||
150 | cmp al, 9 |
||
151 | ja error_hostname |
||
152 | lea ebx, [ebx*4 + ebx] |
||
153 | shl ebx, 1 |
||
154 | add ebx, eax |
||
155 | jmp .portloop |
||
156 | |||
157 | .port_done: |
||
158 | xchg bl, bh |
||
159 | mov [sockaddr1.port], bx |
||
160 | |||
161 | .done: |
||
3813 | hidnplayr | 162 | ; Say to the user that we're resolving |
163 | invoke con_write_asciiz, str_resolve |
||
4922 | ashmew2 | 164 | invoke con_write_asciiz, buf_cmd |
3701 | hidnplayr | 165 | ; resolve name |
166 | push esp ; reserve stack place |
||
4922 | ashmew2 | 167 | invoke getaddrinfo, buf_cmd, 0, 0, esp |
3701 | hidnplayr | 168 | pop esi |
169 | ; test for error |
||
170 | test eax, eax |
||
3813 | hidnplayr | 171 | jnz error_resolve |
3701 | hidnplayr | 172 | ; write results |
3800 | hidnplayr | 173 | invoke con_write_asciiz, str8 ; ' (',0 |
174 | mov eax, [esi+addrinfo.ai_addr] ; convert IP address to decimal notation |
||
175 | mov eax, [eax+sockaddr_in.sin_addr] ; |
||
176 | mov [sockaddr1.ip], eax ; |
||
177 | invoke inet_ntoa, eax ; |
||
178 | invoke con_write_asciiz, eax ; print ip |
||
179 | invoke freeaddrinfo, esi ; free allocated memory |
||
180 | invoke con_write_asciiz, str9 ; ')',10,0 |
||
181 | ; open the socket |
||
3701 | hidnplayr | 182 | mcall socket, AF_INET4, SOCK_STREAM, 0 |
183 | cmp eax, -1 |
||
3813 | hidnplayr | 184 | je error_socket |
5011 | hidnplayr | 185 | mov [controlsocket], eax |
3800 | hidnplayr | 186 | ; connect to the server |
3813 | hidnplayr | 187 | invoke con_write_asciiz, str_connect |
5011 | hidnplayr | 188 | mcall connect, [controlsocket], sockaddr1, 18 |
4918 | hidnplayr | 189 | cmp eax, -1 |
190 | je error_connect |
||
3701 | hidnplayr | 191 | mov [status], STATUS_CONNECTING |
3813 | hidnplayr | 192 | ; Tell the user we're waiting for the server now. |
193 | invoke con_write_asciiz, str_waiting |
||
3701 | hidnplayr | 194 | |
3813 | hidnplayr | 195 | ; Reset 'offset' variable, it's used by the data receiver |
3790 | hidnplayr | 196 | mov [offset], 0 |
197 | |||
3789 | hidnplayr | 198 | wait_for_servercommand: |
3813 | hidnplayr | 199 | ; Any commands still in our buffer? |
3790 | hidnplayr | 200 | cmp [offset], 0 |
3813 | hidnplayr | 201 | je .receive ; nope, receive some more |
3790 | hidnplayr | 202 | mov esi, [offset] |
4922 | ashmew2 | 203 | mov edi, buf_cmd |
3790 | hidnplayr | 204 | mov ecx, [size] |
205 | add ecx, esi |
||
206 | jmp .byteloop |
||
3701 | hidnplayr | 207 | |
208 | ; receive socket data |
||
3790 | hidnplayr | 209 | .receive: |
4918 | hidnplayr | 210 | mcall 26, 9 |
211 | add eax, TIMEOUT*100 |
||
212 | mov [timeout], eax |
||
213 | .receive_loop: |
||
214 | mcall 23, 50 ; Wait for event with timeout |
||
215 | mcall 26, 9 |
||
216 | cmp eax, [timeout] |
||
217 | jge error_timeout |
||
5011 | hidnplayr | 218 | mcall recv, [controlsocket], buf_buffer1, BUFFERSIZE, MSG_DONTWAIT |
4918 | hidnplayr | 219 | test eax, eax |
220 | jnz .got_data |
||
221 | cmp ebx, EWOULDBLOCK |
||
222 | jne error_socket |
||
223 | jmp .receive_loop |
||
3701 | hidnplayr | 224 | |
4918 | hidnplayr | 225 | .got_data: |
3790 | hidnplayr | 226 | mov [offset], 0 |
3789 | hidnplayr | 227 | |
4922 | ashmew2 | 228 | ; extract commands, copy them to "buf_cmd" buffer |
229 | lea ecx, [eax + buf_buffer1] ; ecx = end pointer |
||
230 | mov esi, buf_buffer1 ; esi = current pointer |
||
231 | mov edi, buf_cmd |
||
3701 | hidnplayr | 232 | .byteloop: |
3789 | hidnplayr | 233 | cmp esi, ecx |
234 | jae wait_for_servercommand |
||
3701 | hidnplayr | 235 | lodsb |
236 | cmp al, 10 ; excellent, we might have a command |
||
237 | je .got_command |
||
3789 | hidnplayr | 238 | cmp al, 13 ; just ignore this byte |
3701 | hidnplayr | 239 | je .byteloop |
240 | stosb |
||
241 | jmp .byteloop |
||
3789 | hidnplayr | 242 | .got_command: ; we have a newline check if its a command |
3790 | hidnplayr | 243 | cmp esi, ecx |
244 | je .no_more_data |
||
245 | mov [offset], esi |
||
246 | sub ecx, esi |
||
247 | mov [size], ecx |
||
248 | jmp .go_cmd |
||
249 | .no_more_data: |
||
250 | mov [offset], 0 |
||
251 | .go_cmd: |
||
4922 | ashmew2 | 252 | lea ecx, [edi - buf_cmd] ; length of command |
3701 | hidnplayr | 253 | xor al, al |
254 | stosb |
||
255 | |||
3789 | hidnplayr | 256 | invoke con_set_flags, 0x03 ; change color |
4922 | ashmew2 | 257 | invoke con_write_asciiz, buf_cmd ; print servercommand |
3813 | hidnplayr | 258 | invoke con_write_asciiz, str_newline |
3800 | hidnplayr | 259 | invoke con_set_flags, 0x07 ; reset color |
3701 | hidnplayr | 260 | |
3789 | hidnplayr | 261 | jmp server_parser ; parse command |
3701 | hidnplayr | 262 | |
3813 | hidnplayr | 263 | |
264 | |||
3789 | hidnplayr | 265 | wait_for_usercommand: |
3701 | hidnplayr | 266 | |
4922 | ashmew2 | 267 | ; Are there any files in the transfer queue? |
268 | |||
5011 | hidnplayr | 269 | cmp [queued], 0 |
4922 | ashmew2 | 270 | ja transfer_queued ; Yes, transfer those first. |
5011 | hidnplayr | 271 | |
3813 | hidnplayr | 272 | ; change color to green for user input |
3789 | hidnplayr | 273 | invoke con_set_flags, 0x0a |
3701 | hidnplayr | 274 | |
3813 | hidnplayr | 275 | ; If we are not yet connected, request username/password |
3701 | hidnplayr | 276 | cmp [status], STATUS_CONNECTED |
277 | je .connected |
||
278 | |||
279 | cmp [status], STATUS_NEEDPASSWORD |
||
280 | je .needpass |
||
281 | |||
282 | ; write prompt |
||
3813 | hidnplayr | 283 | invoke con_write_asciiz, str_prompt |
3701 | hidnplayr | 284 | ; read string |
4922 | ashmew2 | 285 | invoke con_gets, buf_cmd, 256 |
3794 | hidnplayr | 286 | |
3813 | hidnplayr | 287 | ; print a newline and reset the color back to grey |
288 | invoke con_write_asciiz, str_newline |
||
3789 | hidnplayr | 289 | invoke con_set_flags, 0x07 |
3701 | hidnplayr | 290 | |
4922 | ashmew2 | 291 | cmp dword[buf_cmd], "cwd " |
3790 | hidnplayr | 292 | je cmd_cwd |
293 | |||
4922 | ashmew2 | 294 | cmp dword[buf_cmd], "mkd " |
3813 | hidnplayr | 295 | je cmd_mkd |
3793 | hidnplayr | 296 | |
4922 | ashmew2 | 297 | cmp dword[buf_cmd], "rmd " |
3813 | hidnplayr | 298 | je cmd_rmd |
299 | |||
4922 | ashmew2 | 300 | cmp dword[buf_cmd], "pwd" + 10 shl 24 |
3794 | hidnplayr | 301 | je cmd_pwd |
302 | |||
4922 | ashmew2 | 303 | cmp dword[buf_cmd], "bye" + 10 shl 24 |
3813 | hidnplayr | 304 | je cmd_bye |
305 | |||
4922 | ashmew2 | 306 | cmp dword[buf_cmd], "rdir" |
5011 | hidnplayr | 307 | je cmd_rdir |
308 | |||
4922 | ashmew2 | 309 | cmp byte[buf_cmd+4], " " |
3813 | hidnplayr | 310 | jne @f |
311 | |||
4922 | ashmew2 | 312 | cmp dword[buf_cmd], "lcwd" |
3813 | hidnplayr | 313 | je cmd_lcwd |
314 | |||
4922 | ashmew2 | 315 | cmp dword[buf_cmd], "retr" |
3813 | hidnplayr | 316 | je cmd_retr |
317 | |||
4922 | ashmew2 | 318 | cmp dword[buf_cmd], "stor" |
3800 | hidnplayr | 319 | je cmd_stor |
3793 | hidnplayr | 320 | |
4922 | ashmew2 | 321 | cmp dword[buf_cmd], "dele" |
3800 | hidnplayr | 322 | je cmd_dele |
323 | |||
3813 | hidnplayr | 324 | @@: |
4922 | ashmew2 | 325 | cmp byte[buf_cmd+4], 10 |
3813 | hidnplayr | 326 | jne @f |
3800 | hidnplayr | 327 | |
4922 | ashmew2 | 328 | cmp dword[buf_cmd], "list" |
3813 | hidnplayr | 329 | je cmd_list |
3802 | hidnplayr | 330 | |
4922 | ashmew2 | 331 | cmp dword[buf_cmd], "help" |
3813 | hidnplayr | 332 | je cmd_help |
3804 | hidnplayr | 333 | |
4922 | ashmew2 | 334 | cmp dword[buf_cmd], "cdup" |
3804 | hidnplayr | 335 | je cmd_cdup |
336 | |||
3813 | hidnplayr | 337 | @@: |
338 | ; Uh oh.. unknown command, tell the user and wait for new input |
||
3789 | hidnplayr | 339 | invoke con_write_asciiz, str_unknown |
3701 | hidnplayr | 340 | jmp wait_for_usercommand |
341 | |||
342 | |||
343 | .connected: |
||
3813 | hidnplayr | 344 | ; request username |
6394 | nisargshah | 345 | cmp [use_params], 1 |
346 | je .copy_user |
||
347 | |||
3789 | hidnplayr | 348 | invoke con_write_asciiz, str_user |
4922 | ashmew2 | 349 | mov dword[buf_cmd], "USER" |
350 | mov byte[buf_cmd+4], " " |
||
3701 | hidnplayr | 351 | jmp .send |
352 | |||
6394 | nisargshah | 353 | .copy_user: |
354 | ; copy user name to buf_cmd |
||
355 | mov edi, buf_cmd |
||
356 | mov esi, param_user |
||
357 | @@: |
||
358 | lodsb |
||
359 | stosb |
||
360 | cmp byte [esi-1], 0 |
||
361 | jne @b |
||
362 | jmp .send |
||
3701 | hidnplayr | 363 | |
364 | .needpass: |
||
3813 | hidnplayr | 365 | ; request password |
6394 | nisargshah | 366 | cmp [use_params], 1 |
367 | je .copy_password |
||
368 | |||
3789 | hidnplayr | 369 | invoke con_write_asciiz, str_pass |
4922 | ashmew2 | 370 | mov dword[buf_cmd], "PASS" |
371 | mov byte[buf_cmd+4], " " |
||
5011 | hidnplayr | 372 | invoke con_set_flags, 0x00 ; black text on black background for password |
6394 | nisargshah | 373 | jmp .send |
3701 | hidnplayr | 374 | |
6394 | nisargshah | 375 | .copy_password: |
376 | ; copy password to buf_cmd |
||
377 | mov edi, buf_cmd |
||
378 | mov esi, param_password |
||
379 | @@: |
||
380 | lodsb |
||
381 | stosb |
||
382 | cmp byte [esi-1], 0 |
||
383 | jne @b |
||
384 | |||
3701 | hidnplayr | 385 | .send: |
386 | ; read string |
||
6394 | nisargshah | 387 | cmp [use_params], 1 |
388 | je @f |
||
4922 | ashmew2 | 389 | mov esi, buf_cmd+5 |
3789 | hidnplayr | 390 | invoke con_gets, esi, 256 |
3701 | hidnplayr | 391 | |
6394 | nisargshah | 392 | @@: |
3800 | hidnplayr | 393 | ; find end of string |
4922 | ashmew2 | 394 | mov edi, buf_cmd+5 |
3701 | hidnplayr | 395 | mov ecx, 256 |
396 | xor al, al |
||
397 | repne scasb |
||
4922 | ashmew2 | 398 | lea esi, [edi-buf_cmd] |
3814 | hidnplayr | 399 | mov word[edi-2], 0x0a0d |
3800 | hidnplayr | 400 | ; and send it to the server |
5011 | hidnplayr | 401 | mcall send, [controlsocket], buf_cmd, , 0 |
3701 | hidnplayr | 402 | |
3813 | hidnplayr | 403 | invoke con_write_asciiz, str_newline |
5011 | hidnplayr | 404 | invoke con_set_flags, 0x07 ; reset color |
3789 | hidnplayr | 405 | jmp wait_for_servercommand |
3701 | hidnplayr | 406 | |
407 | |||
408 | |||
5011 | hidnplayr | 409 | ; files for rdir operation are queued |
410 | transfer_queued: |
||
3701 | hidnplayr | 411 | |
5011 | hidnplayr | 412 | mov esi, [ptr_queue] ; always pointing to current part of ptr_fname_start |
413 | mov edi, buf_cmd+5 ; always point to filename for retr command |
||
414 | .build_filename: |
||
415 | lodsb |
||
416 | stosb |
||
417 | cmp al, 10 |
||
418 | je .get_file ; filename ends with character 10 |
||
419 | test al, al |
||
420 | jnz .build_filename |
||
421 | |||
422 | ; Error occured, we reached the end of the buffer before [queued] reached 0 |
||
423 | mov [queued], 0 |
||
424 | mcall 68, 13, [ptr_fname] ; free buffer |
||
425 | test eax, eax |
||
426 | jz error_heap |
||
427 | jmp wait_for_usercommand |
||
428 | |||
429 | .get_file: |
||
430 | mov byte[edi], 0 ; end filename with 0 byte |
||
431 | mov [ptr_queue], esi |
||
432 | dec [queued] |
||
433 | jnz cmd_retr |
||
434 | |||
435 | mcall 68, 13, [ptr_fname] ; free buffer |
||
436 | test eax, eax |
||
437 | jz error_heap |
||
438 | jmp cmd_retr |
||
439 | |||
440 | |||
441 | |||
442 | open_dataconnection: |
||
443 | |||
444 | test [mode], 1 |
||
445 | jnz .active |
||
446 | |||
447 | mcall send, [controlsocket], str_PASV, str_PASV.length, 0 |
||
3701 | hidnplayr | 448 | ret |
449 | |||
5011 | hidnplayr | 450 | .active: |
451 | mcall socket, AF_INET4, SOCK_STREAM, 0 |
||
452 | cmp eax, -1 |
||
453 | je error_socket |
||
454 | mov [datasocket], eax |
||
455 | |||
456 | mov ax, [acti_port_start] |
||
457 | xchg al, ah |
||
458 | mov [sockaddr2.port], ax |
||
459 | |||
460 | mcall bind, [datasocket], sockaddr2, 18 |
||
461 | cmp eax, -1 |
||
462 | je error_socket |
||
463 | |||
464 | mcall listen, [datasocket], 1 |
||
465 | cmp eax, -1 |
||
466 | je error_socket |
||
467 | |||
468 | mov dword[buf_buffer1], 'PORT' |
||
469 | mov byte[buf_buffer1+4], ' ' |
||
470 | mov edi, buf_buffer1+5 |
||
471 | mov esi, str_active_ip |
||
472 | .loop: |
||
473 | lodsb |
||
474 | test al, al |
||
475 | jz .ip_ok |
||
476 | stosb |
||
477 | jmp .loop |
||
478 | .ip_ok: |
||
479 | mov al, ',' |
||
480 | stosb |
||
481 | movzx eax, byte[sockaddr2.port+0] |
||
482 | call dword_ascii |
||
483 | mov al, ',' |
||
484 | stosb |
||
485 | movzx eax, byte[sockaddr2.port+1] |
||
486 | call dword_ascii |
||
487 | mov ax, 0x0a0d |
||
488 | stosw |
||
489 | lea esi, [edi - buf_buffer1] |
||
490 | mcall send, [controlsocket], buf_buffer1, , 0 |
||
491 | |||
492 | mcall accept, [datasocket], sockaddr2, 18 ; time to accept the awaiting connection.. |
||
493 | cmp eax, -1 |
||
494 | je error_socket |
||
3818 | hidnplayr | 495 | push eax |
5011 | hidnplayr | 496 | mcall close, [datasocket] |
497 | pop [datasocket] |
||
498 | |||
499 | mcall recv, [controlsocket], buf_buffer1, BUFFERSIZE, 0 |
||
500 | |||
3701 | hidnplayr | 501 | ret |
502 | |||
5011 | hidnplayr | 503 | ; eax = input |
504 | ; edi = ptr where to write |
||
505 | dword_ascii: |
||
506 | |||
507 | push edx ebx ecx |
||
508 | mov ebx, 10 |
||
509 | xor ecx, ecx |
||
510 | |||
511 | @@: |
||
512 | xor edx, edx |
||
513 | div ebx |
||
514 | add edx, '0' |
||
515 | push dx |
||
516 | inc ecx |
||
517 | test eax, eax |
||
518 | jnz @r |
||
519 | |||
520 | @@: |
||
521 | pop ax |
||
522 | stosb |
||
523 | dec ecx |
||
524 | jnz @r |
||
525 | |||
526 | pop ecx ebx edx |
||
527 | ret |
||
528 | |||
529 | error_hostname: |
||
530 | invoke con_set_flags, 0x0c ; print errors in red |
||
531 | invoke con_write_asciiz, str_err_host |
||
532 | jmp wait_for_keypress |
||
533 | |||
4918 | hidnplayr | 534 | error_connect: |
535 | invoke con_set_flags, 0x0c ; print errors in red |
||
536 | invoke con_write_asciiz, str_err_connect |
||
537 | jmp wait_for_keypress |
||
3701 | hidnplayr | 538 | |
4918 | hidnplayr | 539 | error_timeout: |
540 | invoke con_set_flags, 0x0c ; print errors in red |
||
541 | invoke con_write_asciiz, str_err_timeout |
||
542 | jmp wait_for_keypress |
||
3701 | hidnplayr | 543 | |
3813 | hidnplayr | 544 | error_socket: |
3818 | hidnplayr | 545 | invoke con_set_flags, 0x0c ; print errors in red |
3813 | hidnplayr | 546 | invoke con_write_asciiz, str_err_socket |
547 | jmp wait_for_keypress |
||
3701 | hidnplayr | 548 | |
3813 | hidnplayr | 549 | error_resolve: |
3818 | hidnplayr | 550 | invoke con_set_flags, 0x0c ; print errors in red |
3813 | hidnplayr | 551 | invoke con_write_asciiz, str_err_resolve |
5011 | hidnplayr | 552 | jmp wait_for_keypress |
3813 | hidnplayr | 553 | |
4922 | ashmew2 | 554 | error_heap: |
5011 | hidnplayr | 555 | invoke con_set_flags, 0x0c ; print errors in red |
4922 | ashmew2 | 556 | invoke con_write_asciiz, str_err_heap |
5011 | hidnplayr | 557 | |
3813 | hidnplayr | 558 | wait_for_keypress: |
3818 | hidnplayr | 559 | invoke con_set_flags, 0x07 ; reset color to grey |
3813 | hidnplayr | 560 | invoke con_write_asciiz, str_push |
3789 | hidnplayr | 561 | invoke con_getch2 |
5011 | hidnplayr | 562 | mcall close, [controlsocket] |
3701 | hidnplayr | 563 | jmp main |
564 | |||
565 | done: |
||
3789 | hidnplayr | 566 | invoke con_exit, 1 |
567 | |||
3701 | hidnplayr | 568 | exit: |
5011 | hidnplayr | 569 | mcall close, [controlsocket] |
570 | exit2: |
||
3701 | hidnplayr | 571 | mcall -1 |
572 | |||
573 | |||
574 | |||
575 | ; data |
||
3813 | hidnplayr | 576 | str_title db 'FTP client',0 |
4918 | hidnplayr | 577 | str_welcome db 'FTP client for KolibriOS v0.12',10 |
3813 | hidnplayr | 578 | db 10 |
579 | db 'Please enter ftp server address.',10,0 |
||
3800 | hidnplayr | 580 | |
6394 | nisargshah | 581 | str_ftp db 'ftp://',0 |
582 | |||
3813 | hidnplayr | 583 | str_prompt db '> ',0 |
584 | str_resolve db 'Resolving ',0 |
||
585 | str_newline db 10,0 |
||
586 | str_err_resolve db 10,'Name resolution failed.',10,0 |
||
587 | str_err_socket db 10,'Socket error.',10,0 |
||
5011 | hidnplayr | 588 | str_err_heap db 10,'Cannot allocate memory from heap.',10,0 |
4918 | hidnplayr | 589 | str_err_timeout db 10,'Timeout - no response from server.',10,0 |
590 | str_err_connect db 10,'Cannot connect to the server.',10,0 |
||
5011 | hidnplayr | 591 | str_err_host db 10,'Invalid hostname.',10,0 |
3813 | hidnplayr | 592 | str8 db ' (',0 |
593 | str9 db ')',10,0 |
||
594 | str_push db 'Push any key to continue.',0 |
||
595 | str_connect db 'Connecting...',10,0 |
||
596 | str_waiting db 'Waiting for welcome message.',10,0 |
||
597 | str_user db "username: ",0 |
||
598 | str_pass db "password: ",0 |
||
599 | str_unknown db "Unknown command or insufficient parameters - type help for more information.",10,0 |
||
600 | str_lcwd db "Local working directory is now: ",0 |
||
3701 | hidnplayr | 601 | |
3813 | hidnplayr | 602 | str_open db "opening data socket",10,0 |
4922 | ashmew2 | 603 | str_close db 10,"closing data socket",10,0 |
604 | str_dot db '.',0 |
||
3701 | hidnplayr | 605 | |
3813 | hidnplayr | 606 | str_help db "available commands:",10 |
607 | db 10 |
||
608 | db "bye - close the connection",10 |
||
609 | db "cdup - change to parent of current directory on the server",10 |
||
610 | db "cwd |
||
611 | db "dele |
||
612 | db "list - list files and folders in current server directory",10 |
||
613 | db "lcwd |
||
614 | db "mkd |
||
615 | db "pwd - print server working directory",10 |
||
616 | db "retr |
||
617 | db "rmd |
||
618 | db "stor |
||
5011 | hidnplayr | 619 | db "rdir - retreive all files from current server dir",10 |
3813 | hidnplayr | 620 | db 10,0 |
621 | |||
5011 | hidnplayr | 622 | str_ini db '.ini', 0 |
623 | str_active db 'active', 0 |
||
624 | str_port_start db 'port_start', 0 |
||
625 | str_port_stop db 'port_stop', 0 |
||
626 | str_ip db 'ip', 0 |
||
627 | str_dir db 'dir', 0 |
||
628 | str_general db 'general', 0 |
||
3821 | hidnplayr | 629 | |
5011 | hidnplayr | 630 | queued dd 0 |
631 | mode db 0 ; passive = 0, active = 1 |
||
632 | |||
3821 | hidnplayr | 633 | ; FTP strings |
634 | |||
635 | str_PASV db 'PASV',13,10 |
||
636 | .length = $ - str_PASV |
||
637 | |||
3701 | hidnplayr | 638 | sockaddr1: |
639 | dw AF_INET4 |
||
5011 | hidnplayr | 640 | .port dw ? |
641 | .ip dd ? |
||
3701 | hidnplayr | 642 | rb 10 |
643 | |||
644 | sockaddr2: |
||
645 | dw AF_INET4 |
||
5011 | hidnplayr | 646 | .port dw ? |
647 | .ip dd ? |
||
3701 | hidnplayr | 648 | rb 10 |
649 | |||
650 | ; import |
||
651 | align 4 |
||
652 | @IMPORT: |
||
653 | |||
5011 | hidnplayr | 654 | library network, 'network.obj', console, 'console.obj', libini, 'libini.obj' |
3701 | hidnplayr | 655 | |
656 | import network, \ |
||
657 | getaddrinfo, 'getaddrinfo', \ |
||
658 | freeaddrinfo, 'freeaddrinfo', \ |
||
659 | inet_ntoa, 'inet_ntoa' |
||
660 | |||
661 | import console, \ |
||
662 | con_start, 'START', \ |
||
663 | con_init, 'con_init', \ |
||
664 | con_write_asciiz,'con_write_asciiz', \ |
||
665 | con_exit, 'con_exit', \ |
||
666 | con_gets, 'con_gets',\ |
||
667 | con_cls, 'con_cls',\ |
||
668 | con_getch2, 'con_getch2',\ |
||
669 | con_set_cursor_pos, 'con_set_cursor_pos',\ |
||
670 | con_write_string, 'con_write_string',\ |
||
3789 | hidnplayr | 671 | con_get_flags, 'con_get_flags', \ |
672 | con_set_flags, 'con_set_flags' |
||
3701 | hidnplayr | 673 | |
5011 | hidnplayr | 674 | import libini, \ |
675 | ini.get_str, 'ini_get_str',\ |
||
676 | ini.get_int, 'ini_get_int' |
||
3701 | hidnplayr | 677 | |
5011 | hidnplayr | 678 | |
3701 | hidnplayr | 679 | i_end: |
680 | |||
3813 | hidnplayr | 681 | ; uninitialised data |
682 | |||
3794 | hidnplayr | 683 | status db ? |
684 | |||
5011 | hidnplayr | 685 | controlsocket dd ? |
3701 | hidnplayr | 686 | datasocket dd ? |
3790 | hidnplayr | 687 | offset dd ? |
688 | size dd ? |
||
3800 | hidnplayr | 689 | operation dd ? |
4918 | hidnplayr | 690 | timeout dd ? |
691 | |||
5011 | hidnplayr | 692 | ptr_fname dd ? |
693 | size_fname dd ? |
||
694 | ptr_queue dd ? |
||
695 | |||
696 | acti_port_start dw ? |
||
697 | acti_port_stop dw ? |
||
698 | acti_port dw ? |
||
699 | |||
700 | str_active_ip rb 16 |
||
701 | |||
3800 | hidnplayr | 702 | filestruct: |
5011 | hidnplayr | 703 | .subfn dd ? |
704 | .offset dd ? |
||
705 | dd ? |
||
706 | .size dd ? |
||
707 | .ptr dd ? |
||
708 | .name rb 1024 |
||
3800 | hidnplayr | 709 | |
4922 | ashmew2 | 710 | buf_buffer1 rb BUFFERSIZE+1 |
711 | buf_buffer2 rb BUFFERSIZE+1 |
||
5011 | hidnplayr | 712 | buf_cmd rb 1024 ; buffer for holding command string |
3794 | hidnplayr | 713 | |
5011 | hidnplayr | 714 | path rb 1024 |
715 | |||
6394 | nisargshah | 716 | use_params db 0 |
717 | param_user rb 1024 |
||
718 | param_password rb 1024 |
||
719 | param_server_addr rb 1024 |
||
720 | param_path rb 1024 |
||
721 | |||
3701 | hidnplayr | 722 | mem: |