diff --git a/programs/network/ftps/trunk/FTPS.ASM b/programs/network/ftps/trunk/FTPS.ASM new file mode 100644 index 0000000000..a36b45d6ca --- /dev/null +++ b/programs/network/ftps/trunk/FTPS.ASM @@ -0,0 +1,1624 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +; FTPS +; FTP Server +; +; Compile with FASM for Menuet +; + +; note: telnet == 23, ftp cmd == 21, data on 20 + +use32 + + org 0x0 + + db 'MENUET01' ; 8 byte id + dd 1 ; header version + dd START ; program start + dd I_END ; program image size + dd 0x170000 ; required amount of memory + dd 0x7FFF0 ; esp = 0x7FFF0 + dd 0, 0 ; no params, no path + +include 'macros.inc' +; Various states of client connection +USER_NONE equ 0 ; Awaiting a connection +USER_CONNECTED equ 1 ; User just connected, prompt given +USER_USERNAME equ 2 ; User given username +USER_LOGGED_IN equ 3 ; User given password + + + + + +START: ; start of execution + ; Clear the screen memory + mov eax, ' ' + mov edi,text + mov ecx,80*30 /4 + cld + rep stosd + + call draw_window + + ; init the receive buffer pointer + mov [buffptr], buff + + ; Init FTP server state machine + mov [state], USER_NONE + + ; Open the listening socket + call connect + +still: + ; check connection status + mov eax,53 + mov ebx,6 ; Get socket status + mov ecx,[CmdSocket] + int 0x40 + + mov ebx, [CmdSocketStatus] + mov [CmdSocketStatus], eax + + cmp eax, ebx + je waitev + + ; If the socket closed by remote host, open it again. + cmp eax, 7 + je con + + ; If socket closed by Reset, open it again + cmp eax, 11 + je con + + ; If a user has just connected, start by outputting welcome msg + cmp eax, 4 + jne noc + + mov esi, loginStr0 + mov edx, loginStr0_end - loginStr0 + call outputStr + + mov [state], USER_CONNECTED + jmp noc + + +con: + ; Need to call disconnect, since a remote close does not fully + ; close the socket + call disconnect + call connect + jmp noc + +noc: + ; Display the changed connected status + call draw_window + +waitev: + mov eax,23 ; wait here for event + mov ebx,1 ; Delay for up to 1s + int 0x40 + + cmp eax,1 ; redraw request ? + je red + cmp eax,2 ; key in buffer ? + je key + cmp eax,3 ; button in buffer ? + je button + + ; any data from the socket? + + mov eax, 53 + mov ebx, 2 ; Get # of bytes in input queue + mov ecx, [CmdSocket] + int 0x40 + test eax, eax + jz still + +read_input: + mov eax, 53 + mov ebx, 3 ; Get a byte from socket in bl + mov ecx, [CmdSocket] + int 0x40 + + call ftpRxCmdData ; process incoming ftp command + + ; Keep processing data until there is no more to process + mov eax, 53 + mov ebx, 2 ; Get # of bytes in input queue + mov ecx, [CmdSocket] + int 0x40 + cmp eax, 0 + jne read_input + + ; Now redraw the text text field. + ; Probably not required, since ftp requires no + ; console i/o. + ; Leave in for now, for debugging. +; (fall through to "red:") +; call draw_text +; jmp still + +red: ; REDRAW WINDOW + call draw_window + jmp still + +key: ; KEY + mov eax,2 ; get but ignore + int 0x40 + jmp still + +button: + mov eax,17 + int 0x40 + cmp ah,1 + jne still + + ; Exit button pressed, so close socket and quit + mov eax,53 + mov ebx,8 + mov ecx,[CmdSocket] + int 0x40 + + ; ... terminate program + mov eax,-1 + int 0x40 + jmp still + + + +; ********************************************* +; ******* WINDOW DEFINITIONS AND DRAW ******** +; ********************************************* +draw_window: + pusha + + mov eax,12 + mov ebx,1 + int 0x40 + + xor eax,eax ; DRAW WINDOW + mov ebx,100*65536+491 + 8 +15 + mov ecx,100*65536+270 + 20 ; 20 for status bar + mov edx,0x13000000 + mov edi,labelt + int 0x40 + + ; draw status bar + mov eax, 13 + mov ebx, 4*65536+484 + 8 +15 + mov ecx, 270*65536 + 3 + mov edx, 0x00557799 + int 0x40 + + + mov esi,contlen-contt ; display connected status + mov edx, contt + cmp [CmdSocketStatus], 4 ; 4 is connected + je pcon + mov esi,discontlen-discontt + mov edx, discontt +pcon: + + mov eax,4 ; status text + mov ebx,380*65536+276 + mov ecx,0x00ffffff + int 0x40 + + ; Draw the text on the screen, clearing it first + ; This can go when we loose debuggin info. + xor eax,eax + mov edi,text+80*30 + mov ecx,80*30 /4 + cld + rep stosd + + call draw_text + + mov eax,12 + mov ebx,2 + int 0x40 + + popa + + ret + + +;*************************************************************************** +; Function +; draw_text +; +; Description +; Updates the text on the screen. This is part of the debugging code +; +; Inputs +; Character to add in bl +; +;*************************************************************************** +draw_text: + + pusha + + mov esi,text + mov eax,0 + mov ebx,0 + newletter: + mov cl,[esi] + cmp cl,[esi+30*80] + jz noletter + yesletter: + mov [esi+30*80],cl + + ; erase character + + pusha + mov edx, 0 ; bg colour + mov ecx, ebx + add ecx, 26 + shl ecx, 16 + mov cx, 9 + mov ebx, eax + add ebx, 6 + shl ebx, 16 + mov bx, 6 + mov eax, 13 + int 0x40 + popa + + ; draw character + + pusha + mov ecx, 0x00ffffff + push bx + mov ebx,eax + add ebx,6 + shl ebx,16 + pop bx + add bx,26 + mov eax,4 + mov edx,esi + mov esi,1 + int 0x40 + popa + + noletter: + + add esi,1 + add eax,6 + cmp eax,80*6 + jb newletter + mov eax,0 + add ebx,10 + cmp ebx,24*10 + jb newletter + + popa + ret + + + +;*************************************************************************** +; Function +; ftpRxCmdData +; +; Description +; Prcoesses incoming command data, calling a handler for each command. +; Commands are built up in buff before being processed. +; +; Inputs +; Character to add in bl +; +;*************************************************************************** +ftpRxCmdData: + ; Quit if we are not connected + ;( This case shouldn't be necessary, but be safe ) + mov al, [state] + cmp al, USER_NONE + je frcd_exit + + ; Store the incoming character + mov esi, [buffptr] + mov [esi], bl + inc esi + mov [buffptr], esi + + ; For debugging, show the data coming in + pusha + call printChar + popa + + ; Do we have an end of line? (LF) + ; if not, just exit + cmp bl, 0x0a + jne frcd_exit + + ; OK we have a complete command. + ; Process, and send response + + ; There are a number of states involved in ftp, + ; to do with logging in. + + mov al, [state] + cmp al, USER_CONNECTED + jne fs001 + + ; This should be the username + + ; TODO validate username + + ; OK, username accepted - ask for password + mov esi, loginStr1 + mov edx, loginStr1_end - loginStr1 + call outputStr + + mov [state], USER_USERNAME + + ; init the receive buffer pointer + mov [buffptr], buff + + jmp frcd_exit + +fs001: + cmp al, USER_USERNAME + jne fs002 + + ; This should be the password + + ; TODO validate password + + ; OK, password accepted - show they are logged in + mov esi, loginStr2 + mov edx, loginStr2_end - loginStr2 + call outputStr + + mov [state], USER_LOGGED_IN + + ; init the receive buffer pointer + mov [buffptr], buff + + jmp frcd_exit + +fs002: + cmp al, USER_LOGGED_IN + jne fs003 + + ; This should be a cmd + call findCmd + mov eax, [cmdPtr] + cmp eax, 0 + + je fs002b + + call [cmdPtr] + +fs002a: + ; init the receive buffer pointer + mov [buffptr], buff + + jmp frcd_exit + +fs002b: + ; an unsupported command was entered. + ; Tell user that the command is not supported + + mov esi, unsupStr + mov edx, unsupStr_end - unsupStr + call outputStr + + jmp fs002a + +fs003: +frcd_exit: + ret + + + +;*************************************************************************** +; Function +; outputStr +; +; Description +; Sends a string over the 'Command' socket +; +; Inputs +; String in esi +; Length in edx +; +;*************************************************************************** +outputStr: + push esi + push edx + mov eax,53 + mov ebx,7 + mov ecx,[CmdSocket] + int 0x40 + pop edx + pop esi + + cmp eax, 0 + je os_exit + + ; The TCP/IP transmit queue is full; Wait a bit, then retry + pusha + mov eax,5 + mov ebx,1 ; Delay for up 100ms + int 0x40 + popa + jmp outputStr +os_exit: + ret + + + +;*************************************************************************** +; Function +; outputDataStr +; +; Description +; Sends a string over the 'Data' socket +; +; Inputs +; String in esi +; Length in edx +; +;*************************************************************************** +outputDataStr: + push esi + push edx + mov eax,53 + mov ebx,7 + mov ecx,[DataSocket] + int 0x40 + pop edx + pop esi + + cmp eax, 0 + je ods_exit + + ; The TCP/IP transmit queue is full; Wait a bit, then retry + pusha + mov eax,5 + mov ebx,20 ; Delay for upto 200ms + int 0x40 + popa + jmp outputDataStr +ods_exit: + ret + + + +;*************************************************************************** +; Function +; printChar +; +; Description +; Writes a character to the screen; Used to display the data coming +; in from the user. Really only useful for debugging. +; +; Inputs +; Character in bl +; +;*************************************************************************** +printChar: + cmp bl,13 ; BEGINNING OF LINE + jne nobol + mov ecx,[pos] + add ecx,1 +boll1: + sub ecx,1 + mov eax,ecx + xor edx,edx + mov ebx,80 + div ebx + cmp edx,0 + jne boll1 + mov [pos],ecx + jmp newdata +nobol: + + cmp bl,10 ; LINE DOWN + jne nolf +addx1: + add [pos],dword 1 + mov eax,[pos] + xor edx,edx + mov ecx,80 + div ecx + cmp edx,0 + jnz addx1 + mov eax,[pos] + jmp cm1 +nolf: + + cmp bl,8 ; BACKSPACE + jne nobasp + mov eax,[pos] + dec eax + mov [pos],eax + mov [eax+text],byte 32 + mov [eax+text+60*80],byte 0 + jmp newdata +nobasp: + + cmp bl,15 ; CHARACTER + jbe newdata +putcha: + mov eax,[pos] + mov [eax+text],bl + mov eax,[pos] + add eax,1 +cm1: + mov ebx,[scroll+4] + imul ebx,80 + cmp eax,ebx + jb noeaxz + mov esi,text+80 + mov edi,text + mov ecx,ebx + cld + rep movsb + mov eax,ebx + sub eax,80 +noeaxz: + mov [pos],eax +newdata: + ret + + +;*************************************************************************** +; Function +; disconnect +; +; Description +; Closes the command socket +; +; Inputs +; None +; +;*************************************************************************** +disconnect: + mov eax, 53 ; Stack Interface + mov ebx,8 ; Close TCP socket + mov ecx,[CmdSocket] + int 0x40 + ret + + + +;*************************************************************************** +; Function +; disconnectData +; +; Description +; Closes the data socket +; +; Inputs +; None +; +;*************************************************************************** +disconnectData: + ; This delay would be better done by allowing the socket code + ; to wait for all data to pass through the stack before closing + pusha + mov eax,5 + mov ebx,200 ; Delay for 2s + int 0x40 + popa + + mov eax, 53 ; Stack Interface + mov ebx,8 ; Close TCP socket + mov ecx,[DataSocket] + int 0x40 + ret + + + + +;*************************************************************************** +; Function +; connect +; +; Description +; Opens the command socket +; +; Inputs +; None +; +;*************************************************************************** +connect: + pusha + + mov eax, 53 ; Stack Interface + mov ebx, 5 ; Open TCP socket + mov esi, 0 ; No remote IP address + mov edx, 0 ; No remote port + mov ecx, 21 ; ftp command port id + mov edi, 0 ; passive open + int 0x40 + mov [CmdSocket], eax + + popa + + ret + + + +;*************************************************************************** +; Function +; connectData +; +; Description +; Opens the data socket +; +; Inputs +; None +; +;*************************************************************************** +connectData: + pusha + + mov eax, 53 ; Stack Interface + mov ebx, 5 ; Open TCP socket + mov esi, [DataIP] ; remote IP address + mov edx, [DataPort] ; remote port + mov ecx, 20 ; ftp data port id + mov edi, 1 ; active open + int 0x40 + mov [DataSocket], eax + + popa + + ret + + + + +;*************************************************************************** +; Function +; findCmd +; +; Description +; Scans the command string for a valid command. The command string +; is in the global variable buff. +; +; Returns result in cmdPtr. This will be zero if none found +; +; Inputs +; None +; +;*************************************************************************** +findCmd: + ; Setup to return 'none' in cmdPtr, if we find no cmd + mov eax, 0 + mov [cmdPtr], eax + cld + mov esi, buff + mov edi, CMDList + +fc000: + cmp [edi], byte 0 ; Are we at the end of the CMDList? + je fc_exit + +fc000a: + cmpsb + + je fc_nextbyte + + ; Command is different - move to the next entry in cmd table + mov esi, buff + +fc001: + ; skip to the next command in the list + cmp [edi], byte 0 + je fc002 + inc edi + jmp fc001 +fc002: + add edi, 5 + jmp fc000 + +fc_nextbyte: + ; Have we reached the end of the CMD text? + cmp [edi], byte 0 + je fc_got ; Yes - so we have a match + jmp fc000a ; No - loop back + +fc_got: + ; Copy the function pointer for the selected command + inc edi + mov eax, [edi] + mov [cmdPtr], eax + +fc_exit: + ret + + + +;*************************************************************************** +; Function +; decStr2Byte +; +; Description +; Converts the decimal string pointed to by esi to a byte +; +; Inputs +; string ptr in esi +; +; Outputs +; esi points to next character not in string +; eax holds result ( 0..255) +; +;*************************************************************************** +decStr2Byte: + xor eax, eax + xor ebx, ebx + mov ecx, 3 + +dsb001: + mov bl, [esi] + + cmp bl, '0' + jb dsb_exit + cmp bl, '9' + ja dsb_exit + + imul eax, 10 + add eax, ebx + sub eax, '0' + inc esi + loop dsb001 + +dsb_exit: + ret + + + +;*************************************************************************** +; Function +; parsePortStr +; +; Description +; Converts the parameters of the PORT command, and stores them in the +; appropriate variables. +; +; Inputs +; None ( string in global variable buff ) +; +; Outputs +; None +; +;*************************************************************************** +parsePortStr: + ; skip past the PORT text to get the the parameters. The command format + ; is + ; PORT i,i,i,i,p,p,0x0d,0x0a + ; where i and p are decimal byte values, high byte first. + xor eax, eax + mov [DataIP], eax + mov [DataPort], eax + mov esi, buff + 4 ; Start at first space character + +pps001: + cmp [esi], byte ' ' ; Look for first non space character + jne pps002 + inc esi + jmp pps001 + +pps002: + call decStr2Byte + add [DataIP], eax + ror dword [DataIP], 8 + inc esi + call decStr2Byte + add [DataIP], eax + ror dword [DataIP], 8 + inc esi + call decStr2Byte + add [DataIP], eax + ror dword [DataIP], 8 + inc esi + call decStr2Byte + add [DataIP], eax + ror dword [DataIP], 8 + inc esi + call decStr2Byte + add [DataPort], eax + shl [DataPort], 8 + inc esi + call decStr2Byte + add [DataPort], eax + + ret + + + +;*************************************************************************** +; Function +; sendDir +; +; Description +; Transmits the directory listing over the data connection. +; The data connection is already open. +; +; Inputs +; None +; +; Outputs +; None +; +;*************************************************************************** +sendDir: + mov ebx, dirinfoblock + and dword [ebx+4], 0 ; start from zero block +sd001: +; Read the next DirBlocksPerCall (=16) blocks + mov eax, 70 + int 0x40 +; Did we read anything? + test eax, eax + jz @f + cmp eax, 6 + jnz sd_exit +@@: + test ebx, ebx + jz sd_exit +; Parse these blocks. There could be up to 16 files specified + mov esi, text + 0x1300 + 0x20 +sd002: + dec ebx + js sd004 + push ebx +; OK, lets parse the entry. Ignore volume entries + test byte [esi], 8 + jnz sd003 +; Valid file or directory. Start to compose the string we will send + mov edi, dirStr +; If we have been called as a result of an NLST command, we only display +; the filename + cmp [buff], byte 'N' + jz sd006 + + mov [edi], byte '-' + test byte [esi], 10h + jz @f + mov [edi], byte 'd' +@@: +; Ok, now copy across the directory listing text that will be constant +; ( I dont bother looking at the read only or archive bits ) + + mov ebx, tmplStr +@@: + inc edi + mov al, [ebx] + test al, al + jz @f + mov [edi], al + inc ebx + jmp @b +@@: +; point to the last character of the string; +; We will write the file size here, backwards + push edi ; Remember where the string ends + + dec edi +; eax holds the number + mov eax, [esi+32] + mov ebx, 10 +@@: + xor edx, edx + div ebx + add dl, '0' + mov [edi], dl + dec edi + test eax, eax + jnz @b + + pop edi +; now create the time & date fields +;timeStr: db ' Jan 1 2000 ',0 + mov al, ' ' + stosb + movzx eax, byte [esi+28+1] + mov eax, dword [months + (eax-1)*4] + stosd + mov al, byte [esi+28] + aam + test ah, ah + jz sd005a + xchg al, ah + add ax, '00' + jmp sd005b +sd005a: + add al, '0' + mov ah, ' ' +sd005b: + stosw + mov al, ' ' + mov ecx, 6 + rep stosb + push edi + movzx eax, word [esi+28+2] +@@: + xor edx, edx + div ebx + add dl, '0' + mov [edi], dl + dec edi + test eax, eax + jnz @b + pop edi + inc edi + mov al, ' ' + stosb +sd006: +; ** End of copying + +; now copy the filename across + lea ebx, [esi+40] +@@: + mov al, [ebx] + inc ebx + test al, al + jz @f + stosb + jmp @b +@@: +terminate: +; Now terminate the line by putting CRLF sequence in + mov al, 0x0D + stosb + mov al, 0x0A + stosb +; Send the completed line to the user over data socket + push esi + mov esi, dirStr + mov edx, edi + sub edx, esi + call outputDataStr + pop esi + +sd003: ; Move to next entry in the block + pop ebx + add esi, 304 + jmp sd002 +sd004: + mov ebx, dirinfoblock + add dword [ebx+4], DirBlocksPerCall + jmp sd001 + +sd_exit: + ret + + + + + +;*************************************************************************** +; Function +; setupFilePath +; +; Description +; Copies the file name from the input request string into the +; file descriptor +; +; Inputs +; None +; +; Outputs +; None +; +;*************************************************************************** +setupFilePath: + mov esi, buff + 4 ; Point to (1 before) first character of file + + ; Skip any trailing spaces or / character +sfp001: + inc esi + cmp [esi], byte ' ' + je sfp001 + cmp [esi], byte '/' + je sfp001 + + ; esi points to start of filename. + + + ; Copy across the directory path '/' + ; into the fileinfoblock + mov edi, filename + mov dword [edi], '/RD/' + mov word [edi+4], '1/' + add edi, 6 + + ; Copy across the filename +sfp002: + cld + movsb + cmp [esi], byte 0x0d + jne sfp002 + mov [edi], byte 0 + ret + + + + +;*************************************************************************** +; Function +; sendFile +; +; Description +; Transmits the requested file over the open data socket +; The file to send is named in the buff string +; +; Inputs +; None +; +; Outputs +; None +; +;*************************************************************************** +sendFile: + call setupFilePath + + ; init fileblock descriptor, for file read + mov ebx, fileinfoblock + and dword [ebx], 0 ; read cmd + and dword [ebx+4], 0 ; first block + +sf002a: + ; now read the file.. + mov eax,70 + int 0x40 + test eax, eax + jz @f + cmp eax, 6 + jnz sf_exit +@@: + push eax + mov esi, text + 0x1300 + mov edx, ebx + call outputDataStr + pop eax + test eax, eax + jnz sf_exit +; wait a bit + mov eax, 5 + mov ebx, 10 + int 0x40 + mov ebx, fileinfoblock + add dword [ebx+4], edx + jmp sf002a + +sf_exit: + ret + + +;*************************************************************************** +; Function +; getFile +; +; Description +; Receives the specified file over the open data socket +; The file to receive is named in the buff string +; +; Inputs +; None +; +; Outputs +; None +; +;*************************************************************************** +getFile: + call setupFilePath + + ; init fileblock descriptor, for file write + xor eax, eax + mov [fsize], eax ; Start filelength at 0 + mov [fileinfoblock+4], eax ; set to 0 + inc eax + inc eax + mov [fileinfoblock], eax ; write cmd + + ; Read data from the socket until the socket closes + ; loop + ; loop + ; read byte from socket + ; write byte to file buffer + ; until no more bytes in socket + ; sleep 100ms + ; until socket no longer connected + ; write file to ram + +gf000: + mov eax, 53 + mov ebx, 2 ; Get # of bytes in input queue + mov ecx, [DataSocket] + int 0x40 + test eax, eax + je gf_sleep + + mov eax, 53 + mov ebx, 3 ; Get a byte from socket in bl + mov ecx, [DataSocket] + int 0x40 ; returned data in bl + + mov esi, text + 0x1300 + add esi, dword [fsize] + mov [esi], bl + inc dword [fsize] + + ; dummy, write to screen + ;call printChar + + jmp gf000 + +gf_sleep: + ; Check to see if socket closed... + mov eax,53 + mov ebx,6 ; Get socket status + mov ecx,[DataSocket] + int 0x40 + + cmp eax, 7 + jne gf001 ; still open, so just sleep a bit + + ; Finished, so write the file + mov eax, [fsize] + mov [fileinfoblock+12], eax + mov eax,70 + mov ebx,fileinfoblock + int 0x40 + + ret ; Finished + +gf001: + ; wait a bit + mov eax,5 + mov ebx,10 ; Delay for up 100ms + int 0x40 + jmp gf000 ; try for more data + + + + + +;*************************************************************************** +; COMMAND HANDLERS FOLLOW +; +; These handlers implement the functionality of each supported FTP Command +; +;*************************************************************************** + +cmdPWD: + ; OK, show the directory name text + mov esi, ramdir + mov edx, ramdir_end - ramdir + call outputStr + + ; TODO give real directory + + ret + + +cmdCWD: + ; Only / is valid for the ramdisk + cmp [buff+5], byte 0x0d + jne ccwd_000 + + ; OK, show the directory name text + mov esi, chdir + mov edx, chdir_end - chdir + jmp ccwd_001 + +ccwd_000: + ; Tell user there is no such directory + mov esi, noFileStr + mov edx, noFileStr_end - noFileStr + +ccwd_001: + call outputStr + + ret + + +cmdQUIT: + ; The remote end will do the close; We just + ; say goodbye. + mov esi, byeStr + mov edx, byeStr_end - byeStr + call outputStr + ret + + +cmdABOR: + + ; Close port + call disconnectData + + mov esi, abortStr + mov edx, abortStr_end - abortStr + call outputStr + + ret + +cmdPORT: + ; TODO + ; Copy the IP and port values to DataIP and DataPort + + call parsePortStr + + ; Indicate the command was accepted + mov esi, cmdOKStr + mov edx, cmdOKStr_end - cmdOKStr + call outputStr + ret + +cmdnoop: + ; Indicate the command was accepted + mov esi, cmdOKStr + mov edx, cmdOKStr_end - cmdOKStr + call outputStr + ret + + +cmdTYPE: + ; TODO + ; Note the type field selected - reject if needed. + + ; Indicate the command was accepted + mov esi, cmdOKStr + mov edx, cmdOKStr_end - cmdOKStr + call outputStr + ret + +cmdsyst: + ; Indicate the system type + mov esi, systStr + mov edx, systStr_end - systStr + call outputStr + ret + + +cmdDELE: + call setupFilePath + + mov ebx, fileinfoblock + mov dword [ebx], 8 + and dword [ebx+4], 0 + push dword [ebx+12] + push dword [ebx+16] + and dword [ebx+12], 0 + and dword [ebx+16], 0 + mov eax, 70 + int 0x40 + pop dword [ebx+16] + pop dword [ebx+12] + + test eax, eax + jne cmdDele_err + + mov esi, delokStr + mov edx, delokStr_end - delokStr + call outputStr + + jmp cmdDele_exit + +cmdDele_err: + mov esi, noFileStr + mov edx, noFileStr_end - noFileStr + call outputStr + + +cmdDele_exit: + ret + + +cmdNLST: +cmdLIST: + ; Indicate the command was accepted + mov esi, startStr + mov edx, startStr_end - startStr + call outputStr + + call connectData + + ; Wait for socket to establish + +cl001: + ; wait a bit + mov eax,5 + mov ebx,10 ; Delay for up 100ms + int 0x40 + + ; check connection status + mov eax,53 + mov ebx,6 ; Get socket status + mov ecx,[DataSocket] + int 0x40 + + cmp eax, 4 + jne cl001 + + ; send directory listing + call sendDir + + ; Close port + call disconnectData + + mov esi, endStr + mov edx, endStr_end - endStr + call outputStr + ret + +cmdRETR: + ; Indicate the command was accepted + mov esi, startStr + mov edx, startStr_end - startStr + call outputStr + + call connectData + + ; Wait for socket to establish + +cr001: + ; wait a bit + mov eax,5 + mov ebx,10 ; Delay for up 100ms + int 0x40 + + ; check connection status + mov eax,53 + mov ebx,6 ; Get socket status + mov ecx,[DataSocket] + int 0x40 + + cmp eax, 4 + jne cr001 + + ; send data to remote user + call sendFile + + ; Close port + call disconnectData + + mov esi, endStr + mov edx, endStr_end - endStr + call outputStr + + + ret + + +cmdSTOR: + ; Indicate the command was accepted + mov esi, storStr + mov edx, storStr_end - storStr + call outputStr + + call connectData + + ; Wait for socket to establish + +cs001: + ; wait a bit + mov eax,5 + mov ebx,10 ; Delay for up 100ms + int 0x40 + + ; check connection status + mov eax,53 + mov ebx,6 ; Get socket status + mov ecx,[DataSocket] + int 0x40 + + cmp eax, 4 + je @f + cmp eax, 7 + jne cs001 +@@: + + ; get data file from remote user + call getFile + + mov esi, endStr + mov edx, endStr_end - endStr + call outputStr + + ; Close port + call disconnectData + + ret + + + +; DATA AREA + +; This is the list of supported commands, and the function to call +; The list end with a NULL. +CMDList: + db 'pwd',0 + dd cmdPWD + + db 'PWD',0 + dd cmdPWD + + db 'XPWD',0 + dd cmdPWD + + db 'xpwd',0 + dd cmdPWD + + db 'QUIT',0 + dd cmdQUIT + + db 'quit',0 + dd cmdQUIT + + db 'PORT',0 + dd cmdPORT + + db 'port',0 + dd cmdPORT + + db 'LIST',0 + dd cmdLIST + + db 'list',0 + dd cmdLIST + + db 'NLST',0 + dd cmdNLST + + db 'nlst',0 + dd cmdNLST + + db 'TYPE',0 + dd cmdTYPE + + db 'type',0 + dd cmdTYPE + + db 'syst',0 + dd cmdsyst + + db 'noop',0 + dd cmdnoop + + db 'CWD',0 + dd cmdCWD + + db 'cwd',0 + dd cmdCWD + + db 'RETR',0 + dd cmdRETR + + db 'retr',0 + dd cmdRETR + + db 'DELE',0 + dd cmdDELE + + db 'dele',0 + dd cmdDELE + + db 'stor',0 + dd cmdSTOR + + db 'STOR',0 + dd cmdSTOR + + db 'ABOR',0 + dd cmdABOR + + db 'abor',0 + dd cmdABOR + + db 0xff,0xf4,0xff,0xf2,'ABOR',0 + dd cmdABOR + + db 0 + + +cmdPtr dd 0 +CmdSocket dd 0x0 +CmdSocketStatus dd 0x0 +DataSocket dd 0x0 +DataSocketStatus dd 0x0 +DataPort dd 0x00 +DataIP dd 0x00 +pos dd 80 * 1 +scroll dd 1 + dd 24 + +labelt db 'FTP Server v0.1',0 +contt db 'Connected' +contlen: +discontt db 'Disconnected' +discontlen: + +cmdOKStr: db '200 Command OK',0x0d,0x0a +cmdOKStr_end: + +loginStr0: db '220- Menuet FTP Server v0.1',0x0d,0x0a + db '220 Username and Password required',0x0d,0x0a +loginStr0_end: + +loginStr1: db '331 Password now required',0x0d,0x0a +loginStr1_end: + +loginStr2: db '230 You are now logged in.',0x0d,0x0a +loginStr2_end: + +byeStr: db '221 Bye bye!',0x0d,0x0a +byeStr_end: + +systStr: db '215 UNIX system type',0x0d,0x0a +systStr_end: + +ramdir: db '257 "/"',0x0d,0x0a +ramdir_end: + +chdir: db '200 directory changed to /',0x0d,0x0a +chdir_end: + +unsupStr: db '500 Unsupported command',0x0d,0x0a +unsupStr_end: + +noFileStr: db '550 No such file',0x0d,0x0a +noFileStr_end: + +delokStr: db '250 DELE command successful',0x0d,0x0a +delokStr_end: + +startStr: db '150 Here it comes...',0x0d,0x0a +startStr_end: + +storStr: db '150 Connecting for STOR',0x0d,0x0a +storStr_end: + +endStr: db '226 Transfer OK, Closing connection',0x0d,0x0a +endStr_end: + +abortStr: db '225 Abort successful',0x0d,0x0a +abortStr_end: + + ; This is the buffer used for building up a directory listing line +dirStr: times 128 db 0 + +; This is template string used in building up a directory listing line +tmplStr: db 'rw-rw-rw- 1 0 0 ',0 + +months: + dd 'Jan ','Feb ','Mar ','Apr ','May ','Jun ' + dd 'Jul ','Aug ','Sep ','Oct ','Nov ','Dec ' + +fileinfoblock: + dd 0x00 + dd 0x00 + dd 0x00 + dd 0x200 ; bytes to read + dd text + 0x1300 ; data area +filename: times 256 db 0 + +; The following lines define data for reading a directory block +DirBlocksPerCall = 16 +dirinfoblock: + dd 1 + dd 0x00 + dd 0x00 + dd DirBlocksPerCall + dd text + 0x1300 ; data area +; The 'filename' for a directory listing +dirpath db '/RD/1',0 + +fsize: dd 0 + +state db 0 +buffptr dd 0 +buff: times 256 db 0 ; Could put this after iend + +; Ram use at the end of the application: +; text : 2400 bytes for screen memory +; text + 0x1300 : file data area +text: +I_END: diff --git a/programs/network/ftps/trunk/build.bat b/programs/network/ftps/trunk/build.bat new file mode 100644 index 0000000000..cc358c8c66 --- /dev/null +++ b/programs/network/ftps/trunk/build.bat @@ -0,0 +1,2 @@ +@fasm ftps.asm ftps +@pause diff --git a/programs/network/ftps/trunk/macros.inc b/programs/network/ftps/trunk/macros.inc new file mode 100644 index 0000000000..14185dbfce --- /dev/null +++ b/programs/network/ftps/trunk/macros.inc @@ -0,0 +1,269 @@ +; new application structure +macro meos_app_start + { + use32 + org 0x0 + + db 'MENUET01' + dd 0x01 + dd __start + dd __end + dd __memory + dd __stack + + if used __params & ~defined __params + dd __params + else + dd 0x0 + end if + + dd 0x0 + } +MEOS_APP_START fix meos_app_start + +macro code + { + __start: + } +CODE fix code + +macro data + { + __data: + } +DATA fix data + +macro udata + { + if used __params & ~defined __params + __params: + db 0 + __end: + rb 255 + else + __end: + end if + __udata: + } +UDATA fix udata + +macro meos_app_end + { + align 32 + rb 2048 + __stack: + __memory: + } +MEOS_APP_END fix meos_app_end + + +; macro for defining multiline text data +struc mstr [sstring] + { + forward + local ssize + virtual at 0 + db sstring + ssize = $ + end virtual + dd ssize + db sstring + common + dd -1 + } + + +; strings +macro sz name,[data] { ; from MFAR [mike.dld] + common + if used name + label name + end if + forward + if used name + db data + end if + common + if used name + .size = $-name + end if +} + +macro lsz name,[lng,data] { ; from MFAR [mike.dld] + common + if used name + label name + end if + forward + if (used name)&(lang eq lng) + db data + end if + common + if used name + .size = $-name + end if +} + + + +; easy system call macro +macro mpack dest, hsrc, lsrc +{ + if (hsrc eqtype 0) & (lsrc eqtype 0) + mov dest, (hsrc) shl 16 + lsrc + else + if (hsrc eqtype 0) & (~lsrc eqtype 0) + mov dest, (hsrc) shl 16 + add dest, lsrc + else + mov dest, hsrc + shl dest, 16 + add dest, lsrc + end if + end if +} + +macro __mov reg,a,b { ; mike.dld + if (~a eq)&(~b eq) + mpack reg,a,b + else if (~a eq)&(b eq) + mov reg,a + end if +} + +macro mcall a,b,c,d,e,f { ; mike.dld + __mov eax,a + __mov ebx,b + __mov ecx,c + __mov edx,d + __mov esi,e + __mov edi,f + int 0x40 +} + + + +; optimize the code for size +__regs fix + +macro add arg1,arg2 + { + if (arg2 eqtype 0) + if (arg2) = 1 + inc arg1 + else + add arg1,arg2 + end if + else + add arg1,arg2 + end if + } + +macro sub arg1,arg2 + { + if (arg2 eqtype 0) + if (arg2) = 1 + dec arg1 + else + sub arg1,arg2 + end if + else + sub arg1,arg2 + end if + } + +macro mov arg1,arg2 + { + if (arg1 in __regs) & ((arg2 eqtype 0) | (arg2 eqtype '0')) + if (arg2) = 0 + xor arg1,arg1 + else if (arg2) = 1 + xor arg1,arg1 + inc arg1 + else if (arg2) = -1 + or arg1,-1 + else if (arg2) > -128 & (arg2) < 128 + push arg2 + pop arg1 + else + mov arg1,arg2 + end if + else + mov arg1,arg2 + end if + } + + +macro struct name + { + virtual at 0 + name name + sizeof.#name = $ - name + end virtual + } + +; structures used in MeOS +struc process_information + { + .cpu_usage dd ? ; +0 + .window_stack_position dw ? ; +4 + .window_stack_value dw ? ; +6 + .not_used1 dw ? ; +8 + .process_name rb 12 ; +10 + .memory_start dd ? ; +22 + .used_memory dd ? ; +26 + .PID dd ? ; +30 + .x_start dd ? ; +34 + .y_start dd ? ; +38 + .x_size dd ? ; +42 + .y_size dd ? ; +46 + .slot_state dw ? ; +50 + dw ? ; +52 - reserved + .client_left dd ? ; +54 + .client_top dd ? ; +58 + .client_width dd ? ; +62 + .client_height dd ? ; +66 + .wnd_state db ? ; +70 + rb (1024-71) + } +struct process_information + +struc system_colors + { + .frame dd ? + .grab dd ? + .grab_button dd ? + .grab_button_text dd ? + .grab_text dd ? + .work dd ? + .work_button dd ? + .work_button_text dd ? + .work_text dd ? + .work_graph dd ? + } +struct system_colors + + +; constants + +; events +EV_IDLE = 0 +EV_TIMER = 0 +EV_REDRAW = 1 +EV_KEY = 2 +EV_BUTTON = 3 +EV_EXIT = 4 +EV_BACKGROUND = 5 +EV_MOUSE = 6 +EV_IPC = 7 +EV_STACK = 8 + +; event mask bits for function 40 +EVM_REDRAW = 1b +EVM_KEY = 10b +EVM_BUTTON = 100b +EVM_EXIT = 1000b +EVM_BACKGROUND = 10000b +EVM_MOUSE = 100000b +EVM_IPC = 1000000b +EVM_STACK = 10000000b \ No newline at end of file