FTPDaemonCore.cpp
资源名称:warftpd.zip [点击查看]
上传用户:surprise9
上传日期:2007-01-04
资源大小:426k
文件大小:56k
源码类别:
Ftp客户端
开发平台:
Visual C++
- // This is part of the WAR SOFTWARE SERIES initiated by Jarle Aase
- // Copyright 1996 by Jarle Aase. All rights reserved.
- // See the "War Software Series Licende Agreement" for details concerning
- // use and distribution.
- // ---
- // This source code, executables and programs containing source code or
- // binaries or proprietetary technology from the War Software Series are
- // NOT alloed used, viewed or tested by any governmental agencies in
- // any countries. This includes the government, departments, police,
- // military etc.
- // ---
- // This file is intended for use with Tab space = 2
- // Created and maintained in MSVC Developer Studio
- // ---
- // NAME : FTPDaemonCore.cpp
- // PURPOSE : Basic FTP Daemon classes
- // PROGRAM :
- // DATE : Sept. 27 1996
- // AUTHOR : Jarle Aase
- // ---
- // REVISION HISTORY
- //
- #include "stdafx.h"
- #define FTP_NAMES
- #include "ftp.h"
- #include "FTPDaemonCore.h"
- #include "Unix.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- ////////////////////////////////////////////////////////////////////
- // FTPD Command parser
- enum // Token ID's
- {
- TOK_USER = TOK_START_TAB, TOK_PASS, TOK_ACCT, TOK_REIN, TOK_XCUP,
- TOK_PORT, TOK_PASV, TOK_TYPE, TOK_STRU, TOK_MODE, TOK_RETR, TOK_STOR,
- TOK_APPE, TOK_MLFL, TOK_MAIL, TOK_MSND, TOK_MSOM, TOK_MSAM, TOK_MRSQ,
- TOK_MRCP, TOK_ALLO, TOK_REST, TOK_RNFR, TOK_RNTO, TOK_ABOR, TOK_DELE,
- TOK_CWD, TOK_LIST, TOK_NLST, TOK_SITE, TOK_STAT, TOK_XCWD, TOK_XMKD,
- TOK_HELP, TOK_NOOP, TOK_MKD, TOK_RMD, TOK_PWD, TOK_CDUP, TOK_STOU,
- TOK_SMNT, TOK_SYST, TOK_SIZE, TOK_MDTM, TOK_XRMD, TOK_XPWD, TOK_QUIT,
- // SITE
- TOK_CHMOD, TOK_CHOWN, TOK_CHGRP, TOK_CHCMT, TOK_FSYSSTAT,
- };
- // Command tokens
- static STokenTab BaseTokens[] =
- {
- {TOK_QUIT, "QUIT" },
- {TOK_USER, "USER" },
- {TOK_PASS, "PASS" },
- {TOK_ACCT, "ACCT" },
- {TOK_REIN, "REIN" },
- {TOK_QUIT, "QUIT" },
- {TOK_PORT, "PORT" },
- {TOK_PASV, "PASV" },
- {TOK_TYPE, "TYPE" },
- {TOK_STRU, "STRU" },
- {TOK_MODE, "MODE" },
- {TOK_RETR, "RETR" },
- {TOK_STOR, "STOR" },
- {TOK_APPE, "APPE" },
- {TOK_MLFL, "MLFL" },
- {TOK_MAIL, "MAIL" },
- {TOK_MSND, "MSND" },
- {TOK_MSOM, "MSOM" },
- {TOK_MSAM, "MSAM" },
- {TOK_MRSQ, "MRSQ" },
- {TOK_MRCP, "MRCP" },
- {TOK_ALLO, "ALLO" },
- {TOK_REST, "REST" },
- {TOK_RNFR, "RNFR" },
- {TOK_RNTO, "RNTO" },
- {TOK_ABOR, "ABOR" },
- {TOK_DELE, "DELE" },
- {TOK_CWD, "CWD" },
- {TOK_XCWD, "XCWD" },
- {TOK_LIST, "LIST" },
- {TOK_NLST, "NLST" },
- {TOK_SITE, "SITE" },
- {TOK_STAT, "STAT" },
- {TOK_HELP, "HELP" },
- {TOK_NOOP, "NOOP" },
- {TOK_MKD, "MKD" },
- {TOK_RMD, "RMD" },
- {TOK_PWD, "PWD" },
- {TOK_XMKD, "XMKD" },
- {TOK_XRMD, "XRMD" },
- {TOK_XPWD, "XPWD" },
- {TOK_CDUP, "CDUP" },
- {TOK_XCUP, "XCUP" },
- {TOK_STOU, "STOU" },
- {TOK_SMNT, "SMNT" },
- {TOK_SYST, "SYST" },
- {TOK_SIZE, "SIZE" },
- {TOK_MDTM, "MDTM" },
- // SITE
- {TOK_CHMOD,"CHMOD"},
- {TOK_CHOWN,"CHOWN"},
- {TOK_CHGRP,"CHGRP"},
- {TOK_CHCMT,"CHCMT"},
- {TOK_FSYSSTAT,"FSYSSTAT"},
- {TOK_INVALID, "" }
- };
- enum // Commands recognized on this level
- {
- CMD_USER = CMD_START_TREE, CMD_PASS, CMD_ACCT, CMD_REIN, CMD_QUIT,
- CMD_PORT, CMD_PASV, CMD_TYPE, CMD_STRU, CMD_MODE, CMD_RETR, CMD_STOR,
- CMD_APPE, CMD_MLFL, CMD_MAIL, CMD_MSND, CMD_MSOM, CMD_MSAM, CMD_MRSQ,
- CMD_MRCP, CMD_ALLO, CMD_REST, CMD_RNFR, CMD_RNTO, CMD_ABOR, CMD_DELE,
- CMD_CWD, CMD_LIST, CMD_NLST, CMD_SITE, CMD_STAT,
- CMD_HELP, CMD_NOOP, CMD_MKD, CMD_RMD, CMD_PWD, CMD_CDUP, CMD_STOU,
- CMD_SMNT, CMD_SYST, CMD_SIZE, CMD_MDTM,
- // SITE
- CMD_CHMOD, CMD_CHGRP, CMD_CHOWN, CMD_CHCMT, CMD_FSYSSTAT,
- };
- static SCommandTree SiteCmds[] =
- {
- {TOK_CHMOD, CMD_CHMOD, PROCESS, CMDF_PARAMETER, NULL, ' ', LEX_WANT_CMD, "SITE CHMOD <sp> mode <sp> file ..." },
- {TOK_CHOWN, CMD_CHOWN, PROCESS, CMDF_PARAMETER, NULL, ' ', LEX_WANT_CMD, "SITE CHOWN <sp> user <sp> file..." },
- {TOK_CHGRP, CMD_CHGRP, PROCESS, CMDF_PARAMETER, NULL, ' ', LEX_WANT_CMD, "SITE CHGRP <sp> class <sp> file..." },
- {TOK_CHCMT, CMD_CHCMT, PROCESS, CMDF_PARAMETER, NULL, ' ', LEX_WANT_CMD, "SITE CHCMT <sp> "comment" <sp> file..."},
- {TOK_FSYSSTAT, CMD_FSYSSTAT, PROCESS, CMDF_NOPARAM, NULL, ' ', LEX_WANT_CMD, "SITE FSYSSTAT"},
- {TOK_INVALID, CMD_INVALID, 0, 0, NULL, 0, 0, NULL}
- };
- // Command tree
- static SCommandTree BaseCmds[] =
- {
- {TOK_USER, CMD_USER, PRELOGIN, CMDF_PARAMETER, NULL, ' ', LEX_WANT_CMD, "USER <sp> username"},
- {TOK_PASS, CMD_PASS, GOTNAME, CMDF_PARAMETER, NULL, ' ', LEX_WANT_CMD, "PASS <sp> password" },
- {TOK_QUIT, CMD_QUIT, PRELOGIN, 0, NULL, ' ', LEX_WANT_CMD, "QUIT (end session)" },
- {TOK_ACCT, CMD_ACCT, PROCESS, CMDF_NOT_IMPLEMENTED, NULL, ' ', LEX_WANT_CMD, "ACCT (specify account)" },
- {TOK_REIN, CMD_REIN, PROCESS, CMDF_NOT_IMPLEMENTED, NULL, ' ', LEX_WANT_CMD, "REIN (reinitialize server state)" },
- {TOK_PORT, CMD_PORT, PRELOGIN, CMDF_PARAMETER, NULL, ' ', LEX_WANT_CMD, "PORT <sp> b0, b1, b2, b3, b4" },
- {TOK_PASV, CMD_PASV, PRELOGIN, CMDF_NOPARAM, NULL, ' ', LEX_WANT_CMD, "PASV (set server in passive mode)" },
- {TOK_TYPE, CMD_TYPE, PRELOGIN, CMDF_PARAMETER, NULL, ' ', LEX_WANT_CMD, "TYPE <sp> [ A | E | I | L ]" },
- {TOK_STRU, CMD_STRU, PROCESS, CMDF_PARAMETER, NULL, ' ', LEX_WANT_CMD, "STRU (specify file structure)" },
- {TOK_MODE, CMD_MODE, PRELOGIN, CMDF_PARAMETER, NULL, ' ', LEX_WANT_CMD, "MODE (specify transfer mode)" },
- {TOK_RETR, CMD_RETR, PROCESS, CMDF_PARAMETER|CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "RETR <sp> file-name" },
- {TOK_STOR, CMD_STOR, PROCESS, CMDF_PARAMETER|CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "STOR <sp> file-name" },
- {TOK_APPE, CMD_APPE, PROCESS, CMDF_PARAMETER|CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "APPE <sp> file-name" },
- {TOK_MLFL, CMD_MLFL, PROCESS, CMDF_NOT_IMPLEMENTED, NULL, ' ', LEX_WANT_CMD, "MLFL (mail file)" },
- {TOK_MAIL, CMD_MAIL, PROCESS, CMDF_NOT_IMPLEMENTED, NULL, ' ', LEX_WANT_CMD, "MAIL (mail to user)" },
- {TOK_MSND, CMD_MSND, PROCESS, CMDF_NOT_IMPLEMENTED, NULL, ' ', LEX_WANT_CMD, "MSND (mail send to terminal)" },
- {TOK_MSOM, CMD_MSOM, PROCESS, CMDF_NOT_IMPLEMENTED, NULL, ' ', LEX_WANT_CMD, "MSOM (mail send to terminal or mailbox)" },
- {TOK_MSAM, CMD_MSAM, PROCESS, CMDF_NOT_IMPLEMENTED, NULL, ' ', LEX_WANT_CMD, "MSAM (mail send to terminal and mailbox)" },
- {TOK_MRSQ, CMD_MRSQ, PROCESS, CMDF_NOT_IMPLEMENTED, NULL, ' ', LEX_WANT_CMD, "MRSQ (mail recipient scheme question)" },
- {TOK_MRCP, CMD_MRCP, PROCESS, CMDF_NOT_IMPLEMENTED, NULL, ' ', LEX_WANT_CMD, "MRCP (mail recipient)" },
- {TOK_ALLO, CMD_ALLO, PROCESS, CMDF_PARAMETER, NULL, ' ', LEX_WANT_CMD, "ALLO <sp> bytes" },
- {TOK_REST, CMD_REST, PRELOGIN, CMDF_PARAMETER, NULL, ' ', LEX_WANT_CMD, "REST <sp> byte offset" },
- {TOK_RNFR, CMD_RNFR, PROCESS, CMDF_PARAMETER|CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "RNFR <sp> file-name" },
- {TOK_RNTO, CMD_RNTO, PROCESS, CMDF_PARAMETER|CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "RNTO <sp> file-name" },
- {TOK_ABOR, CMD_ABOR, PROCESS, 0, NULL, ' ', LEX_WANT_CMD, "(abort operation)" },
- {TOK_DELE, CMD_DELE, PROCESS, CMDF_PARAMETER|CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "DELE <sp> file-name" },
- {TOK_CWD, CMD_CWD, PROCESS, CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "CWD [ <sp> directory-name ]" },
- {TOK_XCWD, CMD_CWD, PROCESS, CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "XCWD [ <sp> directory-name ]" },
- {TOK_LIST, CMD_LIST, PROCESS, CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "LIST [ <sp> path-name ]" },
- {TOK_NLST, CMD_NLST, PROCESS, CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "NLST [ <sp> path-name ]" },
- {TOK_SITE, CMD_SITE, PRELOGIN, CMDF_PARAMETER, SiteCmds, ' ', LEX_WANT_CMD, "SITE site-cmd [ <sp> arguments ]" },
- {TOK_STAT, CMD_STAT, PROCESS, 0, NULL, ' ', LEX_WANT_CMD, "STAT [ <sp> path-name ]" },
- {TOK_HELP, CMD_HELP, PRELOGIN, 0, NULL, ' ', LEX_WANT_CMD, "HELP [ <sp> <string> ]" },
- {TOK_NOOP, CMD_NOOP, PRELOGIN, CMDF_NOPARAM, NULL, ' ', LEX_WANT_CMD, "NOOP (no operation)" },
- {TOK_MKD, CMD_MKD, PROCESS, CMDF_PARAMETER|CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "MKD <sp> path-name" },
- {TOK_XMKD, CMD_MKD, PROCESS, CMDF_PARAMETER|CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "XMKD <sp> path-name" },
- {TOK_RMD, CMD_RMD, PROCESS, CMDF_PARAMETER|CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "RMD <sp> path-name" },
- {TOK_XRMD, CMD_RMD, PROCESS, CMDF_PARAMETER|CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "XRMD <sp> path-name" },
- {TOK_PWD, CMD_PWD, PROCESS, CMDF_NOPARAM, NULL, ' ', LEX_WANT_CMD, "PWD (return current directory)" },
- {TOK_XPWD, CMD_PWD, PROCESS, CMDF_NOPARAM, NULL, ' ', LEX_WANT_CMD, "XPWD (return current directory)" },
- {TOK_CDUP, CMD_CDUP, PROCESS, 0, NULL, ' ', LEX_WANT_CMD, "CDUP (change to parent directory)" },
- {TOK_XCUP, CMD_CDUP, PROCESS, 0, NULL, ' ', LEX_WANT_CMD, "CDUP (change to parent directory)" },
- {TOK_STOU, CMD_STOU, PROCESS, CMDF_PARAMETER, NULL, ' ', LEX_WANT_CMD, "STOU <sp> file-name" },
- {TOK_SMNT, CMD_SMNT, PROCESS, CMDF_NOT_IMPLEMENTED, NULL, ' ', LEX_WANT_CMD, "SMNT (structure mount)" },
- {TOK_SYST, CMD_SYST, PRELOGIN, CMDF_NOPARAM, NULL, ' ', LEX_WANT_CMD, "SYST (get type of operating system)" },
- {TOK_SIZE, CMD_SIZE, PROCESS, CMDF_PARAMETER|CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "SIZE <sp> path-name" },
- {TOK_MDTM, CMD_MDTM, PROCESS, CMDF_PARAMETER|CMDF_PARSE_CMD_LINE, NULL, ' ', LEX_WANT_CMD, "MDTM <sp> path-name" },
- {TOK_INVALID, CMD_INVALID, 0, 0, NULL, 0, 0, NULL}
- };
- CFTPDParser::CFTPDParser()
- {
- m_Commands = (SCommandTree *) BaseCmds;
- m_Tokens = (STokenTab *) BaseTokens;
- }
- // The FTP protocol command interface is fairly simple.
- // We don't call the regular CCmdParser::ParseCmd() but do the parsing
- // ourself.
- int CFTPDParser::ParseCmd(LPCSTR CmdLine, CCmdArgs& Args, int Level, BOOL& DoParseCmdLine)
- {
- int TokenID;
- LPCSTR LexCmdLine = CmdLine;
- SCommandTreeDef *CmdPtr = m_Commands;
- again:
- TokenID = yyLex(&LexCmdLine, m_Tokens, ' ', LEX_WANT_CMD, Args);
- if (TokenID < TOK_START_TAB)
- return CMD_PARSE_ERROR; // Error
- // Find the command ID
- while(CmdPtr && (CmdPtr->TokenID != TokenID) && (CmdPtr->TokenID != TOK_INVALID))
- ++CmdPtr;
- if (!CmdPtr)
- return CMD_UNKNOWN_COMMAND;
- if (CmdPtr->NextLevel)
- {
- ASSERT(CmdPtr->CommandID == CMD_SITE);
- CmdPtr = CmdPtr->NextLevel;
- goto again;
- }
- // Try to get parameter
- TokenID = yyLex(&LexCmdLine, m_Tokens, 0, LEX_WANT_STRING, Args);
- // Check for login level and availibility
- if (CmdPtr->AccessLevel > Level)
- return CMD_BAD_LEVEL;
- // Check for required parameter
- if ((CmdPtr->Flags & CMDF_PARAMETER)
- && (TokenID == TOK_END_OF_TOKENS))
- return CMD_MISSING_PARAMETER;
- // Check for no parameter
- if ((CmdPtr->Flags & CMDF_NOPARAM)
- && (TokenID != TOK_END_OF_TOKENS))
- return CMD_UNKNOWN_PARAMETER;
- // Is the command implemented?
- if (CmdPtr->Flags & CMDF_NOT_IMPLEMENTED)
- return CMD_NOT_IMPLEMENTED;
- DoParseCmdLine = (CmdPtr->Flags & CMDF_PARSE_CMD_LINE) != 0;
- return CmdPtr->CommandID;
- }
- ////////////////////////////////////////////////////////////////////
- // CFTPDaemonCore
- CFtpDaemonCore *CFtpDaemonCore::m_pCFtpDaemonCore = NULL;
- CFtpDaemonCore::CFtpDaemonCore()
- {
- m_pCFtpDaemonCore = this;
- }
- CFtpDaemonCore::~CFtpDaemonCore()
- {
- m_Options.SaveAll();
- CUserFsys::CloseFileSystem();
- m_pCFtpDaemonCore = NULL;
- }
- // Initialize and go online
- BOOL CFtpDaemonCore::Create(LPCSTR IniFile, CLog *Log)
- {
- m_Log = Log;
- m_Options.Create(NULL,IniFile,"FTPD", COPTION_FTPD_CORE);
- m_Options.LoadAll();
- // Start the file system
- if (!CUserFsys::FsysIsStarted())
- {
- if (!CUserFsys::StartFileSystem(NULL))
- return FALSE;
- }
- CDaemonBase::GetSvr()->RefreshStats();
- if (!m_Listen.Initialize(m_Options.m_Port, "FTP", m_Options.m_IPname))
- {
- return FALSE;
- }
- return TRUE;
- }
- void CFtpDaemonCore::LogMsg(int flag, LPCSTR Format, ...)
- {
- CString cBuf;
- if (!ShouldLog(m_Log, flag))
- return;
- ASSERT(AfxIsValidString(Format, FALSE));
- ASSERT(m_Log != NULL);
- ASSERT(AfxIsValidAddress(m_Log,sizeof(CLog)));
- cBuf.Format("FTPD: %s", Format);
- va_list argList;
- va_start(argList, Format);
- m_Log->LogMsgV(flag, cBuf, argList);
- va_end(argList);
- }
- /////////////////////////////////////////////////////////////////////////////////
- // FTP server listen socket
- void CFTPDCoreListenSock::OnAccept( int nErrorCode )
- {
- try
- {
- _OnAccept(nErrorCode);
- }
- catch(CSocketException *pExc)
- {
- LogMsg(LOGF_DEBUG,"CFTPDCoreListenSock::OnAccept(%d) - Caught exception '%s' from module %s",
- nErrorCode, pExc->m_ErrorText, pExc->m_ErrorText);
- if (!OnHandleWinsockErr(pExc->m_ErrorNum))
- delete this;
- delete pExc;
- }
- catch(...)
- {
- LogMsg(LOGF_ERROR,"CFTPDCoreListenSock::OnAccept(%d) - Caught unknown exception", nErrorCode);
- }
- }
- void CFTPDCoreListenSock::_OnAccept( int nErrorCode )
- {
- int err;
- CSock::OnAccept(nErrorCode);
- if (nErrorCode)
- return;
- CFTPDCoreCtrlSock *NewSocket = new CFTPDCoreCtrlSock;
- // EXT module
- if (err = PrcExt(CAPIHandler::OnPreFTPDAccept,0,(WPARAM)&NewSocket,(LPARAM)this))
- {
- if (err == CFuncList::AbortError)
- delete NewSocket;
- return;
- }
- try
- {
- if (!DoAccept(NewSocket))
- {
- delete NewSocket;
- return;
- }
- }
- catch(CSocketException *pExc)
- {
- if (pExc->m_pSock == NewSocket)
- {
- LogMsg(LOGF_DEBUG,"CFTPDCoreListenSock::_OnAccept(%d) - Caught exception '%s' from module %s. Connecting socket is being killed.",
- nErrorCode, pExc->m_ErrorText, pExc->m_ErrorText);
- delete NewSocket;
- delete pExc;
- return;
- }
- // Can't handle this here...
- throw pExc;
- }
- catch(...)
- {
- LogMsg(LOGF_ERROR,"CFTPDCoreListenSock::_OnAccept(%d) - Caught unknown exception", nErrorCode);
- return;
- }
- // EXT module
- if (err = PrcExt(CAPIHandler::OnPostFTPDAccept,0,(WPARAM)&NewSocket,(LPARAM)this))
- {
- if (err == CFuncList::AbortError)
- delete NewSocket;
- return;
- }
- // Intitialize connection
- NewSocket->EnableMacros();
- NewSocket->SendCtrlMsg(220,"[$systemname] ([$programname] [$programversion]) ready [%c][+sysmsg0.txt]");
- }
- BOOL CFTPDCoreListenSock::Initialize(int PortNumber, LPCSTR ServiceName, LPCSTR ListenIP)
- {
- if (!PortNumber)
- PortNumber = 21; // FTP
- if (!ServiceName)
- ServiceName = "FTP";
- m_Type = LT_FTP;
- BOOL IsOnline = CDaemonServiceSocket::Initialize(PortNumber,ServiceName, ListenIP);
- CDaemonStatusSvr::SetOnline(IsOnline);
- return IsOnline;
- }
- /////////////////////////////////////////////////////////////////////////////////
- // FTP server Control Socket
- // This is the FTP server module
- IMPLEMENT_DYNAMIC(CFTPDCoreCtrlSock, CTextSock);
- CFTPDCoreCtrlSock::CFTPDCoreCtrlSock()
- {
- SOCKADDR_IN *s_in = (SOCKADDR_IN *)&m_Sockaddr;
- m_ArgSave.Empty();
- m_Fsys = NULL;
- m_DataSock = NULL;
- // Set RFC 959 default values.
- m_FTPmode = MODE_S;
- m_FTPtype = TYPE_A;
- m_FTPstru = STRU_F;
- m_FTPform = FORM_N;
- memset(&m_Sockaddr, 0, sizeof(struct sockaddr));
- // Increase login counter
- CDaemonStatusSvr::IncUserCnt(TRUE);
- PrcExt(CAPIHandler::OnFTPDCoreCtrlSock,0,0,(LPARAM)this);
- }
- CFTPDCoreCtrlSock::~CFTPDCoreCtrlSock()
- {
- LogMsg(LOGF_DEBUG,"~CFTPDCoreCtrlSock() - %s.", m_DataSock ? "deleting data socket" : "no datasocket");
- if (m_DataSock)
- delete m_DataSock;
- //Log out from file system
- if (m_Fsys)
- m_Fsys->Logout();
- // Decrease login counter
- CDaemonStatusSvr::IncUserCnt(FALSE);
- }
- void CFTPDCoreCtrlSock::IncXferCnt(BOOL Add)
- {
- CDaemonStatusSvr::IncXferCnt(Add);
- }
- void CFTPDCoreCtrlSock::OnClose( int nErrorCode )
- {
- m_SuspendOnClose = TRUE; // Turn it on - just in case...
- try
- {
- CTextSock::OnClose(nErrorCode);
- CSocketException::Throw(this, "CFTPDCoreCtrlSock::OnClose()", nErrorCode, NULL);
- }
- catch(CSocketException *pExc)
- {
- LogMsg(LOGF_DEBUG,"CFTPDCoreCtrlSock::OnClose(%d) - Caught exception '%s' from module %s",
- nErrorCode, pExc->m_ErrorText, pExc->m_ErrorText);
- if (!OnHandleWinsockErr(pExc->m_ErrorNum))
- delete this;
- delete pExc;
- }
- catch(...)
- {
- LogMsg(LOGF_ERROR,"CFTPDCoreListenSock::OnClose(%d) - Caught unknown exception", nErrorCode);
- return;
- }
- }
- void CFTPDCoreCtrlSock::OnReceive( int nErrorCode )
- {
- try
- {
- CTextSock::OnReceive(nErrorCode);
- }
- catch(CSocketException *pExc)
- {
- LogMsg(LOGF_DEBUG,"CFTPDCoreCtrlSock::OnReceive(%d) - Caught exception '%s' from module %s",
- nErrorCode, pExc->m_ErrorText, pExc->m_ErrorText);
- if (!OnHandleWinsockErr(pExc->m_ErrorNum))
- delete this;
- delete pExc;
- }
- catch(...)
- {
- LogMsg(LOGF_ERROR,"CFTPDCoreListenSock::OnReceive(%d) - Caught unknown exception", nErrorCode);
- return;
- }
- }
- void CFTPDCoreCtrlSock::OnSend( int nErrorCode )
- {
- try
- {
- CTextSock::OnSend(nErrorCode);
- }
- catch(CSocketException *pExc)
- {
- LogMsg(LOGF_DEBUG,"CFTPDCoreCtrlSock::OnSend(%d) - Caught exception '%s' from module %s",
- nErrorCode, pExc->m_ErrorText, pExc->m_ErrorText);
- if (!OnHandleWinsockErr(pExc->m_ErrorNum))
- delete this;
- delete pExc;
- }
- catch(...)
- {
- LogMsg(LOGF_ERROR,"CFTPDCoreListenSock::OnSend(%d) - Caught unknown exception", nErrorCode);
- return;
- }
- }
- void CFTPDCoreCtrlSock::OnConnect( int nErrorCode )
- {
- try
- {
- _OnConnect(nErrorCode);
- }
- catch(CSocketException *pExc)
- {
- LogMsg(LOGF_DEBUG,"CFTPDCoreCtrlSock::OnConnect(%d) - Caught exception '%s' from module %s",
- nErrorCode, pExc->m_ErrorText, pExc->m_ErrorText);
- if (!OnHandleWinsockErr(pExc->m_ErrorNum))
- delete this;
- delete pExc;
- return;
- }
- catch(...)
- {
- LogMsg(LOGF_ERROR,"CFTPDCoreListenSock::OnConnect(%d) - Caught unknown exception", nErrorCode);
- return;
- }
- SetIdleTime(1000 * 60 * 3); // 3 minuts idle time on login
- m_Timer.Reset();
- }
- void CFTPDCoreCtrlSock::_OnConnect( int nErrorCode )
- {
- CTextSock::OnConnect(nErrorCode);
- // Initialize the sockaddr
- ASSERT(CFtpDaemonCore::m_pCFtpDaemonCore != NULL);
- SOCKADDR_IN *s_in = (SOCKADDR_IN *)&m_Sockaddr;
- int Len = sizeof(struct sockaddr);
- GetPeerName(&m_Sockaddr,&Len);
- s_in->sin_family = AF_INET;
- s_in->sin_port = htons(CFtpDaemonCore::m_pCFtpDaemonCore->m_Options.m_Port);
- }
- void CFTPDCoreCtrlSock::Virgin()
- {
- CTextSock::Virgin();
- }
- BOOL CFTPDCoreCtrlSock::ProcessTelnetNegotiation(int ch1, int ch2)
- {
- return CTextSock::ProcessTelnetNegotiation(ch1, ch2);
- }
- void CFTPDCoreCtrlSock::InsertPendingText()
- {
- CTextSock::InsertPendingText();
- }
- enum // Macro Table
- {
- MT_DIRMSG, MT_DISKFREE, MT_USERTYPE, MT_CMAX, MT_CAMAX
- };
- MACROTABLE BaseMacros[] =
- {
- {"diskfree", MT_DISKFREE,"Free disk space in the current directory."},
- {"dirmsg", MT_DIRMSG, "Directory change message"},
- {"usertype", MT_USERTYPE,"User type. Anonymous, user or administrator"},
- {"maxusers", MT_CMAX, "Max number of users online."},
- {"maxanons", MT_CAMAX, "Max number of anonymous users online."},
- {"", 0, ""}
- };
- BOOL CFTPDCoreCtrlSock::ExpandMacro(LPSTR *To, LPCSTR MacroName, int AvailBytes)
- {
- if (CTextSock::ExpandMacro(To, MacroName, AvailBytes))
- return TRUE;
- CString Macro("");
- if (*MacroName == '$')
- {
- for(MACROTABLE *pMT = BaseMacros; *pMT->Name; pMT++)
- {
- if (!stricmp(pMT->Name, MacroName + 1))
- {
- switch(pMT->Symb)
- {
- case MT_USERTYPE:
- if (m_IsLoggedInAnonymously)
- Macro = "anonymous";
- else if (CUsr::IsAdmin(m_User))
- Macro = "supervisor";
- else
- Macro = "user";
- break;
- case MT_DIRMSG:
- {
- /*
- CString Path;
- Path.Format("%s\.message.txt", m_CWD);
- CFsys::GetFsys()->DosPath(Path.GetBuffer(1));
- Path.ReleaseBuffer();
- FILE *fp = fopen(Path,"r");
- if (fp)
- {
- char buf[1024];
- while(fgets(buf, sizeof(buf), fp))
- Macro += buf;
- fclose(fp);
- }
- */
- }
- break;
- case MT_DISKFREE:
- {
- /*
- CString Path(m_CWD);
- CFsys::GetFsys()->DosPath(Path.GetBuffer(1));
- Path.ReleaseBuffer();
- __int64 MySize = GetFreeDiskSpace(Path);
- char buf[128];
- sprintf(buf, "%I64d", MySize);
- Macro = buf;
- */
- }
- break;
- case MT_CAMAX:
- Macro = COptions::GetOption(
- COPTION_FTPD_CORE,
- FTPDCORE_OPTIONS__MAX_ANON_CONNECTOIONS);
- break;
- case MT_CMAX:
- Macro = COptions::GetOption(
- COPTION_FTPD_CORE,
- FTPDCORE_OPTIONS__MAX_CONNECTIONS);
- break;
- default:
- Macro.Format("(Macro '%s' is not yet available)", MacroName);
- break;
- }
- break;
- }
- }
- }
- else
- {
- // File name
- FILE *fp;
- CString Fname;
- if (*MacroName == '+')
- {
- Fname = MacroName + 1;
- Macro = "rn";
- }
- else
- Fname = MacroName;
- CString Upath;
- /*if (strpbrk(Fname,"/\:"))
- {
- CFsys::GetFsys()->UnixPath(Upath.GetBuffer(1));
- Upath.ReleaseBuffer();
- CFsys::GetFsys()->MkPath(m_RootDir, m_CWD, Fname, Upath.GetBuffer(MAX_PATH));
- if (!CFsys::GetFsys()->CheckPermission(m_User, m_RootDir, Upath, FALSE, NODE_READ))
- {
- denied:
- LogMsg(LOGF_SECURITY,"CFTPDCoreCtrlSock::ExpandMacro(%s) - Permission denied to file!", MacroName);
- Macro.Format("(Permission denied to file '%s')", Fname);
- goto done;
- }
- CFsys::GetFsys()->DosPath(Upath.GetBuffer(1));
- }
- else*/ if (!strnicmp("sysmsg", Fname, 6))
- {
- Upath = Fname;
- }
- /*else
- goto denied;*/
- if (Upath && *Upath)
- {
- if ((fp = fopen(Upath,"r")) != NULL)
- {
- {
- char buf[512];
- while(fgets(buf, sizeof(buf), fp))
- Macro += buf;
- }
- fclose(fp);
- int OfsSave = m_InsertOffset;
- m_InsertOffset += (*To - &m_OutBuf[CBufferSock::m_BufferUsed]);
- SendCtrlMsg(m_LastRcode, Macro, TRUE, FALSE);
- *To = &m_OutBuf[CBufferSock::m_BufferUsed];
- m_InsertOffset = OfsSave;
- return TRUE;
- }
- else
- {
- LogMsg(LOGF_DEBUG,"CFTPDCoreCtrlSock::ExpandMacro(%s) - Unable to open file.", MacroName);
- return TRUE;
- }
- }
- }
- //done:
- int Len = Macro.GetLength();
- if (Len && (Len < AvailBytes))
- {
- memcpy(*To, Macro, Len);
- *To = *To + Len;
- return TRUE;
- }
- return FALSE;
- }
- // Return TRUE if the socket still exist
- BOOL CFTPDCoreCtrlSock::OnCommand(LPCSTR Text)
- {
- BOOL DoParseCmdLine = FALSE;
- if (!CTextSock::OnCommand(Text))
- return FALSE;
- m_LastCommandText = Text;
- // EXT module
- if (PrcSockExt(CSock::iOnCommand,0,(WPARAM)0,(LPARAM)&Text))
- return TRUE;
- m_Args.PrepereNew();
- m_UnixArgs.PrepereNew();
- int CmdID = m_Parser.ParseCmd(Text,m_Args, m_State, DoParseCmdLine);
- if (DoParseCmdLine)
- {
- m_Fsys->PrepereCommandLine(CmdID);
- return TRUE;
- }
- else
- return OnCommand(CmdID);
- }
- BOOL CFTPDCoreCtrlSock::OnCommand(int CmdID)
- {
- BOOL Rval = TRUE;
- switch(CmdID)
- {
- case CMD_USER:
- m_Restart = 0; m_ArgSave.Empty();
- if (m_User = CUsr::Login(LT_FTP,m_Args[1], NULL, this))
- goto logged_in;
- m_State = GOTNAME;
- m_ArgSave = m_Args[1];
- break;
- case CMD_PASS:
- m_Restart = 0;
- logged_in:
- if (m_User = CUsr::Login(LT_FTP, m_ArgSave, m_Args[1], this))
- {
- if (!OnLogin(m_Args))
- return FALSE;
- SendMsg(230,"User %s logged in. Access restrictions apply.", m_LoginName);
- m_State = PROCESS;
- }
- else
- m_State = PRELOGIN; // Try again...
- m_ArgSave.Empty();
- break;
- case CMD_ACCT:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnAcct(m_Args))
- return FALSE;
- break;
- case CMD_QUIT:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnQuit(m_Args))
- return FALSE;
- break;
- case CMD_REIN:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnRein(m_Args))
- return FALSE;
- break;
- case CMD_PORT:
- m_ArgSave.Empty();
- if (!OnPort(m_Args))
- return FALSE;
- break;
- case CMD_PASV:
- m_ArgSave.Empty();
- if (!OnPasv(m_Args))
- return FALSE;
- break;
- case CMD_TYPE:
- m_ArgSave.Empty();
- if (!OnType(m_Args))
- return FALSE;
- break;
- case CMD_STRU:
- m_ArgSave.Empty();
- if (!OnStru(m_Args))
- return FALSE;
- break;
- case CMD_MODE:
- m_ArgSave.Empty();
- if (!OnMode(m_Args))
- return FALSE;
- break;
- case CMD_RETR:
- m_ArgSave.Empty();
- if (!OnRetr(m_Args))
- return FALSE;
- m_Restart = 0;
- break;
- case CMD_STOR:
- m_ArgSave.Empty();
- if (!OnStor(m_Args))
- return FALSE;
- m_Restart = 0;
- break;
- case CMD_APPE:
- m_ArgSave.Empty();
- if (!OnAppe(m_Args))
- return FALSE;
- m_Restart = 0;
- break;
- case CMD_ALLO:
- m_ArgSave.Empty();
- if (!OnAllo(m_Args))
- return FALSE;
- break;
- case CMD_REST:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnRest(m_Args))
- return FALSE;
- break;
- case CMD_RNFR:
- m_Restart = 0;
- m_ArgSave = m_Args[1];
- if (!OnRnFr(m_Args))
- return FALSE;
- break;
- case CMD_RNTO:
- m_Restart = 0;
- if (!OnRnTo(m_Args))
- return FALSE;
- m_ArgSave.Empty();
- break;
- case CMD_ABOR:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnAbor(m_Args))
- return FALSE;
- break;
- case CMD_DELE:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnDele(m_Args))
- return FALSE;
- break;
- case CMD_CWD:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnCwd(m_Args))
- return FALSE;
- break;
- case CMD_LIST:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnList(m_Args))
- return FALSE;
- break;
- case CMD_NLST:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnNlst(m_Args))
- return FALSE;
- break;
- case CMD_SITE:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnSite(m_Args))
- return FALSE;
- break;
- case CMD_STAT:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnStat(m_Args))
- return FALSE;
- break;
- case CMD_HELP:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnHelp(m_Args))
- return FALSE;
- break;
- case CMD_NOOP:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnNoop(m_Args))
- return FALSE;
- break;
- case CMD_MKD:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnMkd(m_Args))
- return FALSE;
- break;
- case CMD_RMD:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnRmd(m_Args))
- return FALSE;
- case CMD_PWD:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnPwd(m_Args))
- return FALSE;
- break;
- case CMD_CDUP:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnCdUp(m_Args))
- return FALSE;
- break;
- case CMD_STOU:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnStou(m_Args))
- return FALSE;
- break;
- case CMD_SMNT:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnSmnt(m_Args))
- return FALSE;
- break;
- case CMD_SYST:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnSyst(m_Args))
- return FALSE;
- break;
- case CMD_SIZE:
- m_ArgSave.Empty();
- if (!OnSize(m_Args))
- return FALSE;
- break;
- case CMD_MDTM:
- m_ArgSave.Empty();
- if (!OnMdtm(m_Args))
- return FALSE;
- break;
- // SITE commands
- case CMD_CHMOD:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnSiteChmod(m_Args))
- return FALSE;
- break;
- case CMD_FSYSSTAT:
- m_Restart = 0; m_ArgSave.Empty();
- if (!OnSiteFsysstat(m_Args))
- return FALSE;
- break;
- // Command errors
- case CMD_MISSING_PARAMETER:
- SendMsg(501,"Missing parameter in command %s", m_LastCommandText);
- break;
- case CMD_UNKNOWN_COMMAND:
- SendMsg(500, "%s: unrecognized command.", m_LastCommandText);
- break;
- case CMD_NOT_IMPLEMENTED:
- SendMsg(502, "%s: command not implemented.", m_LastCommandText);
- break;
- case CMD_BAD_LEVEL:
- m_Restart = 0; m_ArgSave.Empty();
- SendMsg(530, "Please login with USER and PASS.");
- break;
- case CMD_PARSE_ERROR:
- case CMD_UNKNOWN_PARAMETER:
- SendMsg(500,"'%s': command not understood.", m_LastCommandText);
- break;
- default:
- SendMsg(502,"%s: Command not implemented.", m_Args[0]);
- break;
- }
- m_PrevCmdID = CmdID;
- return Rval;
- }
- /////////////////////////////////////////////////////////////////////////////////
- // FTP server implementation functions
- BOOL CFTPDCoreCtrlSock::OnQuit(CCmdArgs& Args)
- {
- SendCtrlMsg(221, "Goodbye.");
- LogMsg(LOGF_INOUT,"User from %s logging off.", m_PeerName);
- CSocketException::Throw(this, "CFTPDCoreCtrlSock::OnQuit()", 0, "User logged out");
- return FALSE; // Socket is deleted
- }
- BOOL CFTPDCoreCtrlSock::OnLogin(CCmdArgs& Args)
- {
- // Set idle time
- SetIdleTime(CUsr::GetRecursiveParam(m_User, "IdleTime", 3 * 60) * 1000);
- SetLogonTime(CUsr::GetRecursiveParam(m_User, "LoginTime", 0) * 60000);
- NotifyLogin(ENL_UPDATE, "");
- m_Fsys = new CFTPDFsys((LPVOID *)&m_Fsys);
- if (!m_Fsys->Create(this))
- {
- delete m_Fsys;
- m_Fsys = NULL;
- SendMsg(421, "Internal error - unable to initialize your file system. Goodbye");
- LogMsg(LOGF_ERROR,"Unable to initialize the users file system.");
- CSocketException::Throw(this, "CFTPDCoreCtrlSock::OnLogin()", 0, "Unable to initialize file system");
- }
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnAcct(CCmdArgs& Args)
- {
- SendMsg(200,"ACCT Command ok.");
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnRein(CCmdArgs& Args)
- {
- SendMsg(502,"%s: Command not implemented.", m_Args[0]);
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnPort(CCmdArgs& Args)
- {
- SOCKADDR_IN *s_in = (SOCKADDR_IN *)&m_Sockaddr;
- SOCKADDR_IN sin;
- int i1, i2, i3, i4, i5, i6;
- if (sscanf(m_Args[1],"%d,%d,%d,%d,%d,%d", &i1, &i2, &i3, &i4, &i5, &i6) != 6)
- {
- SendMsg(501,"'%s': Must be 6 digits.", Args.Arg(1));
- return TRUE;
- }
- sin.sin_addr.S_un.S_un_b.s_b1 = (unsigned char)i1;
- sin.sin_addr.S_un.S_un_b.s_b2 = (unsigned char)i2;
- sin.sin_addr.S_un.S_un_b.s_b3 = (unsigned char)i3;
- sin.sin_addr.S_un.S_un_b.s_b4 = (unsigned char)i4;
- sin.sin_port = htons((i5 << 8) | i6);
- if ((ntohs(sin.sin_port) > 1023) && (s_in->sin_addr.s_addr > 0))
- {
- SendMsg(200, "PORT command successful.");
- s_in->sin_addr.S_un.S_addr = sin.sin_addr.S_un.S_addr;
- s_in->sin_port = sin.sin_port;
- }
- else
- {
- LogMsg(LOGF_SECURITY, "CFTPDCoreCtrlSock::OnPort(%s): refused PORT %lX,%d",
- Args.Arg(1), sin.sin_addr.s_addr, ntohs(sin.sin_port));
- SendMsg(500, "Illegal PORT Command");
- }
- LogMsg(LOGF_DEBUG,"OnPort(%s): PORT %lX,%d.", Args.Arg(1), sin.sin_addr.s_addr, ntohs(sin.sin_port));
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnPasv(CCmdArgs& Args)
- {
- return m_DataSock->Create(this, &m_DataSock, m_FTPmode, m_FTPstru, m_FTPform,
- m_FTPtype, &m_Sockaddr, TRUE);
- }
- BOOL CFTPDCoreCtrlSock::OnType(CCmdArgs& Args)
- {
- // Parse the type.
- int cmd_form, cmd_type, cmd_bytesz, TokenID;
- LPCSTR LexCmdLine = Args.Arg(1);
- TokenID = m_Parser.yyLex(&LexCmdLine, m_Parser.m_Tokens, ' ', LEX_WANT_CHAR, Args);
- if (TokenID != TOK_CHAR)
- {
- unknown_type:
- SendMsg(501,"'%s %s': unknown type.", Args.Arg(0), Args.Arg(1));
- return TRUE;
- }
- ASSERT(Args.m_argc == 3);
- switch(toupper(*Args.Arg(2)))
- {
- case 'A':
- cmd_type = TYPE_A;
- cmd_form = FORM_N;
- // Check for form parameter
- check_form:
- TokenID = m_Parser.yyLex(&LexCmdLine, m_Parser.m_Tokens, ' ', LEX_WANT_CHAR, Args);
- if (TokenID == TOK_CHAR)
- {
- ASSERT(Args.m_argc == 4);
- switch(toupper(*Args.Arg(3)))
- {
- case 'N': cmd_form = FORM_N; break;
- case 'T': cmd_form = FORM_T; break;
- case 'C': cmd_form = FORM_C; break;
- default:
- SendMsg(501,"'%s %s': unknown form (%s).", Args.Arg(0), Args.Arg(1), Args.Arg(3));
- return TRUE;
- }
- }
- // Validiate...
- if (cmd_form == FORM_N)
- {
- SendMsg(200, "Type set to A.");
- m_FTPtype = cmd_type;
- m_FTPform = cmd_form;
- }
- else
- SendMsg(504, "Form must be N.");
- break;
- case 'E':
- SendMsg(504, "Type E not implemented.");
- goto check_form;
- case 'I':
- SendMsg(200, "Type set to I.");
- m_FTPtype = TYPE_I;
- break;
- case 'L':
- cmd_bytesz = 8;
- cmd_type = TYPE_L;
- // Check for bytesize parameter
- TokenID = m_Parser.yyLex(&LexCmdLine, m_Parser.m_Tokens, ' ', LEX_WANT_INT, Args);
- if (TokenID == TOK_CHAR)
- {
- ASSERT(Args.m_argc == 4);
- cmd_bytesz = atoi(Args.Arg(3));
- }
- else if (atoi(Args.Arg(2) + 1))
- {
- // This is for a bug in the BBN ftp
- cmd_bytesz = atoi(Args.Arg(2) + 1);
- }
- if (cmd_bytesz == 8)
- {
- SendMsg(200, "Type set to L (byte size 8).");
- m_FTPtype = cmd_type;
- }
- else
- SendMsg(504, "Byte size must be 8.");
- break;
- default:
- goto unknown_type;
- }
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnStru(CCmdArgs& Args)
- {
- int TokenID;
- LPCSTR LexCmdLine = Args.Arg(1);
- TokenID = m_Parser.yyLex(&LexCmdLine, m_Parser.m_Tokens, ' ', LEX_WANT_CHAR, Args);
- if (TokenID != TOK_CHAR)
- {
- SendMsg(501,"'%s %s': unknown struct.", Args.Arg(0), Args.Arg(1));
- return TRUE;
- }
- ASSERT(Args.m_argc == 3);
- switch(toupper(*Args.Arg(2)))
- {
- case 'F':
- m_FTPstru = STRU_F;
- SendMsg(200, "STRU F ok.");
- break;
- default:
- SendMsg(504, "Unimplemented STRU type.");
- return TRUE;
- }
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnMode(CCmdArgs& Args)
- {
- int TokenID;
- LPCSTR LexCmdLine = Args.Arg(1);
- TokenID = m_Parser.yyLex(&LexCmdLine, m_Parser.m_Tokens, ' ', LEX_WANT_CHAR, Args);
- if (TokenID != TOK_CHAR)
- {
- SendMsg(501,"'%s %s': unknown mode.", Args.Arg(0), Args.Arg(1));
- return TRUE;
- }
- ASSERT(Args.m_argc == 3);
- switch(toupper(*Args.Arg(2)))
- {
- case 'S':
- m_FTPmode = MODE_S;
- SendMsg(200, "MODE S ok.");
- break;
- default:
- SendMsg(504, "Unimplemented MODE type.");
- return TRUE;
- }
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnRetr(CCmdArgs& Args)
- {
- return DoRetr(Args, 0);
- }
- BOOL CFTPDCoreCtrlSock::OnStor(CCmdArgs& Args)
- {
- return DoStor(Args, 0);
- }
- BOOL CFTPDCoreCtrlSock::OnAppe(CCmdArgs& Args)
- {
- return DoStor(Args, XMITF_APPE);
- }
- BOOL CFTPDCoreCtrlSock::OnAllo(CCmdArgs& Args)
- {
- SendMsg(502,"%s: Command not implemented.", Args.Arg(0));
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnRest(CCmdArgs& Args)
- {
- m_Restart = atoi(Args.Arg(1));
- SendMsg(350, "Restarting at byte offset %u. Send STORE or RETRIEVE to initiate transfer.",
- m_Restart);
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnRnFr(CCmdArgs& Args)
- {
- if (m_UnixArgs.m_argc != 2)
- {
- LogMsg(LOGF_DEBUG,"OnRnFr() - Ambigous RNFR command: %s", Args[1]);
- SendMsg(550,"Ambigous RNFR command: %s", Args[1]);
- return TRUE;
- }
- m_ArgSave = m_UnixArgs[1];
- SendMsg(350, "RNFR Ok. Ready for destination name.");
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnRnTo(CCmdArgs& Args)
- {
- CString cFnameBuf;
- if (m_PrevCmdID != CMD_RNFR)
- {
- SendMsg(503,"Bad sequence of commands.");
- return TRUE;
- }
- if (m_UnixArgs.m_argc != 2)
- {
- LogMsg(LOGF_DEBUG,"OnRnTo() - Ambigous RNFR command: %s", m_UnixArgs[1]);
- SendMsg(550,"Ambigous RNFR command: %s", m_UnixArgs[1]);
- return TRUE;
- }
- ASSERT(AfxIsValidString(m_ArgSave));
- if (!m_Fsys->MoveFile(m_ArgSave, m_UnixArgs[1]))
- {
- LogMsg(LOGF_DEBUG,"OnRnTo() - RenamePath(%s,%s) failed before callback.", m_ArgSave, cFnameBuf);
- SendMsg(550,"Permission denied.");
- return TRUE;
- }
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnAbor(CCmdArgs& Args)
- {
- if (m_DataSock)
- {
- ASSERT(AfxIsValidAddress(m_DataSock,sizeof(CFTPDataSock)));
- m_DataSock->m_HaveToldUserThatTransfereIsComplete = TRUE;
- delete m_DataSock;
- }
- SendMsg(225, "ABOR command successful.");
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnDele(CCmdArgs& Args)
- {
- return DoDele(Args);
- }
- BOOL CFTPDCoreCtrlSock::OnCwd(CCmdArgs& Args)
- {
- // Expand the command line to allow "CD war*"
- if (m_UnixArgs.m_argc > 2)
- {
- // The pattern matching routines returned more than one path...
- SendMsg(550,"Ambigous CWD command.");
- }
- else if (!DoChdir((m_UnixArgs.m_argc == 2) ? m_UnixArgs.Arg(1) : NULL))
- {
- // Failed
- SendMsg(550,"Permission denied.");
- }
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnList(CCmdArgs& Args)
- {
- return ProcessList("-lAf", Args);
- }
- BOOL CFTPDCoreCtrlSock::OnNlst(CCmdArgs& Args)
- {
- return ProcessList("", Args);
- }
- BOOL CFTPDCoreCtrlSock::OnSite(CCmdArgs& Args)
- {
- // EXT module
- if (PrcSockExt(CSock::iOnSITECmd,0,(WPARAM)0,(LPARAM)&Args))
- return TRUE;
- SendMsg(502,"%s: Command not implemented.", Args.Arg(0));
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnStat(CCmdArgs& Args)
- {
- if (Args.m_argc == 2)
- {
- // STAT path command
- SendMsg(504,"STAT <path> command not implemented.");
- return TRUE;
- }
- else
- {
- CWarString cBuf;
- ASSERT(Args.m_argc == 1);
- // Stat command without
- SendCtrlMsg(211,"[$systemname] FTP server status:", TRUE, FALSE);
- SendMsg(0,"n Version [$programname] [$programversion]");
- if (!isdigit(m_DNSName[0]))
- cBuf.Format("%s (%s)", m_DNSName, m_PeerName);
- else
- cBuf.Format("%s", m_DNSName);
- SendMsg(0," Connected to %s", cBuf);
- if (m_State >= PROCESS)
- {
- if (m_IsLoggedInAnonymously)
- SendMsg(0, " Logged in anonymously");
- else
- SendMsg(0, " Logged in as %s", m_LoginName);
- }
- else if (m_State == GOTNAME)
- SendMsg(0, " Waiting for password");
- else if (m_State == PRELOGIN)
- SendMsg(0, " Waiting for user name");
- else
- SendMsg(0, " Unknown internal state %d", m_Type);
- cBuf.Format(" TYPE: %s", SafeStringIndex(typenames, m_FTPtype, 5));
- if ((m_FTPtype == TYPE_A) || (m_FTPtype == TYPE_E))
- cBuf.FormatCat(", FORM: %s", SafeStringIndex(formnames, m_FTPform, 4));
- if (m_FTPtype == TYPE_L)
- cBuf.FormatCat(" %d", 8);
- cBuf.FormatCat("; STRUcture: %s; transfer MODE: %s",
- SafeStringIndex(strunames, m_FTPstru, 4), SafeStringIndex(modenames,m_FTPmode, 4));
- SendMsg(0, "%s", cBuf);
- if (m_DataSock)
- SendMsg(0, " Data connection ready/open");
- else
- SendMsg(0, " No data connection");
- SendMsg(211, "End of status");
- }
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnHelp(CCmdArgs& Args)
- {
- CString cBuf = "";
- STokenTabDef *Token;
- SCommandTreeDef *Cmd;
- int Index = 0;
- if (Args.m_argc == 2)
- {
- LPCSTR CmdName = Args.Arg(1);
- // Help on a command
- for(Token = BaseTokens; Token->TokenID != TOK_INVALID; Token++)
- {
- // Lookup cmd
- if (!stricmp(CmdName,Token->Token))
- {
- for(Cmd = BaseCmds; Cmd->CommandID != CMD_INVALID; Cmd++)
- {
- if (Cmd->TokenID == Token->TokenID)
- {
- SendMsg(214,"Syntax: %s", Cmd->CommandSyntax);
- break;
- }
- }
- break;
- }
- }
- if (!Cmd || !Token)
- SendMsg(502,"Unknown command %s", CmdName);
- }
- else
- {
- // Just list all commands
- SendCtrlMsg(214, "The following commands are recognized. (* =>'s unimplemented)", TRUE);
- SendCtrlMsg(0,"n", TRUE, FALSE);
- for(Token = BaseTokens; Token->TokenID != TOK_INVALID; Token++)
- {
- // Lookup cmd
- for(Cmd = BaseCmds; Cmd->CommandID != CMD_INVALID; Cmd++)
- {
- if (Cmd->TokenID == Token->TokenID)
- {
- cBuf += " ";
- cBuf += Token->Token;
- cBuf += (Cmd->Flags & CMDF_NOT_IMPLEMENTED) ? '*' : ' ';
- if (strlen(Token->Token) == 3)
- cBuf += ' ';
- if (!(++Index % 8))
- {
- cBuf += 'n';
- SendCtrlMsg(0, cBuf, TRUE);
- cBuf = "";
- }
- break;
- }
- }
- }
- if (cBuf.GetLength())
- {
- cBuf += 'n';
- SendCtrlMsg(0, cBuf, TRUE);
- }
- SendMsg(214, "Direct comments to [$email]");
- }
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnNoop(CCmdArgs& Args)
- {
- SendMsg(200, "NOOP command successful.");
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnMkd(CCmdArgs& Args)
- {
- return DoMkDir(Args);
- }
- BOOL CFTPDCoreCtrlSock::OnRmd(CCmdArgs& Args)
- {
- return DoDele(Args);
- }
- BOOL CFTPDCoreCtrlSock::OnPwd(CCmdArgs& Args)
- {
- SendMsg(257, ""%s" is current directory.", m_Fsys->m_CWD);
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnCdUp(CCmdArgs& Args)
- {
- m_UnixArgs.AddArg("CD");
- m_UnixArgs.AddArg("..");
- OnCwd(Args);
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnStou(CCmdArgs& Args)
- {
- return DoStor(Args, XMITF_UNIQUE);
- }
- BOOL CFTPDCoreCtrlSock::OnSmnt(CCmdArgs& Args)
- {
- SendMsg(502,"%s: Command not implemented.", Args.Arg(0));
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnSyst(CCmdArgs& Args)
- {
- SendMsg(215, "UNIX Type: L8 Server: "War FTPD light 2.01a" OS: "%s"", OsName());
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnSize(CCmdArgs& Args)
- {
- CString cBuf, cFnameBuf;
- switch(m_FTPtype)
- {
- case TYPE_L:
- case TYPE_I:
- case TYPE_A:
- {
- if (m_UnixArgs.m_argc != 2)
- {
- LogMsg(LOGF_DEBUG,"OnSize() - Ambigous SIZE command: %s", Args.Arg(1));
- SendMsg(550,"Ambigous SIZE command: %s", Args.Arg(1));
- return TRUE;
- }
- if (!m_Fsys->Size(m_UnixArgs[1]))
- {
- LogMsg(LOGF_DEBUG,"OnSize() - FindFirstFile(%s) failed before callback.", m_UnixArgs[1]);
- SendMsg(451,"Server error.");
- }
- }
- break;
- default:
- SendMsg(504, "SIZE not implemented for Type %c.", "?AEIL"[max((unsigned)m_FTPtype, 5)]);
- }
- return TRUE;
- }
- /*
- * MDTM is not in RFC959, but Postel has blessed it and
- * it will be in the updated RFC.
- *
- * Return modification time of file as an ISO 3307
- * style time. E.g. YYYYMMDDHHMMSS or YYYYMMDDHHMMSS.xxx
- * where xxx is the fractional second (of any precision,
- * not necessarily 3 digits)
- */
- BOOL CFTPDCoreCtrlSock::OnMdtm(CCmdArgs& Args)
- {
- if (m_UnixArgs.m_argc != 2)
- {
- LogMsg(LOGF_DEBUG,"OnMdtm() - Ambigous SIZE command: %s", Args.Arg(1));
- SendMsg(550,"Ambigous SIZE command: %s", Args.Arg(1));
- return TRUE;
- }
- if (!m_Fsys->Mdtm(m_UnixArgs[1]))
- {
- LogMsg(LOGF_DEBUG,"Mdtm(%s) - failed before callback.", m_UnixArgs[1]);
- SendMsg(451,"Server error.");
- return TRUE;
- }
- return TRUE;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Support functions
- // Process LIST and NLST commands.
- BOOL CFTPDCoreCtrlSock::ProcessList(LPCSTR LineArguments, CCmdArgs& Args)
- {
- CString cBuf;
- static LPSTR Cmd = "/bin/ls";
- m_UnixArgs.Replace(0,Cmd);
- if (LineArguments && *LineArguments)
- m_UnixArgs.Insert(1,LineArguments);
- m_Fsys->m_FsysPath3 = LineArguments ? LineArguments : "";
- return m_Fsys->List();
- }
- BOOL CFTPDCoreCtrlSock::CallbackProcessList(int nErrorCode)
- {
- if (nErrorCode)
- {
- SendMsg(550, "Failed to execute %s, error code %d.", m_UnixArgs.Arg(0), nErrorCode);
- LogMsg(LOGF_WARNINGS,"ProcessList() - Failed to execute %s, error code %d.", m_UnixArgs.Arg(0), nErrorCode);
- return TRUE;
- }
- if (!m_DataSock->Create(this, &m_DataSock, m_FTPmode, m_FTPstru, m_FTPform, m_FTPtype, &m_Sockaddr, FALSE))
- {
- ASSERT(AfxIsValidAddress(m_DataSock, sizeof(CFTPDataSock)));
- LogMsg(LOGF_WARNINGS,"ProcessList() - Failed to create data socket.");
- return TRUE;
- }
- CString cBuf;
- cBuf.Format("%s%s%s", m_UnixArgs.Arg(0), m_Fsys->m_FsysPath3.IsEmpty() ? "" : " ", m_Fsys->m_FsysPath3);
- try
- {
- if (!m_DataSock->SendFile(m_Fsys->m_FsysPath2, cBuf, TRUE, m_Restart, 0))
- {
- // SendFile() has already told the user the reason for this and destroyed the socket...
- LogMsg(LOGF_DEBUG,"ProcessList() - SendFile() failed.");
- return TRUE;
- }
- }
- catch(CSocketException *pExc)
- {
- LogMsg(LOGF_DEBUG,"CFTPDCoreCtrlSock::CallbackProcessList(%d) - Caught exception '%s' from module %s",
- nErrorCode, pExc->m_ErrorText, pExc->m_ErrorText);
- if (pExc->m_pSock == (CSock *)m_DataSock)
- {
- delete m_DataSock;
- m_DataSock = NULL;
- delete pExc;
- return FALSE;
- }
- throw pExc; // We can't handle this...
- }
- return TRUE;
- }
- // Change directory. Does not inform user about errors.
- BOOL CFTPDCoreCtrlSock::DoChdir(LPCSTR Path)
- {
- return m_Fsys->ChDir(Path);
- }
- // Send a file to the remote host
- BOOL CFTPDCoreCtrlSock::DoRetr(CCmdArgs& Args, DWORD Flags)
- {
- CString cBuf, cFnameBuf;
- if (m_UnixArgs.m_argc > 2)
- {
- LogMsg(LOGF_DEBUG,"DoRetr() - Ambigous RETR command: %s", Args.Arg(1));
- SendMsg(550,"Ambigous RETR command: %s", Args.Arg(1));
- return TRUE;
- }
- if (!m_DataSock->Create(this, &m_DataSock, m_FTPmode, m_FTPstru, m_FTPform, m_FTPtype, &m_Sockaddr, FALSE))
- {
- ASSERT(AfxIsValidAddress(m_DataSock, sizeof(CFTPDataSock)));
- LogMsg(LOGF_WARNINGS,"DoRetr() - Failed to create data socket.");
- return TRUE;
- }
- m_DataSock->m_pFile = new CWarFile(m_Fsys);
- ASSERT((Flags & XMITF_APPE) == 0);
- if (!m_DataSock->SendFile(m_UnixArgs.Arg(1), cBuf, Flags & XMITF_TEMP, m_Restart, 0))
- {
- // SendFile() has already told the user the reason for this and destroyed the socket...
- LogMsg(LOGF_DEBUG,"DoRetr() - SendFile() failed.");
- return TRUE;
- }
- return TRUE;
- }
- // Receive a file from the remote host
- BOOL CFTPDCoreCtrlSock::DoStor(CCmdArgs& Args, DWORD Flags)
- {
- CString cBuf, cFnameBuf;
- DWORD FTPflags = 0;
- if (m_UnixArgs.m_argc > 2)
- {
- LogMsg(LOGF_DEBUG,"DoStor() - Ambigous STOR command: %s", Args.Arg(1));
- SendMsg(550,"Ambigous RETR command: %s", Args.Arg(1));
- return TRUE;
- }
- // Handle unique
- if (Flags & XMITF_UNIQUE)
- {
- FTPflags |= CWarFile::UNIQUE_NAME;
- }
- // Handle for APPEND mode
- if (Flags & XMITF_APPE)
- {
- if (m_Restart)
- {
- LogMsg(LOGF_DEBUG,"DoStor() - Can't combine APPE and REST");
- SendMsg(550,"Can't combine APPE and REST");
- return TRUE;
- }
- m_Restart = FLEN_MAX;
- }
- if (!m_DataSock->Create(
- this, &m_DataSock, m_FTPmode, m_FTPstru, m_FTPform, m_FTPtype, &m_Sockaddr, FALSE, FTPflags))
- {
- ASSERT(AfxIsValidAddress(m_DataSock, sizeof(CFTPDataSock)));
- LogMsg(LOGF_WARNINGS,"DoRetr() - Failed to create data socket.");
- return TRUE;
- }
- m_DataSock->m_pFile = new CWarFile(m_Fsys);
- if (!m_DataSock->ReceiveFile(m_UnixArgs.Arg(1), cBuf, 0, m_Restart, 0))
- {
- // ReceiveFile() has already told the user the reason for this and destroyed the socket...
- LogMsg(LOGF_DEBUG,"DoStor() - ReceiveFile() failed.");
- return TRUE;
- }
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::MkUniquePath(CString& cFnameBuf)
- {
- ASSERT(AfxIsValidString(cFnameBuf));
- CString cBuf = cFnameBuf;
- HANDLE h;
- int cnt = 0;
- while((h = CreateFile(
- cBuf,
- GENERIC_WRITE,
- 0,
- NULL,
- CREATE_NEW,
- FILE_FLAG_DELETE_ON_CLOSE,
- NULL)) == INVALID_HANDLE_VALUE)
- {
- int err;
- if ((err = GetLastError()) != ERROR_FILE_EXISTS)
- {
- LogMsg(LOGF_DEBUG,"MkUniquePath(%s) - Got unexpected error: %s.",
- cFnameBuf, GetLastErrorText(err));
- return FALSE;
- }
- if (++cnt > 20)
- {
- LogMsg(LOGF_DEBUG,"MkUniquePath(%s) - Failed. Tried %d names.",
- cFnameBuf, cnt - 1);
- return FALSE;
- }
- cBuf.Format("%s%d", cFnameBuf, cnt);
- }
- ASSERT(h != INVALID_HANDLE_VALUE);
- CloseHandle(h);
- LogMsg(LOGF_DEBUG,"MkUniquePath(%s) - Found unique filename: %s.",
- cFnameBuf, cBuf);
- cFnameBuf = cBuf;
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::DoDele(CCmdArgs& Args)
- {
- if (m_UnixArgs.m_argc != 2)
- {
- LogMsg(LOGF_DEBUG,"DoDele() - Ambigous %s command: %s", Args[0], m_UnixArgs[1]);
- SendMsg(550,"Ambigous %s command: %s", Args[0], m_UnixArgs[1]);
- return TRUE;
- }
- if (!m_Fsys->DeleteGeneric(m_UnixArgs[1]))
- {
- LogMsg(LOGF_DEBUG,"DoDele() - Failed to delete before callback: %s", Args[1]);
- SendMsg(550,"Server error. Failed to delete.");
- return TRUE;
- }
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::DoMkDir(CCmdArgs& Args)
- {
- if (!m_Fsys->CreateDirectory(Args[1]))
- {
- LogMsg(LOGF_DEBUG,"DoMkDir() - Failed to create directory before callback: %s", Args.Arg(1));
- SendMsg(550,"Server error. Failed to cerate directory.");
- }
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnSiteChmod(CCmdArgs &Args)
- {
- CCmdArgs MyArgs("chmod", Args[2], m_Parser);
- if (!m_Fsys->ChMod(MyArgs))
- {
- SendMsg(451, "chmod failed.");
- LogMsg(LOGF_WARNINGS,"chmod failed before callback");
- }
- return TRUE;
- }
- BOOL CFTPDCoreCtrlSock::OnSiteFsysstat(CCmdArgs &Args)
- {
- CCmdArgs MyArgs("chmod", Args[2], m_Parser);
- if (!m_Fsys->FsysStat())
- {
- SendMsg(451, "Site Fsysstat failed.");
- LogMsg(LOGF_WARNINGS,"OnSiteFsysstat failed before callback");
- }
- return TRUE;
- }
- //////////////////////////////////////////////////////////////////////////////////////////
- // CFTPDFsys
- CFTPDFsys::CFTPDFsys(LPVOID *pRef)
- :CUserFsys(pRef)
- {
- ;
- }
- BOOL CFTPDFsys::SetOnHold()
- {
- m_AsyncSelectMaskSaved = m_pSock->m_AsyncSelectMask;
- m_StateSaved = m_pSock->m_State;
- // Prevent socket read/write events
- m_pSock->m_AsyncSelectMask &= ~(FD_READ | FD_WRITE);
- m_pSock->AsyncSelect(m_pSock->m_AsyncSelectMask);
- // Set block state
- m_pSock->m_State = HOLD;
- return TRUE;
- }
- void CFTPDFsys::ReleaseHold()
- {
- m_pSock->m_State = m_StateSaved;
- m_pSock->m_AsyncSelectMask = m_AsyncSelectMaskSaved;
- m_pSock->AsyncSelect(m_pSock->m_AsyncSelectMask);
- }
- void CFTPDFsys::CheckForZombie()
- {
- CUserFsys::CheckForZombie();
- }
- BOOL CFTPDFsys::Create(CFTPDCoreCtrlSock *pSock)
- {
- ASSERT(m_pRef != NULL);
- m_pSock = pSock;
- m_IsAdmin = CUsr::IsAdmin(m_pSock->m_User);
- USER Class = CUsr::GetUserClass(m_pSock->m_User);
- CString Roots, Home;
- CString AssignToName;
- CString UmaskStr;
- USER AssignTo = INVALID_USER_VALUE;
- DWORD Umask = 0;
- CUsr::GetRecursiveParam(m_pSock->m_User, "root", "", Roots);
- CUsr::GetRecursiveParam(m_pSock->m_User, "home", "", Home);
- CUsr::GetRecursiveParam(m_pSock->m_User, "AssignFilesTo", "", AssignToName);
- CUsr::GetRecursiveParam(m_pSock->m_User, "Umask", "", UmaskStr);
- sscanf(UmaskStr, "%o", &Umask);
- if (!AssignToName.IsEmpty())
- AssignTo = CUsr::FindUser(UT_USER, (LPCSTR)AssignToName);
- return CUserFsys::Create(Roots, Home, m_pSock->m_User, Class, pSock->m_SocketName, Umask, AssignTo);
- }
- // Called after the file system is initialized
- // for the user
- BOOL CFTPDFsys::OnCreate(int nErrorCode)
- {
- CUserFsys::OnCreate(nErrorCode);
- if (nErrorCode)
- {
- m_pSock->SendMsg(421, "Internal error - unable to initialize your file system. Goodbye");
- m_pSock->LogMsg(LOGF_ERROR,"Unable to initialize the users file system.");
- delete m_pSock;
- return FALSE;
- }
- m_pSock->m_State = PROCESS;
- return TRUE;
- }
- /////////////////////////////////////////////////////////////////////////////////////
- // High level calls for CFTPDFsys
- BOOL CFTPDFsys::PrepereCommandLine(int CmdIDtoRemember)
- {
- m_FsysPath1.Empty();
- m_lParam = (LPARAM)CmdIDtoRemember;
- for(int Index = 0; Index < m_pSock->m_Args.m_argc; Index++)
- {
- if (!m_FsysPath1.IsEmpty())
- m_FsysPath1 += 'n';
- m_FsysPath1 += m_pSock->m_Args[Index];
- }
- return ProcessRequest(FSM_PRPCMDLINE, (WPARAM)this, 0);
- }
- BOOL CFTPDFsys::OnPrpCmdLine(int nErrorCode)
- {
- LPSTR p = m_FsysPath1.GetBuffer(1);
- for(p = strtok(p, "n"); p; p = strtok(NULL, "n"))
- {
- m_pSock->m_UnixArgs.AddArg(p);
- }
- return m_pSock->OnCommand((int)m_lParam);
- }
- BOOL CFTPDFsys::List()
- {
- m_FsysPath1.Empty();
- for(int Index = 0; Index < m_pSock->m_UnixArgs.m_argc; Index++)
- {
- if (!m_FsysPath1.IsEmpty())
- m_FsysPath1 += 'n';
- m_FsysPath1 += m_pSock->m_UnixArgs.Arg(Index);
- }
- return ProcessRequest(FSM_LIST, (WPARAM)this, 0);
- }
- BOOL CFTPDFsys::OnList(int nErrorCode)
- {
- return m_pSock->CallbackProcessList(nErrorCode);
- }
- CString CFTPDFsys::GetFullPath(LPCSTR Path, DWORD AccessFlags)
- {
- ASSERT(FALSE);
- return "/";
- }
- BOOL CFTPDFsys::RenamePath(LPCSTR OldName, LPCSTR NewName)
- {
- return TRUE;
- }
- BOOL CFTPDFsys::CheckPermission(LPCSTR Path, BOOL IsDir, int PermsWanted)
- {
- return TRUE;
- }
- BOOL CFTPDFsys::ChDir(LPCSTR Path)
- {
- m_CallbackID = CB_CHDIR;
- return CUserFsys::ChDir(Path);
- }
- BOOL CFTPDFsys::Mdtm(LPCSTR Path)
- {
- m_CallbackID = CB_MDTM;
- return CUserFsys::Stat(Path);
- }
- BOOL CFTPDFsys::Size(LPCSTR Path)
- {
- m_CallbackID = CB_SIZE;
- return CUserFsys::Stat(Path);
- }
- BOOL CFTPDFsys::OnChdir(int nErrorCode)
- {
- switch(m_CallbackID)
- {
- case CB_CHDIR:
- return CallbackChDir(nErrorCode);
- }
- return CUserFsys::OnChdir(nErrorCode);
- }
- BOOL CFTPDFsys::CallbackChDir(int nErrorCode)
- {
- if (nErrorCode)
- {
- m_pSock->SendMsg(550, "Permission denied.");
- }
- else
- {
- m_pSock->SendMsg(250, ""%s" is current directory.", m_CWD);
- }
- return nErrorCode == 0;
- }
- BOOL CFTPDFsys::OnChmod(int nErrorCode)
- {
- if (nErrorCode && m_Output.IsEmpty())
- {
- m_pSock->SendMsg(551, "chmod failed.");
- m_pSock->LogMsg(LOGF_WARNINGS,"chmod failed after callback, error %d", nErrorCode);
- }
- else
- {
- m_pSock->SuspendMacros();
- m_pSock->SendMsg(200, "chmod: %s", m_Output);
- m_pSock->EnableMacros();
- }
- return TRUE;
- }
- BOOL CFTPDFsys::OnFsysStat(int nErrorCode)
- {
- if (nErrorCode && m_Output.IsEmpty())
- {
- m_pSock->SendMsg(551, "SITE FSYSSTAT failed.");
- m_pSock->LogMsg(LOGF_WARNINGS,"OnFsysStat failed after callback, error %d", nErrorCode);
- }
- else
- {
- m_pSock->SuspendMacros();
- m_pSock->SendMsg(200, "%s", m_Output);
- m_pSock->EnableMacros();
- }
- return TRUE;
- }
- BOOL CFTPDFsys::OnCreateDirectory(int nErrorCode)
- {
- if (nErrorCode && m_Output.IsEmpty())
- {
- m_pSock->SendMsg(551, "Permission denied.");
- m_pSock->LogMsg(LOGF_WARNINGS,"OnCreateDirectory failed after callback, error %d", nErrorCode);
- }
- else
- {
- m_pSock->SendMsg(257, "Directory created");
- }
- return TRUE;
- }
- BOOL CFTPDFsys::OnDeleteDirectory(int nErrorCode)
- {
- return OnDelete(nErrorCode);
- }
- BOOL CFTPDFsys::OnDeleteFile(int nErrorCode)
- {
- return OnDelete(nErrorCode);
- }
- BOOL CFTPDFsys::OnDeleteGeneric(int nErrorCode)
- {
- return OnDelete(nErrorCode);
- }
- BOOL CFTPDFsys::OnDelete(int nErrorCode)
- {
- if (nErrorCode && m_Output.IsEmpty())
- {
- m_pSock->SendMsg(551, "Permission denied.");
- m_pSock->LogMsg(LOGF_WARNINGS,"OnDelete failed after callback, error %d", nErrorCode);
- }
- else
- {
- m_pSock->SendMsg(250, "%s is deleted", m_FsysPath1);
- }
- return TRUE;
- }
- BOOL CFTPDFsys::OnMoveFile(int nErrorCode)
- {
- if (nErrorCode && m_Output.IsEmpty())
- {
- m_pSock->SendMsg(551, "Permission denied.");
- m_pSock->LogMsg(LOGF_WARNINGS,"OnDelete failed after callback, error %d", nErrorCode);
- }
- else
- {
- m_pSock->LogMsg(LOGF_FILEACC,"Renamed/moved %s to %s",m_FsysPath1, m_FsysPath2);
- m_pSock->SendMsg(250,"RNTO command successful.");
- }
- return TRUE;
- }
- BOOL CFTPDFsys::OnStat(int nErrorCode)
- {
- switch(m_CallbackID)
- {
- case CB_SIZE:
- return OnStatSize(nErrorCode);
- case CB_MDTM:
- return OnStatMDTM(nErrorCode);
- }
- return FALSE;
- }
- BOOL CFTPDFsys::OnStatSize(int nErrorCode)
- {
- char buf[32];
- if (nErrorCode)
- {
- m_pSock->SendMsg(551, "Permission denied.");
- m_pSock->LogMsg(LOGF_WARNINGS,"OnStatSize failed after callback, error %d", nErrorCode);
- return TRUE;
- }
- if (m_FilePerms & NODE_DIR)
- {
- m_pSock->LogMsg(LOGF_DEBUG,"OnStatSize() - Not a plain file.");
- m_pSock->SendMsg(550, "%s: not a plain file.", m_FsysPath1);
- return TRUE;
- }
- sprintf(buf,"%I64d", m_FileLen);
- m_pSock->SendMsg(213, "%s", buf);
- return TRUE;
- }
- BOOL CFTPDFsys::OnStatMDTM(int nErrorCode)
- {
- if (nErrorCode)
- {
- m_pSock->SendMsg(551, "Permission denied.");
- m_pSock->LogMsg(LOGF_WARNINGS,"OnStatMDTM failed after callback, error %d", nErrorCode);
- return TRUE;
- }
- if (m_FilePerms & NODE_DIR)
- {
- m_pSock->LogMsg(LOGF_DEBUG,"OnMdtm() - Not a plain file.");
- m_pSock->SendMsg(550, "%s: not a plain file.", m_FsysPath1);
- return TRUE;
- }
- FILETIME lt;
- SYSTEMTIME st;
- FileTimeToLocalFileTime(&m_FileTime,<);
- FileTimeToSystemTime(<,&st);
- m_pSock->SendMsg(213, "%04d%02d%02d%02d%02d%02d.%d",
- st.wYear,
- st.wMonth,
- st.wDay,
- st.wHour,
- st.wMinute,
- st.wSecond,
- st.wMilliseconds);
- return TRUE;
- }