diff --git a/kernel/branches/net/applications/ftpd/commands.inc b/kernel/branches/net/applications/ftpd/commands.inc index fd033049b0..92b16bb137 100644 --- a/kernel/branches/net/applications/ftpd/commands.inc +++ b/kernel/branches/net/applications/ftpd/commands.inc @@ -31,57 +31,43 @@ parse_cmd: ; esi must point to command align 4 -commands: ; all commands must be in uppercase +commands: ; all commands must be in uppercase db 'ABOR' dd cmdABOR - db 'CWD', 0 dd cmdCWD - db 'DELE' dd cmdDELE - db 'LIST' dd cmdLIST - db 'NLST' dd cmdNLST - db 'NOOP' dd cmdNOOP - db 'PASS' dd cmdPASS - + db 'PASV' + dd cmdPASV db 'PWD', 0 ; Print Working Directory dd cmdPWD - db 'PORT' dd cmdPORT - db 'QUIT' dd cmdQUIT - db 'RETR' dd cmdRETR - db 'STOR' dd cmdSTOR - db 'SYST' dd cmdSYST - db 'TYPE' dd cmdTYPE - db 'USER' dd cmdUSER - db 'XPWD' dd cmdPWD - - db 0 ; end marker + db 0 ; end marker align 4 @@ -102,6 +88,143 @@ cmdDELE: align 4 cmdLIST: + cmp [mode], MODE_ACTIVE + jne @f + mcall connect, [datasocketnum], datasock, datasock.length + cmp eax, -1 + je .err + @@: + + mcall send, [socketnum2], str150, str150.length, 0 ; here it comes.. + + push FA_READONLY + FA_FOLDER + push str_mask + push home_dir + call [file.find.first] + + mov edi, buffer + jmp .parse_file + + .checknextfile: + push edx + call [file.find.next] + + .parse_file: + test eax, eax + jz .done + + mov edx, eax + +; first, convert the attributes + test [eax + FileInfoA.Attributes], FA_FOLDER + jnz .folder + + test [eax + FileInfoA.Attributes], FA_READONLY + jnz .readonly + + mov eax, '-rw-' + stosd + jmp .attr + + .folder: + mov eax, 'drwx' + stosb + jmp .attr + + .readonly: + mov eax, '-r--' + stosd + + .attr: + mov eax, 'rw-r' + stosd + mov ax, 'w-' + stosw + mov al, ' ' + stosb + +; now.. + mov ax, '1 ' + stosw + +; now write owner, everything is owned by FTP, woohoo! + mov eax, 'FTP ' + stosd + stosd + +; now the filesize in ascii + mov ebx, dword [edx + FileInfoA.FileSize] + call dword_to_ascii + + mov al, ' ' + stosb + +; then date (month/day/year) + movzx ebx, [edx + FileInfoA.DateModify + FileDateTime.month] + mov eax, [months + 4*ebx] + stosd + + movzx ebx, [edx + FileInfoA.DateModify + FileDateTime.day] + call dword_to_ascii + + mov al, ' ' + stosb + + movzx ebx, [edx + FileInfoA.DateModify + FileDateTime.year] + call dword_to_ascii + + mov al, ' ' + stosb + +; and last but not least, filename + lea esi, [edx + FileInfoA.FileName] + mov ecx, 250 + .nameloop: + lodsb + test al, al + jz .namedone + stosb + loop .nameloop + + .namedone: + mov ax, 0x0d0a + stosw + jmp .checknextfile + + .done: + push edx + call [file.find.close] + + xor al, al + stosb + + push buffer + call [con_write_asciiz] + + lea esi, [edi - buffer] + mcall send, [datasocketnum], buffer, , 0 + + mcall close, [datasocketnum] + + cmp [mode], MODE_PASSIVE_OK + jne @f + mov [mode], MODE_PASSIVE_WAIT + @@: + + mcall send, [socketnum2], str226, str226.length, 0 ; transfer ok + + ret + + .err: + pushd 0x0c + call [con_set_flags] + + push str_err1 + call [con_write_asciiz] + + pushd 0x07 + call [con_set_flags] + ret align 4 @@ -129,13 +252,47 @@ cmdPASS: align 4 cmdPASV: - mov [mode], MODE_PASSIVE - -; TODO: open the UDP socket and return our IP + port - ; 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2) ; where a1.a2.a3.a4 is the IP address and p1*256+p2 is the port number. + mcall socket, AF_INET4, SOCK_STREAM, 0 + cmp eax, -1 +; je .err + mov [passivesocknum], eax + + mov [datasock.port], 2000 + mov [datasock.ip], 0 + + mcall bind, [passivesocknum], datasock, datasock.length + cmp eax, -1 + je bind_err + + mcall listen, [passivesocknum], 1 + + mov [mode], MODE_PASSIVE_WAIT + + mov edi, buffer + mov eax, '227 ' ; FIXME (now hardcoded to 127.0.0.1:2000) + stosd + mov eax, '(127' + stosd + mov eax, ',0,0' + stosd + mov eax, ',1,7' + stosd + mov eax, ',208' + stosd + mov al, ')' + stosb + mov ax, 0x0d0a + stosw + xor al, al + stosb + + lea esi, [edi - buffer] + + mcall send, [socketnum2], buffer, ,0 + ret align 4 @@ -161,6 +318,10 @@ cmdPWD: mcall send, [socketnum2], buffer, , 0 +; push work_dir +; push str_pwd +; call [con_printf] + ret align 4 @@ -198,15 +359,11 @@ cmdPORT: mov [datasock.port], dx - mcall socket, AF_INET4, SOCK_DGRAM, 0 + mcall socket, AF_INET4, SOCK_STREAM, 0 cmp eax, -1 je .err mov [datasocketnum], eax - mcall connect, [datasocketnum], datasock, datasock.length - cmp eax, -1 - je .err - mcall send, [socketnum2], str225, str225.length, 0 ret @@ -226,6 +383,23 @@ cmdQUIT: align 4 cmdRETR: +; mcall connect, [datasocketnum], datasock, datasock.length +; cmp eax, -1 +; je .err + +; push O_READ +; push home_dir +; call [file.open] +; test eax, eax +; jz .cannot_open +; +; push BUFFERSIZE +; push buffer +; push eax +; call [file.read] +; cmp eax, -1 +; jz .cannot_open + ret align 4 @@ -360,11 +534,20 @@ ascii_to_byte: .done: ret +align 4 +dword_to_ascii: ; edi = ptr where to write, ebx is number + + mov eax, '1' + stosb + + ret + str150 db '150 Here it comes...', 13, 10 +.length = $ - str150 str200 db '200 Command OK.', 13, 10 .length = $ - str200 str215 db '215 UNIX type: L8', 13, 10 @@ -376,6 +559,7 @@ str221 db '221 Bye!', 13, 10 str225 db '225 Data connection open', 13, 10 .length = $ - str225 str226 db '226 Transfer OK, Closing connection', 13, 10 +.length = $ - str226 str230 db '230 You are now logged in.', 13, 10 .length = $ - str230 str250 db '250 command successful', 13, 10 diff --git a/kernel/branches/net/applications/ftpd/ftpd.asm b/kernel/branches/net/applications/ftpd/ftpd.asm index ef0e330780..c01eeaeec0 100644 --- a/kernel/branches/net/applications/ftpd/ftpd.asm +++ b/kernel/branches/net/applications/ftpd/ftpd.asm @@ -28,7 +28,8 @@ TYPE_LOCAL = 10000000b ; bits per byte must be specified MODE_NOTREADY = 0 MODE_ACTIVE = 1 -MODE_PASSIVE = 2 +MODE_PASSIVE_WAIT = 2 +MODE_PASSIVE_OK = 3 use32 db 'MENUET01' ; signature @@ -44,6 +45,8 @@ include '../macros.inc' purge mov,add,sub include '../proc32.inc' include '../dll.inc' +include '../struct.inc' +include '../libio.inc' include '../network.inc' include 'commands.inc' @@ -131,14 +134,27 @@ start: .loop: mcall 10 + cmp [mode], MODE_PASSIVE_WAIT + jne @f + mcall accept, [passivesocknum], datasock, datasock.length + cmp eax, -1 + je @f + mov [datasocketnum], eax + mov [mode], MODE_PASSIVE_OK + + push str_datasock + call [con_write_asciiz] + @@: + mcall recv, [socketnum2], buffer, buffer.length cmp eax, -1 je .loop + or eax, eax + jz .loop push eax mov byte[buffer+eax], 0 - pushd 0x0a call [con_set_flags] @@ -211,8 +227,20 @@ str6 db 'Could not open socket',10,10,0 str7 db 'Got data!',10,10,0 str8 db 'Error accepting connection',10,10,0 -str_logged_in db 'Login ok',10,10,0 -str_pass_ok db 'Password ok - Logged in',10,10,0 +str_logged_in db 'Login ok',10,10,0 +str_pass_ok db 'Password ok - Logged in',10,10,0 +str_pwd db 'Current directory is "%s"\n',0 +str_err1 db 'ERROR: cannot connect to remote socket',10,10,0 +str_err2 db 'ERROR: cannot open directory',10,10,0 +str_datasock db 'Passive data socket connected!',10,10,0 + + +str_mask db '*', 0 + + +months: + dd 'Jan ','Feb ','Mar ','Apr ','May ','Jun ' + dd 'Jul ','Aug ','Sep ','Oct ','Nov ','Dec ' filename db '.ini', 0 str_port db 'port', 0 @@ -255,7 +283,10 @@ import libio, \ file.size , 'file_size' , \ file.open , 'file_open' , \ file.read , 'file_read' , \ - file.close , 'file_close' + file.close , 'file_close' , \ + file.find.first , 'file_find_first', \ + file.find.next , 'file_find_next', \ + file.find.close , 'file_find_close' i_end: @@ -266,11 +297,12 @@ socketnum dd ? ; thread specific data socketnum2 dd ? state dd ? -home_dir rb 1024 +home_dir db '/rd/1/',0 work_dir rb 1024 type db ? mode db ? ; active/passive +passivesocknum dd ? datasocketnum dd ? datasock: