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