当前位置:网站首页>tars源码分析之5
tars源码分析之5
2022-07-04 06:33:00 【涛歌依旧】
cgi的相关实现,一起来看下,还是很常规的:
#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控件名称:" + _sFileName + "] ";
sBuffer += " [真实文件名称:" + _sRealFileName + "] ";
sBuffer += " [服务器端文件名称:" + _sServerFileName + "] ";
sBuffer += " [大小(字节):" + TC_Common::tostr(_iSize) + "] ";
sBuffer += " [超过大小限制:" + 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)
{
//文件上传模式
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) //最后一个参数
{
sName = decodeURL(TC_Common::trimleft(sName, " "));
sValue = decodeURL(sValue);
mpCookies[sName] = sValue;
sName = "";
sValue= "";
}
iFlag = 0; //取值
}
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; //取名称
}
}
else if (iFlag)
{
sName += sBuffer[pos];
}
else
{
sValue += sBuffer[pos];
}
++pos;
}
}
void TC_Cgi::ignoreLine()
{
string sBuffer;
//读取直到有一个空行
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;
}
//内容写入文件
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");
}
//控件名称
sName = sBuffer.substr(pos1, pos2 - pos1);
pos1 = sBuffer.find("filename=\"");
if(pos1 != string::npos)
{
FILE *fp = NULL;
string sTheFile;
//上传文件的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");
}
//获取文件名
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));
//组成文件名称
string sUploadFileName = _sUploadFilePrefix + "_" + TC_Common::tostr(_mpUpload.size());
//记录上传文件路径
_mpUpload[sName]._sFileName = sName;
_mpUpload[sName]._sRealFileName = sValue;
_mpUpload[sName]._sServerFileName = sUploadFileName;
sTheFile = sName;
//打开文件
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;
//读取内容到文件
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;
}
//新的一个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));
//新的一个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;
}
}
边栏推荐
- AWT introduction
- JSON web token -- comparison between JWT and traditional session login authentication
- lightroom 导入图片灰色/黑色矩形 多显示器
- High performance parallel programming and optimization | lesson 02 homework at home
- ADC voltage calculation of STM32 single chip microcomputer
- buuctf-pwn write-ups (8)
- Detectron: train your own data set -- convert your own data format to coco format
- uniapp 自定义环境变量
- What is a spotlight effect?
- MySQL installation and configuration
猜你喜欢
R统计绘图-随机森林分类分析及物种丰度差异检验组合图
buuctf-pwn write-ups (8)
树形dp
C實現貪吃蛇小遊戲
Functions in C language (detailed explanation)
如何避免 JVM 内存泄漏?
How to use multithreading to export excel under massive data? Source code attached!
2022 wechat enterprise mailbox login entry introduction, how to open and register enterprise wechat enterprise mailbox?
Review | categories and mechanisms of action of covid-19 neutralizing antibodies and small molecule drugs
Error CVC complex type 2.4. a: Invalid content beginning with element 'base extension' was found. Should start with one of '{layoutlib}'.
随机推荐
ES6 modularization
CORS is not intended to protect API endpoints - nikofischer
采用中微BATG135实现IIC数据/指令交互
Detectron: train your own data set -- convert your own data format to coco format
Detailed explanation of common APIs for component and container containers: frame, panel, scrollpane
Tree DP
Internet of things protocol ZigBee ZigBee module uses the concept of protocol stack
Stc8h development (XII): I2C drive AT24C08, at24c32 series EEPROM storage
C实现贪吃蛇小游戏
QT QTableWidget 表格列置顶需求的思路和代码
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?
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
Layoutmanager layout manager: flowlayout, borderlayout, GridLayout, gridbaglayout, CardLayout, BoxLayout
Reading notes of Clickhouse principle analysis and Application Practice (4)
树形dp
微信小程序使用rich-text中图片宽度超出问题
List of top ten professional skills required for data science work
Software keywords and process information intercepted by Golden Shield video player
Mysql 45讲学习笔记(十三)表数据删掉一半,表文件大小不变
C realize Snake games