当前位置:网站首页>Analysis of tars source code 5
Analysis of tars source code 5
2022-07-04 06:36:00 【Tao song remains the same】
cgi Related implementation of , Let's see , It's still very routine :
#include "util/tc_cgi.h"
#include "util/tc_common.h"
#include "util/tc_http.h"
#include <string.h>
namespace tars
{
ostream &operator<<(ostream &os, const TC_Cgi_Upload &tcCgiUpload)
{
os << tcCgiUpload.tostr();
return os;
}
TC_Cgi_Upload::TC_Cgi_Upload(const TC_Cgi_Upload &tcCgiUpload)
{
_sFileName = tcCgiUpload._sFileName;
_sRealFileName = tcCgiUpload._sRealFileName;
_sServerFileName= tcCgiUpload._sServerFileName;
_iSize = tcCgiUpload._iSize;
_bOverSize = tcCgiUpload._bOverSize;
}
TC_Cgi_Upload & TC_Cgi_Upload::operator=(const TC_Cgi_Upload &tcCgiUpload)
{
if(this != &tcCgiUpload)
{
_sFileName = tcCgiUpload._sFileName;
_sRealFileName = tcCgiUpload._sRealFileName;
_sServerFileName= tcCgiUpload._sServerFileName;
_iSize = tcCgiUpload._iSize;
_bOverSize = tcCgiUpload._bOverSize;
}
return *this;
}
string TC_Cgi_Upload::tostr() const
{
string sBuffer;
sBuffer = "[file Control name :" + _sFileName + "] ";
sBuffer += " [ Real file name :" + _sRealFileName + "] ";
sBuffer += " [ Server side file name :" + _sServerFileName + "] ";
sBuffer += " [ size ( byte ):" + TC_Common::tostr(_iSize) + "] ";
sBuffer += " [ Size limit exceeded :" + TC_Common::tostr(_bOverSize) + "] ";
return sBuffer;
}
TC_Cgi::TC_Cgi()
: _is(NULL)
, _iMaxUploadFiles(1)
, _iUploadMaxSize(20971520)
, _bOverUploadFiles(false)
, _iMaxContentLength(20971520)
, _bUploadFileOverSize(false)
{
}
TC_Cgi::~TC_Cgi()
{
}
void TC_Cgi::setUpload(const string &sUploadFilePrefix, int iMaxUploadFiles, size_t iUploadMaxSize, size_t iMaxContentLength)
{
_sUploadFilePrefix = sUploadFilePrefix;
_iMaxUploadFiles = iMaxUploadFiles;
_iUploadMaxSize = iUploadMaxSize;
_iMaxContentLength = iMaxContentLength;
}
void TC_Cgi::parseCgi()
{
char **env = environ;
while(*env != NULL)
{
string s(*env);
string::size_type pos = s.find('=');
if(pos != string::npos)
{
_env[s.substr(0, pos)] = s.substr(pos + 1);
}
++env;
}
_is = &cin;
readCgiInput(_mmpParams, _mpCookies);
}
void TC_Cgi::parseCgi(const TC_HttpRequest &request)
{
setCgiEnv("QUERY_STRING", request.getRequestParam());
setCgiEnv("CONTENT_LENGTH", TC_Common::tostr(request.getContentLength()));
setCgiEnv("HTTP_COOKIE", request.getHeader("Cookie"));
setCgiEnv("CONTENT_TYPE", request.getHeader("Content-Type"));
setCgiEnv("REQUEST_METHOD", request.isGET() ? "GET" : "POST");
_buffer = request.getContent();
_iss.str(_buffer);
_is = &_iss;
readCgiInput(_mmpParams, _mpCookies);
}
void TC_Cgi::getPOST(string &sBuffer)
{
string::size_type iSize = atoi(getCgiEnv(TC_Cgi::ENM_CONTENT_LENGTH).c_str());
if( iSize > _iMaxContentLength)
{
throw TC_Cgi_Exception("[TC_Cgi::getPOST] : CONTENT_LENGTH is too large!");
}
if(iSize <= 0)
{
return;
}
sBuffer = _buffer;
if(sBuffer.length() < iSize)
{
throw TC_Cgi_Exception("[TC_Cgi::getPOST] : Read CONTENT error: content size " + TC_Common::tostr(sBuffer.length()) + "<" + TC_Common::tostr(iSize));
}
}
void TC_Cgi::getGET(string &sBuffer)
{
sBuffer = getCgiEnv(TC_Cgi::ENM_QUERY_STRING);
}
void TC_Cgi::readCgiInput(multimap<string, string> &mmpParams, map<string, string> &mpCooies)
{
string sBuffer = TC_Cgi::getCgiEnv(TC_Cgi::ENM_HTTP_COOKIE);
parseCookies(mpCooies, sBuffer);
if (getCgiEnv(ENM_REQUEST_METHOD).find("POST") != string::npos)
{
// File upload mode
if (getCgiEnv(ENM_CONTENT_TYPE).find("multipart/form-data") != string::npos)
{
parseUpload(mmpParams);
}
else if (getCgiEnv(ENM_CONTENT_TYPE).find("application/x-www-form-urlencoded") != string::npos)
{
getPOST(sBuffer);
parseNormal(mmpParams, sBuffer);
}
getGET(sBuffer);
}
else if (getCgiEnv(ENM_REQUEST_METHOD).find("GET") != string::npos)
{
getGET(sBuffer);
}
else
{
//default is GET
getGET(sBuffer);
}
if (sBuffer.length() == 0)
{
return ;
}
parseNormal(mmpParams, sBuffer);
}
void TC_Cgi::parseNormal(multimap<string, string> &mmpParams, const string& sBuffer)
{
int iFlag = 0;
string sName;
string sValue;
string sTmp;
string::size_type len = sBuffer.length();
string::size_type pos = 0;
while (pos < len)
{
sTmp = "";
if(iFlag == 0)
{
while ( (sBuffer[pos] != '=') && (pos < len) )
{
sTmp += (sBuffer[pos] == '+') ? ' ' : sBuffer[pos];
++pos;
}
}
else
{
while ( (sBuffer[pos] != '&') && (pos < len) )
{
sTmp += (sBuffer[pos] == '+') ? ' ' : sBuffer[pos];
++pos;
}
}
if (iFlag == 0) //param name
{
sName = TC_Cgi::decodeURL(sTmp);
if ( (sBuffer[pos] != '=') || (pos == len - 1) )
{
sValue = "";
mmpParams.insert(multimap<string, string>::value_type(sName, sValue));
}
else
{
iFlag = 1;
}
}
else
{
sValue = TC_Cgi::decodeURL(sTmp);
mmpParams.insert(multimap<string, string>::value_type(sName, sValue));
iFlag = 0;
}
++pos;
}
}
void TC_Cgi::parseCookies(map<string, string> &mpCookies, const string& sBuffer)
{
string::size_type len = sBuffer.length();
string::size_type pos = 0;
if(len == 0)
{
return;
}
string sName;
string sValue;
int iFlag = 1;
while(pos < len)
{
if(sBuffer[pos] == '=')
{
if( pos == len - 1) // Last parameter
{
sName = decodeURL(TC_Common::trimleft(sName, " "));
sValue = decodeURL(sValue);
mpCookies[sName] = sValue;
sName = "";
sValue= "";
}
iFlag = 0; // Value
}
else if ( (sBuffer[pos] == ';') || (pos == len - 1) )
{
if(iFlag == 0)
{
if(pos == len - 1)
{
sValue += sBuffer[pos];
}
sName = decodeURL(TC_Common::trimleft(sName, " "));
sValue = decodeURL(sValue);
mpCookies[sName] = sValue;
sName = "";
sValue= "";
iFlag = 1; // Take the name
}
}
else if (iFlag)
{
sName += sBuffer[pos];
}
else
{
sValue += sBuffer[pos];
}
++pos;
}
}
void TC_Cgi::ignoreLine()
{
string sBuffer;
// Read until there is a blank line
while(true)
{
if(!getline(*_is, sBuffer))
{
throw TC_Cgi_Exception("[TC_Cgi::parseFormData] 'multipart/form-data' Format is error");
}
sBuffer = TC_Common::trim(sBuffer, "\r\n");
if(sBuffer.empty())
{
break;
}
}
}
bool TC_Cgi::writeFile(FILE*fp, const string &sFileName, const string &sBuffer, size_t &iTotalWrite)
{
if(!fp)
{
return false;
}
if(_mpUpload[sFileName]._bOverSize
|| iTotalWrite > _iUploadMaxSize
|| (iTotalWrite + sBuffer.length()) > _iUploadMaxSize)
{
_mpUpload[sFileName]._bOverSize = true;
_bUploadFileOverSize = true;
return false;
}
// Content written to file
int ret = fwrite(sBuffer.c_str(), 1, sBuffer.length(), fp);
if(ret != (int)sBuffer.length())
{
fclose(fp);
throw TC_Cgi_Exception("[TC_Cgi::parseFormData] upload file '" + _mpUpload[sFileName]._sServerFileName + "' error:" + string(strerror(errno)));
}
iTotalWrite += sBuffer.length();
_mpUpload[sFileName]._iSize = iTotalWrite;
return true;
}
void TC_Cgi::parseFormData(multimap<string, string> &mmpParams, const string &sBoundary)
{
string sBuffer;
if(!getline(*_is, sBuffer))
{
throw TC_Cgi_Exception("[TC_Cgi::parseFormData] 'multipart/form-data' Format is error");
}
string sName;
string sValue;
string::size_type pos1 = string("Content-Disposition: form-data; name=\"").length();
string::size_type pos2 = sBuffer.find('"', pos1);
if(pos2 == string::npos)
{
throw TC_Cgi_Exception("[TC_Cgi::parseFormData] 'multipart/form-data' Format is error");
}
// Control name
sName = sBuffer.substr(pos1, pos2 - pos1);
pos1 = sBuffer.find("filename=\"");
if(pos1 != string::npos)
{
FILE *fp = NULL;
string sTheFile;
// Of uploaded files form data
pos1 += 10; //filename=
pos2 = sBuffer.find('"', pos1);
if(pos2 == string::npos)
{
throw TC_Cgi_Exception("[TC_Cgi::parseFormData] 'multipart/form-data' Format is error");
}
// Get the file name
sValue = sBuffer.substr(pos1, pos2 - pos1);
if( sValue.length() > 0)
{
if(_iMaxUploadFiles < 0 || _mpUpload.size() < (size_t)_iMaxUploadFiles)
{
mmpParams.insert(multimap<string, string>::value_type(sName, sValue));
// Name of constituent document
string sUploadFileName = _sUploadFilePrefix + "_" + TC_Common::tostr(_mpUpload.size());
// Record the upload file path
_mpUpload[sName]._sFileName = sName;
_mpUpload[sName]._sRealFileName = sValue;
_mpUpload[sName]._sServerFileName = sUploadFileName;
sTheFile = sName;
// Open file
if ( (fp = fopen(sUploadFileName.c_str(),"w")) == NULL)
{
mmpParams.clear(); //clear , exception safe
throw TC_Cgi_Exception("[TC_Cgi::parseFormData] Upload File '" + sValue + "' to '" + sUploadFileName +"' error! " + string(strerror(errno)));
}
}
else
{
_bOverUploadFiles = true;
}
}
ignoreLine();
string sLastBuffer;
size_t iTotalWrite = 0;
// Read content to file
while(getline(*_is, sBuffer))
{
string sTmp = TC_Common::trimright(sBuffer);
if(sTmp.find(sBoundary) != string::npos)
{
if(sLastBuffer.length() < 2)
{
if(fp)
{
fclose(fp);
}
throw TC_Cgi_Exception("[TC_Cgi::parseFormData] 'multipart/form-data' Format is error");
}
sLastBuffer = sLastBuffer.substr(0, sLastBuffer.length() - 2);
writeFile(fp, sTheFile, sLastBuffer, iTotalWrite);
if(fp)
{
fclose(fp);
fp = NULL;
}
// The new one form data
if(sTmp == sBoundary)
{
parseFormData(mmpParams, sBoundary);
return;
}
else if(sTmp == sBoundary + "--")
{
return;
}
{
throw TC_Cgi_Exception("[TC_Cgi::parseFormData] 'multipart/form-data' Format is error");
}
}
if(!sLastBuffer.empty())
{
writeFile(fp, sTheFile, sLastBuffer, iTotalWrite);
}
sLastBuffer = sBuffer + "\n";
}
if(fp)
{
fclose(fp);
fp = NULL;
}
}
else
{
ignoreLine();
string sLastBuffer;
while(getline(*_is, sBuffer))
{
string sTmp = TC_Common::trimright(sBuffer);
if(sTmp.find(sBoundary) != string::npos)
{
if(sLastBuffer.length() < 2)
{
throw TC_Cgi_Exception("[TC_Cgi::parseFormData] 'multipart/form-data' Format is error");
}
sLastBuffer = sLastBuffer.substr(0, sLastBuffer.length() - 2);
mmpParams.insert(multimap<string, string>::value_type(sName, sLastBuffer));
// The new one form data
if(sTmp == sBoundary)
{
parseFormData(mmpParams, sBoundary);
return;
}
else if(sTmp == sBoundary + "--")
{
return;
}
throw TC_Cgi_Exception("[TC_Cgi::parseFormData] 'multipart/form-data' Format is error");
}
sLastBuffer += sBuffer + "\n";
}
}
}
void TC_Cgi::parseUpload(multimap<string, string> &mmpParams)
{
string::size_type iSize = atoi(getCgiEnv(TC_Cgi::ENM_CONTENT_LENGTH).c_str());
if( iSize > _iMaxContentLength)
{
throw TC_Cgi_Exception("[TC_Cgi::parseUpload] : CONTENT_LENGTH is too large!");
}
//get content type
string sContentType = getCgiEnv(TC_Cgi::ENM_CONTENT_TYPE);
string::size_type bPos = sContentType.find("boundary=");
if(bPos == string::npos)
{
return;
}
//get boundary, boundary separete params
string sBoundary(sContentType.substr(bPos + 9));
sBoundary = "--" + sBoundary;
string sBuffer;
if(!getline(*_is, sBuffer))
{
throw TC_Cgi_Exception("[TC_Cgi::parseFormData] 'multipart/form-data' Format is error");
}
sBuffer = TC_Common::trim(sBuffer);
if(sBuffer == sBoundary)
{
parseFormData(mmpParams, sBoundary);
}
else
{
throw TC_Cgi_Exception("[TC_Cgi::parseUpload] 'multipart/form-data' Format is error");
}
}
string &TC_Cgi::operator[](const string &sName)
{
multimap<string, string>::iterator it;
if((it = _mmpParams.find(sName)) != _mmpParams.end())
{
return it->second;
}
return _mmpParams.insert(multimap<string, string>::value_type(sName, ""))->second;
}
string TC_Cgi::getValue(const string& sName) const
{
multimap<string, string>::const_iterator it;
if((it = _mmpParams.find(sName)) != _mmpParams.end())
{
return it->second;
}
return "";
}
const vector<string>& TC_Cgi::getMultiValue(const string& sName, vector<string> &vtValue) const
{
vtValue.clear();
multimap<string, string>::const_iterator itEnd = _mmpParams.end();
for( multimap<string, string>::const_iterator it = _mmpParams.begin(); it != itEnd; ++it)
{
if(it->first == sName)
{
vtValue.push_back(it->second);
}
}
return vtValue;
}
const multimap<string, string> &TC_Cgi::getParamMap() const
{
return _mmpParams;
}
map<string, string> TC_Cgi::getParamMapEx() const
{
map<string, string> mpCgiParam;
multimap<string, string>::const_iterator it = _mmpParams.begin();
multimap<string, string>::const_iterator itEnd = _mmpParams.end();
while(it != itEnd)
{
mpCgiParam[it->first] = it->second;
++it;
}
return mpCgiParam;
}
const map<string, string> &TC_Cgi::getCookiesMap() const
{
return _mpCookies;
}
bool TC_Cgi::isUploadOverSize() const
{
return _bUploadFileOverSize;
}
bool TC_Cgi::isUploadOverSize(vector<TC_Cgi_Upload> &vtUploads) const
{
vtUploads.clear();
map<string, TC_Cgi_Upload>::const_iterator itEnd = _mpUpload.end();
for( map<string, TC_Cgi_Upload>::const_iterator it = _mpUpload.begin(); it != itEnd; ++it)
{
if(it->second._bOverSize)
{
vtUploads.push_back(it->second);
}
}
return vtUploads.size() > 0;
}
const map<string, TC_Cgi_Upload> &TC_Cgi::getUploadFilesMap() const
{
return _mpUpload;
}
size_t TC_Cgi::getUploadFilesCount() const
{
return _mpUpload.size();
}
string TC_Cgi::getCookie(const string &sName) const
{
map<string, string>::const_iterator it = _mpCookies.find(sName);
if(it != _mpCookies.end())
{
return it->second;
}
return "";
}
string TC_Cgi::setCookie(const string &sName, const string &sValue, const string &sExpires, const string &sPath, const string &sDomain, bool bSecure)
{
if(sName.length() == 0)
{
return "";
}
ostringstream os;
os << "Set-Cookie: %s=%s;",sName.c_str(),sValue.c_str();
if (sExpires.length() > 0)
{
os << "EXPIRES=%s;",sExpires.c_str();
}
if (sPath.length() > 0)
{
os << "PATH=%s;", sPath.c_str();
}
if (sDomain.length() > 0)
{
os << "DOMAIN=%s;", sDomain.c_str();
}
if (bSecure)
{
os << "SECURE";
}
os << endl;
_mpCookies[sName] = sValue;
return os.str();
}
bool TC_Cgi::isParamEmpty() const
{
return _mmpParams.empty();
}
bool TC_Cgi::isParamExist(const string& sName) const
{
return _mmpParams.find(sName) != _mmpParams.end();
}
string TC_Cgi::getCgiEnv(int iEnv)
{
switch(iEnv)
{
case ENM_SERVER_SOFTWARE:
return getCgiEnv("SERVER_SOFTWARE");
case ENM_SERVER_NAME:
return getCgiEnv("SERVER_NAME");
case ENM_GATEWAY_INTERFACE:
return getCgiEnv("GATEWAY_INTERFACE");
case ENM_SERVER_PROTOCOL:
return getCgiEnv("SERVER_PROTOCOL");
case ENM_SERVER_PORT:
return getCgiEnv("SERVER_PORT");
case ENM_REQUEST_METHOD:
return getCgiEnv("REQUEST_METHOD");
case ENM_PATH_INFO:
return getCgiEnv("PATH_INFO");
case ENM_PATH_TRANSLATED:
return getCgiEnv("PATH_TRANSLATED");
case ENM_SCRIPT_NAME:
return getCgiEnv("SCRIPT_NAME");
case ENM_HTTP_COOKIE:
return getCgiEnv("HTTP_COOKIE");;
case ENM_QUERY_STRING:
return getCgiEnv("QUERY_STRING");
case ENM_REMOTE_HOST:
return getCgiEnv("REMOTE_HOST");
case ENM_REMOTE_ADDR:
return getCgiEnv("REMOTE_ADDR");
case ENM_AUTH_TYPE:
return getCgiEnv("AUTH_TYPE");
case ENM_REMOTE_USER:
return getCgiEnv("REMOTE_USER");
case ENM_REMOTE_IDENT:
return getCgiEnv("REMOTE_IDENT");
case ENM_CONTENT_TYPE:
return getCgiEnv("CONTENT_TYPE");
case ENM_CONTENT_LENGTH:
return getCgiEnv("CONTENT_LENGTH");
case ENM_HTTP_USER_AGENT:
return getCgiEnv("HTTP_USER_AGENT");
default:
return "";
}
}
string TC_Cgi::getCgiEnv(const string &sEnv)
{
if(_env.find(sEnv) != _env.end())
{
return _env[sEnv];
}
return "";
}
void TC_Cgi::setCgiEnv(const string &sName, const string &sValue)
{
_env[sName] = sValue;
}
string TC_Cgi::htmlHeader(const string &sHeader)
{
return "Content-type: " + sHeader + "\n\n";
}
string TC_Cgi::decodeURL(const string &sUrl)
{
string sDecodeUrl;
register string::size_type pos = 0;
string::size_type len = sUrl.length();
sDecodeUrl = "";
while (pos < len)
{
if(sUrl[pos] == '+')
{
sDecodeUrl += ' ';
++pos;
}
else if(sUrl[pos] == '%')
{
sDecodeUrl += TC_Common::x2c(sUrl.substr(pos + 1));
pos += 3;
}
else
{
sDecodeUrl += sUrl[pos];
++pos;
}
}
return sDecodeUrl;
}
string TC_Cgi::encodeURL(const string &sUrl)
{
static char HEX_TABLE[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
string result;
for (size_t i = 0; i < sUrl.length(); i++)
{
char c = sUrl[i];
if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
result.append(1, c);
else if(c == ' ')
{
result.append(1, '+');
}
else
{
result.append(1, '%');
result.append(1, HEX_TABLE[(c >> 4) & 0x0f]);
result.append(1, HEX_TABLE[c & 0x0f]);
}
}
return result;
}
string TC_Cgi::encodeHTML(const string &src, bool blankEncode)
{
if (src == "")
return "";
string result = src;
result = TC_Common::replace(result, "&", "&");
result = TC_Common::replace(result, "<", "<");
result = TC_Common::replace(result, ">", ">");
result = TC_Common::replace(result, "\"", """);
if (blankEncode)
{
result = TC_Common::replace(result, "\t", " ");
result = TC_Common::replace(result, " ", " ");
result = TC_Common::replace(result, "\r\n", "<br>");
result = TC_Common::replace(result, "\n", "<br>");
}
return result;
}
string TC_Cgi::encodeXML(const string &src)
{
if (src == "")
return "";
string result = src;
result = TC_Common::replace(result, "&", "&");
result = TC_Common::replace(result, "<", "<");
result = TC_Common::replace(result, ">", ">");
result = TC_Common::replace(result, "\"", """);
result = TC_Common::replace(result, "'", "'");
return result;
}
}边栏推荐
- Stc8h development (XII): I2C drive AT24C08, at24c32 series EEPROM storage
- C實現貪吃蛇小遊戲
- 【MySQL】数据库视图的介绍、作用、创建、查看、删除和修改(附练习题)
- 对List进行排序工具类,可以对字符串排序
- C language - Blue Bridge Cup - Snake filling
- 如何实现视频平台会员多账号登录
- Invalid revision: 3.18.1-g262b901-dirty
- 2022 where to find enterprise e-mail and which is the security of enterprise e-mail system?
- [openvino+paddle] paddle detection / OCR / SEG export based on paddle2onnx
- Manually page the list (parameter list, current page, page size)
猜你喜欢

Arcpy uses the updatelayer function to change the symbol system of the layer

C # symmetric encryption (AES encryption) ciphertext results generated each time, different ideas, code sharing

QT get random color value and set label background color code

4G wireless all network solar hydrological equipment power monitoring system bms110

Inputstream/outputstream (input and output of file)

C réaliser des jeux de serpents gourmands

Learn about the Internet of things protocol WiFi ZigBee Bluetooth, etc. --- WiFi and WiFi protocols start from WiFi. What do we need to know about WiFi protocol itself?

【MySQL】数据库视图的介绍、作用、创建、查看、删除和修改(附练习题)

Layoutmanager layout manager: flowlayout, borderlayout, GridLayout, gridbaglayout, CardLayout, BoxLayout

P26-P34 third_ template
随机推荐
Option (024) - do all objects have prototypes?
MySQL information_ Schema database
[backpack DP] backpack problem
How to implement cross domain requests
After the festival, a large number of people change careers. Is it still time to be 30? Listen to the experience of the past people
What is the sheji principle?
what the fuck! If you can't grab it, write it yourself. Use code to realize a Bing Dwen Dwen. It's so beautiful ~!
STC8H开发(十二): I2C驱动AT24C08,AT24C32系列EEPROM存储
thread priority
tars源码分析之6
tars源码分析之1
198. House raiding
QT qtablewidget table column top requirements ideas and codes
Mysql 45讲学习笔记(十一)字符串字段怎么加索引
[Android reverse] function interception (CPU cache mechanism | CPU cache mechanism causes function interception failure)
C實現貪吃蛇小遊戲
Lightroom import picture gray / Black rectangular multi display
《ClickHouse原理解析与应用实践》读书笔记(4)
【MySQL】数据库视图的介绍、作用、创建、查看、删除和修改(附练习题)
Mysql 45讲学习笔记(六)全局锁