kolibrios/programs/network/ftpc/servercommands.inc

287 lines
6.3 KiB
PHP
Raw Normal View History

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,
; thus they are simply ignored in this simple command parser.
cmp dword[buf_cmd], "150 "
je data_loop
cmp dword[buf_cmd], "220 "
je welcome
; cmp dword[buf_cmd], "226 "
; je transfer_ok
cmp dword[buf_cmd], "227 "
je pasv_ok
cmp dword[buf_cmd], "230 "
je login_ok
; cmp dword[buf_cmd], "250"
; je op_ok
cmp dword[buf_cmd], "331 "
je pass
; cmp dword[buf_cmd], "421 "
; je timeout
cmp dword[buf_cmd], "503 " ; login first
je welcome
cmp dword[buf_cmd], "530 " ; password incorrect
je welcome
cmp dword[buf_cmd], "550 "
je close_datacon
cmp byte[buf_cmd+3], "-"
je wait_for_servercommand
jmp wait_for_usercommand
welcome:
mov [status], STATUS_CONNECTED
jmp wait_for_usercommand
pass:
mov [status], STATUS_NEEDPASSWORD
jmp wait_for_usercommand
login_ok:
mov [status], STATUS_LOGGED_IN
jmp wait_for_usercommand
pasv_ok:
sub ecx, 4
jb .fail
mov al, "("
mov edi, buf_cmd + 4
repne scasb
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je error_socket
mov [datasocket], eax
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
call ascii_dec
mov byte[sockaddr2.port+1], bl
invoke con_write_asciiz, str_open
mcall connect, [datasocket], sockaddr2, 18
; cmp eax, -1
; je error_socket
jmp wait_for_servercommand
.fail:
invoke con_write_asciiz, str_unknown
jmp wait_for_servercommand
data_loop:
invoke con_write_asciiz, str_dot
cmp [operation], OPERATION_STOR
je .stor
; we are receiving data
mcall recv, [datasocket], buf_buffer2, BUFFERSIZE, 0
test ebx, ebx
jnz .done
mov byte[buf_buffer2 + eax], 0
cmp [operation], OPERATION_RETR
je .retr
cmp [operation], OPERATION_RDIR
je .rdir
; not retreiving, just print to console
invoke con_write_asciiz, buf_buffer2
jmp data_loop
; retreiving, save to file
.retr:
mov [filestruct.ptr], buf_buffer2
mov [filestruct.size], eax
push eax
mcall 70, filestruct
pop eax
add [filestruct.offset], eax
jmp data_loop
; storing, send all data
.stor:
mcall 70, filestruct
cmp eax, 6 ; end of file
je .last_call
test eax, eax ; error
; jne .fileerror
add [filestruct.offset], ebx
mov esi, ebx
mcall send, [datasocket], buf_buffer2, , 0
jmp .stor
.last_call:
mov esi, ebx
mcall send, [datasocket], buf_buffer2, , 0
.done:
invoke con_write_asciiz, str_close
mcall close, [datasocket]
mov [operation], OPERATION_NONE
jmp wait_for_servercommand
.rdir:
cmp [size_fname], 0
jne .realloc
.malloc: ; create a new dynamic block
mov ecx, eax
inc ecx
mcall 68,12 ; eax now points to new buffer
test eax,eax
je error_heap
mov [ptr_fname_start], eax
jmp .rdir_init
.realloc: ; expand block created with .malloc
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_start]
test eax, eax
je error_heap
mov [ptr_fname_start], eax ; eax contains the new block now
add eax, [size_fname]
.rdir_init: ; copies filenames into our buffer
mov esi, buf_buffer2
mov edi, eax
.copy_buf:
lodsb
cmp al,13 ; ignore any \r character
je .copy_buf
stosb
cmp al, 10
jne .not_end
inc [queued]
.not_end:
test al,al
jne .copy_buf
dec edi
dec edi
mov eax, [ptr_fname_start]
mov [ptr_queue], eax
sub edi, eax ; edi contains the current size now
mov [size_fname], edi
jmp data_loop
; files for rdir operation are queued
transfer_queued:
mov esi, [ptr_queue] ; always pointing to current part of ptr_fname_start
mov edi, buf_cmd+5 ; always point to filename for retr command
.build_filename:
lodsb
stosb
cmp al,10
je .get_file ; filename ends with character 10
test al,al
jz .null_found ; this should be end of buffer
jmp .build_filename
.null_found:
mov [queued],0
jmp .free
.get_file:
dec [queued]
jnz .after_free
.free:
mcall 68,13,[ptr_fname_start] ; freeing the buffer
test eax,eax
jz error_heap
jmp wait_for_usercommand
.after_free:
xor al,al ; appending 0 after retr command
stosb
mov eax, esi
mov [ptr_queue], eax
jmp cmd_retr
close_datacon:
cmp [operation], OPERATION_NONE
je wait_for_usercommand
invoke con_write_asciiz, str_close
mcall close, [datasocket]
jmp wait_for_usercommand
ascii_dec:
xor ebx, ebx
mov cl, 4 ; max length is 3 digits + 1 separator
.loop:
lodsb
sub al, '0'
jb .done
cmp al, 9
ja .done
lea ebx, [ebx*4+ebx] ; ebx *5
shl ebx, 1 ; ebx *2
add bl, al
dec cl
jnz .loop
.done:
ret