📄 request.cpp
字号:
// request.cc// code for request.h// copyright SafeTP Development Group, Inc., 2000 Terms of use are as specified in license.txt#include "request.h" // this module#include "missing.h" // stricmp#include <ctype.h> // isspace#include "sockutil.h" // socket calls#include "xassert.h" // xassert#ifndef SAFETPC#include "lineread.h" // StreamLineReader#endif// textual representations of the requests, in the// same order as the RequestCommand enumerationstatic char const * const requestMap[] = { "(unknown)", // 959 commands "USER", "PASS", "ACCT", "CWD", "CDUP", "SMNT", "QUIT", "REIN", "PORT", "PASV", "TYPE", "STRU", "MODE", "RETR", "STOR", "STOU", "APPE", "ALLO", "REST", "RNFR", "RNTO", "ABOR", "DELE", "RMD", "MKD", "PWD", "LIST", "NLST", "SITE", "SYST", "STAT", "HELP", "NOOP", // 2228 commands "AUTH", "ADAT", "PROT", "PBSZ", "CCC", "MIC", "CONF", "ENC", // old commands "XCUP", "XCWD", "XMKD", "XPWD", "XRMD", "SIZE", // nonstandard commands "MDTM", // new commands "DIGT",};// if profiling reveals this is a bottleneck, it// can be replaced with a better algorithmRequestCommand textToRequestCommand(char const *cmd){ // NOTE: RFC959, section 5.3, states that commands // are case insensitive. Thus, stricmp is used. loopi(TABLESIZE(requestMap)) { if (0==missing_stricmp(cmd, requestMap[i])) { return (RequestCommand)i; } } return CMD_UNKNOWN;}char const *requestCommandToText(RequestCommand c){ xassert(validRequestCommand(c)); return requestMap[c];}bool validRequestCommand(RequestCommand c){ // get >= 0 test for free by using unsigned comparison return (unsigned)c < NUM_COMMAND_REQUESTS;}Request::Request(Request const &obj) : text(obj.text), command(obj.text), data(NULL), // set below c(obj.c){ data = text.pcharc() + (obj.data - obj.text.pcharc());}Request::Request(RequestCommand cmd, char const *dat) : command(requestCommandToText(cmd)), c(cmd){ xassert(validRequestCommand(cmd)); composeText(dat);}Request::Request(char const *cmd, char const *dat) : command(cmd) // cmd as-is{ c = textToRequestCommand(command); // integer code composeText(dat);}void Request::composeText(char const *dat){ if (dat != NULL) { text = stringb(command << " " << dat); // command, space, data data = text.pchar() + command.length() + 1; // data starts one char after cmd ends } else { text = command; // command only data = text.pchar() + command.length(); // "", essentially }}Request::Request(char const *src) : text(src){ parse();}Request::Request(SOCKET s){ text = recvLine(s); parse();}#ifndef SAFETPCRequest::Request(StreamLineReader &reader){ if (!reader.getNextLine(text)) { // unexpected EOF xassert(!"unexpected end of stream"); } parse();}#endifvoid Request::send(SOCKET s) const{ #if 0 // original code sendAllString(s, text); sendEOL(s); #else // There are some firewalls, one of which in installed at ohio-state.edu, which // believe that PORT requests must arrive, in their entirety, as a single IP // datagram. The above code, unfortunately, usually results in two IP datagrams, // one for the request text and one for the CRLF pair. // // Therefore, as a fix, we will put all the data into a single buffer first. // // This is probably more efficient anyway, since new/strncpy/delete is probably // less expensive than the additional system call. int len = strlen(text); // length *without* CRLF char *buf = new char[len+2]; strncpy(buf, text, len); // main text buf[len] = '\r'; buf[len+1] = '\n'; // CRLF try { sendAll(s, buf, len+2); } catch (...) { delete[] buf; // prevent leak throw; } delete[] buf; #endif}void Request::parse(){ // grab a pointer to the internal char* of 'text' char const *p = text.pcharc(); // ++ begin hack ++ // skip binary characters that may precede a command // this is a temporary hack to fix an incompatibility with IE // which sends a telnet IP & synch before ABOR // we really need a more general solution to this problem while (!isprint(*p) && *p!=0) { p++; } // did we skip anything? if (p != text.pcharc()) { text = p; // replace old text with trimmed text p = text.pcharc(); // grab internal char* again } // -- end hack -- // find first non-ws character while (isspace(*p)) { p++; } char const *cmd_start = p; // find next ws while (*p!=0 && !isspace(*p)) { p++; } char const *cmd_end = p; // pull off command command = string(cmd_start, cmd_end-cmd_start); c = textToRequestCommand(command); // find next non-ws; this is data (may be "") while (isspace(*p)) { p++; } data = p;}bool Request::isCommand(char const *cmd) const{ return 0==missing_stricmp(command, cmd);}string Request::getTextNoPassword() const{ if (getCmd() == CMD_PASS) { return string("PASS ********"); } else { return getText(); }}// ---------------- test code -------------------#ifdef TEST_REQUEST#include <iostream.h> // coutint main(){ { char const *text = "AUTH frobozz-snazzy"; Request req(text); // parse xassert(req.getCmd() == CMD_AUTH); cout << req.getText() << endl; Request req2(req); // copy ctor xassert(req.getCmd() == CMD_AUTH); cout << req.getText() << endl; } return 0;}#endif // TEST_REQUEST
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -