Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 6581 → Rev 6582

/programs/develop/libraries/box_lib/trunk/tl_nod_16_w.bmp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:executable
+*
\ No newline at end of property
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/programs/develop/libraries/box_lib/trunk/tl_sys_16_w.bmp
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:executable
+*
\ No newline at end of property
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/programs/network/ftpc/README.txt
0,0 → 1,32
Usage instructions -
 
1) By default log file is created in /usbhd0/1. If the folder is uavailable,
the program will throw an error. Configure the folder from ftpc.ini
 
2) Browse the local and remote folders using UP/DOWN arrow keys and press ENTER
to download/upload the file. Scrolling might not work due to lack of support
from the boxlib library
 
3) It might be difficult to read log file contents using certain text editors.
gedit works fine
 
 
Known issues -
 
1) Uploading large files may not work. I do not know whether this is an FTPC
issue or a network-stack realted issue
 
2) FTPC may freeze on rare occasions. Simply close and restart it
 
3) Download may fail abruptly if disk becomes full. Unfortunately, as of now,
there is no support for checking available disk space beforehand from kernel
itself
 
4) Text in console and log file is not properly formatted
 
 
Future improvements -
 
1) Display more informative error messages (especially in GUI)
 
2) Allow resizing of GUI window and align GUI elements automatically
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/programs/network/ftpc/console.inc
0,0 → 1,155
;;================================================================================================;;
console: ;////////////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Console-specific functions - initialization, clear screen, ;;
;? .get_cmd - Takes user command as input from the console ;;
;? .server_addr - Gets server address from user in the form address:port ;;
;? .get_username/.get_pass - Takes username/password as input from the user ;;
;;------------------------------------------------------------------------------------------------;;
;> ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
 
dd .init
dd .server_addr
dd .get_username
dd .get_cmd
dd .print
dd .set_flags
dd .list
dd .progress
dd .error
 
.init:
; load console library
stdcall dll.Load, @IMPORT_CONSOLE
; initialize console
invoke con_start, 1
invoke con_init, 120, 43, 120, 300, str_title
invoke con_cls
; Welcome user
invoke con_write_asciiz, str_welcome
ret
 
.server_addr:
mov [initial_login], 1
invoke con_cls
invoke con_set_flags, 0x07
; ask for server addr
invoke con_write_asciiz, str_srv_addr
; write prompt (in green color)
invoke con_set_flags, 0x0a
invoke con_write_asciiz, str_prompt
; read string
invoke con_gets, param_server_addr, 256
; check for exit
test eax, eax
jz .exit
cmp byte [param_server_addr], 10
jz .exit
 
.port:
invoke con_write_asciiz, str_port
invoke con_gets, param_port, 256
 
; read username
.get_username:
invoke con_set_flags, 0x0a
invoke con_write_asciiz, str_user
invoke con_gets, param_user, 256
 
; read password
.get_pass:
invoke con_write_asciiz, str_pass
invoke con_set_flags, 0x00 ; black text on black background for password
invoke con_gets, param_password, 256
invoke con_set_flags, 0x0a
 
cmp [initial_login], 1
jne arg_handler.copy_user
mov [initial_login], 0
 
; get initial path
.get_path:
invoke con_write_asciiz, str_path
invoke con_gets, param_path, 256
invoke con_write_asciiz, str_newline
 
jmp arg_handler.connect
 
.get_cmd:
; write prompt
invoke con_write_asciiz, str_prompt
; read string
invoke con_gets, buf_cmd, 256
 
; print a newline and reset the color back to grey
invoke con_write_asciiz, str_newline
invoke con_set_flags, 0x07
 
jmp wait_for_usercommand.parse_cmd
 
.print:
pushad
 
invoke con_write_asciiz, [esp+36]
mov esi, [esp+36]
mov ecx, -1
@@:
inc ecx
lodsb
test al, al
jnz @b
; write to log file
mov eax, [esp+36]
cmp [logfile_offset], -1
je @f
call write_to_file
 
@@:
popad
ret 4
 
.set_flags:
invoke con_set_flags, [esp+4]
ret 4
 
.list:
invoke con_write_asciiz, buf_buffer2
jmp data_loop
 
.progress: ; edx = no. of bytes transferred
mov eax, edx
mov edi, str_bytes_done
call dword_ascii
mov byte[edi],0
icall eax, interface_addr, interface.print, str_downloaded, str_bytes_done, str_bytes
ret
 
.error:
invoke con_getch2
jmp .server_addr
 
.exit:
invoke con_exit, 1
jmp exit
 
 
align 4
@IMPORT_CONSOLE:
 
library console, 'console.obj'
 
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_write_asciiz, 'con_write_asciiz', \
con_exit, 'con_exit', \
con_gets, 'con_gets', \
con_cls, 'con_cls', \
con_getch2, 'con_getch2', \
con_set_cursor_pos, 'con_set_cursor_pos', \
con_write_string, 'con_write_string', \
con_get_flags, 'con_get_flags', \
con_set_flags, 'con_set_flags'
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/programs/network/ftpc/ftpc.asm
6,6 → 6,7
;; ftpc.asm - FTP client for KolibriOS ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; Modified by nisargshah323@gmail.com (2016) ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
41,16 → 42,49
dd path ; path
 
include '../../macros.inc'
macro ijmp reg, addr, method
{
mov reg, [addr]
add reg, [method]
jmp dword[reg]
}
macro icall reg, addr, method, [arg]
{
mov reg, [addr]
add reg, [method]
if ~ arg eq
pushd arg
end if
call dword[reg]
}
 
purge mov,add,sub
 
include '../../proc32.inc'
include '../../dll.inc'
include '../../network.inc'
 
include '../../develop/libraries/box_lib/trunk/box_lib.mac'
include '../../develop/libraries/box_lib/load_lib.mac'
 
include 'console.inc'
include 'gui.inc'
include 'login_gui.inc'
include 'usercommands.inc'
include 'servercommands.inc'
include 'parser.inc'
 
start:
; TODO: Add Pasta support to FTPC
 
;;================================================================================================;;
start: ;//////////////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Program entry point - initialize heap, load libraries and settings ;;
;;------------------------------------------------------------------------------------------------;;
;> ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
; initialize heap for using dynamic blocks
mcall 68,11
test eax,eax
62,9 → 96,6
stdcall dll.Load, @IMPORT
test eax, eax
jnz exit
; initialize console
invoke con_start, 1
invoke con_init, 80, 25, 80, 250, str_title
; find path to main settings file (ftpc.ini)
mov edi, path ; Calculate the length of zero-terminated string
xor al, al
99,48 → 130,144
invoke ini.get_str, path, str_general, str_dir, buf_buffer1, BUFFERSIZE, 0
mcall 30, 1, buf_buffer1 ; set working directory
 
; Check for parameters, if there are some, resolve the address right away
; TODO: parse ftp://user:password@server.com:port/folder/subfolder type urls.
; initialize log file
invoke ini.get_str, path, str_general, str_logfile, log_file, 512, 0
mov [filestruct2.subfn], 2
mov [filestruct2.offset], 0
mov [filestruct2.size], 0
mov [filestruct2.ptr], 0
mov [filestruct2.name], log_file
mcall 70, filestruct2
 
; Usage: ftpc [-cli] [ftp://username:password@server:port/path]
 
; mov dword[buf_cmd], '-cli' ;;;; to test CLI ;;;;;
 
cmp byte [buf_cmd], 0
jne resolve
jne @f
mov [interface_addr], gui
jmp .args_ok
@@: cmp dword[buf_cmd], '-cli'
jne .error
mov [interface_addr], console
jmp .args_ok
 
main:
; Clear screen
invoke con_cls
; Welcome user
invoke con_write_asciiz, str_welcome
; write prompt (in green color)
invoke con_set_flags, 0x0a
invoke con_write_asciiz, str_prompt
; read string
invoke con_gets, buf_cmd, 256
; check for exit
test eax, eax
jz done
cmp byte [buf_cmd], 10
jz done
; reset color back to grey and print newline
invoke con_set_flags, 0x07
invoke con_write_asciiz, str_newline
.args_ok:
 
no_resolve:
mov [sockaddr1.port], 21 shl 8
icall eax, interface_addr, interface.init
; check for ftp://username:pass@server:port/path urls
cmp dword[buf_cmd], 'ftp:'
je parse_args
cmp dword[buf_cmd+5], 'ftp:'
je parse_args
ijmp eax, interface_addr, interface.server_addr
 
; delete terminating '\n'
mov esi, buf_cmd
.error:
call console.init
invoke con_write_asciiz, str_args_err
invoke con_getch2
call console.exit
jmp exit
 
;;================================================================================================;;
arg_handler: ;////////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Passes initial connection info from console/GUI to FTP core and the other way around ;;
;;------------------------------------------------------------------------------------------------;;
;> esp+4 = pointer to the argument passed to the function ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
 
.get_username:
; request username
ijmp eax, interface_addr, interface.get_username
 
.copy_user:
mov dword[buf_cmd], "USER"
mov byte[buf_cmd+4], " "
; copy user name to buf_cmd (for command line args)
mov edi, buf_cmd+5
mov esi, param_user
@@:
movsb
cmp byte [esi-1], 0
jne @b
mov word[edi-1], 0x0a0d
 
lea esi, [edi+1-buf_cmd]
jmp server_connect.send
 
.get_pass:
mov dword[buf_cmd], "PASS"
mov byte[buf_cmd+4], " "
; copy password to buf_cmd (for command line args)
mov edi, buf_cmd+5
mov esi, param_password
@@:
movsb
cmp byte[esi-1], 0
jne @b
mov word[edi-1], 0x0a0d
 
lea esi, [edi+1-buf_cmd]
jmp server_connect.send
 
.get_path:
; copy path from param_path to buf_cmd
mov dword[buf_cmd], "CWD "
mov edi, buf_cmd+4
mov esi, param_path
@@:
lodsb
cmp al, ':'
je .do_port
stosb
cmp al, 0x20
ja @b
mov word[edi-1], 0x0a0d
 
lea esi, [edi+1-buf_cmd]
jmp server_connect.send
 
.connect:
; copy server address to buf_cmd
mov esi, param_server_addr
mov edi, buf_cmd
@@:
lodsb
stosb
cmp al, 0x20
ja @r
mov byte [esi-1], 0
jmp .done
mov byte[edi-1], 0 ; delete terminating '\n'
 
cmp [param_port], 0x20
jbe server_connect.default_port
mov esi, param_port
jmp server_connect.do_port
 
 
;;================================================================================================;;
server_connect: ;/////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Establishes a connection to the FTP server (common block for all interfaces) ;;
;? .do_port - Port is specified by the user and needs to be converted from ASCII ;;
;;------------------------------------------------------------------------------------------------;;
;> esi = pointer to port no. ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
 
.send:
; send username/password/path to the server
mcall send, [controlsocket], buf_cmd, , 0
icall eax, interface_addr, interface.print, str_newline
icall eax, interface_addr, interface.set_flags, 0x07 ; reset color
jmp wait_for_servercommand
 
; resolve port if specified
.do_port:
xor eax, eax
xor ebx, ebx
mov byte [esi-1], 0
.portloop:
lodsb
cmp al, 0x20
161,11 → 288,15
.port_done:
xchg bl, bh
mov [sockaddr1.port], bx
jmp .done
 
.default_port:
mov [sockaddr1.port], 21 shl 8
 
.done:
; Say to the user that we're resolving
invoke con_write_asciiz, str_resolve
invoke con_write_asciiz, buf_cmd
icall eax, interface_addr, interface.set_flags, 0x07 ; reset color
icall eax, interface_addr, interface.print, str_resolve, buf_cmd
; resolve name
push esp ; reserve stack place
invoke getaddrinfo, buf_cmd, 0, 0, esp
177,14 → 308,13
jmp error
@@:
; write results
invoke con_write_asciiz, str8 ; ' (',0
icall eax, interface_addr, interface.print, str8 ; ' (',0
mov eax, [esi+addrinfo.ai_addr] ; convert IP address to decimal notation
mov eax, [eax+sockaddr_in.sin_addr] ;
mov [sockaddr1.ip], eax ;
invoke inet_ntoa, eax ;
invoke con_write_asciiz, eax ; print ip
icall ebx, interface_addr, interface.print, eax, str9 ; <ip>,')',10,0
invoke freeaddrinfo, esi ; free allocated memory
invoke con_write_asciiz, str9 ; ')',10,0
; open the socket
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
193,7 → 323,7
jmp error
@@: mov [controlsocket], eax
; connect to the server
invoke con_write_asciiz, str_connect
icall eax, interface_addr, interface.print, str_connect
mcall connect, [controlsocket], sockaddr1, 18
cmp eax, -1
jne @f
201,12 → 331,22
jmp error
@@: mov [status], STATUS_CONNECTING
; Tell the user we're waiting for the server now.
invoke con_write_asciiz, str_waiting
icall eax, interface_addr, interface.print, str_waiting
 
; Reset 'offset' variable, it's used by the data receiver
mov [offset], 0
 
wait_for_servercommand:
 
;;================================================================================================;;
wait_for_servercommand: ;/////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Checks if any data received from the server is present in buffer. ;;
;? If not, receives and processes it ;;
;;------------------------------------------------------------------------------------------------;;
;> ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
; Any commands still in our buffer?
cmp [offset], 0
je .receive ; nope, receive some more
268,16 → 408,25
xor al, al
stosb
 
invoke con_set_flags, 0x03 ; change color
invoke con_write_asciiz, buf_cmd ; print servercommand
invoke con_write_asciiz, str_newline
invoke con_set_flags, 0x07 ; reset color
icall eax, interface_addr, interface.set_flags, 0x03 ; change color
icall eax, interface_addr, interface.print, buf_cmd, str_newline
icall eax, interface_addr, interface.set_flags, 0x07 ; reset color
 
jmp server_parser ; parse command
 
 
 
wait_for_usercommand:
;;================================================================================================;;
wait_for_usercommand: ;///////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Reads the FTP command entered by the user and compares it with valid FTP commands. ;;
;? Jumps to appropriate handling routine in usercommands.inc ;;
;;------------------------------------------------------------------------------------------------;;
;> status = socket connection status ;;
;> buf_cmd = command entered by the user ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
 
; Are there any files in the transfer queue?
 
285,24 → 434,19
ja transfer_queued ; Yes, transfer those first.
; change color to green for user input
invoke con_set_flags, 0x0a
icall eax, interface_addr, interface.set_flags, 0x0a
 
; If we are not yet connected, request username/password
 
cmp [status], STATUS_CONNECTED
je .connected
je arg_handler.get_username
 
cmp [status], STATUS_NEEDPASSWORD
je .needpass
je arg_handler.get_pass
 
; write prompt
invoke con_write_asciiz, str_prompt
; read string
invoke con_gets, buf_cmd, 256
ijmp eax, interface_addr, interface.get_cmd
 
; print a newline and reset the color back to grey
invoke con_write_asciiz, str_newline
invoke con_set_flags, 0x07
 
.parse_cmd:
cmp dword[buf_cmd], "cwd "
je cmd_cwd
 
349,78 → 493,15
cmp dword[buf_cmd], "cdup"
je cmd_cdup
 
cmp dword[buf_cmd], "abor"
je cmd_abor
 
@@:
; Uh oh.. unknown command, tell the user and wait for new input
invoke con_write_asciiz, str_unknown
icall eax, interface_addr, interface.print, str_unknown
jmp wait_for_usercommand
 
 
.connected:
; request username
cmp [use_params], 1
je .copy_user
 
invoke con_write_asciiz, str_user
mov dword[buf_cmd], "USER"
mov byte[buf_cmd+4], " "
jmp .send
 
.copy_user:
; copy user name to buf_cmd
mov edi, buf_cmd
mov esi, param_user
@@:
lodsb
stosb
cmp byte [esi-1], 0
jne @b
jmp .send
 
.needpass:
; request password
cmp [use_params], 1
je .copy_password
 
invoke con_write_asciiz, str_pass
mov dword[buf_cmd], "PASS"
mov byte[buf_cmd+4], " "
invoke con_set_flags, 0x00 ; black text on black background for password
jmp .send
 
.copy_password:
; copy password to buf_cmd
mov edi, buf_cmd
mov esi, param_password
@@:
lodsb
stosb
cmp byte [esi-1], 0
jne @b
 
.send:
; read string
cmp [use_params], 1
je @f
mov esi, buf_cmd+5
invoke con_gets, esi, 256
 
@@:
; find end of string
mov edi, buf_cmd+5
mov ecx, 256
xor al, al
repne scasb
lea esi, [edi-buf_cmd]
mov word[edi-2], 0x0a0d
; and send it to the server
mcall send, [controlsocket], buf_cmd, , 0
 
invoke con_write_asciiz, str_newline
invoke con_set_flags, 0x07 ; reset color
jmp wait_for_servercommand
 
 
 
; files for rdir operation are queued
transfer_queued:
 
551,27 → 632,113
pop ecx ebx edx
ret
 
error:
 
;;================================================================================================;;
write_to_file: ;//////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Writes input buffer to log file ;;
;;------------------------------------------------------------------------------------------------;;
;> eax = pointer to buffer ;;
;> ecx = size of buffer ;;
;;------------------------------------------------------------------------------------------------;;
;< eax = status of SF 70.3 ;;
;;================================================================================================;;
mov [filestruct2.subfn], 3
m2m [filestruct2.offset], [logfile_offset]
mov [filestruct2.size], ecx
mov [filestruct2.ptr], eax
mov [filestruct2.name], log_file
mcall 70, filestruct2
test eax, eax
jz @f
mov [logfile_offset], -1 ; disable logging
call error_fs
icall ebx, interface_addr, interface.print, str_no_logging
ret
@@:
mov eax, [logfile_offset]
add eax, ecx
mov [logfile_offset], eax
ret
 
;;================================================================================================;;
error: ;//////////////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Generic error routine. Prints the error string passed to it. ;;
;;------------------------------------------------------------------------------------------------;;
;> eax = pointer to the error string ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
push eax
invoke con_set_flags, 0x0c ; print errors in red
icall ebx, interface_addr, interface.set_flags, 0x0c ; print errors in red
pop eax
invoke con_write_asciiz, eax
icall ebx, interface_addr, interface.print, eax
jmp wait_for_keypress
 
 
; Error handling block for filesystem errors
error_fs:
cmp eax, 12
jne @f
mov ebx, str_fs_err_12
@@:
cmp eax, 11
jne @f
mov ebx, str_fs_err_11
@@:
cmp eax, 10
jne @f
mov ebx, str_fs_err_10
@@:
cmp eax, 9
jne @f
mov ebx, str_fs_err_9
@@:
cmp eax, 8
jne @f
mov ebx, str_fs_err_8
@@:
cmp eax, 7
jne @f
mov ebx, str_fs_err_7
@@:
cmp eax, 6
jne @f
mov ebx, str_fs_err_6
@@:
cmp eax, 5
jne @f
mov ebx, str_fs_err_5
@@:
cmp eax, 3
jne @f
mov ebx, str_fs_err_3
@@:
cmp eax, 2
jne @f
mov ebx, str_fs_err_2
@@:
mov edi, fs_error_code
call dword_ascii ; convert error code in eax to ascii
icall eax, interface_addr, interface.set_flags, 0x0c ; print errors in red
icall eax, interface_addr, interface.print, str_err_fs, fs_error_code, ebx
mov word[fs_error_code], ' ' ; clear error code for next time
icall eax, interface_addr, interface.set_flags, 0x0a
 
ret
 
error_heap:
invoke con_set_flags, 0x0c ; print errors in red
invoke con_write_asciiz, str_err_heap
icall eax, interface_addr, interface.set_flags, 0x0c ; print errors in red
icall eax, interface_addr, interface.print, str_err_heap
wait_for_keypress:
invoke con_set_flags, 0x07 ; reset color to grey
invoke con_write_asciiz, str_push
invoke con_getch2
mcall close, [controlsocket]
jmp main
icall eax, interface_addr, interface.set_flags, 0x07 ; reset color to grey
icall eax, interface_addr, interface.print, str_push
ijmp eax, interface_addr, interface.error
 
done:
invoke con_exit, 1
 
exit:
mcall close, [controlsocket]
exit2:
582,11 → 749,9
; data
str_title db 'FTP client',0
str_welcome db 'FTP client for KolibriOS v0.12',10
db 10
db 'Please enter ftp server address.',10,0
db 10,0
str_srv_addr db 'Please enter ftp server address.',10,0
 
str_ftp db 'ftp://',0
 
str_prompt db '> ',0
str_resolve db 'Resolving ',0
str_newline db 10,0
601,6 → 766,18
str_err_connect db 10,'[75,4 connect]: Cannot connect to the server.',10,0
str_err_host db 10,'Invalid hostname.',10,0
str_err_params db 10,'Invalid parameters',10,0
str_err_fs db 10,'File system error: code ',0
fs_error_code db ' ',0 ; file system error code
str_fs_err_2 db ' [Function is not supported for the given file system]',10,0
str_fs_err_3 db ' [Unknown file system]',10,0
str_fs_err_5 db ' [File/Folder not found]',10,0
str_fs_err_6 db ' [End of file, EOF]',10,0
str_fs_err_7 db ' [Pointer lies outside of application memory]',10,0
str_fs_err_8 db ' [Disk is full]',10,0
str_fs_err_9 db ' [File system error]',10,0
str_fs_err_10 db ' [Access denied]',10,0
str_fs_err_11 db ' [Device error]',10,0
str_fs_err_12 db ' [File system requires more memory]',10,0
str8 db ' (',0
str9 db ')',10,0
str_push db 'Push any key to continue.',0
608,8 → 785,14
str_waiting db 'Waiting for welcome message.',10,0
str_user db "username: ",0
str_pass db "password: ",0
str_port db "port (default 21): ",0
str_path db "path (optional): ",0
str_unknown db "Unknown command or insufficient parameters - type help for more information.",10,0
str_lcwd db "Local working directory is now: ",0
str_bytes_done db ' ',0
str_downloaded db 'Downloaded ',0
str_bytes db ' bytes',13,0
str_args_err db 'Invalid arguments. USAGE: ftpc [-cli] [ftp://username:password@server:port/path]',10,0
 
str_open db "opening data socket",10,0
str_close db 10,"closing data socket",10,0
638,10 → 821,13
str_ip db 'ip', 0
str_dir db 'dir', 0
str_general db 'general', 0
str_logfile db 'logfile',0
str_no_logging db 'Error writing to log file. Logging disabled',0
 
queued dd 0
mode db 0 ; passive = 0, active = 1
 
 
; FTP strings
 
str_PASV db 'PASV',13,10
659,11 → 845,25
.ip dd ?
rb 10
 
struc interface
{
.init dd 0
.server_addr dd 4
.get_username dd 8
.get_cmd dd 12
.print dd 16
.set_flags dd 20
.list dd 24
.progress dd 28
.error dd 32
}
interface interface
 
; import
align 4
@IMPORT:
 
library network, 'network.obj', console, 'console.obj', libini, 'libini.obj'
library network, 'network.obj', libini, 'libini.obj'
 
import network, \
getaddrinfo, 'getaddrinfo', \
670,19 → 870,6
freeaddrinfo, 'freeaddrinfo', \
inet_ntoa, 'inet_ntoa'
 
import console, \
con_start, 'START', \
con_init, 'con_init', \
con_write_asciiz,'con_write_asciiz', \
con_exit, 'con_exit', \
con_gets, 'con_gets',\
con_cls, 'con_cls',\
con_getch2, 'con_getch2',\
con_set_cursor_pos, 'con_set_cursor_pos',\
con_write_string, 'con_write_string',\
con_get_flags, 'con_get_flags', \
con_set_flags, 'con_set_flags'
 
import libini, \
ini.get_str, 'ini_get_str',\
ini.get_int, 'ini_get_int'
692,8 → 879,12
 
; uninitialised data
 
interface_addr rd 1
 
status db ?
 
file_size dd ?
 
controlsocket dd ?
datasocket dd ?
offset dd ?
719,16 → 910,34
.ptr dd ?
.name rb 1024
 
filestruct2:
.subfn dd ?
.offset dd ?
dd 0
.size dd ?
.ptr dd ?
db 0
.name dd ?
 
folder_buf rb 40
 
 
buf_buffer1 rb BUFFERSIZE+1
buf_buffer2 rb BUFFERSIZE+1
buf_cmd rb 1024 ; buffer for holding command string
log_file rb 512 ; holds log file path
logfile_offset rd 1
 
path rb 1024
 
use_params db 0
initial_login rb 1
param_user rb 1024
param_password rb 1024
param_server_addr rb 1024
param_path rb 1024
param_port rb 6
 
sc system_colors
rb 1024
 
mem:
/programs/network/ftpc/ftpc.ini
2,7 → 2,7
; 0 = passive / 1 = active
mode=0
dir=/tmp0/1/
 
logfile=/usbhd0/1/ftpc.log
[active]
; Local starting port for active connections
port_start=2000
/programs/network/ftpc/gui.inc
0,0 → 1,1191
@use_library_mem mem.Alloc, mem.Free, mem.ReAlloc, dll.Load
fn_icon1 db '../../develop/libraries/box_lib/trunk/tl_sys_16_w.bmp', 0
fn_icon2 db '../../develop/libraries/box_lib/trunk/tl_nod_16_w.bmp', 0
bmp_icon dd 0
 
TLIST_SZ = 325+16 ;=341. 16 is x-size of scroll bar
TLIST1_X = 50
TLIST2_X = 409
BT_SZ_X = 40
SYS_COL = 0xe6e6e6
BT_COL = 0xcccccc
STR_COL = 0x595959 ;0x000000
 
; TODO: automatic resizing of GUI elements on window resizing
 
align 4
;;================================================================================================;;
gui: ;////////////////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? GUI-specific functions ;;
;;------------------------------------------------------------------------------------------------;;
;> none ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
 
dd .init
dd .server_addr
dd .get_username
dd .get_cmd
dd .print
dd .set_flags
dd .list
dd .progress
dd .error
 
.init:
; load libraries
stdcall dll.Load, @IMPORT_BOXLIB
test eax, eax
jnz .exit
 
mcall 48, 3, sc, sizeof.system_colors
mcall 40, 0xC0000027 ; set event mask
ret
 
.server_addr:
mov [auto_list], 1
jmp login_gui.server_addr
 
.get_username:
jmp login_gui.get_username
 
 
;;================================================================================================;;
.main: ;//////////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Initialize tree list, editbox and textedit elements ;;
;;------------------------------------------------------------------------------------------------;;
;> none ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
 
stdcall [ted_init], tedit0
mov dword[tedit0.rec.width], 9
mov dword[tedit0.rec.height], 16
 
stdcall dword[edit_box_set_text], edit_volume, root_dir
 
; initialize tree list elements
stdcall dword[tl_data_init], tree1
stdcall dword[tl_data_init], tree2
 
; read *.bmp file system icons
copy_path fn_icon1,path,filestruct.name, 0
mov ecx, 3*256*13
stdcall mem.Alloc, ecx
mov [bmp_icon], eax
mov [filestruct.ptr], eax
mov [filestruct.subfn], 0
mov [filestruct.offset], 54
mov [filestruct.size], ecx
mcall 70, filestruct
cmp ebx, 0
jl @f
m2m dword[tree1.data_img_sys], dword[bmp_icon]
m2m dword[tree2.data_img_sys], dword[bmp_icon]
 
@@:
; read * .bmp file with the icon of nodes
copy_path fn_icon2, path, filestruct.name, 0
mov ecx, 3*256*13
stdcall mem.Alloc, ecx
mov [bmp_icon], eax
mov [filestruct.ptr], eax
;mov [filestruct.subfn], 0
;mov [filestruct.offset], 54
mov [filestruct.size], ecx
mcall 70, filestruct
cmp ebx, 0
jl @f
m2m dword[tree1.data_img], dword[bmp_icon]
m2m dword[tree2.data_img], dword[bmp_icon]
@@:
mcall 67, 35, 20, 830, 555 ; resize to main gui window's coordinates
call .draw
; create initial tree list for root_dir
call populate_local_tree_list
jmp arg_handler.connect
 
.get_cmd:
dec [auto_list]
jnz .redraw
call .clear_remote_tree
jmp cmd_list
 
.redraw:
call .draw
 
align 4
.still:
mcall 10
 
dec eax
jz .redraw
dec eax
jz .key
dec eax
jz .button
sub eax, 3
jz .mouse
 
jmp .still
 
.error:
jmp login_gui.error
 
.exit:
; stdcall mem.Free,[bmp_icon]
stdcall dword[tl_data_clear], tree1
stdcall dword[tl_data_clear], tree2
stdcall [ted_delete], tedit0
jmp exit
 
align 4
.draw:
mcall 12, 1
; main window
mcall 0, <35,830>, <20,555>, 0x34000000+SYS_COL, 0x805080DD, hed
 
;-------------------------
; textedit components
;-------------------------
mcall 9, procinfo, -1
mov edi, tedit0
call EvSize
 
movzx ebx,word[procinfo.client_box.width]
inc bx
mcall 13, , ted_wnd_t
stdcall [ted_draw], tedit0
 
; draw "disconnect" button
mcall 8, <50,85>, <25,25>, 3, BT_COL
; string "disconnect"
mcall 4, <50+5,25+5>, 0xb0000000+STR_COL, str_disconnect
; draw "Copy" button
mcall 8, <50,40>, <326,25>, 4, BT_COL
; string "copy"
mcall 4, <50+5,326+5>, 0xb0000000+STR_COL, str_copy
; draw "Search" button
mcall 8, <TLIST2_X+TLIST_SZ-55,55>, <20,25>, 5, BT_COL
; string "Search"
mcall 4, <TLIST2_X+TLIST_SZ-55+5,20+5>, 0xb0000000+STR_COL, str_search
 
; draw "LIST" button
mcall 8, <TLIST2_X+TLIST_SZ-4*BT_SZ_X-15,BT_SZ_X>, <50,25>, 12, BT_COL
; string "LIST"
mcall 4, <TLIST2_X+TLIST_SZ-4*BT_SZ_X-15+5,50+5>, 0xb0000000+STR_COL, str_list
; draw "DELE" button
mcall 8, <TLIST2_X+TLIST_SZ-3*BT_SZ_X-10,BT_SZ_X>, <50,25>, 7, BT_COL
; string "DELE"
mcall 4, <TLIST2_X+TLIST_SZ-3*BT_SZ_X-10+5,50+5>, 0xb0000000+STR_COL, str_dele
; draw "RDIR" button
mcall 8, <TLIST2_X+TLIST_SZ-2*BT_SZ_X-5,BT_SZ_X>, <50,25>, 8, BT_COL
; string "RDIR"
mcall 4, <TLIST2_X+TLIST_SZ-2*BT_SZ_X-5+5,50+5>, 0xb0000000+STR_COL, str_rdir
; draw "RMD" button
mcall 8, <TLIST2_X+TLIST_SZ-BT_SZ_X,BT_SZ_X>, <50,25>, 9, BT_COL
; string "RMD"
mcall 4, <TLIST2_X+TLIST_SZ-BT_SZ_X+5,50+5>, 0xb0000000+STR_COL, str_rmd
 
; draw "mkd" button
mcall 8, <TLIST2_X+TLIST_SZ-BT_SZ_X,BT_SZ_X>, <80,20>, 6, BT_COL
; string "mkd"
mcall 4, <TLIST2_X+TLIST_SZ-BT_SZ_X+5,80+5>, 0xb0000000+STR_COL, str_mkd
; draw "cancel" button
mcall 8, <555,55>, <308,25>, 10, BT_COL
; string "Cancel"
mcall 4, <555+5,308+5>, 0xb0000000+STR_COL, str_abort
; draw "change volume" button
mcall 8, <TLIST1_X+TLIST_SZ-55,55>, <100-20,22>, 11, BT_COL
; string "Change"
mcall 4, <TLIST1_X+TLIST_SZ-55+5,100-20+5>, 0xb0000000+STR_COL, str_change
 
;--------------------------
; tree list components
;--------------------------
stdcall dword[tl_draw], tree1
stdcall dword[tl_draw], tree2
mov dword[wScr.all_redraw], 1
stdcall [scrollbar_ver_draw], wScr
 
mov dword[wScr2.all_redraw],1
stdcall [scrollbar_ver_draw], wScr2
 
stdcall [edit_box_draw], edit_mkd
stdcall [edit_box_draw], edit_volume
stdcall [edit_box_draw], edit_search
 
; progress bar
stdcall [progressbar_draw], pb
 
mcall 12,2
ret
 
align 16
.mouse:
mcall 37, 1
cmp word[tedit0.wnd.top], ax
jg .no_edit
 
shr eax, 16
cmp word[tedit0.wnd.left], ax
jg .no_edit
 
mcall 37, 3
bt eax, 24
jnc @f
 
stdcall [ted_but_select_word], tedit0
jmp .still
 
@@:
stdcall [ted_mouse], tedit0
jmp .still
 
.no_edit:
stdcall [tl_mouse], tree1
stdcall [tl_mouse], tree2
stdcall [edit_box_mouse], edit_mkd
stdcall [edit_box_mouse], edit_volume
stdcall [edit_box_mouse], edit_search
jmp .still
 
align 16
.key:
mcall 2
stdcall [tl_key], tree1
stdcall [tl_key], tree2
stdcall [edit_box_key], edit_mkd
stdcall [edit_box_key], edit_volume
stdcall [edit_box_key], edit_search
jmp .still
 
align 16
.button:
mcall 17
 
cmp ah, 3
jne @f
ijmp eax, interface_addr, interface.server_addr
jmp .still
 
@@:
cmp ah, 4
jne @f
stdcall [ted_but_copy], tedit0
jmp .still
 
@@:
cmp ah, 5
jne @f
je filter_remote_list
 
@@:
cmp ah, 6
je create_remote_dir
 
cmp ah, 7
je delete_file
 
cmp ah, 8
je cmd_rdir
 
cmp ah, 9
je remove_dir
 
cmp ah, 10
je cmd_abor
 
cmp ah, 11
jne @f
call populate_local_tree_list
 
@@:
cmp ah, 12
jne @f
call .clear_remote_tree
je cmd_list
 
@@:
cmp ah, 1
je .exit
jmp .still
 
.print:
pushad
mov ebx, ted_opt_ed_change_time + ted_opt_ed_move_cursor
mov ecx, 2 ; 0a0d
mov esi, [esp+36]
mov word[tedit_buffer], 0x0a0d
lea edi, [tedit_buffer+2]
 
@@:
movsb
inc ecx
cmp byte[esi], 0
jne @b
stdcall [ted_text_add], tedit0, tedit_buffer, ecx, ebx
stdcall [ted_draw], tedit0
; write to log file
mov eax, [esp+36]
cmp [logfile_offset], -1 ; disabled logging?
je @f
call write_to_file
 
@@:
popad
ret 4
 
.set_flags:
ret 4
 
 
;;================================================================================================;;
.list: ;//////////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? update tree2 with remote directory listing ;;
;;------------------------------------------------------------------------------------------------;;
;> buf_buffer2 = received data buffer ;;
;> eax = size of data ;;
;> remote_list_buf = buffer containing last incomplete entry (if any) ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
 
push edx
push eax
; check if any incomplete entry to be parsed
cmp byte[remote_list_buf], 0
je .no_backlog
; find end of remote_list_buf
mov edi, remote_list_buf
mov al, 0
repne scasb
; copy rest of the incomplete entry to remote_list_buf
mov esi, buf_buffer2
dec edi
 
@@:
movsb
cmp word[esi-2], 0x0a0d
jne @b
mov byte[edi], 0
mov ecx, edi
sub ecx, remote_list_buf ; ecx = length of remote_list_buf
mov ebx, esi ; ebx = address at which next parse should start
mov edi, remote_list_buf
jmp .start_parsing
 
.no_backlog:
mov ecx, eax ; ecx = number of bytes remaining to parse in buf_buffer2
mov edi, buf_buffer2
 
.start_parsing:
; find pointer to name
cmp byte[edi], 'd' ; file is a directory
je @f
cmp byte[edi], 'l' ; link
je @f
mov word[node_entry2], 'fi'
jmp .parse
 
@@:
mov word[node_entry2], 'fo'
 
.parse:
mov edx, 8
 
@@:
mov al, ' '
mov ecx, [esp]
add ecx, buf_buffer2
sub ecx, edi
repne scasb
 
; check if the (last) entry is incomplete
test ecx, ecx
jz .store_last_entry
 
rep scasb
test ecx, ecx
jz .store_last_entry
dec edx
jnz @b
 
lea esi, [edi-1]
lea edi, [node_entry2+4]
@@:
movsb
cmp word[esi], 0x0a0d ; end of entry
jne @b
mov byte[edi], 0
 
; add node to tree list
cmp word[node_entry2], 'fi'
jne @f
stdcall dword[tl_node_add], tree2, 0, node_entry2
jmp .added_remote_node
 
@@:
stdcall dword[tl_node_add], tree2, 0x10000, node_entry2
 
.added_remote_node:
; check whether we are parsing remote_list_buf
cmp byte[remote_list_buf], 0
je @f
mov byte[remote_list_buf], 0 ; done parsing remote_list_buf
mov edi, ebx
mov eax, [esp]
mov ecx, buf_buffer2
add ecx, eax
sub ecx, ebx
jmp .start_parsing
 
@@:
; any more entries to parse?
lea edi, [esi+2] ; skip 0a0d
cmp byte[edi], 0
jne .start_parsing
jmp .done_parsing
 
.store_last_entry:
; find index of the last incomplete entry
mov ecx, -1
mov eax, [esp]
lea edi, [buf_buffer2+eax-2]
mov al, 0x0a
std
repne scasb
cld
 
; copy last (incomplete) entry of buf_buffer2 to remote_list_buf
lea esi, [edi+2]
mov edi, remote_list_buf
@@:
movsb
cmp byte[esi-1], 0
jne @b
 
.done_parsing:
call .draw ; to update tree list immediately in case of "auto_list"
pop eax
pop edx
jmp data_loop
 
; clear tree list and add ".." node before executing "LIST"
.clear_remote_tree:
stdcall dword[tl_info_clear], tree2
mov dword[node_entry2+4], 0x2E2E
stdcall dword[tl_node_add], tree2, 0x10000, node_entry2
ret
 
 
;;================================================================================================;;
.progress: ;//////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Update progress bar every time new data is received from data_loop block ;;
;;------------------------------------------------------------------------------------------------;;
;> edx = no. of bytes downloaded ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
 
; detect abort
mcall 17
cmp ah, 10
je cmd_abor
 
push eax ebx ecx edx
mov ebx, [file_size]
mov ecx, 100
mov eax, edx
mul ecx
div ebx
cmp eax, 100
jle @f
mov eax, 100
 
@@:
mov dword[pb], eax
push pb
call [progressbar_draw]
pop edx ecx ebx eax
ret
 
 
remove_dir:
 
stdcall dword[tl_node_get_data], tree2
cmp word[eax], 'fo'
jne gui.still
lea esi, [eax+4]
lea edi, [buf_cmd+4]
@@:
movsb
cmp byte[esi], 0
jne @b
mov word[edi], 0x000a
jmp cmd_rmd
 
 
delete_file:
 
stdcall dword[tl_node_get_data], tree2
cmp word[eax], 'fi'
jne gui.still
lea esi, [eax+4]
lea edi, [buf_cmd+5]
@@:
movsb
cmp byte[esi], 0
jne @b
mov word[edi], 0x000a
jmp cmd_dele
 
 
create_remote_dir:
 
lea edi, [buf_cmd+4]
mov esi, new_dir_buf
@@:
movsb
cmp byte[esi], 0
jne @b
mov word[edi], 0x000a
jmp cmd_mkd
 
 
; Function to call when you press [Enter]
align 4
fun_on_enter:
 
stdcall dword[tl_node_get_data], tree1
cmp word[eax], 'fi'
je @f
lea ecx, [eax+4] ; discard first 4 bytes
call populate_local_tree_list.read_new_dir
;stdcall dword[tl_draw], tree1
ret
 
@@:
lea esi, [eax+4]
lea edi, [buf_cmd+5]
@@:
movsb
cmp byte[esi], 0
jne @b
mov word[edi], 0x000a
jmp cmd_stor
 
 
; Function to call when you press [Enter]
; for treelist with remote directory listing
align 4
fun_on_enter2:
 
stdcall dword[tl_node_get_data], tree2
lea esi, [eax+4]
cmp dword[esi], 0x2E2E
jne @f
mov [auto_list], 1
jmp cmd_cdup
 
@@:
cmp word[eax], 'fo'
je @f
lea edi, [buf_cmd+5]
jmp .copy
 
@@:
lea edi, [buf_cmd+4]
 
.copy:
movsb
cmp byte[esi], 0
jne .copy
mov word[edi], 0x000a ; extra character before 0 to compensate for
; newline in console code
cmp word[eax], 'fo'
je @f
jmp cmd_retr
 
@@:
stdcall dword[tl_info_clear], tree2
mov [auto_list], 1
jmp cmd_cwd
 
 
;;================================================================================================;;
populate_local_tree_list: ;///////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Update tree1 with file names from current working directory ;;
;;------------------------------------------------------------------------------------------------;;
;> none ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
 
mov [filestruct.subfn], 1
mov [filestruct.size], 32
mov [filestruct.ptr], folder_data
mov ecx, root_dir
 
.read_new_dir: ; ecx = pointer to folder name
; parse ".."
cmp word[ecx], '..'
jne @f
cmp byte[ecx+2], 0
jne @f
 
; removes last file name from filestruct.name
mcall 30, 2, filestruct.name,1024 ; get absolute path for cwd
lea edi, [filestruct.name+eax] ; edi = pointer to the tail of file name
mov al, '/'
mov ecx, -1
std
repne scasb
cld
mov byte[edi+1], 0
mov ecx, filestruct.name
 
@@:
mcall 30, 1, ; set cwd
mcall 30, 2, filestruct.name, 1024 ; get absolute path for cwd
; clear all nodes in tree list
stdcall dword[tl_info_clear], tree1
mov [filestruct.offset], 0
 
; read 32 blocks
.outer:
mcall 70, filestruct
;int3
test eax, eax
jz @f
cmp eax, 6 ; EOF
je @f
call error_fs
jmp .done
@@:
test ebx, ebx
je .done ; when no. of blocks is multiple of 32
add [filestruct.offset], ebx
mov ecx, ebx
mov edx, folder_data+32+40 ; pointer to first file's name in BDFE
 
.inner: ; ebx = total number of BDFEs
; ecx = number of BDFEs remaining
; edx = pointer to file's name in BDFE
; ignore "." entry
cmp word[edx], 0x002E
je .added
; copy file/folder name to node_entry
mov esi, edx
mov edi, node_entry+4
@@:
movsb
cmp byte [esi-1], 0
jne @b
; check whether this is a file or a folder
mov al, byte[edx-40]
and al, 0x10
jz @f
; add a folder to tree
mov word[node_entry], 'fo'
stdcall dword[tl_node_add], tree1, 0x10000, node_entry
jmp .added
 
@@:
; add a file to tree
mov word[node_entry], 'fi'
stdcall dword[tl_node_add], tree1, 0, node_entry
 
.added:
add edx, 304 ; 304 = length of BDFE. jump to next file's name
loop .inner
stdcall dword[tl_draw], tree1
cmp ebx, 32
je .outer ; more BDFEs to come
 
.done:
ret
 
 
MIN_M_WND_H equ 500 ;
;input:
; edi = pointer to tedit struct
align 4
EvSize:
pushad
mov ebx, ted_scr_h
mov esi, ted_scr_w
 
m2m ted_wnd_w, [procinfo.client_box.width]
mov eax, ted_wnd_l
sub ted_wnd_w, eax
sub ted_wnd_w, 70
movzx eax, word[esi+sb_offs_size_x]
sub ted_wnd_w, eax
 
;m2m ted_wnd_h,[procinfo.client_box.height] ;
;cmp ted_wnd_h,MIN_M_WND_H
;jg @f
mov ted_wnd_h, MIN_M_WND_H
;@@:
 
movzx eax, word[ebx+sb_offs_size_y]
sub ted_wnd_h, eax
mov eax, ted_wnd_t
sub ted_wnd_h, eax
 
stdcall [ted_init_scroll_bars], tedit0,2
 
popad
ret
 
 
;;================================================================================================;;
filter_remote_list: ;/////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Filter tree list according to pattern specified in 'filter' ;;
;;------------------------------------------------------------------------------------------------;;
;> none ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
stdcall dword[tl_cur_beg], tree2
 
.next_node:
stdcall dword[tl_node_get_data], tree2
; check whether any nodes left
test eax, eax
jnz @f
stdcall dword[tl_draw], tree2
stdcall dword[edit_box_set_text], edit_search, str_null
je gui.still
 
@@:
cmp byte[filter], 0
je gui.still
 
; calculate size of node entry
lea esi, [eax+4]
mov edi, esi
mov ecx, -1
@@:
lodsb
inc ecx
test al, al
jnz @b
 
; calculate size of pattern
mov esi, filter
mov edx, -1
@@:
lodsb
inc edx
test al, al
jnz @b
 
mov esi, filter
 
call search
pop esi
test al, al
 
jnz .get_next
stdcall dword[tl_node_delete], tree2
jmp @f
 
.get_next:
stdcall dword[tl_cur_next], tree2
 
@@:
jmp .next_node
 
 
;;================================================================================================;;
search: ;/////////////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Search for a substring within a string ;;
;;------------------------------------------------------------------------------------------------;;
;> edi = pointer to haystack ;;
;> ecx = size of haystack ;;
;> esi = pointer to needle ;;
;> edx = size of needle ;;
;;------------------------------------------------------------------------------------------------;;
;< al = 0 (not found) / 1 (found) ;;
;;================================================================================================;;
push ebx ecx edx esi edi
; if length of haystack < length of needle
cmp ecx, edx
jge @f
mov bh, 0
jmp .done
@@:
mov bh, 1 ; flag (0 = not found, 1 = found)
sub ecx, edx
dec edi
 
.outer:
cmp ecx, 0
jl .done
dec ecx
inc edi
mov bh, 1 ; flag (0 = not found, 1 = found)
mov edx, [esp+8]
mov esi, [esp+4]
 
.inner:
test edx, edx
jz .done
dec edx
 
mov eax, esi
sub eax, [esp+4]
mov al, byte[edi+eax]
mov bl, byte[esi]
 
inc esi
cmp al, bl
je .inner
mov bh, 0
jmp .outer
 
 
.done:
mov al, bh
pop edi esi edx ecx ebx
ret
 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 
hed db 'FTP Client - KolibriOS',0
str_change db 'Change',0
str_disconnect db 'Disconnect',0
str_copy db 'Copy',0
str_mkd db 'MKD',0
str_dele db 'DELE',0
str_rdir db 'RDIR',0
str_rmd db 'RMD',0
str_abort db 'Cancel',0
str_search db 'Search',0
str_list db 'LIST',0
str_null db 0
 
;----------------------
; tree list elements
;----------------------
tree1 tree_list 64, 500, tl_list_box_mode, 16, 16, \
0xffffff, BT_COL, 0x000000, TLIST1_X, 105, TLIST_SZ-16, 185, 14, 4,\
0, el_focus, wScr, fun_on_enter
 
tree2 tree_list 64, 500, tl_list_box_mode, 16, 16, \
0xffffff, BT_COL, 0x000000, TLIST2_X, 105, TLIST_SZ-16, 185, 14, 4, \
0, el_focus, wScr2, fun_on_enter2
 
; editbox for mkd
edit_mkd edit_box TLIST_SZ-45, TLIST2_X, 82, 0xffffff, 0x6a9480, 0, \
0xAABBCC, 0, 99, new_dir_buf, mouse_dd, 0
 
; editbox for default volume
edit_volume edit_box TLIST_SZ-60, TLIST1_X, 105-20, 0xffffff, 0x6a9480, 0, \
0xAABBCC, 0, 99, root_dir, mouse_dd, 0
 
; editbox for search
edit_search edit_box TLIST_SZ-60, TLIST2_X, 25, 0xffffff, 0x6a9480, 0, \
0xAABBCC, 0, 99, filter,mouse_dd, 0
; A subsidiary structure for scrolling
align 4
wScr:
.x:
.size_x dw 16 ;+0
.start_x dw 250+50-16 ;+2
.y:
.size_y dw 185 ;+4
.start_y dw 105 ;+6
.btn_high dd 15 ;+8
.type dd 1 ;+12
.max_area dd 100 ;+16
.cur_area dd 30 ;+20
.position dd 0 ;+24
.bckg_col dd 0xeeeeee ;+28
.frnt_col dd 0xbbddff ;+32
.line_col dd 0 ;+36
.redraw dd 0 ;+40
.delta dw 0 ;+44
.delta2 dw 0 ;+46
.run_x:
.r_size_x dw 0 ;+48
.r_start_x dw 0 ;+50
.run_y:
.r_size_y dw 0 ;+52
.r_start_y dw 0 ;+54
.m_pos dd 0 ;+56
.m_pos_2 dd 0 ;+60
.m_keys dd 0 ;+64
.run_size dd 0 ;+68
.position2 dd 0 ;+72
.work_size dd 0 ;+76
.all_redraw dd 0 ;+80
.ar_offset dd 1 ;+84
 
align 4
wScr2:
.x:
.size_x dw 16 ;+0
.start_x dw 675+50-16 ;+2
.y:
.size_y dw 185 ;+4
.start_y dw 105 ;+6
.btn_high dd 15 ;+8
.type dd 1 ;+12
.max_area dd 100 ;+16
.cur_area dd 30 ;+20
.position dd 0 ;+24
.bckg_col dd 0xeeeeee ;+28
.frnt_col dd 0xbbddff ;+32
.line_col dd 0 ;+36
.redraw dd 0 ;+40
.delta dw 0 ;+44
.delta2 dw 0 ;+46
.run_x:
.r_size_x dw 0 ;+48
.r_start_x dw 0 ;+50
.run_y:
.r_size_y dw 0 ;+52
.r_start_y dw 0 ;+54
.m_pos dd 0 ;+56
.m_pos_2 dd 0 ;+60
.m_keys dd 0 ;+64
.run_size dd 0 ;+68
.position2 dd 0 ;+72
.work_size dd 0 ;+76
.all_redraw dd 0 ;+80
.ar_offset dd 1 ;+84
;----------------------
; end tree list element
;----------------------
 
;----------------------
; textedit elements
;----------------------
align 4
tedit0:
.wnd BOX 50,355,325,240 ;+ 0 195,5+40,325,240
.rec BOX 30,13,7,10 ;+16
.drag_m db 0 ;+32
.drag_k db 0 ;+33
.sel rb 16 ;+34
.seln rb 16 ;+50
.tex dd 0 ;+66 text memory pointer
.tex_1 dd 0 ;+70 text first symbol pointer
.tex_end dd 0 ;+74 text end memory pointer
.cur_x dd 0 ;+78
.cur_y dd 0 ;+82
.max_chars dd 4096 ;+86
.count_colors_text dd 1 ;+90
.count_key_words dd 0 ;+94
.color_cursor dd SYS_COL ;+98
.color_wnd_capt dd BT_COL ;+102
.color_wnd_work dd 0xffffff ;+106
.color_wnd_bord dd 0x737373 ;+110
.color_select dd 0x0000ff ;+114
.color_cur_text dd 0xffff00 ;+118
.color_wnd_text dd 0x000000 ;+122
.syntax_file dd 0 ;+126
.syntax_file_size dd 500 ;+130
.text_colors dd 0 ;+134
.help_text_f1 dd 0 ;+138
.help_id dd -1 ;+142
.key_words_data dd 0 ;+146
.tim_ch dd ? ;+150
.tim_undo dd ? ;+154
.tim_ls dd ? ;+158
.tim_co dd ? ;+162
.el_focus dd el_focus ;+166
.err_save db 0 ;+170
.panel_id db 0 ;+171
.key_new db 0 ;+172
.symbol_new_line db 20 ;+173
.scr_w dd scrol_w1 ;+174
.scr_h dd scrol_h1 ;+178
.arr_key_pos dd 0 ;+182
.buffer dd ed_buffer ;+186
.buffer_find dd 0 ;+190
.cur_ins db 1 ;+194
.mode_color db 1 ;+195
.mode_invis db 0 ;+196
.gp_opt db 0 ;+197
dd 0;.fun_on_key_ctrl_o dd but_ctrl_o ;+198
.fun_on_key_ctrl_f dd 0 ;+202 ... Ctrl+F
dd 0;.fun_on_key_ctrl_n dd but_ctrl_n ;+206 ... Ctrl+N
.fun_on_key_ctrl_s dd 0 ;+210 ... Ctrl+S
.buffer_size dd 4096 ;+214
.fun_find_err dd 0 ;+218
.fun_init_synt_err dd 0 ;+222
.fun_draw_panel_buttons dd 0 ;+226
.fun_draw_panel_find dd 0 ;+230
.fun_draw_panel_syntax dd 0 ;+234
.fun_save_err dd 0 ;+238
.increase_size dd 1000 ;+242
.ptr_free_symb dd ? ;+246
.font_size dd 16 shl 24 ; +250
 
align 4
scrol_w1:
.x:
.size_x dw 16 ;+0
.start_x dw 85 ;+2
.y:
.size_y dw 100 ; +4
.start_y dw 15 ; +6
.btn_high dd 15 ; +8
.type dd 1 ;+12
.max_area dd 100 ;+16
rb 4+4
.bckg_col dd 0xeeeeee ;+28
.frnt_col dd 0xbbddff ;+32
.line_col dd 0x808080 ;+36
.redraw dd 0 ;+40
.delta dw 0 ;+44
.delta2 dw 0 ;+46
.run_x:
rb 2*4+4*6
.all_redraw dd 0 ;+80
.ar_offset dd 1 ;+84
;---------------------------------------------------------------------
align 4
scrol_h1:
.x:
.size_x dw 85 ;+0
.start_x dw 30 ;+2
.y:
.size_y dw 16 ;+4
.start_y dw 100 ;+6
.btn_high dd 15 ;+8
.type dd 1 ;+12
.max_area dd 100 ;+16
rb 4+4
.bckg_col dd 0xeeeeee ;+28
.frnt_col dd 0xbbddff ;+32
.line_col dd 0x808080 ;+36
.redraw dd 0 ;+40
.delta dw 0 ;+44
.delta2 dw 0 ;+46
.run_x:
rb 2*4+4*6
.all_redraw dd 0 ;+80
.ar_offset dd 1 ;+84
 
;------------
;Progress bar
;------------
struc pb
{
dd 0 ; PB_VALUE equ +0
dd (TLIST2_X+TLIST1_X+TLIST_SZ)/2-150 ; PB_LEFT equ +4. 150 = PB_WIDTH/2
dd 315; PB_TOP equ +8
dd 300; PB_WIDTH equ +12
dd 15 ; PB_HEIGHT equ +16
dd ? ; PB_STYLE equ +20
dd 0 ; PB_MIN equ +24
dd 100; PB_MAX equ +28
dd 0xffffff; PB_BACK_COLOR equ +32
dd 0x00ff40; PB_PROGRESS_COLOR equ +36
dd 0x808080; PB_FRAME_COLOR equ +40
}
pb pb
 
 
align 4
@IMPORT_BOXLIB:
 
library box_lib, 'box_lib.obj'
 
import box_lib, \
edit_box_draw, 'edit_box', \
edit_box_key, 'edit_box_key', \
edit_box_mouse, 'edit_box_mouse', \
edit_box_set_text, 'edit_box_set_text', \
version_ed, 'version_ed', \
scrollbar_ver_draw ,'scrollbar_v_draw', \
scrollbar_ver_mouse,'scrollbar_v_mouse', \
scrollbar_hor_draw, 'scrollbar_h_draw', \
scrollbar_hor_mouse,'scrollbar_h_mouse', \
version_scrollbar, 'version_scrollbar', \
tl_data_init, 'tl_data_init', \
tl_data_clear, 'tl_data_clear', \
tl_info_clear, 'tl_info_clear', \
tl_key, 'tl_key', \
tl_mouse, 'tl_mouse', \
tl_draw, 'tl_draw', \
tl_node_add, 'tl_node_add', \
tl_node_set_data, 'tl_node_set_data', \
tl_node_get_data, 'tl_node_get_data', \
tl_node_delete, 'tl_node_delete', \
tl_cur_beg, 'tl_cur_beg', \
tl_cur_next, 'tl_cur_next', \
tl_cur_perv, 'tl_cur_perv', \
tl_node_close_open, 'tl_node_close_open', \
ted_but_sumb_upper, 'ted_but_sumb_upper', \
ted_but_sumb_lover, 'ted_but_sumb_lover', \
ted_can_save, 'ted_can_save', \
ted_clear, 'ted_clear', \
ted_delete, 'ted_delete', \
ted_draw, 'ted_draw', \
ted_init, 'ted_init', \
ted_init_scroll_bars, 'ted_init_scroll_bars', \
ted_init_syntax_file, 'ted_init_syntax_file', \
ted_is_select, 'ted_is_select', \
ted_key, 'ted_key', \
ted_mouse, 'ted_mouse', \
ted_open_file, 'ted_open_file', \
ted_save_file, 'ted_save_file', \
ted_text_add, 'ted_text_add', \
ted_but_select_word,'ted_but_select_word', \
ted_but_cut, 'ted_but_cut', \
ted_but_copy, 'ted_but_copy', \
ted_but_paste, 'ted_but_paste', \
ted_but_undo, 'ted_but_undo', \
ted_but_redo, 'ted_but_redo', \
ted_but_reverse, 'ted_but_reverse', \
ted_but_find_next, 'ted_but_find_next', \
ted_text_colored, 'ted_text_colored', \
progressbar_draw, 'progressbar_draw'
 
 
auto_list db 1 ; to run LIST immediately after CWD
filter rb 512
root_dir db '/rd/1'
rb 507
new_dir_buf rb 512
folder_data rb 32+32*304
node_entry db '1111'
rb 512
node_entry2 db '1111'
rb 512
remote_list_buf rb 1024
conv_tabl rb 128
ed_buffer rb 100
tedit_buffer rb 1024
el_focus dd 0
;-----------------------
 
procinfo process_information
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/programs/network/ftpc/login_gui.inc
0,0 → 1,123
SYS_COL = 0xe6e6e6
BT_COL = 0xcccccc
STR_COL = 0x595959 ;0x000000
 
;;================================================================================================;;
login_gui: ;//////////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? Login GUI-specific functions ;;
;;------------------------------------------------------------------------------------------------;;
;> none ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
 
; TODO: print error strings (wrong user, pass, etc.)
 
.server_addr:
mov [initial_login], 1
 
.get_username:
; in case of error when either login_gui.server_addr or
; login_gui.get_username is called, should resize window
mcall 67, 320, 300, 390, 200 ; resize to login gui window size
 
.redraw:
call .draw
jmp .still
 
 
align 4
.draw:
mcall 12, 1
mcall 0, <320,390>, <300,200>, 0x34000000+SYS_COL, 0x805080DD, hed
 
stdcall [edit_box_draw], edit_usr
stdcall [edit_box_draw], edit_pass
stdcall [edit_box_draw], edit_server
stdcall [edit_box_draw], edit_port
stdcall [edit_box_draw], edit_path
 
; draw "connect" button
mcall 8, <162,65>, <140,25>, 2, BT_COL
 
; draw strings
mcall 4, <3,5>, 0xb0000000, gui_str_usr
mcall 4, <3,25>, 0xb0000000, gui_str_pass
mcall 4, <3,45>, 0xb0000000, gui_str_server
mcall 4, <3,65>, 0xb0000000, gui_str_port
mcall 4, <3,85>, 0xb0000000, gui_str_path
mcall 4, <167,145>, 0xb0000000+STR_COL, gui_str_connect
mcall 4, <3,115>, 0xb0ff0000, [str_error_addr]
mov [str_error_addr], gui_str_null ; reset error string address
 
mcall 12, 2
ret
 
align 4
.still:
mcall 10 ; wait for event
dec eax
jz .redraw
dec eax
jz .key
dec eax
jz .button
 
stdcall [edit_box_mouse], edit_usr
stdcall [edit_box_mouse], edit_pass
stdcall [edit_box_mouse], edit_server
stdcall [edit_box_mouse], edit_port
stdcall [edit_box_mouse], edit_path
 
jmp .still
 
.button:
mcall 17
 
dec ah
jz .exit
 
dec ah ; 'Connect' button clicked
jz gui.main
 
jmp .still
 
.key:
mcall 2
 
stdcall [edit_box_key], edit_usr
stdcall [edit_box_key], edit_pass
stdcall [edit_box_key], edit_server
stdcall [edit_box_key], edit_port
stdcall [edit_box_key], edit_path
 
jmp .still
 
.error:
mov [str_error_addr], gui_str_error
jmp .server_addr
.exit:
jmp gui.exit
 
 
gui_str_connect db 'Connect',0
gui_str_usr db 'Username:',0
gui_str_pass db 'Password:',0
gui_str_server db 'Server:',0
gui_str_port db 'Port:',0
gui_str_path db 'Path:',0
gui_str_error db 'ERROR! Check log file for details',0
gui_str_null db ' ',0
 
str_error_addr dd gui_str_null
 
; login window components
edit_usr edit_box 300,75,5, 0xffffff,0x6f9480,0,0xAABBCC,0,99,param_user,mouse_dd,ed_focus
edit_pass edit_box 300,75,25,0xffffff,0x6a9480,0,0xAABBCC,0,99,param_password,mouse_dd,ed_pass
edit_server edit_box 300,75,45,0xffffff,0x6a9480,0,0xAABBCC,0,99,param_server_addr,mouse_dd,0
edit_port edit_box 50,75,65,0xffffff,0x6a9480,0,0xAABBCC,0,99,param_port,mouse_dd,ed_figure_only
edit_path edit_box 300,75,85,0xffffff,0x6a9480,0,0xAABBCC,0,99,param_path,mouse_dd,0
 
mouse_dd rd 1
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/programs/network/ftpc/parser.inc
1,126 → 1,88
resolve:
;;================================================================================================;;
parse_args: ;/////////////////////////////////////////////////////////////////////////////////////;;
;;------------------------------------------------------------------------------------------------;;
;? parses command line arguments of type ;;
;? ftp://user:password@server:port/folder/subfolder type urls and attempts to connect ;;
;? automatically ;;
;;------------------------------------------------------------------------------------------------;;
;> buf_cmd = pointer to command line arguments ;;
;;------------------------------------------------------------------------------------------------;;
;< none ;;
;;================================================================================================;;
 
; parse command line parameters of type
; ftp://user:password@server.com:port/folder/subfolder type urls
 
; check ftp://
xor edx, edx
cmp dword[buf_cmd], 'ftp:'
jne @f
mov esi, buf_cmd
mov edi, str_ftp
xor ecx, ecx
jmp .start
@@:
mov al, byte [esi+edx]
mov bl, byte [edi+edx]
inc edx
cmp al, bl
jne main
cmp byte [edi+edx], '/'
jne @b
inc ecx
cmp ecx, 2
jne @b
mov esi, buf_cmd+5
 
.start:
; check ftp://
cmp dword[esi], 'ftp:'
jne .error
cmp word[esi+4], '//'
jne .error
 
; parse user
mov dword[param_user], "USER"
mov byte[param_user+4], " "
inc edx
add esi, edx
lea edi, [param_user+5]
.user:
lea edi, [param_user]
@@:
lodsb
cmp al, 0
jne @f
mov eax, str_err_params
jmp error
@@: stosb
test al, al
jz .error
stosb
cmp byte [esi], ':'
jne .user
mov word [edi], 0x0a0d
mov byte [edi+2], 0
jne @b
mov byte [edi], 0
 
; parse password
inc esi
mov dword[param_password], "PASS"
mov byte[param_password+4], " "
lea edi, [param_password+5]
.pass:
lea edi, [param_password]
@@:
lodsb
cmp al, 0
jne @f
mov eax, str_err_params
jmp error
@@: stosb
test al, al
jz .error
stosb
cmp byte [esi], '@'
jne .pass
mov word [edi], 0x0a0d
mov byte [edi+2], 0
jne @b
mov byte [edi], 0
; parse server address
inc esi
mov edi, param_server_addr
.addr:
@@:
lodsb
cmp al, 0
jne @f
mov eax, str_err_params
jmp error
@@: stosb
test al, al
jz .error
stosb
cmp byte [esi], ':'
jne .addr
jne @b
mov byte [edi], 0
 
; parse port
inc esi
xor eax, eax
xor ebx, ebx
mov [sockaddr1.port], 21 shl 8
.port:
lea edi, [param_port]
@@:
lodsb
cmp al, 0
jne @f
mov eax, str_err_params
jmp error
@@: cmp al, '/'
jbe .port_done
sub al, '0'
jnb @f
mov eax, str_err_host
jmp error
@@: cmp al, 9
jna @f
mov eax, str_err_host
jmp error
@@: lea ebx, [ebx*4 + ebx]
shl ebx, 1
add ebx, eax
jmp .port
.port_done:
xchg bl, bh
mov [sockaddr1.port], bx
test al, al
jz .error
stosb
cmp byte [esi], '/'
jne @b
mov byte [edi], 0
 
; parse path
mov dword[param_path], "CWD "
lea edi, [param_path+4]
.path:
lodsb
stosb
inc esi
lea edi, [param_path]
@@:
movsb
cmp byte [esi], 0
jne .path
mov word [edi], 0x0a0d
mov byte [edi+2], 0
jne @b
mov byte [edi], 0
 
; parameters resolved successfully
mov [use_params], 1
; parameters parsed successfully
jmp arg_handler.connect
 
; copy server address to buf_cmd
mov esi, param_server_addr
mov edi, buf_cmd
.copy:
lodsb
stosb
cmp byte [edi], 0
jne .copy
mov byte [esi], 0
 
jmp no_resolve.done
 
.error:
mov eax, str_err_params
jmp error
/programs/network/ftpc/servercommands.inc
5,11 → 5,14
; 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+4], "Open"
je init_download_count
 
cmp dword[buf_cmd], "150 "
je data_loop
 
cmp dword[buf_cmd], "220 "
je welcome
je connect_ok
 
; cmp dword[buf_cmd], "226 "
; je transfer_ok
33,7 → 36,6
je welcome
 
cmp dword[buf_cmd], "530 " ; password incorrect
mov [use_params], 0
je welcome
 
cmp dword[buf_cmd], "550 "
50,6 → 52,11
jmp wait_for_usercommand
 
 
connect_ok:
 
mov [status], STATUS_CONNECTED
jmp arg_handler.copy_user
 
pass:
 
mov [status], STATUS_NEEDPASSWORD
59,21 → 66,14
login_ok:
 
mov [status], STATUS_LOGGED_IN
cmp [use_params], 0
je wait_for_usercommand
 
cmp [param_path+4], 0
je wait_for_usercommand
cmp [param_path], 0x20 ; no path specified
jbe wait_for_usercommand
; copy path to buf_cmd and execute CWD
mov edi, buf_cmd
mov esi, param_path
@@:
lodsb
stosb
cmp byte[esi-1], 0
jne @b
jmp cmd_cwd
jmp arg_handler.get_path
 
 
pasv_ok:
 
sub ecx, 4
104,7 → 104,7
call ascii_dec
mov byte[sockaddr2.port+1], bl
 
invoke con_write_asciiz, str_open
icall eax, interface_addr, interface.print, str_open
mcall connect, [datasocket], sockaddr2, 18
cmp eax, -1
jne @f
113,19 → 113,56
@@: jmp wait_for_servercommand
 
.fail:
invoke con_write_asciiz, str_unknown
icall eax, interface_addr, interface.print, str_unknown
jmp wait_for_servercommand
 
 
; 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
 
@@:
; 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:
 
invoke con_write_asciiz, str_dot
 
cmp [operation], OPERATION_STOR
je .stor
 
push edx
; we are receiving data
mcall recv, [datasocket], buf_buffer2, BUFFERSIZE, 0
pop edx ; get byte count
add edx, eax
test ebx, ebx
jnz .done
mov byte[buf_buffer2 + eax], 0
136,10 → 173,18
cmp [operation], OPERATION_RDIR
je .rdir
cmp [operation], OPERATION_LIST
je .list
; not retreiving, just print to console
invoke con_write_asciiz, buf_buffer2
icall eax, interface_addr, interface.print, buf_buffer2
jmp data_loop
 
; for console, simply print. for gui, add name to tree list
.list:
ijmp ebx, interface_addr, interface.list
 
 
; retreiving, save to file
.retr:
mov [filestruct.ptr], buf_buffer2
146,8 → 191,15
mov [filestruct.size], eax
push eax
mcall 70, filestruct
test eax, eax
jz @f
call error_fs
jmp close_datacon
@@:
pop eax
add [filestruct.offset], eax
 
icall eax, interface_addr, interface.progress
jmp data_loop
 
; storing, send all data
156,18 → 208,25
cmp eax, 6 ; end of file
je .last_call
test eax, eax ; error
; jne .fileerror
jz @f
call error_fs
jmp close_datacon
@@:
add [filestruct.offset], ebx
mov esi, ebx
mcall send, [datasocket], buf_buffer2, , 0
mov edx, [filestruct.offset]
icall eax, interface_addr, interface.progress
jmp .stor
 
.last_call:
mov esi, ebx
mcall send, [datasocket], buf_buffer2, , 0
mov edx, [filestruct.offset]
icall eax, interface_addr, interface.progress
 
.done:
invoke con_write_asciiz, str_close
icall eax, interface_addr, interface.print, str_close
mcall close, [datasocket]
mov [operation], OPERATION_NONE
jmp wait_for_servercommand
209,7 → 268,7
close_datacon:
cmp [operation], OPERATION_NONE
je wait_for_usercommand
invoke con_write_asciiz, str_close
icall eax, interface_addr, interface.print, str_close
mcall close, [datasocket]
jmp wait_for_usercommand
 
/programs/network/ftpc/usercommands.inc
15,7 → 15,7
 
; Close the control connection
mcall close, [controlsocket]
jmp main
ijmp eax, interface_addr, interface.server_addr
 
 
cmd_pwd:
46,7 → 46,7
cmd_dele:
 
mov dword[buf_cmd], "DELE"
mov byte[buf_cmd], " "
mov byte[buf_cmd+4], " "
 
mov ecx, 256
xor al, al
76,9 → 76,8
call open_dataconnection
; Create/open the file
; TODO: check beforehand if the disk has enough free space available to store the file
 
; Create/open the file
 
mov esi, buf_cmd+5
mov ecx, 256-5
call set_filename
90,9 → 89,11
mov [filestruct.ptr], 0
 
mcall 70, filestruct
cmp eax, -1
; je fileerror
 
test eax, eax
jz @f
call error_fs
jmp close_datacon
@@:
; Prepare to write to the file
 
mov [filestruct.subfn], 3 ; write to file
111,7 → 112,7
mov dword[edi - 2], 0x0a0d
mcall send, [controlsocket], buf_cmd, , 0
 
invoke con_write_asciiz, buf_cmd ; print command
icall eax, interface_addr, interface.print, buf_cmd
jmp wait_for_servercommand
 
cmd_rdir:
136,16 → 137,28
 
mov [operation], OPERATION_STOR
 
mov [filestruct.subfn], 0 ; read file
; get file size
mov [filestruct.subfn], 5
mov [filestruct.offset], 0
mov [filestruct.offset+4], 0
mov [filestruct.size], BUFFERSIZE
mov [filestruct.ptr], buf_buffer2
mov [filestruct.size], 0
mov [filestruct.ptr], folder_buf
 
mov esi, buf_cmd+5
mov ecx, 256-5
call set_filename
 
mcall 70, filestruct
 
mov eax, dword[folder_buf+32] ; supports file size upto 4GB
mov [file_size], eax
 
mov [filestruct.subfn], 0 ; read file
; mov [filestruct.offset], 0
; mov [filestruct.offset+4], 0
mov [filestruct.size], BUFFERSIZE
mov [filestruct.ptr], buf_buffer2
 
mov dword[buf_cmd], "STOR"
mov byte[buf_cmd+4], " "
 
169,20 → 182,35
.loop:
lodsb
cmp al, 10
je .done
je .check
test al, al
je .done
je .check
loop .loop
.done:
 
.check:
mov byte[esi-1], 0
 
; check whether entered path is valid (folder exists)
mov [filestruct2.subfn], 5
mov [filestruct2.offset], 0
mov [filestruct2.size], 0
mov [filestruct2.ptr], folder_buf
mov [filestruct2.name], buf_cmd+5
mcall 70, filestruct2
test eax, eax
jz @f
cmp eax, 2
je @f
call error_fs
jmp wait_for_usercommand
 
@@:
mcall 30, 1, buf_cmd+5 ; set working directory
 
.print:
mcall 30, 2, buf_cmd, 256 ; and read it again
icall eax, interface_addr, interface.print, str_lcwd, buf_cmd, str_newline
 
invoke con_write_asciiz, str_lcwd
invoke con_write_asciiz, buf_cmd
invoke con_write_asciiz, str_newline
 
jmp wait_for_usercommand
 
 
189,7 → 217,7
cmd_cdup:
 
mov dword[buf_cmd], "CDUP"
mov word[buf_cmd+4], 0x0d0a
mov word[buf_cmd+4], 0x0a0d
mcall send, [controlsocket], buf_cmd, 6, 0
 
jmp wait_for_servercommand
227,6 → 255,12
jmp wait_for_servercommand
 
 
cmd_abor:
 
mcall close, [datasocket]
jmp wait_for_servercommand
 
 
; esi = source ptr
; ecx = max length of source buffer
set_filename: