forked from LosaDev/ls-2019-source
LosaDev source snapshot 2019
This commit is contained in:
commit
c198676e97
20588 files changed
+8812878
No files matched your search
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* Copyright 2008-2009 Cheng Shi. All rights reserved.
|
||||
* Email: [email protected]
|
||||
*/
|
||||
|
||||
#ifndef REGEXP_H
|
||||
#define REGEXP_H
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 6385 6011 4127)
|
||||
#include "atlrx.h"
|
||||
#pragma warning(pop)
|
||||
|
||||
/*
|
||||
* Parameters
|
||||
* [in] regExp: Value of type string which is the input regular expression.
|
||||
* [in] caseSensitive: Value of type bool which indicate whether the parse is case sensitive.
|
||||
* [in] groupCount: Value of type int which is the group count of the regular expression.
|
||||
* [in] source: Value of type string reference which is the source to parse.
|
||||
* [out] result: Value of type vecotr of strings which is the output of the parse.
|
||||
* [in] allowDuplicate: Value of type bool which indicates whether duplicate items are added to the output result.
|
||||
*
|
||||
* Return Value
|
||||
* Returns true if the function succeeds, or false otherwise.
|
||||
*
|
||||
* Remarks
|
||||
* The output result is devided into groups. User should get the groups according to the group count. For example:
|
||||
* 1. RegExp = L"{ab}", source = L"abcabe", then result = L"ab", L"ab".
|
||||
* 2. RegExp = L"{ab}{cd}", source = L"abcdeabecd", then result = L"ab", L"cd", L"ab", L"cd".
|
||||
*/
|
||||
inline bool ParseRegExp(const wstring ®Exp, bool caseSensitive, int groupCount, const wstring &source, vector<wstring> &result, bool allowDuplicate = false)
|
||||
{
|
||||
result.clear();
|
||||
if (regExp.size() <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (groupCount <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (source.size() <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CAtlRegExp<CAtlRECharTraitsW> re;
|
||||
REParseError error = re.Parse(regExp.c_str(), caseSensitive);
|
||||
if (error != REPARSE_ERROR_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
wchar_t *pSource = new wchar_t[source.size()+1];
|
||||
wchar_t *pSourceEnd = pSource + source.size();
|
||||
if (pSource == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
wcscpy_s(pSource, source.size()+1, source.c_str());
|
||||
BOOL bSucceed = TRUE;
|
||||
CAtlREMatchContext<CAtlRECharTraitsW> mc;
|
||||
const wchar_t *pFrom = pSource;
|
||||
const wchar_t *pTo = NULL;
|
||||
while (bSucceed)
|
||||
{
|
||||
bSucceed = re.Match(pFrom, &mc, &pTo);
|
||||
if (bSucceed)
|
||||
{
|
||||
const wchar_t *pStart = NULL;
|
||||
const wchar_t *pEnd = NULL;
|
||||
vector<wstring> tempMatch;
|
||||
for (int i = 0; i < groupCount; i++)
|
||||
{
|
||||
mc.GetMatch(i, &pStart, &pEnd);
|
||||
if (pStart != NULL && pEnd != NULL)
|
||||
{
|
||||
wstring match(pStart, pEnd-pStart);
|
||||
tempMatch.push_back(match);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool bAdd = true;
|
||||
if (!allowDuplicate)
|
||||
{
|
||||
// Check whether this match already exists in the vector.
|
||||
for (vector<wstring>::iterator it = result.begin(); it != result.end();)
|
||||
{
|
||||
bool bEqual = true;
|
||||
for (vector<wstring>::iterator tempMatchIt = tempMatch.begin(); tempMatchIt != tempMatch.end(); tempMatchIt++, it++)
|
||||
{
|
||||
bool bGroupEqual = true;
|
||||
if (caseSensitive)
|
||||
{
|
||||
bGroupEqual = (wcscmp(it->c_str(), tempMatchIt->c_str()) == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bGroupEqual = (_wcsicmp(it->c_str(), tempMatchIt->c_str()) == 0);
|
||||
}
|
||||
if (!bGroupEqual)
|
||||
{
|
||||
bEqual = false;
|
||||
}
|
||||
}
|
||||
if (bEqual)
|
||||
{
|
||||
bAdd = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bAdd)
|
||||
{
|
||||
for (vector<wstring>::iterator tempMatchIt = tempMatch.begin(); tempMatchIt != tempMatch.end(); tempMatchIt++)
|
||||
{
|
||||
result.push_back(*tempMatchIt);
|
||||
}
|
||||
}
|
||||
if (pTo < pSourceEnd)
|
||||
{
|
||||
pFrom = pTo;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] pSource;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // REGEXP_H
|
||||
@@ -0,0 +1,569 @@
|
||||
/**
|
||||
* Copyright 2008-2009 Cheng Shi. All rights reserved.
|
||||
* Email: [email protected]
|
||||
*/
|
||||
|
||||
#ifndef STRINGPROCESS_H
|
||||
#define STRINGPROCESS_H
|
||||
|
||||
#include "RegExp.h"
|
||||
#include <Windows.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <comutil.h>
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127)
|
||||
#include <atlcomtime.h>
|
||||
#pragma warning(pop)
|
||||
using namespace std;
|
||||
|
||||
inline wstring Trim(const wstring &source, const wstring &targets)
|
||||
{
|
||||
wstring::size_type start = 0;
|
||||
wstring::size_type end = 0;
|
||||
for (start = 0; start < source.size(); start++)
|
||||
{
|
||||
bool bIsTarget = false;
|
||||
for (wstring::size_type i = 0; i < targets.size(); i++)
|
||||
{
|
||||
if (source[start] == targets[i])
|
||||
{
|
||||
bIsTarget = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bIsTarget)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (end = source.size() - 1; (int)end >= 0; end--)
|
||||
{
|
||||
bool bIsTarget = false;
|
||||
for (wstring::size_type i = 0; i < targets.size(); i++)
|
||||
{
|
||||
if (source[end] == targets[i])
|
||||
{
|
||||
bIsTarget = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bIsTarget)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
wstring result = L"";
|
||||
if (end >= start && start < source.size() && end >= 0)
|
||||
{
|
||||
result = source.substr(start, end-start+1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool PrepareString(wchar_t *dest, size_t *size, const wstring &src)
|
||||
{
|
||||
if (dest == NULL)
|
||||
{
|
||||
if (size != NULL)
|
||||
{
|
||||
*size = src.size();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size != NULL)
|
||||
{
|
||||
wcsncpy_s(dest, *size, src.c_str(), _TRUNCATE);
|
||||
if (*size <= src.size())
|
||||
{
|
||||
::SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline wstring ReplaceString(const wstring &srcStr, const wstring &oldStr, const wstring &newStr)
|
||||
{
|
||||
if (srcStr.size() <= 0 || oldStr.size() <= 0)
|
||||
{
|
||||
return srcStr;
|
||||
}
|
||||
wstring strReturn = srcStr;
|
||||
wstring::size_type offset = 0;
|
||||
wstring::size_type start = strReturn.find(oldStr);
|
||||
while (start != wstring::npos)
|
||||
{
|
||||
offset = start + newStr.size();
|
||||
strReturn.replace(start, oldStr.size(), newStr);
|
||||
start = strReturn.find(oldStr, offset);
|
||||
}
|
||||
|
||||
return strReturn;
|
||||
}
|
||||
|
||||
inline int StringToInteger(const wstring &number)
|
||||
{
|
||||
if (number.size() <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
wstring num = ReplaceString(number, L",", L"");
|
||||
num = ReplaceString(num, L" ", L"");
|
||||
|
||||
return _wtoi(num.c_str());
|
||||
}
|
||||
|
||||
inline wstring LowerString(const wstring &text)
|
||||
{
|
||||
if (text.size() <= 0)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
unsigned int iLength = text.size() + 1;
|
||||
wchar_t *pTemp = new wchar_t[iLength];
|
||||
if (pTemp == NULL)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
wcscpy_s(pTemp, iLength, text.c_str());
|
||||
_wcslwr_s(pTemp, iLength);
|
||||
wstring retStr = pTemp;
|
||||
delete[] pTemp;
|
||||
|
||||
return retStr;
|
||||
}
|
||||
|
||||
inline wstring UpperString(const wstring &text)
|
||||
{
|
||||
if (text.size() <= 0)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
unsigned int iLength = text.size() + 1;
|
||||
wchar_t *pTemp = new wchar_t[iLength];
|
||||
if (pTemp == NULL)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
wcscpy_s(pTemp, iLength, text.c_str());
|
||||
_wcsupr_s(pTemp, iLength);
|
||||
wstring retStr = pTemp;
|
||||
delete[] pTemp;
|
||||
|
||||
return retStr;
|
||||
}
|
||||
|
||||
inline wstring GetAnchorText(const wstring &anchor)
|
||||
{
|
||||
wstring regExp = L"<a.*?>[ \t\r\n]*{.*?}[ \t\r\n]*</a>";
|
||||
vector<wstring> result;
|
||||
if (ParseRegExp(regExp, false, 1, anchor, result) && result.size() == 1)
|
||||
{
|
||||
wstring text = result[0];
|
||||
return text;
|
||||
}
|
||||
|
||||
return L"";
|
||||
}
|
||||
|
||||
inline wstring GetAnchorLink(const wstring &anchor)
|
||||
{
|
||||
wstring regExp = L"<a.*?href=\"|\'{.*?}\"|\'.*?>.*?</a>";
|
||||
vector<wstring> result;
|
||||
if (ParseRegExp(regExp, false, 1, anchor, result) && result.size() == 1)
|
||||
{
|
||||
wstring link = result[0];
|
||||
return link;
|
||||
}
|
||||
|
||||
return L"";
|
||||
}
|
||||
|
||||
inline bool SeparateString(const wstring &content, const wstring &delimiter, vector<wstring> &result)
|
||||
{
|
||||
if (content.size() <= 0 || delimiter.size() <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
result.clear();
|
||||
wstring::size_type start = 0;
|
||||
wstring::size_type index = 0;
|
||||
index = content.find(delimiter, start);
|
||||
while (index != wstring::npos)
|
||||
{
|
||||
wstring::size_type size = index - start;
|
||||
if (size > 0)
|
||||
{
|
||||
wstring temp = content.substr(start, size);
|
||||
if (temp.size() > 0)
|
||||
{
|
||||
result.push_back(temp);
|
||||
}
|
||||
}
|
||||
start += size + delimiter.size();
|
||||
index = content.find(delimiter, start);
|
||||
}
|
||||
if (content.find(delimiter) != wstring::npos)
|
||||
{
|
||||
wstring last = content.substr(start);
|
||||
if (last.size() > 0)
|
||||
{
|
||||
result.push_back(last);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline wstring URLEncoding(const wstring &keyword, bool convertToUTF8 = true)
|
||||
{
|
||||
int iLength = 0;
|
||||
char *szKeyword = NULL;
|
||||
|
||||
if (convertToUTF8)
|
||||
{
|
||||
iLength = ::WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
keyword.c_str(),
|
||||
keyword.length(),
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (iLength <= 0)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
szKeyword = new char[iLength];
|
||||
if (szKeyword == NULL)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
iLength = ::WideCharToMultiByte(CP_UTF8,
|
||||
0,
|
||||
keyword.c_str(),
|
||||
keyword.length(),
|
||||
szKeyword,
|
||||
iLength,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
string strKeyword = (char *)(_bstr_t)keyword.c_str();
|
||||
iLength = (int)strKeyword.length();
|
||||
szKeyword = new char[strKeyword.length() + 1];
|
||||
strcpy_s(szKeyword, strKeyword.length() + 1, strKeyword.c_str());
|
||||
}
|
||||
|
||||
wstring encodedKeyword = L"";
|
||||
string strEncodedKeyword = "";
|
||||
for (int i = 0; i < iLength; i++)
|
||||
{
|
||||
unsigned char c = (unsigned char)szKeyword[i];
|
||||
char temp[MAX_PATH] = "";
|
||||
sprintf_s(temp, MAX_PATH, "%%%2X", c);
|
||||
if (temp[1] == ' ')
|
||||
{
|
||||
temp[1] = '0';
|
||||
}
|
||||
strEncodedKeyword += temp;
|
||||
}
|
||||
if (szKeyword != NULL)
|
||||
{
|
||||
delete[] szKeyword;
|
||||
}
|
||||
encodedKeyword = (wchar_t *)(_bstr_t)strEncodedKeyword.c_str();
|
||||
encodedKeyword = ReplaceString(encodedKeyword, L" ", L"+");
|
||||
|
||||
return encodedKeyword;
|
||||
}
|
||||
|
||||
inline unsigned int GetSeparateKeywordMatchGrade(const wstring &source, const wstring &keyword)
|
||||
{
|
||||
if (source.length() <= 0 || keyword.length() <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
wstring lowerSource = LowerString(source);
|
||||
wstring lowerKeyword = LowerString(keyword);
|
||||
|
||||
unsigned int grade = 0;
|
||||
if (lowerKeyword.length() <= 3)
|
||||
{
|
||||
if (lowerSource.find(lowerKeyword) != wstring::npos)
|
||||
{
|
||||
grade = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
grade = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int matchLength = 0;
|
||||
unsigned int index = 0;
|
||||
while (index < lowerKeyword.length())
|
||||
{
|
||||
unsigned int compareLength = lowerKeyword.length() - index;
|
||||
while (compareLength > 0 && index < lowerKeyword.length())
|
||||
{
|
||||
wstring subKeyword = lowerKeyword.substr(index, compareLength);
|
||||
if (lowerSource.find(subKeyword) != wstring::npos)
|
||||
{
|
||||
matchLength += compareLength;
|
||||
index += compareLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
compareLength--;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
grade = matchLength * 100 / lowerKeyword.length();
|
||||
}
|
||||
|
||||
return grade;
|
||||
}
|
||||
|
||||
inline unsigned int GetKeywordMatchGrade(const wstring &source, const wstring & keyword)
|
||||
{
|
||||
if (source.length() <= 0 || keyword.length() <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int grade = 0;
|
||||
wstring src = source;
|
||||
while (src.find(L"\t") != wstring::npos)
|
||||
{
|
||||
src = ReplaceString(src, L"\t", L" ");
|
||||
}
|
||||
while (src.find(L" ") != wstring::npos)
|
||||
{
|
||||
src = ReplaceString(src, L" ", L" ");
|
||||
}
|
||||
vector<wstring> results;
|
||||
if (SeparateString(keyword, L" ", results) && results.size() > 0)
|
||||
{
|
||||
unsigned int keywordTotalLength = 0;
|
||||
for (vector<wstring>::size_type index = 0; index < results.size(); index++)
|
||||
{
|
||||
keywordTotalLength += results[index].length();
|
||||
}
|
||||
for (vector<wstring>::size_type index = 0; index < results.size(); index++)
|
||||
{
|
||||
grade += GetSeparateKeywordMatchGrade(src, results[index]) * results[index].length() / keywordTotalLength;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
grade = GetSeparateKeywordMatchGrade(src, keyword);
|
||||
}
|
||||
|
||||
return grade;
|
||||
}
|
||||
|
||||
inline wstring GetDateString(const COleDateTime &time, const wstring &separator = L"-", bool align = true)
|
||||
{
|
||||
wstring date = L"";
|
||||
wchar_t szTemp[MAX_PATH] = L"";
|
||||
|
||||
swprintf_s(szTemp, MAX_PATH, L"%d", time.GetYear());
|
||||
date += szTemp;
|
||||
date += separator;
|
||||
|
||||
memset(szTemp, 0, sizeof(wchar_t) * MAX_PATH);
|
||||
swprintf_s(szTemp, MAX_PATH, L"%d", time.GetMonth());
|
||||
if (time.GetMonth() < 10 && align)
|
||||
{
|
||||
date += L"0";
|
||||
}
|
||||
date += szTemp;
|
||||
date += separator;
|
||||
|
||||
memset(szTemp, 0, sizeof(wchar_t) * MAX_PATH);
|
||||
swprintf_s(szTemp, MAX_PATH, L"%d", time.GetDay());
|
||||
if (time.GetDay() < 10 && align)
|
||||
{
|
||||
date += L"0";
|
||||
}
|
||||
date += szTemp;
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
inline wstring GetDateString(int dayOffset, const wstring &separator = L"-", bool align = true)
|
||||
{
|
||||
COleDateTime time = COleDateTime::GetCurrentTime();
|
||||
time += COleDateTimeSpan(dayOffset, 0, 0, 0);
|
||||
|
||||
return GetDateString(time, separator, align);
|
||||
}
|
||||
|
||||
inline wstring GetTimeString(const COleDateTime &time, const wstring &separator = L":", bool align = true)
|
||||
{
|
||||
wstring date = L"";
|
||||
wchar_t szTemp[MAX_PATH] = L"";
|
||||
|
||||
swprintf_s(szTemp, MAX_PATH, L"%d", time.GetHour());
|
||||
date += szTemp;
|
||||
date += separator;
|
||||
|
||||
memset(szTemp, 0, sizeof(wchar_t) * MAX_PATH);
|
||||
swprintf_s(szTemp, MAX_PATH, L"%d", time.GetMinute());
|
||||
if (time.GetMinute() < 10 && align)
|
||||
{
|
||||
date += L"0";
|
||||
}
|
||||
date += szTemp;
|
||||
date += separator;
|
||||
|
||||
memset(szTemp, 0, sizeof(wchar_t) * MAX_PATH);
|
||||
swprintf_s(szTemp, MAX_PATH, L"%d", time.GetSecond());
|
||||
if (time.GetSecond() < 10 && align)
|
||||
{
|
||||
date += L"0";
|
||||
}
|
||||
date += szTemp;
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
inline wstring MD5(const wstring &text)
|
||||
{
|
||||
if (text.size() <= 0)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
string asciiText = (char *)(_bstr_t)text.c_str();
|
||||
wstring encrypted = L"";
|
||||
HCRYPTPROV hCryptProv = NULL;
|
||||
if (::CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET))
|
||||
{
|
||||
HCRYPTHASH hHash = NULL;
|
||||
if (::CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash))
|
||||
{
|
||||
if (::CryptHashData(hHash, (BYTE *)asciiText.c_str(), asciiText.size(), 0))
|
||||
{
|
||||
BYTE result[16];
|
||||
DWORD dwSize = 16;
|
||||
wchar_t temp[3] = L"";
|
||||
if (::CryptGetHashParam(hHash, HP_HASHVAL, result, &dwSize, 0))
|
||||
{
|
||||
for (unsigned int i = 0; i < 16; i++)
|
||||
{
|
||||
memset(temp, 0, 6);
|
||||
swprintf(temp, 3, L"%02x", result[i]);
|
||||
encrypted += temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
::CryptDestroyHash(hHash);
|
||||
::CryptReleaseContext(hCryptProv, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
inline wstring FilterFileName(const wstring &name)
|
||||
{
|
||||
if (name.size() <= 0)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
wstring filteredName = name;
|
||||
filteredName = ReplaceString(filteredName, L"/", L"_");
|
||||
filteredName = ReplaceString(filteredName, L"\\", L"_");
|
||||
filteredName = ReplaceString(filteredName, L":", L"_");
|
||||
filteredName = ReplaceString(filteredName, L"*", L"_");
|
||||
filteredName = ReplaceString(filteredName, L"?", L"_");
|
||||
filteredName = ReplaceString(filteredName, L"\"", L"_");
|
||||
filteredName = ReplaceString(filteredName, L"<", L"_");
|
||||
filteredName = ReplaceString(filteredName, L">", L"_");
|
||||
filteredName = ReplaceString(filteredName, L"|", L"_");
|
||||
|
||||
return filteredName;
|
||||
}
|
||||
|
||||
inline wstring GetMagic(unsigned int length)
|
||||
{
|
||||
srand(::GetTickCount());
|
||||
if (length <= 0)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
wstring margic = L"";
|
||||
for (unsigned int i = 0; i < length; i++)
|
||||
{
|
||||
wchar_t szMargic[50] = L"";
|
||||
swprintf_s(szMargic, 50, L"%c", rand() % 26 + L'a');
|
||||
margic += szMargic;
|
||||
}
|
||||
|
||||
return margic;
|
||||
}
|
||||
|
||||
inline wstring GetHost(const wstring &url)
|
||||
{
|
||||
if (url.size() <= 0)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
wstring urlWidthoutHttp = ReplaceString(LowerString(url), L"http://", L"");
|
||||
|
||||
unsigned int index = urlWidthoutHttp.find(L"/");
|
||||
if (index == wstring::npos)
|
||||
{
|
||||
index = urlWidthoutHttp.find(L"\\");
|
||||
}
|
||||
if (index == wstring ::npos)
|
||||
{
|
||||
return urlWidthoutHttp;
|
||||
}
|
||||
|
||||
return urlWidthoutHttp.substr(0, index);
|
||||
}
|
||||
|
||||
inline wstring GetValidFileName(const wstring &fileName)
|
||||
{
|
||||
if (fileName.size() == 0)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
wstring tempFileName = fileName;
|
||||
tempFileName = ReplaceString(tempFileName, L"\\", L"_");
|
||||
tempFileName = ReplaceString(tempFileName, L"/", L"_");
|
||||
tempFileName = ReplaceString(tempFileName, L":", L"_");
|
||||
tempFileName = ReplaceString(tempFileName, L"*", L"_");
|
||||
tempFileName = ReplaceString(tempFileName, L"?", L"_");
|
||||
tempFileName = ReplaceString(tempFileName, L"\"", L"_");
|
||||
tempFileName = ReplaceString(tempFileName, L"<", L"_");
|
||||
tempFileName = ReplaceString(tempFileName, L">", L"_");
|
||||
tempFileName = ReplaceString(tempFileName, L"|", L"_");
|
||||
tempFileName = ReplaceString(tempFileName, L"\r", L"_");
|
||||
tempFileName = ReplaceString(tempFileName, L"\n", L"_");
|
||||
tempFileName = ReplaceString(tempFileName, L"%", L"_");
|
||||
|
||||
return tempFileName;
|
||||
}
|
||||
|
||||
#endif // STRINGPROCESS_H
|
||||
@@ -0,0 +1,858 @@
|
||||
/**
|
||||
* Copyright 2008-2010 Cheng Shi. All rights reserved.
|
||||
* Email: [email protected]
|
||||
*/
|
||||
|
||||
#ifndef WINHTTPCLIENT_H
|
||||
#define WINHTTPCLIENT_H
|
||||
|
||||
#pragma comment(lib, "Winhttp.lib")
|
||||
|
||||
#include "RegExp.h"
|
||||
#include "StringProcess.h"
|
||||
#include <comutil.h>
|
||||
#include <windows.h>
|
||||
#include <Winhttp.h>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
typedef bool (*PROGRESSPROC)(double);
|
||||
|
||||
static const unsigned int INT_RETRYTIMES = 3;
|
||||
static wchar_t *SZ_AGENT = L"WinHttpClient";
|
||||
static const int INT_BUFFERSIZE = 10240; // Initial 10 KB temporary buffer, double if it is not enough.
|
||||
|
||||
class WinHttpClient
|
||||
{
|
||||
public:
|
||||
inline WinHttpClient(PROGRESSPROC progressProc = NULL);
|
||||
inline ~WinHttpClient(void);
|
||||
|
||||
void Init();
|
||||
void Destroy();
|
||||
|
||||
public:
|
||||
// It is a synchronized method and may take a long time to finish.
|
||||
inline bool SendHttpRequest(const wstring &httpVerb = L"GET", bool disableAutoRedirect = false);
|
||||
inline wstring GetResponseHeader(void);
|
||||
inline wstring GetResponseContent(void);
|
||||
inline wstring GetResponseCharset(void);
|
||||
inline wstring GetResponseStatusCode(void);
|
||||
inline wstring GetResponseLocation(void);
|
||||
inline wstring GetRequestHost(void);
|
||||
inline const BYTE *GetRawResponseContent(void);
|
||||
inline unsigned int GetRawResponseContentLength(void);
|
||||
inline unsigned int GetRawResponseReceivedContentLength(void);
|
||||
inline bool SaveResponseToFile(const wstring &filePath);
|
||||
inline wstring GetResponseCookies(void);
|
||||
inline bool SetAdditionalRequestCookies(const wstring &cookies);
|
||||
inline bool SetAdditionalDataToSend(BYTE *data, unsigned int dataSize);
|
||||
inline bool UpdateUrl(const wstring &url);
|
||||
inline bool ResetAdditionalDataToSend(void);
|
||||
inline bool SetAdditionalRequestHeaders(const wstring &additionalRequestHeaders);
|
||||
inline bool SetRequireValidSslCertificates(bool require);
|
||||
inline bool SetProxy(const wstring &proxy);
|
||||
inline DWORD GetLastError(void);
|
||||
inline bool SetUserAgent(const wstring &userAgent);
|
||||
inline bool SetForceCharset(const wstring &charset);
|
||||
inline bool SetProxyUsername(const wstring &username);
|
||||
inline bool SetProxyPassword(const wstring &password);
|
||||
inline bool SetTimeouts(unsigned int resolveTimeout = 0,
|
||||
unsigned int connectTimeout = 60000,
|
||||
unsigned int sendTimeout = 30000,
|
||||
unsigned int receiveTimeout = 30000);
|
||||
|
||||
private:
|
||||
inline WinHttpClient(const WinHttpClient &other);
|
||||
inline WinHttpClient &operator =(const WinHttpClient &other);
|
||||
inline bool SetProgress(unsigned int byteCountReceived);
|
||||
|
||||
HINTERNET m_sessionHandle;
|
||||
bool m_requireValidSsl;
|
||||
wstring m_requestURL;
|
||||
wstring m_requestHost;
|
||||
wstring m_responseHeader;
|
||||
wstring m_responseContent;
|
||||
wstring m_responseCharset;
|
||||
BYTE *m_pResponse;
|
||||
unsigned int m_responseByteCountReceived; // Up to 4GB.
|
||||
PROGRESSPROC m_pfProcessProc;
|
||||
unsigned int m_responseByteCount;
|
||||
wstring m_responseCookies;
|
||||
wstring m_additionalRequestCookies;
|
||||
BYTE *m_pDataToSend;
|
||||
unsigned int m_dataToSendSize;
|
||||
wstring m_additionalRequestHeaders;
|
||||
wstring m_proxy;
|
||||
DWORD m_dwLastError;
|
||||
wstring m_statusCode;
|
||||
wstring m_userAgent;
|
||||
bool m_bForceCharset;
|
||||
wstring m_proxyUsername;
|
||||
wstring m_proxyPassword;
|
||||
wstring m_location;
|
||||
unsigned int m_resolveTimeout;
|
||||
unsigned int m_connectTimeout;
|
||||
unsigned int m_sendTimeout;
|
||||
unsigned int m_receiveTimeout;
|
||||
};
|
||||
|
||||
WinHttpClient::WinHttpClient(PROGRESSPROC progressProc)
|
||||
: m_sessionHandle(NULL),
|
||||
m_requireValidSsl(false),
|
||||
m_responseHeader(L""),
|
||||
m_responseContent(L""),
|
||||
m_responseCharset(L""),
|
||||
m_requestHost(L""),
|
||||
m_pResponse(NULL),
|
||||
m_responseByteCountReceived(0),
|
||||
m_pfProcessProc(progressProc),
|
||||
m_responseByteCount(0),
|
||||
m_responseCookies(L""),
|
||||
m_additionalRequestCookies(L""),
|
||||
m_pDataToSend(NULL),
|
||||
m_dataToSendSize(0),
|
||||
m_proxy(L""),
|
||||
m_dwLastError(0),
|
||||
m_statusCode(L""),
|
||||
m_userAgent(SZ_AGENT),
|
||||
m_bForceCharset(false),
|
||||
m_proxyUsername(L""),
|
||||
m_proxyPassword(L""),
|
||||
m_location(L""),
|
||||
m_resolveTimeout(0),
|
||||
m_connectTimeout(60000),
|
||||
m_sendTimeout(30000),
|
||||
m_receiveTimeout(30000)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
WinHttpClient::~WinHttpClient(void)
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void WinHttpClient::Init()
|
||||
{
|
||||
m_requestURL = L"";
|
||||
}
|
||||
|
||||
void WinHttpClient::Destroy()
|
||||
{
|
||||
if (m_pResponse != NULL)
|
||||
{
|
||||
delete[] m_pResponse;
|
||||
}
|
||||
if (m_pDataToSend != NULL)
|
||||
{
|
||||
delete[] m_pDataToSend;
|
||||
}
|
||||
|
||||
if (m_sessionHandle != NULL)
|
||||
{
|
||||
::WinHttpCloseHandle(m_sessionHandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool WinHttpClient::SendHttpRequest(const wstring &httpVerb, bool disableAutoRedirect)
|
||||
{
|
||||
if (m_requestURL.size() <= 0)
|
||||
{
|
||||
m_dwLastError = ERROR_PATH_NOT_FOUND;
|
||||
return false;
|
||||
}
|
||||
// Make verb uppercase.
|
||||
wstring verb = httpVerb;
|
||||
if (_wcsicmp(httpVerb.c_str(), L"GET") == 0)
|
||||
{
|
||||
verb = L"GET";
|
||||
}
|
||||
else if (_wcsicmp(verb.c_str(), L"POST") == 0)
|
||||
{
|
||||
verb = L"POST";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dwLastError = ERROR_INVALID_PARAMETER;
|
||||
return false;
|
||||
}
|
||||
bool bRetVal = true;
|
||||
|
||||
if (m_sessionHandle == NULL)
|
||||
{
|
||||
m_sessionHandle = ::WinHttpOpen(m_userAgent.c_str(),
|
||||
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
||||
WINHTTP_NO_PROXY_NAME,
|
||||
WINHTTP_NO_PROXY_BYPASS,
|
||||
0);
|
||||
if (m_sessionHandle == NULL)
|
||||
{
|
||||
m_dwLastError = ::GetLastError();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
::WinHttpSetTimeouts(m_sessionHandle,
|
||||
m_resolveTimeout,
|
||||
m_connectTimeout,
|
||||
m_sendTimeout,
|
||||
m_receiveTimeout);
|
||||
|
||||
wchar_t szHostName[MAX_PATH] = L"";
|
||||
wchar_t szURLPath[MAX_PATH * 5] = L"";
|
||||
URL_COMPONENTS urlComp;
|
||||
memset(&urlComp, 0, sizeof(urlComp));
|
||||
urlComp.dwStructSize = sizeof(urlComp);
|
||||
urlComp.lpszHostName = szHostName;
|
||||
urlComp.dwHostNameLength = MAX_PATH;
|
||||
urlComp.lpszUrlPath = szURLPath;
|
||||
urlComp.dwUrlPathLength = MAX_PATH * 5;
|
||||
urlComp.dwSchemeLength = 1; // None zero
|
||||
|
||||
if (::WinHttpCrackUrl(m_requestURL.c_str(), m_requestURL.size(), 0, &urlComp))
|
||||
{
|
||||
m_requestHost = szHostName;
|
||||
HINTERNET hConnect = NULL;
|
||||
hConnect = ::WinHttpConnect(m_sessionHandle, szHostName, urlComp.nPort, 0);
|
||||
if (hConnect != NULL)
|
||||
{
|
||||
DWORD dwOpenRequestFlag = (urlComp.nScheme == INTERNET_SCHEME_HTTPS) ? WINHTTP_FLAG_SECURE : 0;
|
||||
HINTERNET hRequest = NULL;
|
||||
hRequest = ::WinHttpOpenRequest(hConnect,
|
||||
verb.c_str(),
|
||||
urlComp.lpszUrlPath,
|
||||
NULL,
|
||||
WINHTTP_NO_REFERER,
|
||||
WINHTTP_DEFAULT_ACCEPT_TYPES,
|
||||
dwOpenRequestFlag);
|
||||
if (hRequest != NULL)
|
||||
{
|
||||
// If HTTPS, then client is very susceptable to invalid certificates
|
||||
// Easiest to accept anything for now
|
||||
if (!m_requireValidSsl && urlComp.nScheme == INTERNET_SCHEME_HTTPS)
|
||||
{
|
||||
DWORD options = SECURITY_FLAG_IGNORE_CERT_CN_INVALID
|
||||
| SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
|
||||
| SECURITY_FLAG_IGNORE_UNKNOWN_CA;
|
||||
::WinHttpSetOption(hRequest,
|
||||
WINHTTP_OPTION_SECURITY_FLAGS,
|
||||
(LPVOID)&options,
|
||||
sizeof(DWORD));
|
||||
}
|
||||
|
||||
bool bGetReponseSucceed = false;
|
||||
unsigned int iRetryTimes = 0;
|
||||
|
||||
// Retry for several times if fails.
|
||||
while (!bGetReponseSucceed && iRetryTimes++ < INT_RETRYTIMES)
|
||||
{
|
||||
if (m_additionalRequestHeaders.size() > 0)
|
||||
{
|
||||
if (!::WinHttpAddRequestHeaders(hRequest, m_additionalRequestHeaders.c_str(), m_additionalRequestHeaders.size(), WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON))
|
||||
{
|
||||
m_dwLastError = ::GetLastError();
|
||||
}
|
||||
}
|
||||
if (m_additionalRequestCookies.size() > 0)
|
||||
{
|
||||
wstring cookies = L"Cookie: ";
|
||||
cookies += m_additionalRequestCookies;
|
||||
if (!::WinHttpAddRequestHeaders(hRequest, cookies.c_str(), cookies.size(), WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON))
|
||||
{
|
||||
m_dwLastError = ::GetLastError();
|
||||
}
|
||||
}
|
||||
if (m_proxy.size() > 0)
|
||||
{
|
||||
WINHTTP_PROXY_INFO proxyInfo;
|
||||
memset(&proxyInfo, 0, sizeof(proxyInfo));
|
||||
proxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
|
||||
wchar_t szProxy[MAX_PATH] = L"";
|
||||
wcscpy_s(szProxy, MAX_PATH, m_proxy.c_str());
|
||||
proxyInfo.lpszProxy = szProxy;
|
||||
|
||||
if (!::WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo)))
|
||||
{
|
||||
m_dwLastError = ::GetLastError();
|
||||
}
|
||||
|
||||
if (m_proxyUsername.size() > 0)
|
||||
{
|
||||
if (!::WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY_USERNAME, (LPVOID)m_proxyUsername.c_str(), m_proxyUsername.size() * sizeof(wchar_t)))
|
||||
{
|
||||
m_dwLastError = ::GetLastError();
|
||||
}
|
||||
if (m_proxyPassword.size() > 0)
|
||||
{
|
||||
if (!::WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY_PASSWORD, (LPVOID)m_proxyPassword.c_str(), m_proxyPassword.size() * sizeof(wchar_t)))
|
||||
{
|
||||
m_dwLastError = ::GetLastError();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (disableAutoRedirect)
|
||||
{
|
||||
DWORD dwDisableFeature = WINHTTP_DISABLE_REDIRECTS;
|
||||
if (!::WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &dwDisableFeature, sizeof(dwDisableFeature)))
|
||||
{
|
||||
m_dwLastError = ::GetLastError();
|
||||
}
|
||||
}
|
||||
bool bSendRequestSucceed = false;
|
||||
if (::WinHttpSendRequest(hRequest,
|
||||
WINHTTP_NO_ADDITIONAL_HEADERS,
|
||||
0,
|
||||
WINHTTP_NO_REQUEST_DATA,
|
||||
0,
|
||||
0,
|
||||
NULL))
|
||||
{
|
||||
bSendRequestSucceed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Query the proxy information from IE setting and set the proxy if any.
|
||||
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig;
|
||||
memset(&proxyConfig, 0, sizeof(proxyConfig));
|
||||
if (::WinHttpGetIEProxyConfigForCurrentUser(&proxyConfig))
|
||||
{
|
||||
if (proxyConfig.lpszAutoConfigUrl != NULL)
|
||||
{
|
||||
WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions;
|
||||
memset(&autoProxyOptions, 0, sizeof(autoProxyOptions));
|
||||
autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL;
|
||||
autoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP;
|
||||
autoProxyOptions.lpszAutoConfigUrl = proxyConfig.lpszAutoConfigUrl;
|
||||
autoProxyOptions.fAutoLogonIfChallenged = TRUE;
|
||||
autoProxyOptions.dwReserved = 0;
|
||||
autoProxyOptions.lpvReserved = NULL;
|
||||
|
||||
WINHTTP_PROXY_INFO proxyInfo;
|
||||
memset(&proxyInfo, 0, sizeof(proxyInfo));
|
||||
|
||||
if (::WinHttpGetProxyForUrl(m_sessionHandle, m_requestURL.c_str(), &autoProxyOptions, &proxyInfo))
|
||||
{
|
||||
if (::WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo)))
|
||||
{
|
||||
if (::WinHttpSendRequest(hRequest,
|
||||
WINHTTP_NO_ADDITIONAL_HEADERS,
|
||||
0,
|
||||
WINHTTP_NO_REQUEST_DATA,
|
||||
0,
|
||||
0,
|
||||
NULL))
|
||||
{
|
||||
bSendRequestSucceed = true;
|
||||
}
|
||||
}
|
||||
if (proxyInfo.lpszProxy != NULL)
|
||||
{
|
||||
::GlobalFree(proxyInfo.lpszProxy);
|
||||
}
|
||||
if (proxyInfo.lpszProxyBypass != NULL)
|
||||
{
|
||||
::GlobalFree(proxyInfo.lpszProxyBypass);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dwLastError = ::GetLastError();
|
||||
}
|
||||
}
|
||||
else if (proxyConfig.lpszProxy != NULL)
|
||||
{
|
||||
WINHTTP_PROXY_INFO proxyInfo;
|
||||
memset(&proxyInfo, 0, sizeof(proxyInfo));
|
||||
proxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
|
||||
wchar_t szProxy[MAX_PATH] = L"";
|
||||
wcscpy_s(szProxy, MAX_PATH, proxyConfig.lpszProxy);
|
||||
proxyInfo.lpszProxy = szProxy;
|
||||
|
||||
if (proxyConfig.lpszProxyBypass != NULL)
|
||||
{
|
||||
wchar_t szProxyBypass[MAX_PATH] = L"";
|
||||
wcscpy_s(szProxyBypass, MAX_PATH, proxyConfig.lpszProxyBypass);
|
||||
proxyInfo.lpszProxyBypass = szProxyBypass;
|
||||
}
|
||||
|
||||
if (!::WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo)))
|
||||
{
|
||||
m_dwLastError = ::GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
if (proxyConfig.lpszAutoConfigUrl != NULL)
|
||||
{
|
||||
::GlobalFree(proxyConfig.lpszAutoConfigUrl);
|
||||
}
|
||||
if (proxyConfig.lpszProxy != NULL)
|
||||
{
|
||||
::GlobalFree(proxyConfig.lpszProxy);
|
||||
}
|
||||
if (proxyConfig.lpszProxyBypass != NULL)
|
||||
{
|
||||
::GlobalFree(proxyConfig.lpszProxyBypass);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dwLastError = ::GetLastError();
|
||||
}
|
||||
}
|
||||
if (bSendRequestSucceed)
|
||||
{
|
||||
if (m_pDataToSend != NULL)
|
||||
{
|
||||
DWORD dwWritten = 0;
|
||||
if (!::WinHttpWriteData(hRequest,
|
||||
m_pDataToSend,
|
||||
m_dataToSendSize,
|
||||
&dwWritten))
|
||||
{
|
||||
m_dwLastError = ::GetLastError();
|
||||
}
|
||||
}
|
||||
if (::WinHttpReceiveResponse(hRequest, NULL))
|
||||
{
|
||||
DWORD dwSize = 0;
|
||||
BOOL bResult = FALSE;
|
||||
bResult = ::WinHttpQueryHeaders(hRequest,
|
||||
WINHTTP_QUERY_RAW_HEADERS_CRLF,
|
||||
WINHTTP_HEADER_NAME_BY_INDEX,
|
||||
NULL,
|
||||
&dwSize,
|
||||
WINHTTP_NO_HEADER_INDEX);
|
||||
if (bResult || (!bResult && (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)))
|
||||
{
|
||||
wchar_t *szHeader = new wchar_t[dwSize];
|
||||
if (szHeader != NULL)
|
||||
{
|
||||
memset(szHeader, 0, dwSize* sizeof(wchar_t));
|
||||
if (::WinHttpQueryHeaders(hRequest,
|
||||
WINHTTP_QUERY_RAW_HEADERS_CRLF,
|
||||
WINHTTP_HEADER_NAME_BY_INDEX,
|
||||
szHeader,
|
||||
&dwSize,
|
||||
WINHTTP_NO_HEADER_INDEX))
|
||||
{
|
||||
m_responseHeader.assign(szHeader);
|
||||
vector<wstring> result;
|
||||
wstring regExp = L"";
|
||||
if (!m_bForceCharset)
|
||||
{
|
||||
regExp = L"charset={[A-Za-z0-9\\-_]+}";
|
||||
if (ParseRegExp(regExp, false, 1, m_responseHeader, result) && result.size() > 0)
|
||||
{
|
||||
m_responseCharset = result[0];
|
||||
}
|
||||
}
|
||||
regExp = L"Content-Length: {[0-9]+}";
|
||||
if (ParseRegExp(regExp, false, 1, m_responseHeader, result) && result.size() > 0)
|
||||
{
|
||||
m_responseByteCount = (unsigned int)_wtoi(result[0].c_str());
|
||||
}
|
||||
regExp = L"Location: {[0-9]+}";
|
||||
if (ParseRegExp(regExp, false, 1, m_responseHeader, result) && result.size() > 0)
|
||||
{
|
||||
m_location = result[0];
|
||||
}
|
||||
regExp = L"Set-Cookie:\\b*{.+?}\\n";
|
||||
if (ParseRegExp(regExp, false, 1, m_responseHeader, result) && result.size() > 0)
|
||||
{
|
||||
for (vector<wstring>::size_type i = 0; i < result.size(); i++)
|
||||
{
|
||||
m_responseCookies += result[i];
|
||||
if (i != result.size() - 1)
|
||||
{
|
||||
m_responseCookies += L"; ";
|
||||
}
|
||||
}
|
||||
m_responseCookies = Trim(m_responseCookies, L" ");
|
||||
if (m_responseCookies.size() > 0 && m_responseCookies[m_responseCookies.size() - 1] != L';')
|
||||
{
|
||||
m_responseCookies += L";";
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] szHeader;
|
||||
}
|
||||
}
|
||||
|
||||
dwSize = 0;
|
||||
bResult = ::WinHttpQueryHeaders(hRequest,
|
||||
WINHTTP_QUERY_STATUS_CODE,
|
||||
WINHTTP_HEADER_NAME_BY_INDEX,
|
||||
NULL,
|
||||
&dwSize,
|
||||
WINHTTP_NO_HEADER_INDEX);
|
||||
if (bResult || (!bResult && (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)))
|
||||
{
|
||||
wchar_t *szStatusCode = new wchar_t[dwSize];
|
||||
if (szStatusCode != NULL)
|
||||
{
|
||||
memset(szStatusCode, 0, dwSize* sizeof(wchar_t));
|
||||
if (::WinHttpQueryHeaders(hRequest,
|
||||
WINHTTP_QUERY_STATUS_CODE,
|
||||
WINHTTP_HEADER_NAME_BY_INDEX,
|
||||
szStatusCode,
|
||||
&dwSize,
|
||||
WINHTTP_NO_HEADER_INDEX))
|
||||
{
|
||||
m_statusCode = szStatusCode;
|
||||
}
|
||||
delete[] szStatusCode;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int iMaxBufferSize = INT_BUFFERSIZE;
|
||||
unsigned int iCurrentBufferSize = 0;
|
||||
if (m_pResponse != NULL)
|
||||
{
|
||||
delete[] m_pResponse;
|
||||
m_pResponse = NULL;
|
||||
}
|
||||
m_pResponse = new BYTE[iMaxBufferSize];
|
||||
if (m_pResponse == NULL)
|
||||
{
|
||||
bRetVal = false;
|
||||
break;
|
||||
}
|
||||
memset(m_pResponse, 0, iMaxBufferSize);
|
||||
do
|
||||
{
|
||||
dwSize = 0;
|
||||
if (::WinHttpQueryDataAvailable(hRequest, &dwSize))
|
||||
{
|
||||
SetProgress(iCurrentBufferSize);
|
||||
BYTE *pResponse = new BYTE[dwSize + 1];
|
||||
if (pResponse != NULL)
|
||||
{
|
||||
memset(pResponse, 0, (dwSize + 1)*sizeof(BYTE));
|
||||
DWORD dwRead = 0;
|
||||
if (::WinHttpReadData(hRequest,
|
||||
pResponse,
|
||||
dwSize,
|
||||
&dwRead))
|
||||
{
|
||||
if (dwRead + iCurrentBufferSize > iMaxBufferSize)
|
||||
{
|
||||
BYTE *pOldBuffer = m_pResponse;
|
||||
m_pResponse = new BYTE[iMaxBufferSize * 2];
|
||||
if (m_pResponse == NULL)
|
||||
{
|
||||
m_pResponse = pOldBuffer;
|
||||
bRetVal = false;
|
||||
break;
|
||||
}
|
||||
iMaxBufferSize *= 2;
|
||||
memset(m_pResponse, 0, iMaxBufferSize);
|
||||
memcpy(m_pResponse, pOldBuffer, iCurrentBufferSize);
|
||||
delete[] pOldBuffer;
|
||||
}
|
||||
memcpy(m_pResponse + iCurrentBufferSize, pResponse, dwRead);
|
||||
iCurrentBufferSize += dwRead;
|
||||
}
|
||||
delete[] pResponse;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dwLastError = ::GetLastError();
|
||||
}
|
||||
}
|
||||
while (dwSize > 0);
|
||||
SetProgress(iCurrentBufferSize);
|
||||
m_responseByteCountReceived = iCurrentBufferSize;
|
||||
|
||||
UINT codePage = CP_ACP;
|
||||
DWORD dwFlag = MB_PRECOMPOSED;
|
||||
if (_wcsnicmp(m_responseCharset.c_str(), L"utf-8", 5) == 0)
|
||||
{
|
||||
codePage = CP_UTF8;
|
||||
dwFlag = 0;
|
||||
}
|
||||
int iLength = ::MultiByteToWideChar(codePage,
|
||||
dwFlag,
|
||||
(LPCSTR)m_pResponse,
|
||||
m_responseByteCountReceived + 1,
|
||||
NULL,
|
||||
0);
|
||||
if (iLength <= 0)
|
||||
{
|
||||
// Use CP_ACP if UTF-8 fail
|
||||
codePage = CP_ACP;
|
||||
dwFlag = MB_PRECOMPOSED;
|
||||
iLength = ::MultiByteToWideChar(codePage,
|
||||
dwFlag,
|
||||
(LPCSTR)m_pResponse,
|
||||
m_responseByteCountReceived + 1,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
if (iLength > 0)
|
||||
{
|
||||
wchar_t *wideChar = new wchar_t[iLength];
|
||||
if (wideChar != NULL)
|
||||
{
|
||||
memset(wideChar, 0, iLength * sizeof(wchar_t));
|
||||
iLength = ::MultiByteToWideChar(codePage,
|
||||
dwFlag,
|
||||
(LPCSTR)m_pResponse,
|
||||
m_responseByteCountReceived + 1,
|
||||
wideChar,
|
||||
iLength);
|
||||
if (iLength > 0)
|
||||
{
|
||||
m_responseContent = wideChar;
|
||||
}
|
||||
delete[] wideChar;
|
||||
}
|
||||
}
|
||||
bGetReponseSucceed = true;
|
||||
|
||||
// If the resposne html web page size is less than 200, retry.
|
||||
if (verb == L"GET" && !disableAutoRedirect)
|
||||
{
|
||||
wstring regExp = L"{<html>}";
|
||||
vector<wstring> result;
|
||||
if (ParseRegExp(regExp, false, 1, m_responseContent, result) && result.size() > 0)
|
||||
{
|
||||
regExp = L"{</html>}";
|
||||
if (!ParseRegExp(regExp, false, 1, m_responseContent, result) || result.size() <= 0)
|
||||
{
|
||||
m_dwLastError = ERROR_INVALID_DATA;
|
||||
bGetReponseSucceed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dwLastError = ::GetLastError();
|
||||
}
|
||||
}
|
||||
} // while
|
||||
if (!bGetReponseSucceed)
|
||||
{
|
||||
bRetVal = false;
|
||||
}
|
||||
|
||||
::WinHttpCloseHandle(hRequest);
|
||||
}
|
||||
::WinHttpCloseHandle(hConnect);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
wstring WinHttpClient::GetResponseHeader(void)
|
||||
{
|
||||
return m_responseHeader;
|
||||
}
|
||||
|
||||
wstring WinHttpClient::GetResponseContent(void)
|
||||
{
|
||||
return m_responseContent;
|
||||
}
|
||||
|
||||
wstring WinHttpClient::GetResponseCharset(void)
|
||||
{
|
||||
return m_responseCharset;
|
||||
}
|
||||
|
||||
wstring WinHttpClient::GetRequestHost(void)
|
||||
{
|
||||
return m_requestHost;
|
||||
}
|
||||
|
||||
bool WinHttpClient::SaveResponseToFile(const wstring &filePath)
|
||||
{
|
||||
if (m_pResponse == NULL || m_responseByteCountReceived <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
FILE *f = NULL;
|
||||
int iResult = _wfopen_s(&f, filePath.c_str(), L"wb");
|
||||
if (iResult == 0 && f != NULL)
|
||||
{
|
||||
fwrite(m_pResponse, m_responseByteCountReceived, 1, f);
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WinHttpClient::SetProgress(unsigned int byteCountReceived)
|
||||
{
|
||||
bool bReturn = false;
|
||||
if (m_pfProcessProc != NULL && m_responseByteCount > 0)
|
||||
{
|
||||
double dProgress = (double)byteCountReceived * 100 / m_responseByteCount;
|
||||
m_pfProcessProc(dProgress);
|
||||
bReturn = true;
|
||||
}
|
||||
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
wstring WinHttpClient::GetResponseCookies(void)
|
||||
{
|
||||
return m_responseCookies;
|
||||
}
|
||||
|
||||
bool WinHttpClient::SetAdditionalRequestCookies(const wstring &cookies)
|
||||
{
|
||||
m_additionalRequestCookies = cookies;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WinHttpClient::SetAdditionalDataToSend(BYTE *data, unsigned int dataSize)
|
||||
{
|
||||
if (data == NULL || dataSize < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_pDataToSend != NULL)
|
||||
{
|
||||
delete[] m_pDataToSend;
|
||||
}
|
||||
m_pDataToSend = NULL;
|
||||
m_pDataToSend = new BYTE[dataSize];
|
||||
if (m_pDataToSend != NULL)
|
||||
{
|
||||
memcpy(m_pDataToSend, data, dataSize);
|
||||
m_dataToSendSize = dataSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset additional data fields
|
||||
bool WinHttpClient::ResetAdditionalDataToSend(void)
|
||||
{
|
||||
if (m_pDataToSend != NULL)
|
||||
{
|
||||
delete[] m_pDataToSend;
|
||||
}
|
||||
|
||||
m_pDataToSend = NULL;
|
||||
m_dataToSendSize = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Allow us to reset the url on subsequent requests
|
||||
bool WinHttpClient::UpdateUrl(const wstring &url)
|
||||
{
|
||||
m_requestURL = url;
|
||||
ResetAdditionalDataToSend();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WinHttpClient::SetAdditionalRequestHeaders(const wstring &additionalRequestHeaders)
|
||||
{
|
||||
m_additionalRequestHeaders = additionalRequestHeaders;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WinHttpClient::SetProxy(const wstring &proxy)
|
||||
{
|
||||
m_proxy = proxy;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we don't require valid SSL Certs then accept any
|
||||
// certificate on an SSL connection
|
||||
bool WinHttpClient::SetRequireValidSslCertificates(bool require)
|
||||
{
|
||||
m_requireValidSsl = require;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const BYTE *WinHttpClient::GetRawResponseContent(void)
|
||||
{
|
||||
return m_pResponse;
|
||||
}
|
||||
|
||||
unsigned int WinHttpClient::GetRawResponseContentLength(void)
|
||||
{
|
||||
return m_responseByteCount;
|
||||
}
|
||||
|
||||
unsigned int WinHttpClient::GetRawResponseReceivedContentLength(void)
|
||||
{
|
||||
return m_responseByteCountReceived;
|
||||
}
|
||||
|
||||
DWORD WinHttpClient::GetLastError(void)
|
||||
{
|
||||
return m_dwLastError;
|
||||
}
|
||||
|
||||
wstring WinHttpClient::GetResponseStatusCode(void)
|
||||
{
|
||||
return m_statusCode;
|
||||
}
|
||||
|
||||
bool WinHttpClient::SetUserAgent(const wstring &userAgent)
|
||||
{
|
||||
m_userAgent = userAgent;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WinHttpClient::SetForceCharset(const wstring &charset)
|
||||
{
|
||||
m_responseCharset = charset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WinHttpClient::SetProxyUsername(const wstring &username)
|
||||
{
|
||||
m_proxyUsername = username;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WinHttpClient::SetProxyPassword(const std::wstring &password)
|
||||
{
|
||||
m_proxyPassword = password;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
wstring WinHttpClient::GetResponseLocation(void)
|
||||
{
|
||||
return m_location;
|
||||
}
|
||||
|
||||
bool WinHttpClient::SetTimeouts(unsigned int resolveTimeout,
|
||||
unsigned int connectTimeout,
|
||||
unsigned int sendTimeout,
|
||||
unsigned int receiveTimeout)
|
||||
{
|
||||
m_resolveTimeout = resolveTimeout;
|
||||
m_connectTimeout = connectTimeout;
|
||||
m_sendTimeout = sendTimeout;
|
||||
m_receiveTimeout = receiveTimeout;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // WINHTTPCLIENT_H
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user