45,9 → 45,8 |
include 'usercommands.inc' |
include 'servercommands.inc' |
|
; entry point |
start: |
|
; disable all events |
mcall 40, 0 |
; load libraries |
stdcall dll.Load, @IMPORT |
55,30 → 54,29 |
jnz exit |
; initialize console |
invoke con_start, 1 |
invoke con_init, 80, 25, 80, 250, title |
|
; Check for parameters |
invoke con_init, 80, 25, 80, 250, str_title |
; Check for parameters, if there are some, resolve the address right away |
cmp byte [s], 0 |
jne resolve |
|
main: |
; Clear screen |
invoke con_cls |
; Welcome user |
invoke con_write_asciiz, str1 |
|
; write prompt |
invoke con_write_asciiz, str_welcome |
; write prompt (in green color) |
invoke con_set_flags, 0x0a |
invoke con_write_asciiz, str2 |
invoke con_write_asciiz, str_prompt |
; read string |
mov esi, s |
invoke con_gets, esi, 256 |
invoke con_write_asciiz, str4 ; newline |
invoke con_set_flags, 0x07 |
invoke con_gets, s, 256 |
; check for exit |
test eax, eax |
jz done |
cmp byte [esi], 10 |
cmp byte [s], 10 |
jz done |
; reset color back to grey and print newline |
invoke con_set_flags, 0x07 |
invoke con_write_asciiz, str_newline |
|
resolve: |
; delete terminating '\n' |
88,10 → 86,9 |
cmp al, 0x20 |
ja @r |
mov byte [esi-1], 0 |
|
invoke con_write_asciiz, str3 |
; Say to the user that we're resolving |
invoke con_write_asciiz, str_resolve |
invoke con_write_asciiz, s |
|
; resolve name |
push esp ; reserve stack place |
invoke getaddrinfo, s, 0, 0, esp |
98,8 → 95,7 |
pop esi |
; test for error |
test eax, eax |
jnz fail |
|
jnz error_resolve |
; write results |
invoke con_write_asciiz, str8 ; ' (',0 |
mov eax, [esi+addrinfo.ai_addr] ; convert IP address to decimal notation |
109,26 → 105,25 |
invoke con_write_asciiz, eax ; print ip |
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 |
je socket_error |
je error_socket |
mov [socketnum], eax |
|
; connect to the server |
invoke con_write_asciiz, str11 |
invoke con_write_asciiz, str_connect |
mcall connect, [socketnum], sockaddr1, 18 |
mov [status], STATUS_CONNECTING |
; Tell the user we're waiting for the server now. |
invoke con_write_asciiz, str_waiting |
|
invoke con_write_asciiz, str12 ; 'waiting for welcome' |
|
; Reset 'offset' variable, it's used by the data receiver |
mov [offset], 0 |
|
wait_for_servercommand: |
|
; Any commands still in our buffer? |
cmp [offset], 0 |
je .receive |
je .receive ; nope, receive some more |
mov esi, [offset] |
mov edi, s |
mov ecx, [size] |
139,7 → 134,7 |
.receive: |
mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, 0 |
inc eax |
jz socket_error |
jz error_socket |
dec eax |
jz wait_for_servercommand |
|
174,15 → 169,19 |
|
invoke con_set_flags, 0x03 ; change color |
invoke con_write_asciiz, s ; print servercommand |
invoke con_write_asciiz, str4 ; newline |
invoke con_write_asciiz, str_newline |
invoke con_set_flags, 0x07 ; reset color |
|
jmp server_parser ; parse command |
|
|
|
wait_for_usercommand: |
|
; change color to green for user input |
invoke con_set_flags, 0x0a |
|
; If we are not yet connected, request username/password |
cmp [status], STATUS_CONNECTED |
je .connected |
|
190,29 → 189,38 |
je .needpass |
|
; write prompt |
invoke con_write_asciiz, str2 |
invoke con_write_asciiz, str_prompt |
; read string |
mov esi, s |
invoke con_gets, esi, 256 |
invoke con_gets, s, 256 |
|
invoke con_write_asciiz, str4 ; newline |
; print a newline and reset the color back to grey |
invoke con_write_asciiz, str_newline |
invoke con_set_flags, 0x07 |
|
cmp dword[s], "list" |
je cmd_list |
|
cmp dword[s], "help" |
je cmd_help |
|
cmp dword[s], "cwd " |
je cmd_cwd |
|
cmp dword[s], "retr" |
je cmd_retr |
cmp dword[s], "mkd " |
je cmd_mkd |
|
cmp dword[s], "rmd " |
je cmd_rmd |
|
cmp dword[s], "pwd" + 10 shl 24 |
je cmd_pwd |
|
cmp dword[s], "bye" + 10 shl 24 |
je cmd_bye |
|
cmp byte[s+4], " " |
jne @f |
|
cmp dword[s], "lcwd" |
je cmd_lcwd |
|
cmp dword[s], "retr" |
je cmd_retr |
|
cmp dword[s], "stor" |
je cmd_stor |
|
219,27 → 227,27 |
cmp dword[s], "dele" |
je cmd_dele |
|
cmp dword[s], "bye" + 10 shl 24 |
je cmd_bye |
@@: |
cmp byte[s+4], 10 |
jne @f |
|
cmp dword[s], "lcwd" |
je cmd_lcwd |
cmp dword[s], "list" |
je cmd_list |
|
cmp dword[s], "mkd " |
je cmd_mkd |
cmp dword[s], "help" |
je cmd_help |
|
cmp dword[s], "rmd " |
je cmd_rmd |
|
cmp dword[s], "cdup" |
je cmd_cdup |
|
@@: |
; Uh oh.. unknown command, tell the user and wait for new input |
invoke con_write_asciiz, str_unknown |
jmp wait_for_usercommand |
|
|
.connected: |
|
; request username |
invoke con_write_asciiz, str_user |
mov dword[s], "USER" |
mov byte[s+4], " " |
247,7 → 255,7 |
|
|
.needpass: |
|
; request password |
invoke con_write_asciiz, str_pass |
mov dword[s], "PASS" |
mov byte[s+4], " " |
267,7 → 275,7 |
; and send it to the server |
mcall send, [socketnum], s, , 0 |
|
invoke con_write_asciiz, str4 ; newline |
invoke con_write_asciiz, str_newline |
invoke con_set_flags, 0x07 ; reset color |
jmp wait_for_servercommand |
|
283,19 → 291,20 |
ret |
|
.fail: |
invoke con_write_asciiz, str6 |
invoke con_write_asciiz, str_err_socket |
ret |
|
|
|
socket_error: |
invoke con_write_asciiz, str6 |
jmp fail.wait |
error_socket: |
invoke con_write_asciiz, str_err_socket |
jmp wait_for_keypress |
|
fail: |
invoke con_write_asciiz, str5 |
.wait: |
invoke con_write_asciiz, str10 |
error_resolve: |
invoke con_write_asciiz, str_err_resolve |
|
wait_for_keypress: |
invoke con_write_asciiz, str_push |
invoke con_getch2 |
jmp main |
|
309,41 → 318,43 |
|
|
; data |
title db 'FTP client',0 |
str1 db 'FTP client for KolibriOS v0.07',10,10,'Please enter ftp server address.',10,0 |
str2 db '> ',0 |
str3 db 'Resolving ',0 |
str4 db 10,0 |
str5 db 10,'Name resolution failed.',10,0 |
str6 db 10,'Socket error.',10,0 |
str_title db 'FTP client',0 |
str_welcome db 'FTP client for KolibriOS v0.08',10 |
db 10 |
db 'Please enter ftp server address.',10,0 |
|
str_prompt db '> ',0 |
str_resolve db 'Resolving ',0 |
str_newline db 10,0 |
str_err_resolve db 10,'Name resolution failed.',10,0 |
str_err_socket db 10,'Socket error.',10,0 |
str8 db ' (',0 |
str9 db ')',10,0 |
str10 db 'Push any key to continue.',0 |
str11 db 'Connecting...',10,0 |
str12 db 'Waiting for welcome message.',10,0 |
str_push db 'Push any key to continue.',0 |
str_connect db 'Connecting...',10,0 |
str_waiting db 'Waiting for welcome message.',10,0 |
str_user db "username: ",0 |
str_pass db "password: ",0 |
str_unknown db "unknown command or insufficient parameters",10,0 |
str_lcwd db "local working directory is now: ",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_open db "opening data socket",10,0 |
|
str_help db "available commands:",10 |
db "help - help",10 |
db 10 |
db "bye - close connection",10 |
db "cdup - change to parent of current directory on server",10 |
db "cwd - change working directoy on server",10 |
db "dele - delete file from server",10 |
db "list - list files and folders in current directory",10 |
db "lcwd - change local working directory",10 |
db "mkd - make directory on the server",10 |
db "pwd - print working directory",10 |
db "retr - retreive file from server",10 |
db "rmd - remove directory from the server",10 |
db "stor - store file on server",10 |
db "bye - close the connection",10 |
db "cdup - change to parent of current directory on the server",10 |
db "cwd <directory> - change working directoy on the server",10 |
db "dele <file> - delete file from the server",10 |
db "list - list files and folders in current server directory",10 |
db "lcwd <path> - change local working directory",10 |
db "mkd <directory> - make directory on the server",10 |
db "pwd - print server working directory",10 |
db "retr <file> - retreive file from the server",10 |
db "rmd <directory> - remove directory from the server",10 |
db "stor <file> - store file on the server",10 |
db 10,0 |
|
str_open db "opening data socket",10,0 |
|
sockaddr1: |
dw AF_INET4 |
.port dw 0x1500 ; 21 |
383,6 → 394,8 |
|
i_end: |
|
; uninitialised data |
|
status db ? |
active_passive db ? |
|