📄 warsvrprotocolftpreply.cpp
字号:
#include "StdAfx.h"#ifndef WAR_ASSERT_H_INCLUDED# define WAR_ASSERT_H_INCLUDED# include <assert.h>#endif#include "WarSvrProtocolFtpReply.h" // class implemented#ifndef WAR_SVR_PROTOCOL_FTP_H# include "WarSvrProtocolFtp.h"#endif#ifndef WAR_LOG_H# include "WarLog.h"#endifusing namespace std;/////////////////////////////// PUBLIC ///////////////////////////////////////WarSvrProtocolFtpReply& operator << (WarSvrProtocolFtpReply& R, war_ccstr_t from){ R.Expand(WarSvrProtocolFtpReply::EXPAND_NONE, from); return R;}WarSvrProtocolFtpReply& operator << (WarSvrProtocolFtpReply& R, const std::string& from){ R.Expand(WarSvrProtocolFtpReply::EXPAND_NONE, from.c_str()); return R;}WarSvrProtocolFtpReply& operator << (WarSvrProtocolFtpReply& R, const war_svrpath_t& from){ R.Expand(WarSvrProtocolFtpReply::EXPAND_NONE, WarUtf8(from.GetPath()).GetUtf8().c_str()); return R;}WarSvrProtocolFtpReply& operator << (WarSvrProtocolFtpReply& R, const char& from){ char buf[sizeof(int)]; buf[0] = from; buf[1] = 0; R.Expand(WarSvrProtocolFtpReply::EXPAND_NONE, buf); return R;}WarSvrProtocolFtpReply& operator << (WarSvrProtocolFtpReply& R, const int& from){ char buf[32]; sprintf(buf, "%d", from); R.Expand(WarSvrProtocolFtpReply::EXPAND_NONE, buf); return R;}WarSvrProtocolFtpReply& operator << (WarSvrProtocolFtpReply& R, const war_flen_t& from){ WarCollector<char> buf; buf << from; R.Expand(WarSvrProtocolFtpReply::EXPAND_NONE, buf.GetValue().c_str()); return R;}WarSvrProtocolFtpReply& operator << (WarSvrProtocolFtpReply& R, const WarSvrProtocolFtpReply::WarFTPDReplyCodesE from){ R.mReplyCode = from; R.Flush(); return R;}WarSvrProtocolFtpReply& operator << (WarSvrProtocolFtpReply& R, const WarSvrProtocolFtpReply::FtpSvrMsgsE from){ R.Expand(WarSvrProtocolFtpReply::EXPAND_ALL, R.mServerReplyMessages[from]); return R;}WarSvrProtocolFtpReply& operator << (WarSvrProtocolFtpReply& R, const WarError& from){ R.mErrorStatus = from; return R;}//============================= LIFECYCLE ====================================WarSvrProtocolFtpReply::WarSvrProtocolFtpReply() : mReplyCode(FTPR_INVALID), mpServer(NULL){}//============================= OPERATORS ====================================//============================= OPERATIONS ===================================void WarSvrProtocolFtpReply::InstallMacro(war_macro_ptr_t& macro_ptr, bool doReplace){ if (doReplace) { war_macro_set_t::iterator P = mMacros.find(macro_ptr); if (P != mMacros.end()) mMacros.erase(P); } mMacros.insert(macro_ptr);}//============================= ACCESS ===================================//============================= INQUIRY ===================================/////////////////////////////// PROTECTED ///////////////////////////////////void WarSvrProtocolFtpReply::Expand(ExpandModesE expandMode, war_ccstr_t textString) throw(WarException){ ExpandModesE my_mode = expandMode; /* Macro expansion to GetServer(). We expand macros on the fly, and can be called recursively. The mode stack ensures that we never expand macros with less restrictions than the inital call gave us. */ if (!textString || !*textString) return; if (!mModeStack.empty()) { // We are called recursively. Use the most // restrictive mode! my_mode = max(my_mode, mModeStack.top()); } mModeStack.push(my_mode); war_ccstr_t p = textString; assert(p != NULL); assert(*p != 0); while(*p) { if ((*p == '\\') && (p[1] == '[')) { p++; mOutBuf += *p++; } else if ((*p == '[') && (my_mode != EXPAND_NONE)) { war_ccstr_t pp = p; string macro_name; int Recurse = 1; while(*++pp) { if (*pp == '[') ++Recurse; else if (*pp == ']') { if (!--Recurse) { ++pp; break; } } macro_name += *pp; } if (Recurse || macro_name.empty()) {give_up_macro: while(p != pp) mOutBuf += *p++; } else if (macro_name[0] == '$') { // Expand text macro try { ExpandMacro(my_mode, macro_name.c_str() +1 ); } catch(WarException) { goto give_up_macro; } } else { // Try file if (my_mode != EXPAND_ALL) goto give_up_macro; // Rules: Only allow filenames - no paths! // We do it simple by being very paranoid :) for(war_ccstr_t p = macro_name.c_str(); *p; p++) { if (!isalnum(*p) && (*p != '-') && (*p != '_') && (*p != '.')) {illegal_stuff: WarLog warn_log(WARLOG_WARNINGS, "WarSvrProtocolFtpReply::Expand()"); warn_log << "Illegal character '" << *p << "' in macro (file-name). " << "File-names can be letters digits and hyphen/underscore only. " << "Macro: " << macro_name << war_endl; goto give_up_macro; } if ((*p == '.') && !isalnum(p[1])) goto illegal_stuff; } WarPath<char> file_name; file_name << mpServer->GetOption("ftpd_TEXTFILES") << WAR_SYSSLASH << macro_name.c_str(); FILE *fp = fopen(file_name.GetPath(), "r"); if (fp) { try { char buf[1024]; while(fgets(buf, sizeof(buf), fp)) Expand(EXPAND_ALL_BUT_FILES, buf); } catch(WarException& ex) { fclose(fp); throw(ex); } fclose(fp); } } p = pp; } else { mOutBuf += *p++; } } mModeStack.pop();}void WarSvrProtocolFtpReply::ExpandMacro(ExpandModesE expandMode, war_ccstr_t macroName){ assert(macroName != NULL); std::string name_buf; war_ccstr_t macro_argument = NULL; war_ccstr_t p = macroName; while(*p) { if (*p == ',') { macro_argument = ++p; break; } name_buf += *p++; } war_macro_ptr_t key_ptr = new WarTextMacro(name_buf.c_str()); war_macro_set_t::const_iterator P = mMacros.find(key_ptr); if (P == mMacros.end()) WarThrow(WarError(WAR_ERR_OBJECT_NOT_FOUND), NULL); WarTextMacro& macro = *(*P); switch(expandMode) { case EXPAND_SAFE: if (!macro.IsSafe()) WarThrow(WarError(WAR_ERR_ACCESS_DENIED), "EXPAND_NONE"); // Fall trough case EXPAND_ALL_BUT_FILES: if (macro.IsFile()) WarThrow(WarError(WAR_ERR_ACCESS_DENIED), "EXPAND_NONE"); // Fall trough case EXPAND_ALL: break; case EXPAND_NONE: WarThrow(WarError(WAR_ERR_ACCESS_DENIED), "EXPAND_NONE"); } Expand(macro.GetMode(), macro.Expand(macro_argument).c_str());}void WarSvrProtocolFtpReply::AssignToServer(WarSvrProtocolFtp *pServer){ assert(mpServer == NULL); mpServer = pServer;}void WarSvrProtocolFtpReply::Flush(){ PreProcessOutput(); GetServer().FlushOut();}#define FLUSH() \{ \ if (p_out > buffer) \ { \ if (ftp_log) \ { \ *p_out = 0; \ ftp_log << buffer; \ } \ GetServer().Send(buffer, p_out - buffer); \ p_out = buffer; \ } \}#define PUTC(ch) \{ \ if (p_out >= p_endbuffer) \ FLUSH(); \ *p_out++ = ch;\}#define PUTS(str) \{ \ war_ccstr_t p_tmp = str; \ while(*p_tmp) \ PUTC(*p_tmp++); \}void WarSvrProtocolFtpReply::PreProcessOutput(){ WarLog ftp_log(WARLOG_DEBUG_FTP, "WarSvrProtocolFtpReply::PreProcessOutput()"); if (mErrorStatus) { mOutBuf += " Error: "; mOutBuf += mErrorStatus.Explain(); mErrorStatus.Reset(); } int reply_code = (int)mReplyCode; war_ccstr_t p = mOutBuf.c_str(); char buffer[1024 * 4]; // tmp output buffer war_cstr_t p_out = buffer; const war_ccptr_t p_endbuffer = buffer + (sizeof(buffer) - 2); #if WAR_RFC2389 int number_of_lines = 0;#endif assert(reply_code >= 100); assert(reply_code < 1000); if (ftp_log) ftp_log << "Replying to client: "; do { // Start of new line bool is_last_line = strchr(p,'\n') == NULL;#if WAR_RFC2389 if (number_of_lines++ && !is_last_line) PUTC(' ') else#endif // WAR_RFC2389 { char buf[8]; sprintf(buf, "%03d%c", reply_code, is_last_line ? ' ' : '-'); PUTS(buf) } while(*p) { if (*p == '\r') { p++; continue; } if (*p == '\n') { p++; PUTC('\r') PUTC('\n') break; } PUTC(*p++) } } while (*p); assert(mOutBuf.empty() == false); if (mOutBuf[mOutBuf.size() -1] != '\n') { PUTC('\r') PUTC('\n') } FLUSH(); ftp_log << war_endl; mOutBuf.erase();}#undef FLUSH#undef PUTC#undef PUTS/////////////////////////////// PRIVATE ///////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -