2013-06-24 21:33:16 +02:00
|
|
|
server_parser:
|
|
|
|
|
|
|
|
; Commands are always 3 numbers and followed by a space
|
|
|
|
; If a server decides it needs multiline output,
|
|
|
|
; first lines will have a dash instead of space after numbers,
|
2013-07-09 22:19:08 +02:00
|
|
|
; thus they are simply ignored in this simple command parser.
|
2013-06-24 21:33:16 +02:00
|
|
|
|
2016-10-07 19:11:07 +02:00
|
|
|
cmp dword[buf_cmd+4], "Open"
|
|
|
|
je init_download_count
|
|
|
|
|
2014-05-12 01:42:10 +02:00
|
|
|
cmp dword[buf_cmd], "150 "
|
2014-05-10 22:36:33 +02:00
|
|
|
je data_loop
|
2013-06-24 21:33:16 +02:00
|
|
|
|
2014-05-12 01:42:10 +02:00
|
|
|
cmp dword[buf_cmd], "220 "
|
2016-10-07 19:11:07 +02:00
|
|
|
je connect_ok
|
2013-06-24 21:33:16 +02:00
|
|
|
|
2014-05-12 01:42:10 +02:00
|
|
|
; cmp dword[buf_cmd], "226 "
|
2013-10-03 20:43:25 +02:00
|
|
|
; je transfer_ok
|
2013-07-09 22:19:08 +02:00
|
|
|
|
2014-05-12 01:42:10 +02:00
|
|
|
cmp dword[buf_cmd], "227 "
|
2013-06-24 21:33:16 +02:00
|
|
|
je pasv_ok
|
|
|
|
|
2014-05-12 01:42:10 +02:00
|
|
|
cmp dword[buf_cmd], "230 "
|
2013-06-24 21:33:16 +02:00
|
|
|
je login_ok
|
|
|
|
|
2014-05-12 01:42:10 +02:00
|
|
|
; cmp dword[buf_cmd], "250"
|
2013-07-10 11:37:01 +02:00
|
|
|
; je op_ok
|
2013-07-09 22:55:18 +02:00
|
|
|
|
2014-05-12 01:42:10 +02:00
|
|
|
cmp dword[buf_cmd], "331 "
|
2013-06-24 21:33:16 +02:00
|
|
|
je pass
|
|
|
|
|
2014-05-12 01:42:10 +02:00
|
|
|
; cmp dword[buf_cmd], "421 "
|
2013-07-09 22:19:08 +02:00
|
|
|
; je timeout
|
|
|
|
|
2014-05-12 01:42:10 +02:00
|
|
|
cmp dword[buf_cmd], "503 " ; login first
|
2013-07-12 22:35:53 +02:00
|
|
|
je welcome
|
|
|
|
|
2014-05-12 01:42:10 +02:00
|
|
|
cmp dword[buf_cmd], "530 " ; password incorrect
|
2013-07-09 22:19:08 +02:00
|
|
|
je welcome
|
|
|
|
|
2014-05-12 01:42:10 +02:00
|
|
|
cmp dword[buf_cmd], "550 "
|
2013-07-10 11:37:01 +02:00
|
|
|
je close_datacon
|
|
|
|
|
2014-05-12 01:42:10 +02:00
|
|
|
cmp byte[buf_cmd+3], "-"
|
2014-04-01 09:20:52 +02:00
|
|
|
je wait_for_servercommand
|
2013-07-09 22:19:08 +02:00
|
|
|
jmp wait_for_usercommand
|
2013-06-24 21:33:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
welcome:
|
|
|
|
|
|
|
|
mov [status], STATUS_CONNECTED
|
2013-07-09 22:19:08 +02:00
|
|
|
jmp wait_for_usercommand
|
2013-06-24 21:33:16 +02:00
|
|
|
|
|
|
|
|
2016-10-07 19:11:07 +02:00
|
|
|
connect_ok:
|
|
|
|
|
|
|
|
mov [status], STATUS_CONNECTED
|
|
|
|
jmp arg_handler.copy_user
|
|
|
|
|
2013-06-24 21:33:16 +02:00
|
|
|
pass:
|
|
|
|
|
|
|
|
mov [status], STATUS_NEEDPASSWORD
|
2013-07-09 22:19:08 +02:00
|
|
|
jmp wait_for_usercommand
|
2013-06-24 21:33:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
login_ok:
|
|
|
|
|
|
|
|
mov [status], STATUS_LOGGED_IN
|
2016-04-12 14:24:28 +02:00
|
|
|
|
2016-10-07 19:11:07 +02:00
|
|
|
cmp [param_path], 0x20 ; no path specified
|
|
|
|
jbe wait_for_usercommand
|
2024-05-29 16:27:12 +02:00
|
|
|
|
2016-04-12 14:24:28 +02:00
|
|
|
; copy path to buf_cmd and execute CWD
|
2016-10-07 19:11:07 +02:00
|
|
|
jmp arg_handler.get_path
|
|
|
|
|
2013-06-24 21:33:16 +02:00
|
|
|
|
|
|
|
pasv_ok:
|
|
|
|
|
2013-07-12 22:35:53 +02:00
|
|
|
sub ecx, 4
|
2013-06-24 21:33:16 +02:00
|
|
|
jb .fail
|
|
|
|
mov al, "("
|
2014-05-12 01:42:10 +02:00
|
|
|
mov edi, buf_cmd + 4
|
2013-06-24 21:33:16 +02:00
|
|
|
repne scasb
|
|
|
|
|
|
|
|
mcall socket, AF_INET4, SOCK_STREAM, 0
|
|
|
|
cmp eax, -1
|
2016-05-28 12:18:22 +02:00
|
|
|
jne @f
|
|
|
|
mov eax, str_err_socket
|
|
|
|
jmp error
|
|
|
|
@@: mov [datasocket], eax
|
2013-06-24 21:33:16 +02:00
|
|
|
|
|
|
|
mov esi, edi
|
|
|
|
call ascii_dec
|
|
|
|
mov byte[sockaddr2.ip+0], bl
|
|
|
|
call ascii_dec
|
|
|
|
mov byte[sockaddr2.ip+1], bl
|
|
|
|
call ascii_dec
|
|
|
|
mov byte[sockaddr2.ip+2], bl
|
|
|
|
call ascii_dec
|
|
|
|
mov byte[sockaddr2.ip+3], bl
|
|
|
|
|
|
|
|
call ascii_dec
|
|
|
|
mov byte[sockaddr2.port+0], bl
|
2013-07-09 22:19:08 +02:00
|
|
|
call ascii_dec
|
|
|
|
mov byte[sockaddr2.port+1], bl
|
2013-06-24 21:33:16 +02:00
|
|
|
|
2016-10-07 19:11:07 +02:00
|
|
|
icall eax, interface_addr, interface.print, str_open
|
2013-06-24 21:33:16 +02:00
|
|
|
mcall connect, [datasocket], sockaddr2, 18
|
2014-07-26 22:36:31 +02:00
|
|
|
cmp eax, -1
|
2016-05-28 12:18:22 +02:00
|
|
|
jne @f
|
|
|
|
mov eax, str_err_connect
|
|
|
|
jmp error
|
|
|
|
@@: jmp wait_for_servercommand
|
2013-06-24 21:33:16 +02:00
|
|
|
|
|
|
|
.fail:
|
2016-10-07 19:11:07 +02:00
|
|
|
icall eax, interface_addr, interface.print, str_unknown
|
2013-07-09 22:19:08 +02:00
|
|
|
jmp wait_for_servercommand
|
2013-06-24 21:33:16 +02:00
|
|
|
|
|
|
|
|
2016-10-07 19:11:07 +02:00
|
|
|
; get file size, initialize count for number of bytes downloaded
|
|
|
|
init_download_count:
|
|
|
|
|
|
|
|
mov edx, 0
|
|
|
|
; search for 'Open' in buf_cmd
|
|
|
|
lea esi, [buf_cmd+3]
|
|
|
|
@@:
|
|
|
|
inc esi
|
|
|
|
cmp dword[esi], 'Open'
|
|
|
|
je @f
|
|
|
|
cmp byte[esi], 0
|
|
|
|
jne @b
|
|
|
|
jmp data_loop
|
2013-06-24 21:33:16 +02:00
|
|
|
|
2016-10-07 19:11:07 +02:00
|
|
|
@@:
|
|
|
|
; get file size
|
|
|
|
mov al, '('
|
|
|
|
mov ecx, -1
|
|
|
|
mov edi, buf_cmd
|
|
|
|
repne scasb
|
|
|
|
xor eax, eax
|
|
|
|
mov ebx, 10
|
|
|
|
xor ecx, ecx
|
|
|
|
mov esi, edi
|
|
|
|
@@:
|
|
|
|
push eax
|
|
|
|
lodsb
|
|
|
|
sub al, '0'
|
|
|
|
mov cl, al
|
|
|
|
pop eax
|
|
|
|
mul ebx
|
|
|
|
add eax, ecx
|
|
|
|
cmp byte[esi], ' '
|
|
|
|
jne @b
|
|
|
|
mov [file_size], eax
|
|
|
|
|
|
|
|
data_loop:
|
2013-10-03 20:43:25 +02:00
|
|
|
|
2013-07-10 11:37:01 +02:00
|
|
|
cmp [operation], OPERATION_STOR
|
|
|
|
je .stor
|
|
|
|
|
2016-10-07 19:11:07 +02:00
|
|
|
push edx
|
2013-07-10 11:37:01 +02:00
|
|
|
; we are receiving data
|
2014-05-12 01:42:10 +02:00
|
|
|
mcall recv, [datasocket], buf_buffer2, BUFFERSIZE, 0
|
2016-10-07 19:11:07 +02:00
|
|
|
pop edx ; get byte count
|
|
|
|
add edx, eax
|
2013-07-09 23:14:47 +02:00
|
|
|
test ebx, ebx
|
2013-07-10 11:37:01 +02:00
|
|
|
jnz .done
|
2014-05-12 01:42:10 +02:00
|
|
|
mov byte[buf_buffer2 + eax], 0
|
2013-07-09 22:19:08 +02:00
|
|
|
|
2013-07-10 11:37:01 +02:00
|
|
|
cmp [operation], OPERATION_RETR
|
|
|
|
je .retr
|
|
|
|
|
2014-07-26 22:36:31 +02:00
|
|
|
cmp [operation], OPERATION_RDIR
|
|
|
|
je .rdir
|
2016-10-07 19:11:07 +02:00
|
|
|
|
|
|
|
cmp [operation], OPERATION_LIST
|
|
|
|
je .list
|
2024-05-29 16:27:12 +02:00
|
|
|
|
2013-07-10 11:37:01 +02:00
|
|
|
; not retreiving, just print to console
|
2016-10-07 19:11:07 +02:00
|
|
|
icall eax, interface_addr, interface.print, buf_buffer2
|
2014-05-10 22:36:33 +02:00
|
|
|
jmp data_loop
|
2013-06-24 21:33:16 +02:00
|
|
|
|
2016-10-07 19:11:07 +02:00
|
|
|
; for console, simply print. for gui, add name to tree list
|
|
|
|
.list:
|
|
|
|
ijmp ebx, interface_addr, interface.list
|
|
|
|
|
|
|
|
|
2013-07-10 11:37:01 +02:00
|
|
|
; retreiving, save to file
|
|
|
|
.retr:
|
2014-05-12 01:42:10 +02:00
|
|
|
mov [filestruct.ptr], buf_buffer2
|
2013-07-10 11:37:01 +02:00
|
|
|
mov [filestruct.size], eax
|
|
|
|
push eax
|
|
|
|
mcall 70, filestruct
|
2016-10-07 19:11:07 +02:00
|
|
|
test eax, eax
|
|
|
|
jz @f
|
|
|
|
call error_fs
|
|
|
|
jmp close_datacon
|
|
|
|
@@:
|
2013-07-10 11:37:01 +02:00
|
|
|
pop eax
|
|
|
|
add [filestruct.offset], eax
|
2016-10-07 19:11:07 +02:00
|
|
|
|
|
|
|
icall eax, interface_addr, interface.progress
|
2014-05-10 22:36:33 +02:00
|
|
|
jmp data_loop
|
2013-07-09 23:14:47 +02:00
|
|
|
|
2013-07-10 11:37:01 +02:00
|
|
|
; storing, send all data
|
|
|
|
.stor:
|
|
|
|
mcall 70, filestruct
|
|
|
|
cmp eax, 6 ; end of file
|
|
|
|
je .last_call
|
|
|
|
test eax, eax ; error
|
2016-10-07 19:11:07 +02:00
|
|
|
jz @f
|
|
|
|
call error_fs
|
|
|
|
jmp close_datacon
|
|
|
|
@@:
|
2013-07-10 11:37:01 +02:00
|
|
|
add [filestruct.offset], ebx
|
|
|
|
mov esi, ebx
|
2014-05-12 01:42:10 +02:00
|
|
|
mcall send, [datasocket], buf_buffer2, , 0
|
2016-10-07 19:11:07 +02:00
|
|
|
mov edx, [filestruct.offset]
|
|
|
|
icall eax, interface_addr, interface.progress
|
2013-07-10 11:37:01 +02:00
|
|
|
jmp .stor
|
|
|
|
|
|
|
|
.last_call:
|
|
|
|
mov esi, ebx
|
2014-05-12 01:42:10 +02:00
|
|
|
mcall send, [datasocket], buf_buffer2, , 0
|
2016-10-07 19:11:07 +02:00
|
|
|
mov edx, [filestruct.offset]
|
|
|
|
icall eax, interface_addr, interface.progress
|
2013-07-10 11:37:01 +02:00
|
|
|
|
|
|
|
.done:
|
2016-10-07 19:11:07 +02:00
|
|
|
icall eax, interface_addr, interface.print, str_close
|
2013-07-09 22:19:08 +02:00
|
|
|
mcall close, [datasocket]
|
2018-10-19 11:42:23 +02:00
|
|
|
|
|
|
|
; refresh local directory list if in gui
|
|
|
|
cmp [operation], OPERATION_RETR
|
|
|
|
jne @f
|
|
|
|
cmp [interface_addr], gui
|
|
|
|
jne @f
|
|
|
|
call populate_local_tree_list
|
|
|
|
@@:
|
2014-05-10 22:36:33 +02:00
|
|
|
mov [operation], OPERATION_NONE
|
2013-07-09 22:19:08 +02:00
|
|
|
jmp wait_for_servercommand
|
2013-06-24 21:33:16 +02:00
|
|
|
|
2014-05-12 01:42:10 +02:00
|
|
|
.rdir:
|
2014-07-26 22:36:31 +02:00
|
|
|
; alloc/realloc memory block to store filenames
|
|
|
|
mov ecx, eax ; eax is size of buffer received
|
|
|
|
inc ecx
|
|
|
|
add ecx, [size_fname] ; added old size to form new required size
|
|
|
|
mcall 68, 20, , [ptr_fname] ; realloc
|
|
|
|
test eax, eax
|
|
|
|
je error_heap
|
|
|
|
mov [ptr_fname], eax ; eax contains the new block now
|
|
|
|
mov [ptr_queue], eax
|
|
|
|
|
|
|
|
; copy filenames into fname buffer
|
|
|
|
mov esi, buf_buffer2
|
|
|
|
mov edi, eax
|
|
|
|
add edi, [size_fname]
|
|
|
|
.copy_buf:
|
|
|
|
lodsb
|
|
|
|
cmp al, 13 ; ignore any carriage return character
|
|
|
|
je .copy_buf
|
|
|
|
stosb
|
|
|
|
cmp al, 10 ; linefeed marks end of filename
|
|
|
|
je @f
|
|
|
|
inc [queued]
|
|
|
|
@@:
|
|
|
|
test al, al ; 0 marks end of buffer
|
|
|
|
jne .copy_buf
|
|
|
|
|
|
|
|
; All received filenames have been copied, calculate new size of fname buffer
|
2024-05-29 16:27:12 +02:00
|
|
|
dec edi ; don't count the trailing 0 byte
|
2014-07-26 22:36:31 +02:00
|
|
|
sub edi, [ptr_fname]
|
2024-05-29 16:27:12 +02:00
|
|
|
mov [size_fname], edi
|
2014-07-26 22:36:31 +02:00
|
|
|
jmp data_loop
|
2014-05-12 01:42:10 +02:00
|
|
|
|
|
|
|
|
2013-07-10 11:37:01 +02:00
|
|
|
close_datacon:
|
2014-05-10 22:36:33 +02:00
|
|
|
cmp [operation], OPERATION_NONE
|
|
|
|
je wait_for_usercommand
|
2016-10-07 19:11:07 +02:00
|
|
|
icall eax, interface_addr, interface.print, str_close
|
2013-07-10 11:37:01 +02:00
|
|
|
mcall close, [datasocket]
|
|
|
|
jmp wait_for_usercommand
|
|
|
|
|
|
|
|
|
2013-06-24 21:33:16 +02:00
|
|
|
ascii_dec:
|
|
|
|
|
|
|
|
xor ebx, ebx
|
2013-07-09 22:19:08 +02:00
|
|
|
mov cl, 4 ; max length is 3 digits + 1 separator
|
2013-06-24 21:33:16 +02:00
|
|
|
.loop:
|
|
|
|
lodsb
|
|
|
|
sub al, '0'
|
|
|
|
jb .done
|
|
|
|
cmp al, 9
|
|
|
|
ja .done
|
2013-07-09 22:19:08 +02:00
|
|
|
lea ebx, [ebx*4+ebx] ; ebx *5
|
|
|
|
shl ebx, 1 ; ebx *2
|
2013-06-24 21:33:16 +02:00
|
|
|
add bl, al
|
|
|
|
dec cl
|
|
|
|
jnz .loop
|
|
|
|
|
|
|
|
.done:
|
|
|
|
ret
|