⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 warsvrprotocolftpcmdall.cpp

📁 ftpserver very good sample
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    try    {        GetServer().CreateDataConnection();        WarSvrProtocolFtpDataConn& rSck = *(GetServer().mDataConnectionPtr);        local_addr = GetServer().GetLocalAddress();        local_addr.SetPort(0);        pair<war_port_t, war_port_t> range, *prange = NULL;        string port_range = GetServer().GetOption("ftpd_PASVRANGE");        if (!port_range.empty())        {            unsigned i1 = 0, i2 = 0;            if ((sscanf(port_range.c_str(), "%u-%u", &i1, &i2) == 2)                && (i1 < i2) && (i2 <= 0xffff))            {                range.first = (war_port_t)i1;                range.second = (war_port_t)i2;                prange = &range;            }            else            {                WarLog err_log(WARLOG_ERROR, "FtpCmdPasv::ExecuteCommand()", &GetServer());                err_log << "Invalid ftpd_PASVRANGE value: "                     << port_range                    << ". Ignoring this setting!"                    << war_endl;            }        }        rSck.Listen(local_addr, 1, prange);    }    catch(WarException e)    {        *mpReply << "Failed to open passive socket. "             << e.Explain() ;                if (GetServer().GetBoolOption("ftpd_STRICTREPLY"))            *mpReply << FTPR_SYNTAX_ERR_500;        else            *mpReply << FTPR_ABORT_451; // Not RFC 959 return code !!         return CMD_FAIL;    }    try    {        const struct sockaddr_in& rsckaddr_in             = GetServer().mDataConnectionPtr->GetLocalAddress().GetSockAddrIn();                const unsigned char *paddr = (unsigned char *)&rsckaddr_in.sin_addr;        const unsigned char *pport = (unsigned char *)&rsckaddr_in.sin_port;                *mpReply << SM_PASV_OK             << " ("            << (int)(unsigned)paddr[0] << ","            << (int)(unsigned)paddr[1] << ","            << (int)(unsigned)paddr[2] << ","            << (int)(unsigned)paddr[3] << ","            << (int)(unsigned)pport[0] << ","            << (int)(unsigned)pport[1]            << ")"            << FTPR_PASV_OK_227;    }    catch(WarException e)    {        *mpReply << "Failed to express PASV reply. "             << e.Explain();        if (GetServer().GetBoolOption("ftpd_STRICTREPLY"))            *mpReply << FTPR_SYNTAX_ERR_500;        else            *mpReply << FTPR_ABORT_451; // Not RFC 959 return code !!         return CMD_FAIL;    }    GetServer().mTransferMode.mConnectionType = CONN_PASSIVE;    WarLog debug_log(WARLOG_DEBUG, "FtpCmdPort::ExecuteCommand()", &GetServer());    if (debug_log)    {        debug_log << "PASV "             << GetServer().mTransferMode.mPortAddress.Explain()            << war_endl;    }    return CMD_SUCCESS;}/////////////////////////////// TYPE ///////////////////////////////////////FtpCmdType::FtpCmdType(WarSvrProtocolFtp& serverCompanion): WarSvrProtocolFtpCmd("TYPE",                        "Select data type",                        "TYPE <SP> <type-code> <CRLF>",                       "RFC 950",                       serverCompanion){}WarSvrProtocolFtpCmd::LastCommandresultE FtpCmdType::ExecuteCommand(){    war_ccstr_t p = GetArgument();    {        while(isspace(*p))            ++p;        if (!*p)        {            *mpReply << SM_MISSING_PARAMETER_IN_CMD << FTPR_ARG_SYNTAX_501;            return CMD_FAIL;        }        switch(toupper(*p))        {        case 'A':            while(isspace(*p))                ++p;            switch(toupper(*p))            {            case 'T':            case 'C':                *mpReply << SM_PARAMETER_NOT_SUPPORTED                     << FTPR_CMD_NOT_IMPL_ARG_504;                return CMD_FAIL;            case 'N':            default:                *mpReply << SM_TYPE_A << FTPR_OK_200;                GetServer().mTransferMode.mType = TYPE_ASCII;                GetServer().mTransferMode.mForm = FORM_NONPRINT;                return CMD_SUCCESS;            }        case 'E':            *mpReply << SM_TYPE_E << FTPR_CMD_NOT_IMPL_ARG_504;            return CMD_FAIL;        case 'I':            *mpReply << SM_TYPE_I << FTPR_OK_200;            GetServer().mTransferMode.mType = TYPE_IMAGE;            return CMD_SUCCESS;        case 'L':             while(isspace(*p))                ++p;             if (*p && (atoi(p) == 8))             {                 *mpReply  << SM_TYPE_L8 << FTPR_OK_200;                 GetServer().mTransferMode.mType = TYPE_LOCALB;                 return CMD_SUCCESS;             }             *mpReply << SM_PARAMETER_NOT_SUPPORTED                  << FTPR_CMD_NOT_IMPL_ARG_504;             return CMD_FAIL;        }    }    return CMD_FAIL; // Compiler food}/////////////////////////////// TRANSFER ///////////////////////////////////////FtpCmdTransfer::FtpCmdTransfer(war_ccstr_t commandName,                                war_ccstr_t commandExplanation, /* Human help*/                               war_ccstr_t commandSyntax, /* Formal */                               war_ccstr_t commandReference, /* RFC */                               WarSvrProtocolFtp& serverCompanion)                               : WarSvrProtocolFtpCmd(commandName,                                commandExplanation,                               commandSyntax,                               commandReference,                               serverCompanion){}war_svrfile_ptr_t FtpCmdTransfer::OpenFile(const WarSvrPath& svrFile,                          war_uint32_t flags)                         throw(WarException){    if ((flags & (F_WRITE | F_APPEND | F_CREATE))        && svrFile.IsSharedUpload()        && !GetServer().IsFileOwnedBySession(svrFile))    {         if (flags & F_MUSTEXIST)        {            WarLog db_log(WARLOG_DEBUG, "FtpCmdTransfer::OpenFile()", &GetServer());                        db_log << "Denying access to overwrite of file in shared upload folder."                << svrFile                << war_endl;                        WarThrow(WarError(WAR_ERR_ACCESS_DENIED), NULL);        }        flags |= F_NOTEXIST;        flags &= ~F_TRUNCATE;    }    else if ((flags & F_READ) && svrFile.IsSharedUpload())    {        WarLog db_log(WARLOG_DEBUG, "FtpCmdTransfer::OpenFile()", &GetServer());        db_log << "Denying access to download from shared upload folder."            << svrFile            << war_endl;        WarThrow(WarError(WAR_ERR_ACCESS_DENIED), NULL);    }    war_svrfile_ptr_t file_ptr         = GetServer().OpenFile(svrFile, flags);    const war_flen_t rest_pos = GetServer().mTransferMode.mRestartPos;    if (0 < rest_pos)    {        if (stricmp(GetServer().GetFtpCmds().GetPreviousCommand().GetName().c_str(),            "REST"))        {            // draft-ietf-ftpext-mlst-11 demands that REST is the last            // command to issue before a transfer command.            WarThrow(WarError(WAR_FTPERR_BAD_SEQUENCE_OF_CMDS), NULL);        }        if ((flags & F_TEXT)            && !GetServer().GetBoolOption("ftpd_ALLOWASCIIRESTART"))            WarThrow(WarError(WAR_FTPDERR_NOASCIIREST), NULL);        if (rest_pos > file_ptr->GetLength())            WarThrow(WarError(WAR_FTPDERR_REST_OUT_OF_RANGE), NULL);        file_ptr->Seek(rest_pos);    }    if (flags & F_TEMPORARY)        GetServer().mCurrentFileLength = -1;    else        GetServer().mCurrentFileLength = file_ptr->GetLength();        return file_ptr;}void FtpCmdTransfer::SendFile(        const war_ccstr_t filePath)        throw(WarException){    GetServer().ResolvPath(filePath);    war_uint32_t my_flags = F_READ | F_SHREAD         | F_MUSTEXIST | F_SEQUENTIAL;    if (TYPE_ASCII == GetServer().mTransferMode.mType)        my_flags |= WarFileEnums::F_TEXT;    war_svrfile_ptr_t my_file_ptr         = OpenFile(GetServer().mCurrentFile, my_flags);    GetServer().OnTransferStart(true, false);    Connect();    GetServer().mDataConnectionPtr->SendFile(my_file_ptr);}void FtpCmdTransfer::ReceiveFile(        const war_ccstr_t filePath,        bool withUniqueName,        bool doAppend)        throw(WarException){    war_uint32_t my_flags = 0;    GetServer().ResolvPath(filePath);    if (withUniqueName)    {        if (!GetServer().GetBoolOption("ftpd_ALLOWSTOU"))        {            *mpReply << SM_COMMAND_FORBIDDEN << FTPR_NOT_IMPL_502;            return;        }                /* Unique filename           This is tricky, as this command is rarely used,           but _are_ used in some special applications.           The normal approach is to count upwards                         sprintf(buf, "name.%d", ++counter);                      and test if a file with that number exists. If the           counter exeeds a (tiny) limit, the command fails.           This approach is cheap, but saves system resources.           We try another approach here, by searching for            files with our name, but without the number,           and simply adding one to the last number found!                 dir_list --> "file.?????.ext"           Where ????? is a number.           This makes this command extreemly expensive, but           usable in industrial applications, as it can handle           up to 99.999 STOU commands in one directory. The bad           news is that we only look for the highest number, and           not holes (deleted files) in the series.           The command should be disabled on most systems.        */        // We don't allow pattern chacaters here, as we will use        // these for lookups        for(war_svrpath_ccstr_t p = GetServer().mCurrentFile.GetAlias().GetPath()            ; *p            ; p++)        {            if ((*p == '*') || (*p == '?') || (*p == '['))                WarThrow(WarError(WAR_ERR_INVALID_PATH), NULL);        }        war_svrpath_t my_path = GetServer().mCurrentFile.GetAlias().GetPathname();        war_svrpath_t my_prefix = GetServer().mCurrentFile.GetAlias().GetFilename();        war_svrpath_t my_postfix = GetServer().mCurrentFile.GetAlias().GetExtension();        if (!my_postfix.IsEmpty())            my_prefix.CutAtLastCh('.');        war_svrpath_t my_pattern;        my_pattern << my_prefix.GetPath()             << ".?????";        if (!my_postfix.IsEmpty())            my_pattern << "."            << my_postfix.GetPath();                WarSvrDirList dir_list(0, GetServer(), false);        dir_list.mPatternList.push_back(my_pattern);        dir_list.Create(WarUtf8(my_path.GetPath()).GetUtf8().c_str());        size_t counter = 1;        const size_t match_punkts = my_postfix.IsEmpty() ? 1 : 2;        const char match_last = (match_punkts == 2) ? '.' : 0;        for(WarDirList::nodelist_t::reverse_iterator P             = dir_list.mList.rbegin()            ; P != dir_list.mList.rend()            ; P++)        {            war_ccstr_t p_start = P->Data().mName,                 p = p_start + P->Data().mNameLen -1;            size_t match = 0;            for(; p > p_start; p--)            {                if (('.' == *p) && (match_punkts == ++match))                {                    if (isdigit(p[1])                        && isdigit(p[2])                        && isdigit(p[3])                        && isdigit(p[4])                        && isdigit(p[5])                        && (match_last == p[6]))                    {                        // We got the highest match!                        counter = atoi(p + 1) + 1;                        goto do_stou;                    }                }            }        }do_stou:        char buf[32];        sprintf(buf, ".%05d", counter);        war_svrpath_t my_unique_path;        my_unique_path << my_path.GetPath()             << WAR_SYSSLASH             << my_prefix.GetPath()             << buf;        if (!my_postfix.IsEmpty())            my_unique_path << "." << my_postfix.GetPath();        GetServer().ResolvPath(WarUtf8(my_unique_path.GetPath()).GetUtf8().c_str());        my_flags = F_CREATE | F_WRITE | F_NOTEXIST | F_SEQUENTIAL;    }    else    {        if (GetServer().mTransferMode.mRestartPos > 0)            my_flags = F_WRITE | F_MUSTEXIST | F_SEQUENTIAL | F_SHREAD;        else if (doAppend)            my_flags = F_WRITE | F_CREATE | F_APPEND | F_SEQUENTIAL | F_SHREAD;        else            my_flags = F_WRITE | F_TRUNCATE | F_SEQUENTIAL | F_SHREAD;    }    if (TYPE_ASCII == GetServer().mTransferMode.mType)        my_flags |= WarFileEnums::F_TEXT;    war_svrfile_ptr_t my_file_ptr         = OpenFile(GetServer().mCurrentFile, my_flags);    GetServer().OnTransferStart(false, false, withUniqueName);    Connect();    GetServer().mDataConnectionPtr->ReceiveFile(my_file_ptr);}void FtpCmdTransfer::Connect()    throw(WarException){    WarSvrProtocolFtp& rsvr = GetServer();    if (CONN_ACTIVE == rsvr.mTransferMode.mConnectionType)    {        // Have to initiate a connectiopn to the client...        if (!rsvr.mDataConnectionPtr.IsEmpty())            rsvr.mDataConnectionPtr = NULL;                rsvr.CreateDataConnection();        rsvr.mDataConnectionPtr->SetAsyncMode();        rsvr.mDataConnectionPtr->Connect(            WAR_SOCK_STREAM,            rsvr.mTransferMode.mPortAddress,            &rsvr.mTransferMode.mLocalAddress);    }    else    {        // Passive connection.        if (rsvr.mDataConnectionPtr.IsEmpty())        {            WarLog err_log(WARLOG_ERROR, "FtpCmdTransfer::Connect

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -