code_app/sdk/webservice/HttpHead.cpp

438 lines
8.7 KiB
C++
Raw Normal View History

#include "HttpHead.h"
const unsigned int asciiTableData[256] =
{
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
0x004, 0x104, 0x104, 0x004, 0x104, 0x104, 0x004, 0x004,
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
0x140, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459,
0x459, 0x459, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
0x0d0, 0x653, 0x653, 0x653, 0x653, 0x653, 0x653, 0x253,
0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
0x253, 0x253, 0x253, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
0x0d0, 0x473, 0x473, 0x473, 0x473, 0x473, 0x473, 0x073,
0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
0x073, 0x073, 0x073, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x004
/* the upper 128 are all zeroes */
};
static void TrimString(std::string& str)
{
std::string str1;
bool add1 = false;
std::string::const_iterator iter1;
for (iter1 = str.begin(); iter1 != str.end(); ++iter1)
{
int c = (HGByte)(*iter1);
if (!add1)
{
if (!isspace(c))
{
str1.push_back(c);
add1 = true;
}
}
else
{
str1.push_back(c);
}
}
if (str1.empty())
{
str.clear();
return;
}
std::string str2;
bool add2 = false;
std::string::const_reverse_iterator iter2;
for (iter2 = str1.rbegin(); iter2 != str1.rend(); ++iter2)
{
int c = (HGByte)(*iter2);
if (!add2)
{
if (!isspace(c))
{
str2.push_back(c);
add2 = true;
}
}
else
{
str2.push_back(c);
}
}
if (str2.empty())
{
str.clear();
return;
}
str = std::string(str2.rbegin(), str2.rend());
}
HttpHead::HttpHead()
{
}
HttpHead::~HttpHead()
{
}
bool HttpHead::Parse(const std::string& head)
{
AnalysisHead(head, m_requestMethod, m_requestURIPath, m_requestURIQueryInfos,
m_requestURIFragment, m_requestHttpVersion, m_headInfos);
return true;
}
void HttpHead::Clear()
{
m_requestMethod.clear();
m_requestURIPath.clear();
m_requestURIQueryInfos.clear();
m_requestURIFragment.clear();
m_requestHttpVersion.clear();
m_headInfos.clear();
}
std::string HttpHead::GetRequestMethod() const
{
return m_requestMethod;
}
std::string HttpHead::GetRequestURIPath() const
{
return m_requestURIPath;
}
HttpPairs HttpHead::GetRequestURIQueryInfos() const
{
return m_requestURIQueryInfos;
}
std::string HttpHead::GetRequestURIFragment() const
{
return m_requestURIFragment;
}
std::string HttpHead::GetRequestHttpVersion() const
{
return m_requestHttpVersion;
}
HttpPairs HttpHead::GetHeadInfos() const
{
return m_headInfos;
}
int HttpHead::GetContentLength() const
{
int len = 0;
for (int i = 0; i < (int)m_headInfos.size(); ++i)
{
#if defined(HG_CMP_MSC)
if (0 == _stricmp("Content-Length", m_headInfos[i].first.c_str()))
#else
if (0 == strcasecmp("Content-Length", m_headInfos[i].first.c_str()))
#endif
{
len = atoi(m_headInfos[i].second.c_str());
break;
}
}
return len;
}
std::string HttpHead::GetContentType() const
{
std::string type;
for (int i = 0; i < (int)m_headInfos.size(); ++i)
{
#if defined(HG_CMP_MSC)
if (0 == _stricmp("Content-Type", m_headInfos[i].first.c_str()))
#else
if (0 == strcasecmp("Content-Type", m_headInfos[i].first.c_str()))
#endif
{
type = m_headInfos[i].second.c_str();
break;
}
}
return type;
}
std::string HttpHead::GetValue(const HttpPairs& infos, const std::string& key)
{
std::string value;
for (int i = 0; i < (int)infos.size(); ++i)
{
if (key == infos[i].first)
{
value = infos[i].second;
break;
}
}
return value;
}
void HttpHead::AnalysisURIQuery(const std::string& query, HttpPairs& queryInfos)
{
std::vector<std::string> queryList;
char* p = new char[query.size() + 1];
strcpy(p, query.c_str());
char* pStr = strtok(p, "&");
if (NULL != pStr)
queryList.push_back(pStr);
while (1)
{
pStr = strtok(NULL, "&");
if (NULL == pStr)
break;
queryList.push_back(pStr);
}
delete[] p;
queryInfos.clear();
for (int i = 0; i < (int)queryList.size(); ++i)
{
p = new char[queryList[i].size() + 1];
strcpy(p, queryList[i].c_str());
std::pair <std::string, std::string> pr;
pStr = strtok(p, "=");
if (NULL != pStr)
pr.first = AnalyURIString(pStr);
pStr = strtok(NULL, "=");
if (NULL != pStr)
pr.second = AnalyURIString(pStr);
queryInfos.push_back(pr);
delete[] p;
}
}
void HttpHead::AnalysisURI(const std::string& uri, std::string& path, HttpPairs& queryInfos, std::string& fragment)
{
size_t pathPos = uri.find('/');
size_t queryPos = uri.find('?');
size_t fragmentPos = uri.find('#');
path.clear();
if (std::string::npos != pathPos)
{
size_t count = std::string::npos;
if (queryPos != std::string::npos)
{
assert(queryPos > pathPos);
count = queryPos - pathPos;
}
else if (fragmentPos != std::string::npos)
{
assert(fragmentPos > pathPos);
count = fragmentPos - pathPos;
}
path = AnalyURIString(uri.substr(pathPos, count));
}
queryInfos.clear();
if (std::string::npos != queryPos)
{
size_t count = std::string::npos;
if (fragmentPos != std::string::npos)
{
assert(fragmentPos > queryPos);
count = fragmentPos - queryPos;
}
std::string query = uri.substr(queryPos + 1, count - 1);
AnalysisURIQuery(query, queryInfos);
}
fragment.clear();
if (std::string::npos != fragmentPos)
{
fragment = AnalyURIString(uri.substr(fragmentPos + 1));
}
}
void HttpHead::AnalysisHead(const std::string& head, std::string& requestMethod, std::string& requestURIPath,
HttpPairs& requestURIQueryInfos, std::string& requestURIFragment, std::string& httpVersion, HttpPairs& headInfos)
{
requestMethod.clear();
requestURIPath.clear();
requestURIQueryInfos.clear();
requestURIFragment.clear();
httpVersion.clear();
headInfos.clear();
std::vector<std::string> headList;
char* p = new char[head.size() + 1];
strcpy(p, head.c_str());
char* pStr = strtok(p, "\r\n");
if (NULL != pStr)
headList.push_back(pStr);
while (1)
{
pStr = strtok(NULL, "\r\n");
if (NULL == pStr)
break;
headList.push_back(pStr);
}
delete[] p;
if (headList.size() < 1)
{
return;
}
std::string requestURI;
// 解析请求行
p = new char[headList[0].size() + 1];
strcpy(p, headList[0].c_str());
pStr = strtok(p, " ");
if (NULL != pStr)
requestMethod = pStr;
pStr = strtok(NULL, " ");
if (NULL != pStr)
requestURI = pStr;
pStr = strtok(NULL, " ");
if (NULL != pStr)
httpVersion = pStr;
delete[] p;
// 解析URI
AnalysisURI(requestURI, requestURIPath, requestURIQueryInfos, requestURIFragment);
// 解析请求头
for (int i = 1; i < (int)headList.size(); ++i)
{
p = new char[headList[i].size() + 1];
strcpy(p, headList[i].c_str());
std::pair <std::string, std::string> pr;
pStr = strtok(p, ":");
if (NULL != pStr)
pr.first = pStr;
pStr = strtok(NULL, ":");
if (NULL != pStr)
pr.second = pStr;
TrimString(pr.first);
TrimString(pr.second);
headInfos.push_back(pr);
delete[] p;
}
}
/*判断ascii码是否是数字0-9*/
static bool asciiIsDigit(char c)
{
/*字符的ascii码&8 结果为0-127则是数字*/
return asciiTableData[(unsigned char)c & (1 << 3)];
}
static int asciiDigitValue(char c)
{
if (asciiIsDigit(c))
return c - '0';
return -1;
}
static int asciiXdigitValue(char c)
{
//printf("-->%c\n",c);
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;//(A B C D E F)->(10 11 12 13 14 15)
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
return asciiDigitValue(c);//('0'...'9')->(0...9)
}
static int unescapeCharacter(const char* scanner)
{
int first = asciiXdigitValue(scanner[0]);
if (first < 0)
return -1;
int second = asciiXdigitValue(scanner[1]);
if (second < 0)
return -1;
return (first << 4) | second; //== (first*16 | second) == (first*16 + second)
}
static char* unescapeUriString(const char* uriString, bool asciiEscape)
{
if (NULL == uriString)
return NULL;
int strLen = (int)strlen(uriString);
char* result = (char*)malloc(strLen + 1);//可推测解码后的长度<=原长度
char* out = result;
const char* in, * end;
for (in = uriString, end = in + strLen; in < end; ++in)
{
int c = *in;
//遇到了'%'才去解析
if ('%' == c)
{
if (in + 3 > end)
break;
//获取%后2个字符的解码值
c = unescapeCharacter(in + 1);
if (c <= 0)
break;
if (asciiEscape && c <= 0x7F)
break;
in += 2;//一般的格式为%后加两个ascii码字符
}
*out++ = c;//存储转义结果
}
*out = '\0';
if (in != end)
{
free(result);
return NULL;
}
return result;
}
std::string HttpHead::AnalyURIString(const std::string& str)
{
std::string ret;
char* decodeStr = unescapeUriString(str.c_str(), false);
if (NULL != decodeStr)
{
ret = decodeStr;
free(decodeStr);
}
return ret;
}