HttpClt.cpp
上传用户:zhanglf88
上传日期:2013-11-19
资源大小:6036k
文件大小:26k
源码类别:

金融证券系统

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "HttpClt.h"
  3. #include "Resource.h"
  4. #include "Base64.h"
  5. #include "Strings.h"
  6. #include "ProxySocket.h"
  7. #include <TCHAR.h>
  8. /////////////////////////////////////////////////////////////////////////////
  9. // CTearException object
  10. IMPLEMENT_DYNCREATE(CTearException, CException)
  11. CTearException::CTearException(int nCode)
  12. {
  13. m_nErrorCode = nCode;
  14. }
  15. BOOL CTearException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError, PUINT pnHelpContext)
  16. {
  17. CString string;
  18. switch (m_nErrorCode)
  19. {
  20. case ERR_TEAR_CANCEL:
  21. break;
  22. case ERR_TEAR_URLFORMAT:
  23. string = szErrUrlFormat;
  24. break;
  25. case ERR_TEAR_REDIRECT:
  26. string = szErrRedirect;
  27. break;
  28. case ERR_TEAR_INTERRUPTED:
  29. string = szErrInterrupted;
  30. break;
  31. case ERR_TEAR_DATATRANSFER:
  32. string = szErrDataTransfer;
  33. break;
  34. }
  35. strncpy(lpszError, string.GetBuffer(string.GetLength()+1), nMaxError);
  36. string.ReleaseBuffer();
  37. return TRUE;
  38. }
  39. void ThrowTearException(int nCode)
  40. {
  41. CTearException* pEx = new CTearException(nCode);
  42. throw pEx;
  43. }
  44. /////////////////////////////////////////////////////////////////////////////
  45. // CHttpClient object
  46. const TCHAR *szHeaderFormat = "%s: %srn";
  47. const TCHAR *szUserAgentKey = _T("User-Agent");
  48. const TCHAR *szUserAgentValue = _T("Internet Explorer");
  49. const TCHAR *szCookieKey = _T("Cookie");
  50. const TCHAR *szRange = _T("Range");
  51. const TCHAR *szCheckSumKey = _T("BLCheckSum");
  52. const TCHAR *szCheckSumKeySuffix = _T("BLCheckSum: ");
  53. const TCHAR *szRegCodeKey = _T("RegCode");
  54. const TCHAR *szUserNameKey = _T("User");
  55. const TCHAR *szPasswdKey = _T("Passwd");
  56. const TCHAR *szDiskSerialKey= _T("SerialCheck");
  57. const TCHAR *szVersionKey = _T("Version");
  58. const TCHAR szHttpURLFormat[] = "http://%s:%d%s";
  59. #ifdef CLKLAN_ENGLISH_US
  60. const TCHAR *szWebpathWGet = _T("/enu/download/ninebulls/wget");
  61. const TCHAR *szWebpathLogin = _T("/enu/download/ninebulls/login");
  62. const TCHAR *szWebpathLogout = _T("/enu/download/ninebulls/logout");
  63. const TCHAR *szWebpathPackageInfo = _T("/enu/download/ninebulls/package3.xml");
  64. const TCHAR *szWebpathServerInfo = _T("/enu/download/ninebulls/server3.xml");
  65. #elif defined CLKVER_OEM
  66. const TCHAR *szWebpathWGet = _T("/download/stockana/wget");
  67. const TCHAR *szWebpathLogin = _T("/download/stockana/login");
  68. const TCHAR *szWebpathLogout = _T("/download/stockana/logout");
  69. const TCHAR *szWebpathPackageInfo = _T("/download/stockana/package3.xml");
  70. const TCHAR *szWebpathServerInfo = _T("/download/stockana/server3.xml");
  71. #else
  72. const TCHAR *szWebpathWGet = _T("/download/clking/wget");
  73. const TCHAR *szWebpathLogin = _T("/download/clking/login");
  74. const TCHAR *szWebpathLogout = _T("/download/clking/logout");
  75. const TCHAR *szWebpathPackageInfo = _T("/download/clking/package3.xml");
  76. const TCHAR *szWebpathServerInfo = _T("/download/clking/server3.xml");
  77. #endif
  78. const TCHAR *szWGetResultKey = _T("retvalue=");
  79. const TCHAR *szResultOKFmt = _T("%sO%s");
  80. const TCHAR *szResultFailed = _T("-ERR");
  81. //////////////////////////////////////////////////////////////////////
  82. // Construction/Destruction
  83. //////////////////////////////////////////////////////////////////////
  84. CHttpClient::CHttpClient()
  85. {
  86. m_nAccessType = INTERNET_OPEN_TYPE_DIRECT;
  87. m_bIsLogin = FALSE;
  88. }
  89. CHttpClient::~CHttpClient()
  90. {
  91. }
  92. BOOL CHttpClient::SetServer(LPCTSTR lpszServer, INTERNET_PORT nPort)
  93. {
  94. if (m_bIsLogin)
  95. {
  96. if (0 != m_strServer.CompareNoCase(lpszServer) || m_nPort != nPort)
  97. m_bIsLogin = FALSE;
  98. }
  99. if (NULL != lpszServer)
  100. m_strServer = lpszServer;
  101. else
  102. m_strServer.Empty();
  103. m_nPort = nPort;
  104. return m_strServer.GetLength()>0;
  105. }
  106. BOOL CHttpClient::SetAccessType(int nAccessType, int nProxyType, LPCTSTR lpszProxyAddress, UINT nProxyPort,
  107. LPCSTR lpszProxyUser, LPCTSTR lpszProxyPasswd)
  108. {
  109. switch(nAccessType)
  110. {
  111. case INTERNET_OPEN_TYPE_PRECONFIG:
  112. m_nAccessType = nAccessType;
  113. break;
  114. case INTERNET_OPEN_TYPE_DIRECT:
  115. m_nAccessType = nAccessType;
  116. break;
  117. case INTERNET_OPEN_TYPE_PROXY:
  118. m_nAccessType = nAccessType;
  119. m_nProxyType = nProxyType;
  120. if (NULL == lpszProxyAddress || strlen(lpszProxyAddress)==0)
  121. {
  122. m_nAccessType = INTERNET_OPEN_TYPE_PRECONFIG;
  123. ASSERT(FALSE);
  124. return FALSE;
  125. }
  126. m_strProxyAddress = lpszProxyAddress;
  127. m_nProxyPort = nProxyPort;
  128. m_strProxyUser = lpszProxyUser;
  129. m_strProxyPasswd = lpszProxyPasswd;
  130. break;
  131. default:
  132. return FALSE;
  133. }
  134. return TRUE;
  135. }
  136. DWORD CHttpClient::WGet(LPCTSTR lpszURL, CString &strResult, PROGRESS_CALLBACK fnCallback, void *cookie)
  137. {
  138. return RequestGet(lpszURL, NULL, &strResult, fnCallback, cookie);
  139. }
  140. DWORD CHttpClient::WGet(LPCTSTR lpszURL, CFile *pFile, PROGRESS_CALLBACK fnCallback, void *cookie)
  141. {
  142. ASSERT(pFile);
  143. return RequestGet(lpszURL, NULL, pFile, fnCallback, cookie);
  144. }
  145. long getHardDriveComputerID();
  146. static CString GetDiskSerial()
  147. {
  148. CString strSerial;
  149. DWORD id = (DWORD)getHardDriveComputerID ();
  150. strSerial.Format("%u", id);
  151. return strSerial;
  152. }
  153. DWORD CHttpClient::WGet(LPCTSTR lpszRegCode, LPCTSTR lpszUserName,
  154. LPCTSTR lpszPasswd, LPCTSTR lpszVersion,
  155. CString &strResult, int nWantLen)
  156. {
  157. CMapStringToString map;
  158. map.SetAt(szRegCodeKey, lpszRegCode);
  159. map.SetAt(szUserNameKey, m_strUserName);
  160. map.SetAt(szPasswdKey, m_strPasswd);
  161. map.SetAt(szVersionKey, lpszVersion);
  162. CString strDiskSerial = GetDiskSerial();
  163. map.SetAt(szDiskSerialKey, strDiskSerial);
  164. CString strURL;
  165. strURL.Format(szHttpURLFormat, m_strServer, m_nPort, szWebpathWGet);
  166. CString strResultLocal, strValue;
  167. DWORD dwRet = RequestPost(strURL, &map, &strResultLocal, NULL, NULL);
  168. if (HTTP_STATUS_OK == dwRet)
  169. {
  170. int nIndex = strResultLocal.Find(szWGetResultKey);
  171. if (-1 != nIndex)
  172. strValue = strResultLocal.Mid(nIndex+strlen(szWGetResultKey), nWantLen);
  173. }
  174. if (strValue.GetLength() == nWantLen)
  175. {
  176. strResult = strValue;
  177. return dwRet;
  178. }
  179. return dwRet;
  180. }
  181. BOOL CHttpClient::Login(LPCTSTR lpszRegCode,
  182. LPCTSTR lpszUserName, LPCTSTR lpszPasswd,
  183. LPCTSTR lpszVersion)
  184. {
  185. if (m_bIsLogin && lpszRegCode && 0 == m_strRegCode.CompareNoCase(lpszRegCode)
  186. && lpszUserName && 0 == m_strUserName.CompareNoCase(lpszUserName))
  187. return TRUE;
  188. m_bIsLogin = FALSE;
  189. m_strRegCode.Empty();
  190. m_strUserName.Empty();
  191. m_strPasswd.Empty();
  192. if (NULL != lpszRegCode)
  193. m_strRegCode = lpszRegCode;
  194. if (NULL != lpszUserName)
  195. m_strUserName = lpszUserName;
  196. if (NULL != lpszPasswd)
  197. m_strPasswd = lpszPasswd;
  198. CMapStringToString map;
  199. map.SetAt(szRegCodeKey, lpszRegCode);
  200. map.SetAt(szVersionKey, lpszVersion);
  201. map.SetAt(szUserNameKey, m_strUserName);
  202. map.SetAt(szPasswdKey, m_strPasswd);
  203. CString strDiskSerial = GetDiskSerial();
  204. map.SetAt(szDiskSerialKey, strDiskSerial);
  205. CString strURL;
  206. strURL.Format(szHttpURLFormat, m_strServer, m_nPort, szWebpathLogin);
  207. CString strResult;
  208. if (HTTP_STATUS_OK == RequestPost(strURL, &map, &strResult, NULL, NULL))
  209. {
  210. CString strResultOK;
  211. strResultOK.Format(szResultOKFmt, "+", "K");
  212. if (-1 != strResult.Find(strResultOK))
  213. {
  214. m_bIsLogin = TRUE;
  215. return TRUE;
  216. }
  217. }
  218. return FALSE;
  219. }
  220. BOOL CHttpClient::Logout()
  221. {
  222. if (!m_bIsLogin)
  223. return FALSE;
  224. m_strRegCode.Empty();
  225. m_strUserName.Empty();
  226. m_strPasswd.Empty();
  227. CString strURL;
  228. strURL.Format(szHttpURLFormat, m_strServer, m_nPort, szWebpathLogout);
  229. CString strResult;
  230. if (HTTP_STATUS_OK == RequestPost(strURL, NULL, &strResult, NULL, NULL))
  231. {
  232. CString strResultOK;
  233. strResultOK.Format(szResultOKFmt, "+", "K");
  234. int nIndex = strResult.Find(strResultOK);
  235. }
  236. m_bIsLogin = FALSE;
  237. return TRUE;
  238. }
  239. BOOL CHttpClient::LoadServerInfo(CString &strResult, PROGRESS_CALLBACK fnCallback, void *cookie)
  240. {
  241. if (!m_bIsLogin)
  242. return FALSE;
  243. CString strURL;
  244. strURL.Format(szHttpURLFormat, m_strServer, m_nPort, szWebpathServerInfo);
  245. return (HTTP_STATUS_OK == RequestGet(strURL, NULL, &strResult, fnCallback, cookie));
  246. }
  247. BOOL CHttpClient::LoadPackageInfo(CString &strResult, PROGRESS_CALLBACK fnCallback, void *cookie)
  248. {
  249. if (!m_bIsLogin)
  250. return FALSE;
  251. CString strURL;
  252. strURL.Format(szHttpURLFormat, m_strServer, m_nPort, szWebpathPackageInfo);
  253. return (HTTP_STATUS_OK == RequestGet(strURL, NULL, &strResult, fnCallback, cookie));
  254. }
  255. BOOL CHttpClient::LoadPackage(LPCTSTR lpszURL, CFile *pFile, PROGRESS_CALLBACK fnCallback, void *cookie)
  256. {
  257. if (!m_bIsLogin)
  258. return FALSE;
  259. return (HTTP_STATUS_OK == RequestGet(lpszURL, NULL, pFile, fnCallback, cookie));
  260. }
  261. BOOL CHttpClient::GetLastErrorMessage(LPTSTR lpszError, UINT nMaxError)
  262. {
  263. if (!m_strLastErrorMessage.IsEmpty())
  264. {
  265. strncpy(lpszError, m_strLastErrorMessage.GetBuffer(m_strLastErrorMessage.GetLength()+1), nMaxError);
  266. m_strLastErrorMessage.ReleaseBuffer();
  267. return strlen(lpszError)>0;
  268. }
  269. if (nMaxError > 0)
  270. lpszError[0] = '';
  271. return FALSE;
  272. }
  273. //////////////////////////////////////////////////////////////
  274. // static methods
  275. const TCHAR  *szUnEscape = _T("^_.-");
  276. BOOL CHttpClient::EscapeString(LPCTSTR lpszValue, CString &strOut)
  277. {
  278. int i = 0;
  279. TCHAR tszTemp[ 4 ];
  280. if (NULL == lpszValue)
  281. return FALSE;
  282. strOut.Empty();
  283. ZeroMemory(tszTemp, sizeof(tszTemp));
  284. for(i=0; i<lstrlen(lpszValue); i++)
  285. {
  286. TCHAR tch = lpszValue[ i ];
  287. if (!_istalnum(tch) && (NULL==_tcschr(szUnEscape, tch)))
  288. {
  289. _stprintf(tszTemp, "%%%02X", (TBYTE)tch);
  290. strOut += tszTemp;
  291. }
  292. else
  293. strOut += tch;
  294. }
  295. return TRUE;
  296. }
  297. BOOL CHttpClient::_MakeHttpData(CMapStringToString &__map, CString &__strOut, LPCTSTR __lpszSep)
  298. {
  299. CString strKey, strValue, strTemp;
  300. POSITION pos;
  301. ASSERT(0 == lstrcmp(__lpszSep, "rn") || 0 == lstrcmp(__lpszSep, "&"));
  302. __strOut = _T("");
  303. pos = __map.GetStartPosition();
  304. while(pos)
  305. {
  306. __map.GetNextAssoc(pos, strKey, strValue);
  307. EscapeString(strValue, strTemp);
  308. __strOut += strKey;
  309. __strOut += _T("=");
  310. __strOut += strTemp;
  311. __strOut += __lpszSep;
  312. }
  313. return TRUE;
  314. }
  315. BOOL CHttpClient::MakeHttpHeader(CMapStringToString &__map, CString &__strOut)
  316. {
  317. CString strKey, strValue, strTemp;
  318. POSITION pos;
  319. pos = __map.GetStartPosition();
  320. while(pos)
  321. {
  322. /* Add other Header */
  323. __map.GetNextAssoc(pos, strKey, strValue);
  324. if (0 != strKey.Compare(szUserAgentKey))
  325. {
  326. strTemp.Format(szHeaderFormat, strKey, strValue);
  327. __strOut += strTemp;
  328. }
  329. }
  330. return TRUE;
  331. }
  332. BOOL CHttpClient::MakePostData(CMapStringToString &__map, CString &__strOut)
  333. {
  334. return _MakeHttpData(__map, __strOut, "rn");
  335. }
  336. BOOL CHttpClient::MakeGetData(CMapStringToString &__map, CString &__strOut)
  337. {
  338. return _MakeHttpData(__map, __strOut, "&");
  339. }
  340. BOOL CHttpClient::PostDataEncoding(CString &strPostData)
  341. {
  342. int len = strPostData.GetLength();
  343. CString strDesData;
  344. CDLocalView des;
  345. des.Create((BYTE *)strPostData.GetBuffer(len), (BYTE *)strDesData.GetBuffer(len+1), len);
  346. (strDesData.GetBuffer(len+1))[len] = '';
  347. size_t srcLen = len;
  348. const char *srcBuf = strDesData.GetBuffer(srcLen);
  349. size_t destSize = 4*(srcLen+2)/3;
  350. destSize += strlen("rn")*destSize/72 + 2;
  351. destSize += 64; /*64;  a little extra room */
  352. /* Allocate destination buffer */
  353. char * destBuf = strPostData.GetBuffer(destSize);
  354. if (0 == destBuf)
  355. {
  356. strDesData.ReleaseBuffer();
  357. strPostData.ReleaseBuffer();
  358. return FALSE;
  359. }
  360. /* Encode source to destination */
  361. size_t destLen = 0;
  362. int result = encode_base64(srcBuf, srcLen, destBuf, destSize, &destLen);
  363. if (destLen < destSize)
  364. destBuf[destLen] = '';
  365. strDesData.ReleaseBuffer();
  366. strPostData.ReleaseBuffer();
  367. return (0 == result && destLen < destSize);
  368. }
  369. BOOL CHttpClient::PostDataDecoding(CString &strPostData)
  370. {
  371. CString strDesData;
  372. int len = strPostData.GetLength();
  373. size_t srcLen = len;
  374. const char *srcBuf = strPostData.GetBuffer(srcLen);
  375. size_t destSize = 4*(srcLen+2)/3;
  376. destSize += strlen("rn")*destSize/72 + 2;
  377. destSize += 64; /*64;  a little extra room */
  378. /* Allocate destination buffer */
  379. char * destBuf = strDesData.GetBuffer(destSize);
  380. if (0 == destBuf)
  381. {
  382. strPostData.ReleaseBuffer();
  383. strDesData.ReleaseBuffer();
  384. return FALSE;
  385. }
  386. /* Encode source to destination */
  387. size_t destLen = 0;
  388. int result = decode_base64(srcBuf, srcLen, destBuf, destSize, &destLen);
  389. if (destLen < destSize)
  390. destBuf[destLen] = '';
  391. strPostData.ReleaseBuffer();
  392. strDesData.ReleaseBuffer();
  393. if (0 != result || destLen >= destSize)
  394. return FALSE;
  395. CDLocalView des;
  396. len = destLen;
  397. des.Destroy((BYTE *)strDesData.GetBuffer(destLen), (BYTE *)strPostData.GetBuffer(len+1), len);
  398. (strPostData.GetBuffer(len+1))[len] = '';
  399. strPostData.ReleaseBuffer();
  400. strDesData.ReleaseBuffer();
  401. return TRUE;
  402. }
  403. //////////////////////////////////////////////////////////////
  404. // common methods
  405. DWORD CHttpClient::RequestGet(LPCTSTR lpszURL, CMapStringToString* pmapParam,
  406. CFile * pFileSave, PROGRESS_CALLBACK fnCallback, void *cookie)
  407. {
  408. if (NULL == lpszURL || strlen(lpszURL) == 0)
  409. return HTTP_STATUS_BAD_REQUEST;
  410. if (NULL != pFileSave && CFile::hFileNull == pFileSave->m_hFile)
  411. {
  412. ASSERT(FALSE);
  413. return HTTP_STATUS_BAD_REQUEST;
  414. }
  415. CString strURL = lpszURL;
  416. if (NULL != pmapParam)
  417. {
  418. CString strParam;
  419. MakeGetData(*pmapParam, strParam);
  420. if (!strParam.IsEmpty())
  421. strURL += "?" + strParam;
  422. }
  423. return Request(strURL, CString(""), pFileSave, NULL, fnCallback, cookie);
  424. }
  425. DWORD CHttpClient::RequestGet(LPCTSTR lpszURL, CMapStringToString* pmapParam,
  426. CString *pstrResult, PROGRESS_CALLBACK fnCallback, void *cookie)
  427. {
  428. if (NULL == lpszURL || strlen(lpszURL) == 0)
  429. return HTTP_STATUS_BAD_REQUEST;
  430. CString strURL = lpszURL;
  431. if (NULL != pmapParam)
  432. {
  433. CString strParam;
  434. MakeGetData(*pmapParam, strParam);
  435. if (!strParam.IsEmpty())
  436. strURL += "?" + strParam;
  437. }
  438. return Request(strURL, CString(""), NULL, pstrResult, fnCallback, cookie);
  439. }
  440. DWORD CHttpClient::RequestPost(LPCTSTR lpszURL, CMapStringToString* pmapParam,
  441. CFile * pFileSave, PROGRESS_CALLBACK fnCallback, void *cookie)
  442. {
  443. if (NULL != pFileSave && CFile::hFileNull == pFileSave->m_hFile)
  444. {
  445. ASSERT(FALSE);
  446. return HTTP_STATUS_BAD_REQUEST;
  447. }
  448. CString strPostData;
  449. if (NULL != pmapParam)
  450. MakePostData(*pmapParam, strPostData);
  451. // PostDataEncoding(strPostData);
  452. return Request(lpszURL, strPostData, pFileSave, NULL, fnCallback, cookie);
  453. }
  454. DWORD CHttpClient::RequestPost(LPCTSTR lpszURL, CMapStringToString* pmapParam,
  455. CString *pstrResult, PROGRESS_CALLBACK fnCallback, void *cookie)
  456. {
  457. CString strPostData;
  458. if (NULL != pmapParam)
  459. MakePostData(*pmapParam, strPostData);
  460. // PostDataEncoding(strPostData);
  461. return Request(lpszURL, strPostData, NULL, pstrResult, fnCallback, cookie);
  462. }
  463. void CHttpClient::DoOpenURL(LPCTSTR lpszURL, DWORD dwHttpRequestFlags,
  464. CString &strHeader, CString &strPostData,
  465. CInternetSession *pSession,
  466. CHttpConnection **ppServer, CHttpFile **ppFile,
  467. PROGRESS_CALLBACK fnCallback, void * cookie)
  468. {
  469. CString strServerName;
  470. CString strObject;
  471. INTERNET_PORT nPort;
  472. DWORD dwServiceType;
  473. int nVerb = (strPostData.GetLength()>0 ? CHttpConnection::HTTP_VERB_POST : CHttpConnection::HTTP_VERB_GET);
  474. if (!AfxParseURL(lpszURL, dwServiceType, strServerName, strObject, nPort) ||
  475. dwServiceType != INTERNET_SERVICE_HTTP)
  476. {
  477. ThrowTearException(ERR_TEAR_URLFORMAT);
  478. }
  479. if (fnCallback)
  480. fnCallback(PROG_HTTPCONNECTTING, 0, NULL, cookie);
  481. CHttpConnection *pServer = pSession->GetHttpConnection(strServerName, dwHttpRequestFlags, nPort, m_strProxyUser, m_strProxyPasswd);
  482. CHttpFile * pFile = pServer->OpenRequest(nVerb, strObject, NULL, 1, NULL, NULL, dwHttpRequestFlags);
  483. pFile->AddRequestHeaders(strHeader, HTTP_ADDREQ_FLAG_COALESCE);
  484. if (strPostData.GetLength() > 0) // post
  485. {
  486. try
  487. {
  488. pFile->SendRequestEx(DWORD(strPostData.GetLength()));
  489. pFile->WriteString(strPostData);
  490. pFile->EndRequest();
  491. }
  492. catch(CInternetException *pp) // HTTP_STATUS_BAD_METHOD
  493. {
  494. pp->Delete();
  495. // close up the redirected site
  496. pFile->Close();
  497. delete pFile;
  498. pFile = NULL;
  499. pServer->Close();
  500. delete pServer;
  501. pServer = NULL;
  502. pServer = pSession->GetHttpConnection(strServerName, dwHttpRequestFlags, nPort, m_strProxyUser, m_strProxyPasswd);
  503. pFile = pServer->OpenRequest(nVerb, strObject, NULL, 1, NULL, NULL, dwHttpRequestFlags);
  504. pFile->AddRequestHeaders(strHeader, HTTP_ADDREQ_FLAG_COALESCE);
  505. pFile->SendRequestEx(DWORD(strPostData.GetLength()));
  506. pFile->WriteString(strPostData);
  507. pFile->EndRequest();
  508. }
  509. }
  510. else
  511. {
  512. pFile->SendRequest();
  513. }
  514. if (fnCallback)
  515. fnCallback(PROG_REQUESTSENT, 0, NULL, cookie);
  516. // Bad Post method
  517. DWORD dwRet = 0;
  518. pFile->QueryInfoStatusCode(dwRet);
  519. // if access was denied, prompt the user for the password
  520. if (dwRet == HTTP_STATUS_DENIED
  521. || dwRet == HTTP_STATUS_PROXY_AUTH_REQ)
  522. {
  523. DWORD dwPrompt;
  524. dwPrompt = pFile->ErrorDlg(NULL, ERROR_INTERNET_INCORRECT_PASSWORD,
  525. FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA
  526. | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, NULL);
  527. // if the user cancelled the dialog, bail out
  528. if (dwPrompt != ERROR_INTERNET_FORCE_RETRY)
  529. ThrowTearException(ERR_TEAR_CANCEL);
  530. if (strPostData.GetLength() > 0) // post
  531. {
  532. try{
  533. pFile->SendRequestEx(DWORD(strPostData.GetLength()));
  534. pFile->WriteString(strPostData);
  535. pFile->EndRequest();
  536. }
  537. catch(CInternetException *pp) // HTTP_STATUS_BAD_METHOD
  538. {
  539. pp->Delete();
  540. pFile->SendRequestEx(DWORD(strPostData.GetLength()));
  541. pFile->WriteString(strPostData);
  542. pFile->EndRequest();
  543. }
  544. }
  545. else
  546. {
  547. pFile->SendRequest();
  548. }
  549. pFile->QueryInfoStatusCode(dwRet);
  550. }
  551. if (dwRet == HTTP_STATUS_BAD_METHOD)
  552. {
  553. // close up the redirected site
  554. pFile->Close();
  555. delete pFile;
  556. pFile = NULL;
  557. pServer->Close();
  558. delete pServer;
  559. pServer = NULL;
  560. pServer = pSession->GetHttpConnection(strServerName, dwHttpRequestFlags, nPort, m_strProxyUser, m_strProxyPasswd);
  561. pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET, strObject, NULL, 1, NULL, NULL, dwHttpRequestFlags);
  562. pFile->AddRequestHeaders(strHeader, HTTP_ADDREQ_FLAG_COALESCE);
  563. if (strPostData.GetLength() > 0) // post
  564. {
  565. pFile->SendRequestEx(DWORD(strPostData.GetLength()));
  566. pFile->WriteString(strPostData);
  567. pFile->EndRequest();
  568. }
  569. else
  570. {
  571. pFile->SendRequest();
  572. }
  573. }
  574. *ppServer = pServer;
  575. *ppFile = pFile;
  576. }
  577. CString CHttpClient::GetNewLocation(CHttpFile * pFile)
  578. {
  579. CString strNewLocation;
  580. pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strNewLocation);
  581. int nPlace = strNewLocation.Find(_T("Location: "));
  582. if (nPlace == -1)
  583. {
  584. ThrowTearException(ERR_TEAR_REDIRECT);
  585. }
  586. strNewLocation = strNewLocation.Mid(nPlace + 10);
  587. nPlace = strNewLocation.Find('n');
  588. if (nPlace > 0)
  589. strNewLocation = strNewLocation.Left(nPlace);
  590. return strNewLocation;
  591. }
  592. void CHttpClient::DoSecurityRequest(CHttpFile * pFile, CString &strPostData)
  593. {
  594. DWORD dwPrompt;
  595. dwPrompt = pFile->ErrorDlg(NULL, ERROR_INTERNET_INCORRECT_PASSWORD,
  596. FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA
  597. | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, NULL);
  598. // if the user cancelled the dialog, bail out
  599. if (dwPrompt != ERROR_INTERNET_FORCE_RETRY)
  600. ThrowTearException(ERR_TEAR_CANCEL);
  601. if (strPostData.GetLength() > 0) // post
  602. {
  603. try{
  604. pFile->SendRequestEx(DWORD(strPostData.GetLength()));
  605. pFile->WriteString(strPostData);
  606. pFile->EndRequest();
  607. }
  608. catch(CInternetException *pp)
  609. {
  610. pp->Delete();
  611. // HTTP_STATUS_BAD_METHOD
  612. pFile->SendRequest();
  613. }
  614. }
  615. else
  616. {
  617. pFile->SendRequest();
  618. }
  619. }
  620. CString FormatProxyString(int nProxyType, LPCTSTR lpszProxyAddress, UINT nProxyPort)
  621. {
  622. if (NULL == lpszProxyAddress || strlen(lpszProxyAddress) <= 0)
  623. return "";
  624. CString strProxy;
  625. CString strProxyType;
  626. if (CProxySocket::TypeSocks4 == nProxyType || CProxySocket::TypeSocks5 == nProxyType)
  627. strProxyType = "socks=";
  628. else if (CProxySocket::TypeHTTP == nProxyType)
  629. strProxyType = "http=";
  630. strProxy.Format("%s%s:%d", strProxyType, lpszProxyAddress, nProxyPort);
  631. return strProxy;
  632. }
  633. DWORD CHttpClient::Request(LPCTSTR lpszURL, CString &strPostData,
  634.  CFile *pFileSave, CString *pstrResult,
  635.  PROGRESS_CALLBACK fnCallback, void *cookie)
  636. {
  637. DWORD dwRet = HTTP_STATUS_BAD_REQUEST;
  638. if (NULL == lpszURL || strlen(lpszURL) == 0)
  639. return dwRet;
  640. int nContentLength = 0;
  641. int nContentLengthLocal = 0;
  642. int nContentLengthFinished = 0;
  643. int nContentLengthTotal = 0;
  644. // prepare header
  645. CString strHeader;
  646. CMapStringToString mapHeader;
  647. if (pFileSave && pFileSave->GetPosition() > 0)
  648. {
  649. nContentLengthFinished = (int)pFileSave->GetPosition();
  650. CString strRange;
  651. strRange.Format("bytes=%u-", nContentLengthFinished);
  652. mapHeader.SetAt(szRange, strRange);
  653. }
  654. if (pstrResult && pstrResult->GetLength() > 0)
  655. {
  656. nContentLengthFinished = pstrResult->GetLength();
  657. CString strRange;
  658. strRange.Format("bytes=%u-", nContentLengthFinished);
  659. mapHeader.SetAt(szRange, strRange);
  660. }
  661. if (m_strCookie.GetLength() > 0)
  662. mapHeader.SetAt(szCookieKey, m_strCookie);
  663. MakeHttpHeader(mapHeader, strHeader);
  664. // default type and flags
  665. DWORD dwHttpRequestFlags = INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_RELOAD
  666. | INTERNET_FLAG_DONT_CACHE
  667. | INTERNET_FLAG_EXISTING_CONNECT; // | INTERNET_FLAG_KEEP_CONNECTION;
  668. CString strProxy;
  669. if (!m_strProxyAddress.IsEmpty())
  670. strProxy = FormatProxyString(m_nProxyType, m_strProxyAddress, m_nProxyPort);
  671. CInternetSession session( szUserAgentValue, 1, m_nAccessType,
  672. strProxy, NULL, INTERNET_FLAG_DONT_CACHE);
  673. // 以下SetOption似乎不起作用
  674. if (!strProxy.IsEmpty() && !m_strProxyAddress.IsEmpty())
  675. {
  676. session.SetOption(INTERNET_OPTION_PROXY_USERNAME, (LPVOID)(LPCTSTR)m_strProxyUser, m_strProxyUser.GetLength());
  677. session.SetOption(INTERNET_OPTION_PROXY_PASSWORD, (LPVOID)(LPCTSTR)m_strProxyPasswd, m_strProxyPasswd.GetLength());
  678. }
  679. session.SetOption(INTERNET_OPTION_RECEIVE_TIMEOUT, 300000);
  680. session.SetOption(INTERNET_OPTION_SEND_TIMEOUT, 30000);
  681. session.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 30000);
  682. CHttpConnection* pServer = NULL;
  683. CHttpFile* pFile = NULL;
  684. try
  685. {
  686. // check to see if this is a reasonable URL
  687. DoOpenURL(lpszURL, dwHttpRequestFlags, strHeader, strPostData, &session, &pServer, &pFile, fnCallback, cookie);
  688. if (NULL == pServer || NULL == pFile)
  689. ThrowTearException(ERR_TEAR_INTERRUPTED);
  690. pFile->QueryInfoStatusCode(dwRet);
  691. if (dwRet == HTTP_STATUS_MOVED ||
  692. dwRet == HTTP_STATUS_REDIRECT ||
  693. dwRet == HTTP_STATUS_REDIRECT_METHOD)
  694. {
  695. CString strNewLocation = GetNewLocation(pFile);
  696. // close up the redirected site
  697. pFile->Close();
  698. delete pFile;
  699. pFile = NULL;
  700. pServer->Close();
  701. delete pServer;
  702. pServer = NULL;
  703. // progress callback
  704. if (fnCallback)
  705. fnCallback(PROG_REDIRECTING, 0, NULL, cookie);
  706. // open new url
  707. DoOpenURL(strNewLocation, dwHttpRequestFlags,
  708. strHeader, strPostData,
  709. &session, &pServer, &pFile, fnCallback, cookie);
  710. pFile->QueryInfoStatusCode(dwRet);
  711. }
  712. if (dwRet == HTTP_STATUS_PARTIAL_CONTENT)
  713. dwRet = HTTP_STATUS_OK;
  714. if (dwRet != HTTP_STATUS_OK)
  715. ThrowTearException(ERR_TEAR_INTERRUPTED);
  716. CString strInfo;
  717. pFile->QueryInfo(HTTP_QUERY_SET_COOKIE, strInfo);
  718. pFile->QueryInfo(HTTP_QUERY_COOKIE, strInfo);
  719. if (strInfo.GetLength())
  720. m_strCookie = strInfo;
  721. pFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH, strInfo);
  722. nContentLength = atol(strInfo);
  723. nContentLengthTotal = nContentLength + nContentLengthFinished;
  724. if (pstrResult && nContentLengthTotal > 0)
  725. pstrResult->GetBuffer(nContentLengthTotal+5);
  726. DWORD dwCheckSum = 0;
  727. BOOL bHasCheckSum = FALSE;
  728. CString strCheckSum;
  729. pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strCheckSum);
  730. int nPlace = strCheckSum.Find(szCheckSumKeySuffix);
  731. if (-1 != nPlace)
  732. {
  733. strCheckSum = strCheckSum.Mid(nPlace+strlen(szCheckSumKeySuffix));
  734. nPlace = strCheckSum.Find('n');
  735. if (nPlace > 0)
  736. {
  737. dwCheckSum = atol(strCheckSum.Left(nPlace));
  738. bHasCheckSum = TRUE;
  739. }
  740. }
  741. if (fnCallback)
  742. fnCallback(PROG_TRANSFERRING, 0, NULL, cookie);
  743. DWORD dwCheckSumLocal = 0;
  744. TCHAR sz[1028];
  745. int nRead = pFile->Read(sz+4, 1023);
  746. while (nRead > 0)
  747. {
  748. sz[4+nRead] = '';
  749. if (NULL != pFileSave)
  750. pFileSave->Write(sz+4, nRead);
  751. if (NULL != pstrResult)
  752. *pstrResult += (TCHAR *)(sz+4);
  753. nContentLengthLocal += nRead;
  754. if (fnCallback && nContentLengthTotal > 0)
  755. fnCallback(PROG_PROGRESS, DWORD(STKLIB_MAXF_PROGRESS*(nContentLengthFinished+nContentLengthLocal)/nContentLengthTotal), NULL, cookie);
  756. if (bHasCheckSum)
  757. {
  758. *((DWORD *)sz) = dwCheckSumLocal;
  759. dwCheckSumLocal = CRC32(sz, nRead);
  760. }
  761. nRead = pFile->Read(sz+4, 1023);
  762. }
  763. if (pstrResult && nContentLengthTotal > 0)
  764. pstrResult->ReleaseBuffer();
  765. if ((nContentLength > 0 && nContentLengthLocal != nContentLength)
  766. || (bHasCheckSum && dwCheckSum != dwCheckSumLocal))
  767. ThrowTearException(ERR_TEAR_DATATRANSFER);
  768. if (fnCallback)
  769. fnCallback(PROG_PROGRESS, STKLIB_MAX_PROGRESS, NULL, cookie);
  770. }
  771. catch (CInternetException* pEx)
  772. {
  773. // catch errors from WinINet
  774. if (HTTP_STATUS_OK == dwRet)
  775. dwRet = HTTP_STATUS_PARTIAL;
  776. TCHAR szErr[1024];
  777. pEx->GetErrorMessage(szErr, 1024);
  778. m_strLastErrorMessage = szErr;
  779. pEx->Delete();
  780. }
  781. catch (CTearException* pEx)
  782. {
  783. TCHAR szErr[1024];
  784. pEx->GetErrorMessage(szErr, 1024);
  785. m_strLastErrorMessage = szErr;
  786. pEx->Delete();
  787. }
  788. catch(CException * pEx)
  789. {
  790. TCHAR szErr[1024];
  791. pEx->GetErrorMessage(szErr, 1024);
  792. m_strLastErrorMessage = szErr;
  793. pEx->Delete();
  794. }
  795. if (pFile != NULL)
  796. {
  797. pFile->Close();
  798. delete pFile;
  799. }
  800. if (pServer != NULL)
  801. {
  802. pServer->Close();
  803. delete pServer;
  804. }
  805. session.Close();
  806. if (nContentLength > 0 && nContentLengthLocal != nContentLength)
  807. return Request(lpszURL, strPostData, pFileSave, pstrResult, fnCallback, cookie);
  808. return dwRet;
  809. }