httpdownload.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:51k
源码类别:

模拟服务器

开发平台:

C/C++

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // HttpDownload.cpp: implementation of the CHttpDownload class.
  3. ////////////////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "HttpDownload.h"
  6. #include "SocksPacket.h"
  7. #define READ_BUFFER_SIZE (10 * 1024) // 缓冲大小 10K
  8. #define DEFAULT_SAVE_DIR _T("C:\") // 缺省保存目录
  9. #define DEFAULT_SAVE_FILE _T("Unknown.htm") // 缺省保存文件名
  10. #define DEFAULT_USERAGENT _T("KAVUpdate/1.0") // 缺省的UserAgent
  11. #define Check(a,b) if((a))return (b);
  12. // 用于BASE64编码、解码的静态常量
  13. CString CHttpDownload::m_strBase64TAB = _T( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" );
  14. int CHttpDownload::m_nBase64Mask[]= { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
  15. ////////////////////////////////////////////////////////////////////////////////
  16. // 构造函数
  17. ////////////////////////////////////////////////////////////////////////////////
  18. CHttpDownload::CHttpDownload()
  19. {
  20. m_strDownloadUrl = _T("");
  21. m_strSavePath = _T("");
  22. m_strTempSavePath = _T("");
  23. m_bSaveResponse = TRUE; //是否需要保存返回
  24. // 停止下载
  25. m_bStopDownload = FALSE;
  26. m_hStopEvent = NULL;
  27. // 强制重新下载(不管已有的文件是否与远程文件相同)
  28. m_bForceDownload = FALSE;
  29. // 是否支持断点续传(假定不支持)
  30. m_bSupportResume = FALSE;
  31. // 文件以及下载大小
  32. m_dwFileSize = 0; // 文件总的大小
  33. m_dwFileDownloadedSize = 0; // 文件总共已经下载的大小
  34. m_dwDownloadSize = 0; // 本次Request需要下载的大小
  35. m_dwDownloadedSize = 0; // 本次Request已经下载的大小
  36. m_dwHeaderSize = 0; // HTTP协议头的长度
  37. m_strHeader = _T(""); // HTTP协议头
  38. // Referer
  39. m_strReferer = _T("");
  40. // UserAgent
  41. m_strUserAgent = DEFAULT_USERAGENT;
  42. // 超时TIMEOUT 连接超时、发送超时、接收超时(单位:毫秒)
  43. m_dwConnTimeout = HTTP_CONN_TIMEOUT;
  44. m_dwRecvTimeout = HTTP_RECV_TIMEOUT;
  45. m_dwSendTimeout = HTTP_SEND_TIMEOUT;
  46. // 重试机制
  47. m_nRetryType = HTTP_RETRY_NONE; //重试类型(0:不重试 1:重试一定次数 2:总是重试)
  48. m_nRetryTimes = 0; //重试次数
  49. m_nRetryDelay = 0; //重试延迟(单位:毫秒)
  50. m_nRetryMax = 0; //重试最大次数
  51. // 错误处理
  52. m_nErrorCount = 0; //错误次数
  53. m_strError = _T(""); //错误信息
  54. m_dwErrorCode = 0; //错误代码
  55. // 向其他窗口发送消息
  56. m_bNotify = FALSE; // 是否向外发送通知消息
  57. m_hNotifyWnd = NULL; // 被通知的窗口
  58. m_nNotifyMessage = 0; // 被通知的消息
  59. // 是否进行验证 : Request-Header: Authorization
  60. m_bAuthorization = FALSE;
  61. m_strUsername = _T("");
  62. m_strPassword = _T("");
  63. // 是否使用代理 
  64. m_bProxy = FALSE;
  65. m_strProxyServer = _T("");
  66. m_nProxyPort = 0;
  67. m_nProxyType = HTTP_PROXY_NONE;
  68. // 代理是否需要验证: Request-Header: Proxy-Authorization
  69. m_bProxyAuthorization = FALSE;
  70. m_strProxyUsername  = _T("");
  71. m_strProxyPassword = _T("");
  72. // 下载过程中所用的变量
  73. m_strServer = _T("");
  74. m_strObject = _T("");
  75. m_strFileName = _T("");
  76. m_nPort = DEFAULT_HTTP_PORT ;
  77. m_nVerb = HTTP_VERB_GET;
  78. m_strData = _T("");
  79. // 是否使用Cookie
  80. m_strCookie = _T("");
  81. m_bUseIECookie = FALSE;
  82. }
  83. ////////////////////////////////////////////////////////////////////////////////
  84. // 析构函数
  85. ////////////////////////////////////////////////////////////////////////////////
  86. CHttpDownload::~CHttpDownload()
  87. {
  88. CloseSocket();
  89. if( m_hStopEvent != NULL )
  90. {
  91. CloseHandle( m_hStopEvent );
  92. m_hStopEvent = NULL;
  93. }
  94. }
  95. //////////////////////////////////////////////////////////////////////////////////
  96. // 函数名:BOOL CreateSocket()
  97. // 用  途:创建SOCKET
  98. // 对全局变量的影响:无
  99. // 参  数:无
  100. // 返回值:BOOL
  101. // TRUE : 成功创建SOCKET
  102. // FALSE: 创建SOCKET失败
  103. ////////////////////////////////////////////////////////////////////////////////
  104. BOOL CHttpDownload::CreateSocket()
  105. {
  106. CloseSocket();
  107. return m_cBufSocket.Create(AF_INET,SOCK_STREAM,0,READ_BUFFER_SIZE);
  108. }
  109. //////////////////////////////////////////////////////////////////////////////////
  110. // 函数名:void CloseSocket()
  111. // 用  途:关闭SOCKET
  112. // 对全局变量的影响:无
  113. // 参  数:无
  114. // 返回值:void
  115. ////////////////////////////////////////////////////////////////////////////////
  116. void CHttpDownload::CloseSocket()
  117. {
  118. m_cBufSocket.Close(TRUE);
  119. }
  120. //////////////////////////////////////////////////////////////////////////////////
  121. // 函数名:int Download(
  122. // LPCTSTR lpszDownloadUrl,
  123. // LPCTSTR lpszSavePath /*= NULL*/,
  124. // BOOL bForceDownload /*= FALSE*/,
  125. // BOOL bSaveResponse /*= TRUE*/,
  126. // int nVerb /*= HTTP_VERB_GET*/,
  127. // LPCTSTR lpszData /*= NULL*/,
  128. // LPTSTR lpszFtpURL /*= NULL*/) 
  129. // 用  途:下载入口,调用此函数来开始下载过程
  130. // 对全局变量的影响:无
  131. // 参  数:
  132. // lpszDownloadUrl : 待下载的网络URL
  133. // lpszSavePath    : 本地保存路径(可以是全路径或者仅仅是目录,目录需以结尾)
  134. // bForceDownload  : 是否强制下载,不管文件是否与远程一致
  135. // bSaveResponse   : 是否保存服务器的返回
  136. // nVerb           : HTTP命令
  137. // lpszData        : 要在发送请求时传给服务器的数据(用于POST)
  138. // lpszFtpURL : 如果重定向到FTP,此指针用来保存FTP的URL
  139. // 返回值:int
  140. // HTTP_RESULT_STOP : 用户停止下载(调用了StopDownload函数)
  141. // HTTP_RESULT_FAIL : 下载失败
  142. // HTTP_RESULT_SUCCESS : 下载成功
  143. // HTTP_RESULT_SAMEAS : 本地已有完全一样的文件,不用再下载
  144. // HTTP_RESULT_REDIRECT_FTP: 重定向到FTP
  145. ////////////////////////////////////////////////////////////////////////////////
  146. int CHttpDownload::Download(LPCTSTR lpszDownloadUrl,LPCTSTR lpszSavePath /*= NULL*/,BOOL bForceDownload /*= FALSE*/,BOOL bSaveResponse /*= TRUE*/,int nVerb /*= HTTP_VERB_GET*/,LPCTSTR lpszData /*= NULL*/,LPTSTR lpszFtpURL /*= NULL*/ )
  147. {
  148. m_bStopDownload   = FALSE;
  149. m_bForceDownload  = bForceDownload;
  150. m_nRetryTimes   = 0;
  151. m_nErrorCount   = 0;
  152. m_strTempSavePath = _T("");
  153. m_bSaveResponse   = bSaveResponse;
  154. m_nVerb   = nVerb;
  155. m_strData   = _T("");
  156. if( lpszData != NULL )
  157. m_strData += lpszData;
  158. // 检验要下载的URL是否为空
  159. m_strDownloadUrl = lpszDownloadUrl;
  160. m_strDownloadUrl.TrimLeft();
  161. m_strDownloadUrl.TrimRight();
  162. if( m_strDownloadUrl.IsEmpty() )
  163. return HTTP_RESULT_FAIL;
  164. // 检验要下载的URL是否有效
  165. if ( !ParseURL(m_strDownloadUrl, m_strServer, m_strObject, m_nPort))
  166. {
  167. // 在前面加上"http://"再试
  168. m_strDownloadUrl = _T("http://") + m_strDownloadUrl;
  169. if ( !ParseURL(m_strDownloadUrl,m_strServer, m_strObject, m_nPort) )
  170. {
  171. TRACE(_T("Failed to parse the URL: %sn"), m_strDownloadUrl);
  172. return HTTP_RESULT_FAIL;
  173. }
  174. }
  175. // 检查本地保存路径
  176. m_strSavePath =  lpszSavePath;
  177. m_strSavePath.TrimLeft();
  178. m_strSavePath.TrimRight();
  179. if( m_strSavePath.IsEmpty() )
  180. m_strSavePath = DEFAULT_SAVE_DIR;
  181. if( m_strSavePath.Right(1) != '\' ) // 只有路径,没有文件名
  182. {
  183. m_strTempSavePath =  m_strSavePath;
  184. m_strTempSavePath += ".tmp";
  185. }
  186. // 创建停止事件
  187. if( m_hStopEvent == NULL )
  188. {
  189. m_hStopEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  190. if( m_hStopEvent == NULL )
  191. return HTTP_RESULT_FAIL;
  192. //seawind
  193. m_cBufSocket.m_hStopEvent = m_hStopEvent;
  194. }
  195. ResetEvent( m_hStopEvent );
  196. // 设置下载数据
  197. m_dwDownloadedSize = 0;
  198. m_dwFileDownloadedSize = 0;
  199. m_dwFileSize = 0;
  200. m_dwDownloadSize = 0;
  201. BOOL bSendOnce = TRUE; // 用于控制向hWndNotify窗口发送消息
  202. BOOL bSendRequestAgain = TRUE;
  203. while( bSendRequestAgain )
  204. {
  205. int nRequestRet = SendRequest( nVerb,lpszFtpURL ) ;
  206. //seawind
  207. //if (WaitForSingleObject(m_hStopEvent, 0) == WAIT_OBJECT_0)
  208. // return HTTP_RESULT_STOP;
  209. Check( m_bStopDownload, HTTP_RESULT_STOP);
  210. switch(nRequestRet)
  211. {
  212. case HTTP_REQUEST_SUCCESS:
  213. // 需要保存否?
  214. if( !m_bSaveResponse )
  215. {
  216. //关闭SOCKET
  217. CloseSocket();
  218. return HTTP_REQUEST_SUCCESS;
  219. }
  220. break;
  221. case HTTP_REQUEST_STOP:
  222. return HTTP_RESULT_STOP;
  223. break;
  224. case HTTP_REQUEST_FAIL:
  225. return HTTP_RESULT_FAIL;
  226. break;
  227. case HTTP_REQUEST_REDIRECT_FTP:
  228. return HTTP_RESULT_REDIRECT_FTP;
  229. break;
  230. case HTTP_REQUEST_ERROR:
  231. Check( m_bStopDownload, HTTP_RESULT_STOP); // 是否应该停止下载
  232. switch( m_nRetryType )
  233. {
  234. case HTTP_RETRY_NONE:
  235. return HTTP_RESULT_FAIL;
  236. break;
  237. case HTTP_RETRY_ALWAYS:
  238. if( m_nRetryDelay > 0 )
  239. {
  240. //为了让等待时也能退出,不能使用Sleep函数
  241. if( WaitForSingleObject(m_hStopEvent,m_nRetryDelay) == WAIT_OBJECT_0 )
  242. return HTTP_RESULT_STOP;
  243. }
  244. continue;
  245. break;
  246. case HTTP_RETRY_TIMES:
  247. if( m_nRetryTimes > m_nRetryMax )
  248. return HTTP_RESULT_FAIL;
  249. m_nRetryTimes++;
  250. if( m_nRetryDelay > 0 )
  251. {
  252. //为了让等待时也能退出,不能使用Sleep函数
  253. if( WaitForSingleObject(m_hStopEvent,m_nRetryDelay) == WAIT_OBJECT_0 )
  254. return HTTP_RESULT_STOP;
  255. }
  256. continue;
  257. break;
  258. default:
  259. return HTTP_RESULT_FAIL;
  260. break;
  261. }
  262. break;
  263. default:
  264. return HTTP_RESULT_FAIL;
  265. break;
  266. }
  267. if( m_strSavePath.Right(1) == '\' )
  268. m_strSavePath += m_strFileName;
  269. if( !m_bForceDownload ) // 非强制下载,检查Last-Modified
  270. {
  271. CFileStatus fileStatus;
  272. if (CFile::GetStatus(m_strSavePath,fileStatus))
  273. {
  274. // 可能会存在1秒的误差
  275. if (( fileStatus.m_mtime - m_TimeLastModified <=2 && m_TimeLastModified-fileStatus.m_mtime<=2 ) && (DWORD)fileStatus.m_size == m_dwFileSize )
  276. return HTTP_RESULT_SAMEAS;
  277. }
  278. }
  279. CFile fileDown;
  280. if(! fileDown.Open(m_strTempSavePath,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite|CFile::shareDenyWrite) )
  281. return HTTP_RESULT_FAIL;
  282. // 应该判断一下是否支持断点续传
  283. if( m_bSupportResume )
  284. {
  285. try
  286. {
  287. fileDown.SeekToEnd();
  288. }
  289. catch(CFileException* e)                                         
  290. {
  291. e->Delete();
  292. return HTTP_RESULT_FAIL;
  293. }
  294. }
  295. // 发送消息
  296. if( bSendOnce && m_bNotify )
  297. {
  298. HTTPDOWNLOADSTATUS DownloadStatus;
  299. DownloadStatus.dwFileSize  = m_dwFileSize;
  300. DownloadStatus.strFileName = m_strFileName;
  301. DownloadStatus.dwFileDownloadedSize  = m_dwFileDownloadedSize;
  302. DownloadStatus.nStatusType = HTTP_STATUS_FILESIZE;
  303. if (WaitForSingleObject(m_hStopEvent, 0) != WAIT_OBJECT_0)
  304. ::SendMessage(m_hNotifyWnd,m_nNotifyMessage,MSG_HTTPDOWNLOAD_STATUS,(LPARAM)&DownloadStatus);
  305. else
  306. return HTTP_RESULT_STOP;
  307. DownloadStatus.nStatusType = HTTP_STATUS_FILENAME;
  308. if (WaitForSingleObject(m_hStopEvent, 0) != WAIT_OBJECT_0)
  309. ::SendMessage(m_hNotifyWnd,m_nNotifyMessage,MSG_HTTPDOWNLOAD_STATUS,(LPARAM)&DownloadStatus);
  310. else
  311. return HTTP_RESULT_STOP;
  312. DownloadStatus.nStatusType = HTTP_STATUS_FILEDOWNLOADEDSIZE;
  313. if (WaitForSingleObject(m_hStopEvent, 0) != WAIT_OBJECT_0)
  314. ::SendMessage(m_hNotifyWnd,m_nNotifyMessage,MSG_HTTPDOWNLOAD_STATUS,(LPARAM)&DownloadStatus);
  315. else
  316. return HTTP_RESULT_STOP;
  317. bSendOnce = FALSE;
  318. }
  319. m_dwDownloadedSize = 0;
  320. // 现在开始读取数据
  321. char szReadBuf[READ_BUFFER_SIZE+1];
  322. /////////////////////////////////////////////
  323. // 如果m_dwDownloadSize = 0 (说明大小未知)
  324. if( m_dwDownloadSize == 0 )
  325. m_dwDownloadSize = 0xFFFFFFFF;
  326. ////////////////////////////////////////////
  327. bSendRequestAgain = FALSE;
  328. do
  329. {
  330. // 是否应该停止下载
  331. Check( m_bStopDownload, HTTP_RESULT_STOP);
  332. ZeroMemory(szReadBuf,READ_BUFFER_SIZE+1);
  333. int nRet =  m_cBufSocket.BSDGetData(szReadBuf,READ_BUFFER_SIZE,m_dwRecvTimeout);
  334. //seawind
  335. Check( m_bStopDownload, HTTP_RESULT_STOP);
  336. if (nRet <= 0)
  337. {
  338. ////////////////////////////////////////
  339. if( m_dwDownloadSize == 0xFFFFFFFF )
  340. break;
  341. ///////////////////////////////////////
  342. m_nErrorCount++;
  343. bSendRequestAgain = TRUE;
  344. break;// 跳出内层循环
  345. }
  346. // 将数据写入文件
  347. try
  348. {
  349. fileDown.Write(szReadBuf,nRet);
  350. }
  351. catch(CFileException* e)
  352. {
  353. e->Delete();
  354. bSendRequestAgain = TRUE;
  355. break;// 跳出内层循环
  356. }
  357. m_dwDownloadedSize += nRet;
  358. m_dwFileDownloadedSize += nRet;
  359. // 通知消息
  360. if( m_bNotify )
  361. {
  362. HTTPDOWNLOADSTATUS DownloadStatus;
  363. DownloadStatus.nStatusType = HTTP_STATUS_FILEDOWNLOADEDSIZE;
  364. DownloadStatus.dwFileDownloadedSize = m_dwFileDownloadedSize;
  365. DownloadStatus.dwFileSize = m_dwFileSize;
  366. DownloadStatus.strFileName = m_strFileName;
  367. if (WaitForSingleObject(m_hStopEvent, 0) != WAIT_OBJECT_0)
  368. ::SendMessage(m_hNotifyWnd,m_nNotifyMessage,MSG_HTTPDOWNLOAD_STATUS,(LPARAM)&DownloadStatus);
  369. else
  370. return HTTP_RESULT_STOP;
  371. }
  372. }while(m_dwDownloadedSize < m_dwDownloadSize);
  373. // 关闭文件
  374. fileDown.Close();
  375. } // WHILE LOOP
  376. //关闭SOCKET
  377. CloseSocket();
  378. // 文件改名
  379. //首先将已有的文件删除
  380. ::DeleteFile(m_strSavePath);
  381. //再将新下载的文件改名
  382. ::MoveFile(m_strTempSavePath, m_strSavePath);
  383.     
  384.     //再将新下载的文件的时间改回去
  385.     CFileStatus fileStatus;
  386.     
  387.     fileStatus.m_size = 0;
  388.     fileStatus.m_attribute = 0;
  389.     
  390.     try
  391.     {
  392.         CFile::GetStatus(m_strSavePath, fileStatus);
  393.         
  394.         fileStatus.m_mtime = m_TimeLastModified;
  395.         CFile::SetStatus(m_strSavePath,fileStatus);
  396.     }
  397.     catch(CFileException *e)
  398.     {
  399.         e->Delete();
  400.     }
  401.     
  402.     return HTTP_RESULT_SUCCESS;
  403. }
  404. //////////////////////////////////////////////////////////////////////////////////
  405. // 函数名:int SendRequest(
  406. // int nVerb /*= HTTP_VERB_GET*/,
  407. // LPTSTR lpszFtpURL/* = NULL*/ ) 
  408. // 用  途:发送HTTP请求
  409. // 对全局变量的影响:无
  410. // 参  数:
  411. // nVerb      : HTTP命令
  412. // lpszFtpURL : 如果重定向到FTP,此指针用来保存FTP的URL
  413. // 返回值:int
  414. // HTTP_REQUEST_STOP : 用户终止
  415. // HTTP_REQUEST_ERROR : 发生一般网络错误,可以重试
  416. // HTTP_REQUEST_SUCCESS : 请求成功
  417. // HTTP_REQUEST_FAIL : 发生验证错误,不用重试
  418. // HTTP_REQUEST_REDIRECT_FTP : 请求被重定向到FTP
  419. ////////////////////////////////////////////////////////////////////////////////
  420. int CHttpDownload::SendRequest(int nVerb /*= HTTP_VERB_GET*/,LPTSTR lpszFtpURL/* = NULL*/)
  421. {
  422. // 判断HTTP命令是否合法
  423. if( nVerb < HTTP_VERB_MIN || nVerb > HTTP_VERB_MAX )
  424. return HTTP_REQUEST_FAIL;
  425. // 保存HTTP命令
  426. m_nVerb = nVerb;
  427. while (TRUE)
  428. {
  429. CString strSend,strAuth,strHeader,strVerb,strCookie,strRange,strText;
  430. int nRet;
  431. char szReadBuf[1025];
  432. DWORD dwContentLength,dwStatusCode;
  433. strSend = _T("");
  434. strAuth = _T("");
  435. strHeader = _T("");
  436. strVerb = _T("");
  437. strCookie = _T("");
  438. strRange = _T("");
  439. strText = _T("");
  440. m_dwFileDownloadedSize = 0; // 文件已经下载大小
  441. m_dwDownloadSize    = 0; // 要下载大小
  442. strVerb = HTTP_VERB_STR[m_nVerb]; // HTTP命令
  443. ///////////////////////////////////////
  444. // 目前的版本中,此信息并没有用
  445. m_strHeader = _T("");
  446. m_dwHeaderSize = 0;
  447. //////////////////////////////////////
  448. Check( !CreateSocket(), HTTP_REQUEST_FAIL); // 创建SOCKET
  449. Check( m_bStopDownload, HTTP_REQUEST_STOP); // 是否应该停止下载
  450. // 建立连接
  451. nRet = MakeConnection( &m_cBufSocket,m_strServer,m_nPort);
  452. Check( nRet != HTTP_REQUEST_SUCCESS, nRet);
  453. Check( m_bStopDownload, HTTP_REQUEST_STOP); // 是否应该停止下载
  454. if( m_nProxyType == HTTP_PROXY_HTTPGET ) // HTTP_GET代理
  455. {
  456. strSend  = strVerb  + m_strDownloadUrl + " HTTP/1.1rn";
  457. if( m_bProxyAuthorization )
  458. {
  459. strAuth = _T("");
  460. Base64Encode(m_strProxyUsername+":"+m_strProxyPassword,strAuth);
  461. strSend += "Proxy-Authorization: Basic "+strAuth+"rn";
  462. }
  463. }
  464. else // 没有Proxy或者不是HTTP_GET代理
  465. strSend  = strVerb  + m_strObject + " HTTP/1.1rn";
  466. // 访问的页面是否是受保护的
  467. if( m_bAuthorization )
  468. {
  469. strAuth = _T("");
  470. Base64Encode(m_strUsername+":"+m_strPassword,strAuth);
  471. strSend += "Authorization: Basic "+strAuth+"rn";
  472. }
  473. strSend += "Host: " + m_strServer + "rn";
  474. strSend += "Accept: */*rn";
  475. strSend += "Pragma: no-cachern"; 
  476. strSend += "Cache-Control: no-cachern";
  477. strSend += "User-Agent: " + m_strUserAgent + "rn";
  478. if( !m_strReferer.IsEmpty() )
  479. strSend += "Referer: " + m_strReferer + "rn";
  480. strSend += "Connection: closern";
  481. // 判断是否使用Cookie
  482. if( m_bUseIECookie )
  483. {
  484. // 获取IE的Cookie
  485. if( GetIECookie(strCookie,m_strDownloadUrl) )
  486. m_strCookie = strCookie;
  487. else
  488. m_strCookie = _T("");
  489. }
  490. // Cookie
  491. if( !m_strCookie.IsEmpty() )
  492. strSend += "Cookie: " + m_strCookie + "rn";
  493. // 是否保存服务器的返回
  494. if( m_bSaveResponse )
  495. {
  496. // 判断m_strSavePath是否为路径
  497. GetFileName();
  498. if( m_strSavePath.Right(1) == '\' )
  499. {
  500. m_strTempSavePath = m_strSavePath;
  501. m_strTempSavePath += m_strFileName;
  502. m_strTempSavePath += ".tmp";
  503. }
  504. // 查看文件已经下载的长度
  505. CFileStatus fileDownStatus;
  506. if (CFile::GetStatus(m_strTempSavePath,fileDownStatus) && !m_bForceDownload )
  507. {
  508. m_dwFileDownloadedSize = fileDownStatus.m_size;
  509. if (m_dwFileDownloadedSize > 0)
  510. {
  511. strRange.Format(_T("Range: bytes=%d-rn"),m_dwFileDownloadedSize );
  512. }
  513. }
  514. strSend += strRange;
  515. }
  516. // Post?
  517. switch( m_nVerb )
  518. {
  519. case HTTP_VERB_GET:
  520. case HTTP_VERB_HEAD:
  521. // strSend += strRange;
  522. break;
  523. case HTTP_VERB_POST:
  524. strSend += "Content-Type: application/x-www-form-urlencodedrn";
  525. strText.Format("Content-Length: %drn", m_strData.GetLength() );
  526. strSend += strText;
  527. break;
  528. case HTTP_VERB_PUT:
  529. default:
  530. break;
  531. }
  532. //必须要加一个空行,否则Http服务器将不会应答
  533. strSend += "rn";
  534. // Post Data?
  535. switch( m_nVerb )
  536. {
  537. case HTTP_VERB_GET:
  538. case HTTP_VERB_HEAD:
  539. break;
  540. case HTTP_VERB_POST:
  541. case HTTP_VERB_PUT:
  542. strSend += m_strData;
  543. break;
  544. default:
  545. break;
  546. }
  547. //发送请求
  548. nRet =  m_cBufSocket.Send((LPCTSTR)strSend,strSend.GetLength(),m_dwSendTimeout);
  549. if( nRet < strSend.GetLength() )
  550. {
  551. if ( m_cBufSocket.GetLastError() == WSAETIMEDOUT) // 超时
  552. continue;
  553. else // 其他错误,可能是网络断了,等待一段时间后重试
  554. return HTTP_REQUEST_ERROR;
  555. }
  556. // 接收HTTP头
  557. BOOL bAgain = TRUE;
  558. while( bAgain )
  559. {
  560. bAgain = FALSE;
  561. strHeader.Empty();
  562. while( TRUE )
  563. {
  564. Check(m_bStopDownload,HTTP_REQUEST_STOP);
  565. ZeroMemory(szReadBuf,1025);
  566. nRet = m_cBufSocket.BSDGetString(szReadBuf,1024,m_dwRecvTimeout);
  567. //seawind
  568. Check(m_bStopDownload,HTTP_REQUEST_STOP);
  569. Check( nRet == SOCKET_FAIL ,HTTP_REQUEST_ERROR);
  570. if( szReadBuf[0] == '' ) // We have encountered "rnrn"
  571. break; 
  572. strHeader += szReadBuf;
  573. if( nRet == SOCKET_SUCCESS )
  574. strHeader += "rn";
  575. }
  576. ///////////////////////////////////////
  577. // 目前的版本中,此信息并没有用
  578. m_strHeader = strHeader;
  579. m_dwHeaderSize = m_strHeader.GetLength();
  580. //////////////////////////////////////
  581. nRet = GetInfo(strHeader,dwContentLength,dwStatusCode,m_TimeLastModified,strCookie,lpszFtpURL);
  582. switch ( nRet )
  583. {
  584. case HTTP_FAIL:
  585. return HTTP_REQUEST_FAIL;
  586. break;
  587. case HTTP_REDIRECT:
  588. m_nVerb = HTTP_VERB_GET;
  589. continue;
  590. break;
  591. case HTTP_REDIRECT_FTP:
  592. return HTTP_REQUEST_REDIRECT_FTP;
  593. break;
  594. case HTTP_SUCCESS:
  595. if( dwStatusCode >= 100  && dwStatusCode <200 )
  596. {
  597. bAgain = TRUE;
  598. continue; // Inner Loop
  599. }
  600. if( m_bSaveResponse )
  601. {
  602. m_dwDownloadSize = dwContentLength;
  603. // 应该判断一下服务器是否支持断点续传
  604. if( strRange.IsEmpty() )
  605. {
  606. m_dwFileSize = dwContentLength; // 整个文件的长度
  607. //seawind
  608. m_bSupportResume = FALSE;
  609. }
  610. else
  611. {
  612. if ( dwStatusCode == 206 ) //支持断点续传
  613. {
  614. m_dwFileSize = (dwContentLength == 0 )?0:(m_dwFileDownloadedSize +dwContentLength);
  615. m_bSupportResume = TRUE;
  616. }
  617. else //不支持断点续传
  618. {
  619. m_bSupportResume = FALSE;
  620. m_dwFileDownloadedSize = 0; //不支持断点续传,此值要设为0
  621. m_dwFileSize = dwContentLength;
  622. }
  623. }// strRange
  624. }// m_bSaveResponse
  625. return HTTP_REQUEST_SUCCESS;
  626. break;
  627. default:
  628. return HTTP_REQUEST_FAIL;
  629. break;
  630. }// SWITCH
  631. } // WHILE bAgain
  632. }// WHILE LOOP
  633. return HTTP_REQUEST_SUCCESS;
  634. }
  635. //////////////////////////////////////////////////////////////////////////////////
  636. // 函数名:void SetProxy(
  637. // LPCTSTR lpszProxyServer,
  638. // int nProxyPort,
  639. // BOOL bProxy/*=TRUE*/,
  640. // BOOL bProxyAuthorization /*= FALSE*/,
  641. // LPCTSTR lpszProxyUsername /*= NULL*/,
  642. // LPCTSTR lpszProxyPassword /*= NULL*/,
  643. // int nProxyType /*= HTTP_PROXY_HTTPGET*/ ) 
  644. // 用  途:设置代理及代理认证方式
  645. // 对全局变量的影响:无
  646. // 参  数:
  647. // lpszProxyServer     : 代理服务器的地址(IP地址或者域名)
  648. // nProxyPort          : 代理服务器的端口
  649. // bProxy              : 是否使用代理(该值为FALSE的时候,前两个参数将被忽略)
  650. // bProxyAuthorization : 代理是否需要验证
  651. // lpszProxyUsername   : 代理服务器验证的用户名
  652. // lpszProxyPassword   : 代理服务器验证的口令
  653. // nProxyType          : 代理服务器的类型
  654. // 返回值:void
  655. ////////////////////////////////////////////////////////////////////////////////
  656. void CHttpDownload::SetProxy(LPCTSTR lpszProxyServer,int nProxyPort,BOOL bProxy/*=TRUE*/,BOOL bProxyAuthorization /*= FALSE*/,LPCTSTR lpszProxyUsername /*= NULL*/,LPCTSTR lpszProxyPassword /*= NULL*/,int nProxyType /*= HTTP_PROXY_HTTPGET*/)
  657. {
  658. if( bProxy && nProxyType == HTTP_PROXY_USEIE ) // 使用IE的Proxy设置
  659. {
  660. if( !GetIEProxy(m_strProxyServer,m_nProxyPort,m_nProxyType) )
  661. {
  662. m_bProxy = FALSE;
  663. m_bProxyAuthorization = FALSE;
  664. m_nProxyPort = 0;
  665. m_nProxyType = HTTP_PROXY_NONE;
  666. m_strProxyServer = _T("");
  667. m_strProxyUsername = _T("");
  668. m_strProxyPassword = _T("");
  669. }
  670. else
  671. {
  672. m_bProxy = TRUE;
  673. if( lpszProxyUsername != NULL )
  674. {
  675. m_bProxyAuthorization = TRUE;
  676. m_strProxyUsername = lpszProxyUsername;
  677. m_strProxyPassword = lpszProxyPassword;
  678. }
  679. else
  680. {
  681. m_bProxyAuthorization = FALSE;
  682. m_strProxyUsername = _T("");
  683. m_strProxyPassword = _T("");
  684. }
  685. }
  686. return; // 返回
  687. }
  688. if( bProxy && lpszProxyServer != NULL)
  689. {
  690. m_bProxy = TRUE;
  691. m_strProxyServer = lpszProxyServer;
  692. m_nProxyPort = nProxyPort;
  693. m_nProxyType = nProxyType;
  694. if( bProxyAuthorization && lpszProxyUsername != NULL)
  695. {
  696. m_bProxyAuthorization = TRUE;
  697. m_strProxyUsername = lpszProxyUsername;
  698. m_strProxyPassword = lpszProxyPassword;
  699. }
  700. else
  701. {
  702. m_bProxyAuthorization = FALSE;
  703. m_strProxyUsername = _T("");
  704. m_strProxyPassword = _T("");
  705. }
  706. }
  707. else
  708. {
  709. m_bProxy = FALSE;
  710. m_bProxyAuthorization = FALSE;
  711. m_nProxyPort = 0;
  712. m_nProxyType = HTTP_PROXY_NONE;
  713. m_strProxyServer = _T("");
  714. m_strProxyUsername = _T("");
  715. m_strProxyPassword = _T("");
  716. }
  717. }
  718. //////////////////////////////////////////////////////////////////////////////////
  719. // 函数名:void SetAuthorization(
  720. // LPCTSTR lpszUsername,
  721. // LPCTSTR lpszPassword,
  722. // BOOL bAuthorization/* = TRUE*/ ) 
  723. // 用  途:设置WWW认证信息(访问被保护的页面时需要)
  724. // 对全局变量的影响:无
  725. // 参  数:
  726. // lpszUsername   : 访问页面的用户名
  727. // lpszPassword   : 口令
  728. // bAuthorization : 是否需要验证(此值为FALSE时,前两个参数将被忽略)
  729. // 返回值:void
  730. ////////////////////////////////////////////////////////////////////////////////
  731. void CHttpDownload::SetAuthorization(LPCTSTR lpszUsername,LPCTSTR lpszPassword,BOOL bAuthorization/* = TRUE*/ )
  732. {
  733. if( bAuthorization && lpszUsername != NULL )
  734. {
  735. m_bAuthorization = TRUE;
  736. m_strUsername  = lpszUsername;
  737. m_strPassword  = lpszPassword;
  738. }
  739. else
  740. {
  741. m_bAuthorization = FALSE;
  742. m_strUsername  = _T("");
  743. m_strPassword  = _T("");
  744. }
  745. }
  746. //////////////////////////////////////////////////////////////////////////////////
  747. // 函数名:void SetNotifyWnd(
  748. // HWND hNotifyWnd,
  749. // int nNotifyMsg,
  750. // BOOL bNotify /*= TRUE */ ) 
  751. // 用  途:设置是否需要发送消息给调用窗口
  752. // 对全局变量的影响:无
  753. // 参  数:
  754. // hNotifyWnd : 接收消息的窗口
  755. // nNotifyMsg : 消息ID
  756. // bNotify    : 是否发送消息(此值为FALSE时,前两个参数将被忽略)
  757. // 返回值:void
  758. ////////////////////////////////////////////////////////////////////////////////
  759. void CHttpDownload::SetNotifyWnd(HWND hNotifyWnd, int nNotifyMsg, BOOL bNotify /*= TRUE */)
  760. {
  761. if( bNotify && (hNotifyWnd != NULL) && ::IsWindow(hNotifyWnd) )
  762. {
  763. m_bNotify = TRUE;
  764. m_hNotifyWnd = hNotifyWnd;
  765. m_nNotifyMessage = nNotifyMsg;
  766. }
  767. else
  768. {
  769. m_bNotify = FALSE;
  770. m_hNotifyWnd = NULL;
  771. m_nNotifyMessage = 0;
  772. }
  773. }
  774. //////////////////////////////////////////////////////////////////////////////////
  775. // 函数名:void SetTimeout(
  776. // DWORD dwSendTimeout,
  777. // DWORD dwRecvTimeout,
  778. // DWORD dwConnTimeout ) 
  779. // 用  途:设置超时
  780. // 对全局变量的影响:无
  781. // 参  数:
  782. // dwSendTimeout : 发送超时
  783. // dwRecvTimeout : 接收超时
  784. // dwConnTimeout : 连接超时
  785. // 返回值:void
  786. ////////////////////////////////////////////////////////////////////////////////
  787. void CHttpDownload::SetTimeout(DWORD dwSendTimeout, DWORD dwRecvTimeout, DWORD dwConnTimeout)
  788. {
  789. if( dwSendTimeout > 0 )
  790. m_dwSendTimeout = dwSendTimeout;
  791. if( dwRecvTimeout > 0 )
  792. m_dwRecvTimeout = dwRecvTimeout;
  793. if( dwConnTimeout > 0 )
  794. m_dwConnTimeout = dwConnTimeout;
  795. }
  796. //////////////////////////////////////////////////////////////////////////////////
  797. // 函数名:void SetUserAgent( LPCTSTR lpszUserAgent ) 
  798. // 用  途:设置UserAgent
  799. // 对全局变量的影响:无
  800. // 参  数:
  801. // lpszUserAgent : 新的UserAgent(例如:Mozilla/4.0 (compatible; MSIE 5.0; Windows 98) )
  802. // 返回值:void
  803. ////////////////////////////////////////////////////////////////////////////////
  804. void CHttpDownload::SetUserAgent(LPCTSTR lpszUserAgent)
  805. {
  806. if( lpszUserAgent == NULL )
  807. m_strUserAgent = DEFAULT_USERAGENT;
  808. else
  809. m_strUserAgent = lpszUserAgent;
  810. if( m_strUserAgent.IsEmpty())
  811. m_strUserAgent = DEFAULT_USERAGENT;
  812. }
  813. //////////////////////////////////////////////////////////////////////////////////
  814. // 函数名:void SetReferer( LPCTSTR lpszReferer ) 
  815. // 用  途:设置Referer(提交者)
  816. // 对全局变量的影响:无
  817. // 参  数:
  818. // lpszReferer :  新的Referer
  819. // 返回值:void
  820. ////////////////////////////////////////////////////////////////////////////////
  821. void CHttpDownload::SetReferer(LPCTSTR lpszReferer)
  822. {
  823. if( lpszReferer != NULL )
  824. m_strReferer = lpszReferer;
  825. else
  826. m_strReferer = _T("");
  827. }
  828. //////////////////////////////////////////////////////////////////////////////////
  829. // 函数名:void SetRetry(
  830. // int nRetryType,
  831. // int nRetryDelay,
  832. // int nRetryMax ) 
  833. // 用  途:设置重试的机制
  834. // 对全局变量的影响:无
  835. // 参  数:
  836. // nRetryType  :  重试方式
  837. // HTTP_RETRY_NONE  - 不重试
  838. // HTTP_RETRY_TIMES - 重试一定次数
  839. // HTTP_RETRY_ALWAYS- 总是重试(可能陷入死循环)
  840. // nRetryDelay : 重试延迟
  841. // nRetryMax   : 最大重试次数(nRetryType为HTTP_RETRY_TIMES时,此值才有意义)
  842. // 返回值:void
  843. ////////////////////////////////////////////////////////////////////////////////
  844. void CHttpDownload::SetRetry(int nRetryType, int nRetryDelay, int nRetryMax)
  845. {
  846. m_nRetryType  = nRetryType;
  847. m_nRetryDelay = nRetryDelay;
  848. m_nRetryMax   = nRetryMax;
  849. // 检查一下m_nRetryMax,如果为0,设为缺省值
  850. //if( (HTTP_RETRY_TIMES == m_nRetryType) && (0 == m_nRetryMax) )
  851. // m_nRetryMax = DEFAULT_HTTP_RETRY_MAX;
  852. }
  853. //////////////////////////////////////////////////////////////////////////////////
  854. // 函数名:BOOL GetDownloadFileStatus(
  855. // IN LPCTSTR lpszDownloadUrl,
  856. // OUT DWORD &dwFileSize,
  857. // OUT CTime &FileTime ) 
  858. // 用  途:获取下载文件的状态
  859. // 对全局变量的影响:无
  860. // 参  数:
  861. // lpszDownloadUrl : 文件的URL
  862. // dwFileSize      : 用于保存文件的大小
  863. // FileTime        : 用于保存文件的修改时间
  864. // 返回值:BOOL
  865. ////////////////////////////////////////////////////////////////////////////////
  866. BOOL CHttpDownload::GetDownloadFileStatus(IN LPCTSTR lpszDownloadUrl,OUT DWORD &dwFileSize, OUT CTime &FileTime)
  867. {
  868. // 检验要下载的URL是否为空
  869. m_strDownloadUrl = lpszDownloadUrl;
  870. m_strDownloadUrl.TrimLeft();
  871. m_strDownloadUrl.TrimRight();
  872. if( m_strDownloadUrl.IsEmpty() )
  873. return FALSE;
  874. // 检验要下载的URL是否有效
  875. if ( !ParseURL(m_strDownloadUrl, m_strServer, m_strObject, m_nPort))
  876. {
  877. // 在前面加上"http://"再试
  878. m_strDownloadUrl = _T("http://") + m_strDownloadUrl;
  879. if ( !ParseURL(m_strDownloadUrl, m_strServer, m_strObject, m_nPort) )
  880. {
  881. TRACE(_T("Failed to parse the URL: %sn"), m_strDownloadUrl);
  882. return FALSE;
  883. }
  884. }
  885. m_strSavePath = "|";
  886. m_strTempSavePath = "|";
  887. m_bStopDownload = FALSE;
  888. if ( SendRequest() !=  HTTP_REQUEST_SUCCESS )
  889. return FALSE;
  890. dwFileSize  = m_dwDownloadSize;
  891. FileTime = m_TimeLastModified;
  892. return TRUE;
  893. }
  894. //////////////////////////////////////////////////////////////////////////////////
  895. // 函数名:BOOL ParseURL(
  896. // IN LPCTSTR lpszURL,
  897. // OUT CString &strServer,
  898. // OUT CString &strObject,
  899. // OUT int& nPort ) 
  900. // 用  途:从URL里面拆分出Server和Object来
  901. // 对全局变量的影响:无
  902. // 参  数:
  903. // lpszURL   : 待拆分的URL
  904. // strServer : 服务器地址
  905. // strObject : 服务器上的目标文件
  906. // nPort     : 服务器的端口
  907. // 返回值:BOOL
  908. ////////////////////////////////////////////////////////////////////////////////
  909. BOOL CHttpDownload::ParseURL(IN LPCTSTR lpszURL, OUT CString &strServer, OUT CString &strObject,OUT int& nPort)
  910. {
  911. CString strURL(lpszURL);
  912. strURL.TrimLeft();
  913. strURL.TrimRight();
  914. // 清除数据
  915. strServer = _T("");
  916. strObject = _T("");
  917. nPort   = 0;
  918. int nPos = strURL.Find("://");
  919. if( nPos == -1 )
  920. return FALSE;
  921. // 进一步验证是否为http://
  922. CString strTemp = strURL.Left( nPos+lstrlen("://") );
  923. strTemp.MakeLower();
  924. if( strTemp.Compare("http://") != 0 )
  925. return FALSE;
  926. strURL = strURL.Mid( strTemp.GetLength() );
  927. nPos = strURL.Find('/');
  928. if ( nPos == -1 )
  929. return FALSE;
  930. strObject = strURL.Mid(nPos);
  931. strTemp   = strURL.Left(nPos);
  932. ///////////////////////////////////////////////////////////////
  933. /// 注意:并没有考虑URL中有用户名和口令的情形和最后有#的情形
  934. /// 例如:http://abc@def:www.yahoo.com:81/index.html#link1
  935. /// 
  936. //////////////////////////////////////////////////////////////
  937. // 查找是否有端口号
  938. nPos = strTemp.Find(":");
  939. if( nPos == -1 )
  940. {
  941. strServer = strTemp;
  942. nPort   = DEFAULT_HTTP_PORT;
  943. }
  944. else
  945. {
  946. strServer = strTemp.Left( nPos );
  947. strTemp   = strTemp.Mid( nPos+1 );
  948. nPort   = (int)_ttoi((LPCTSTR)strTemp);
  949. }
  950. return TRUE;
  951. }
  952. //////////////////////////////////////////////////////////////////////////////////
  953. // 函数名:int GetInfo(
  954. // IN LPCTSTR lpszHeader,
  955. // OUT DWORD& dwContentLength,
  956. // OUT DWORD& dwStatusCode,
  957. // OUT CTime& TimeLastModified,
  958. // OUT CString& strCookie,
  959. // LPTSTR lpszFtpURL ) 
  960. // 用  途:从返回的HTTP协议头里获得必要的信息
  961. // 对全局变量的影响:无
  962. // 参  数:
  963. // lpszHeader       : HTTP协议头
  964. // dwContentLength  : content-length字段的值
  965. // dwStatusCode     : 状态码
  966. // TimeLastModified : last-modified字段的值
  967. // strCookie        : 用来保存Cookie
  968. // lpszFtpURL       : 用来保存重定向到FTP的URL
  969. // 返回值:int
  970. // HTTP_FAIL : 不合法的HTTP协议头,失败
  971. // HTTP_REDIRECT : 重定向
  972. // HTTP_SUCCESS : 成功
  973. ////////////////////////////////////////////////////////////////////////////////
  974. int CHttpDownload::GetInfo(IN LPCTSTR lpszHeader,OUT DWORD& dwContentLength,OUT DWORD& dwStatusCode,OUT CTime& TimeLastModified,OUT CString& strCookie,LPTSTR lpszFtpURL)
  975. {
  976. dwContentLength = 0;
  977. dwStatusCode = 0;
  978. TimeLastModified= CTime::GetCurrentTime();
  979. strCookie = _T("");
  980. CString strHeader(lpszHeader);
  981. strHeader.MakeLower();
  982. //拆分出HTTP应答的头信息的第一行
  983. int nPos = strHeader.Find("rn");
  984. if (nPos == -1)
  985. return HTTP_FAIL;
  986. // 获得返回码: Status Code
  987. CString strStatusLine = strHeader.Left(nPos);
  988. strStatusLine.TrimLeft();
  989. strStatusLine.TrimRight();
  990. nPos = strStatusLine.Find(' ');
  991. if( nPos == -1 )
  992. return HTTP_FAIL;
  993. strStatusLine = strStatusLine.Mid(nPos+1);
  994. nPos = strStatusLine.Find(' ');
  995. if( nPos == -1 )
  996. return HTTP_FAIL;
  997. strStatusLine = strStatusLine.Left(nPos);
  998. dwStatusCode = (DWORD)_ttoi((LPCTSTR)strStatusLine);
  999. // 检查返回码
  1000. if( dwStatusCode >= 300 && dwStatusCode < 400 ) //首先检测一下服务器的应答是否为重定向
  1001. {
  1002. nPos = strHeader.Find("location:");
  1003. if (nPos == -1)
  1004. return HTTP_FAIL;
  1005. CString strRedirectURL = strHeader.Mid(nPos + strlen("location:"));
  1006. nPos = strRedirectURL.Find("rn");
  1007. if (nPos == -1)
  1008. return HTTP_FAIL;
  1009. strRedirectURL = strRedirectURL.Left(nPos);
  1010. strRedirectURL.TrimLeft();
  1011. strRedirectURL.TrimRight();
  1012. // 设置Referer
  1013. m_strReferer = m_strDownloadUrl;
  1014. // 判断是否重定向到其他的服务器
  1015. // 从版本1.7开始,支持重定向到FTP服务器
  1016. if( strRedirectURL.Mid(0,6) == _T("ftp://") )
  1017. {
  1018. if( lpszFtpURL != NULL )
  1019. memcpy( lpszFtpURL,(LPCTSTR)strRedirectURL,strRedirectURL.GetLength() );
  1020. return HTTP_REDIRECT_FTP;
  1021. }
  1022. if( strRedirectURL.Mid(0,7) == _T("http://") )
  1023. {
  1024. m_strDownloadUrl = strRedirectURL;
  1025. // 检验要下载的URL是否有效
  1026. if ( !ParseURL(m_strDownloadUrl, m_strServer, m_strObject, m_nPort))
  1027. return HTTP_FAIL;
  1028. return HTTP_REDIRECT;
  1029. }
  1030. // 重定向到本服务器的其他地方
  1031. strRedirectURL.Replace("\","/");
  1032. // 是相对于根目录
  1033. if( strRedirectURL[0] == '/' )
  1034. {
  1035. m_strObject = strRedirectURL;
  1036. return HTTP_REDIRECT;
  1037. }
  1038. // 是相对当前目录
  1039. int nParentDirCount = 0;
  1040. nPos = strRedirectURL.Find("../");
  1041. while (nPos != -1)
  1042. {
  1043. strRedirectURL = strRedirectURL.Mid(nPos+3);
  1044. nParentDirCount++;
  1045. nPos = strRedirectURL.Find("../");
  1046. }
  1047. for (int i=0; i<=nParentDirCount; i++)
  1048. {
  1049. nPos = m_strDownloadUrl.ReverseFind('/');
  1050. if (nPos != -1)
  1051. m_strDownloadUrl = m_strDownloadUrl.Left(nPos);
  1052. }
  1053. m_strDownloadUrl = m_strDownloadUrl+"/"+strRedirectURL;
  1054. if ( !ParseURL(m_strDownloadUrl, m_strServer, m_strObject, m_nPort))
  1055. return HTTP_FAIL;
  1056. return HTTP_REDIRECT;
  1057. }
  1058. // 发生错误,不用重试(不管是服务器或者是客户端的)
  1059. if( dwStatusCode >=400 )
  1060. return HTTP_FAIL;
  1061. // 获取ContentLength(如果没有,就返回0,表示长度未知)
  1062. nPos = strHeader.Find("content-length:");
  1063. if( nPos != -1 )
  1064. {
  1065. CString strConentLen = strHeader.Mid(nPos + strlen("content-length:"));
  1066. nPos = strConentLen.Find("rn");
  1067. if (nPos != -1)
  1068. {
  1069. strConentLen = strConentLen.Left(nPos);
  1070. strConentLen.TrimLeft();
  1071. strConentLen.TrimRight();
  1072. // Content-Length:
  1073. dwContentLength = (DWORD) _ttoi( (LPCTSTR)strConentLen );
  1074. }
  1075. }
  1076. // 获取Last-Modified:
  1077. nPos = strHeader.Find("last-modified:");
  1078. if (nPos != -1)
  1079. {
  1080. CString strTime = strHeader.Mid(nPos + strlen("last-modified:"));
  1081. nPos = strTime.Find("rn");
  1082. if (nPos != -1)
  1083. {
  1084. strTime = strTime.Left(nPos);
  1085. strTime.TrimLeft();
  1086. strTime.TrimRight();
  1087. TimeLastModified = GetTime(strTime);
  1088. }
  1089. }
  1090. // 获取Cookie
  1091. nPos = strHeader.Find("set-cookie:");
  1092. if (nPos != -1)
  1093. {
  1094. CString strText = strHeader.Mid(nPos + strlen("set-cookie:"));
  1095. nPos = strText.Find("rn");
  1096. if (nPos != -1)
  1097. {
  1098. strCookie = strText.Left(nPos);
  1099. strCookie.TrimLeft();
  1100. strCookie.TrimRight();
  1101. int nPos1 = strCookie.Find("expires=");
  1102. int nPos2 = strCookie.Find("domain=");
  1103. int nPos3 = strCookie.Find("path=");
  1104. nPos = -1;
  1105. if( nPos1 != -1 )
  1106. nPos = nPos1;
  1107. if( nPos2 != -1 )
  1108. nPos = ( nPos == -1 )? nPos2:((nPos > nPos2 )?nPos2:nPos);
  1109. if( nPos3 != -1 )
  1110. nPos = ( nPos == -1 )? nPos3:((nPos > nPos3 )?nPos3:nPos);
  1111. if( nPos != -1 )
  1112. strCookie = strCookie.Left( nPos );
  1113. // 删除最后的;
  1114. if( strCookie.Right(1) == ";" )
  1115. strCookie = strCookie.Left( strCookie.GetLength() -1 );
  1116. }
  1117. }
  1118. return HTTP_SUCCESS;
  1119. }
  1120. //////////////////////////////////////////////////////////////////////////////////
  1121. // 函数名:CTime GetTime( LPCTSTR lpszTime ) 
  1122. // 用  途:将GMT字符串转化成时间
  1123. // 对全局变量的影响:无
  1124. // 参  数:
  1125. // lpszTime : 时间字符串
  1126. // 返回值:CTime
  1127. ////////////////////////////////////////////////////////////////////////////////
  1128. CTime CHttpDownload::GetTime(LPCTSTR lpszTime)
  1129. {
  1130. int nDay,nMonth,nYear,nHour,nMinute,nSecond;
  1131. CString strTime = lpszTime;
  1132. int nPos = strTime.Find(',');
  1133. if (nPos != -1)
  1134. {
  1135. strTime = strTime.Mid(nPos+1);
  1136. strTime.TrimLeft();
  1137. CString strDay,strMonth,strYear,strHour,strMinute,strSecond;
  1138. CString strAllMonth = "jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec";
  1139. strDay = strTime.Left(2);
  1140. nDay = atoi(strDay);
  1141. strMonth = strTime.Mid(3,3);
  1142. strMonth.MakeLower();
  1143. nPos = strAllMonth.Find(strMonth);
  1144. if (nPos != -1)
  1145. {
  1146. strMonth.Format("%d",((nPos/4)+1));
  1147. nMonth = atoi(strMonth);
  1148. }
  1149. else
  1150. nMonth = 1;
  1151. strTime = strTime.Mid(6);
  1152. strTime.TrimLeft();
  1153. nPos = strTime.FindOneOf(" t");
  1154. if (nPos != -1)
  1155. {
  1156. strYear = strTime.Left(nPos);
  1157. nYear = atoi(strYear);
  1158. }
  1159. else
  1160. nYear = 2000;
  1161. strTime = strTime.Mid(nPos+1);
  1162. strHour = strTime.Left(2);
  1163. nHour = atoi(strHour);
  1164. strMinute = strTime.Mid(3,2);
  1165. nMinute = atoi(strMinute);
  1166. strSecond = strTime.Mid(6,2);
  1167. nSecond = atoi(strSecond);
  1168. }
  1169. CTime time(nYear,nMonth,nDay,nHour,nMinute,nSecond);
  1170. return time;
  1171. }
  1172. //////////////////////////////////////////////////////////////////////////////////
  1173. // 函数名:void GetFileName()
  1174. // 用  途:从下载URL中获取文件名
  1175. // 对全局变量的影响:无
  1176. // 参  数:无
  1177. // 返回值:void
  1178. ////////////////////////////////////////////////////////////////////////////////
  1179. void CHttpDownload::GetFileName()
  1180. {
  1181. // 获取的文件名
  1182. int nSlash = m_strObject.ReverseFind(_T('/'));
  1183. if (nSlash == -1)
  1184. nSlash = m_strObject.ReverseFind(_T('\'));
  1185. if (nSlash != -1 && m_strObject.GetLength() > 1)
  1186. m_strFileName = m_strObject.Right(m_strObject.GetLength() - nSlash - 1);
  1187. else
  1188. m_strFileName = m_strObject;
  1189. m_strFileName.TrimLeft();
  1190. m_strFileName.TrimRight();
  1191. // 文件名为空或无效
  1192. if( m_strFileName.IsEmpty() || !IsValidFileName(m_strFileName) )
  1193. m_strFileName = DEFAULT_SAVE_FILE;
  1194. }
  1195. //////////////////////////////////////////////////////////////////////////////////
  1196. // 函数名:void StopDownload()
  1197. // 用  途:终止下载 
  1198. // 对全局变量的影响:无
  1199. // 参  数:无
  1200. // 返回值:void
  1201. ////////////////////////////////////////////////////////////////////////////////
  1202. void CHttpDownload::StopDownload()
  1203. {
  1204. m_bStopDownload = TRUE;
  1205. if ( m_hStopEvent != NULL )
  1206. SetEvent(m_hStopEvent);
  1207. }
  1208. //////////////////////////////////////////////////////////////////////////////////
  1209. // 函数名:int Base64Decode(
  1210. // IN LPCTSTR lpszDecoding,
  1211. // OUT CString &strDecoded ) 
  1212. // 用  途:BASE64解码
  1213. // 对全局变量的影响:无
  1214. // 参  数:
  1215. // lpszDecoding : 待解码字符串
  1216. // strDecoded   : 解码结果
  1217. // 返回值:int,解码后的长度
  1218. ////////////////////////////////////////////////////////////////////////////////
  1219. int CHttpDownload::Base64Decode(IN LPCTSTR lpszDecoding, OUT CString &strDecoded)
  1220. {
  1221. int nIndex =0;
  1222. int nDigit;
  1223.     int nDecode[ 256 ];
  1224. int nSize;
  1225. int nNumBits = 6;
  1226. if( lpszDecoding == NULL )
  1227. return 0;
  1228. if( ( nSize = lstrlen(lpszDecoding) ) == 0 )
  1229. return 0;
  1230. // Build Decode Table
  1231. for( int i = 0; i < 256; i++ ) 
  1232. nDecode[i] = -2; // Illegal digit
  1233. for( i=0; i < 64; i++ )
  1234. {
  1235. nDecode[ m_strBase64TAB[ i ] ] = i;
  1236. nDecode[ '=' ] = -1; 
  1237.     }
  1238. // Clear the output buffer
  1239. strDecoded = _T("");
  1240. long lBitsStorage  =0;
  1241. int nBitsRemaining = 0;
  1242. int nScratch = 0;
  1243. UCHAR c;
  1244. // Decode the Input
  1245. for( nIndex = 0, i = 0; nIndex < nSize; nIndex++ )
  1246. {
  1247. c = lpszDecoding[ nIndex ];
  1248. // 忽略所有不合法的字符
  1249. if( c> 0x7F)
  1250. continue;
  1251. nDigit = nDecode[c];
  1252. if( nDigit >= 0 ) 
  1253. {
  1254. lBitsStorage = (lBitsStorage << nNumBits) | (nDigit & 0x3F);
  1255. nBitsRemaining += nNumBits;
  1256. while( nBitsRemaining > 7 ) 
  1257. {
  1258. nScratch = lBitsStorage >> (nBitsRemaining - 8);
  1259. strDecoded += (nScratch & 0xFF);
  1260. i++;
  1261. nBitsRemaining -= 8;
  1262. }
  1263. }
  1264.     }
  1265. return strDecoded.GetLength();
  1266. }
  1267. //////////////////////////////////////////////////////////////////////////////////
  1268. // 函数名:int Base64Encode(
  1269. // IN LPCTSTR lpszEncoding,
  1270. // OUT CString &strEncoded ) 
  1271. // 用  途:BASE64编码
  1272. // 对全局变量的影响:无
  1273. // 参  数:
  1274. // lpszEncoding : 待编码的字符串
  1275. // strEncoded   : 编码结果
  1276. // 返回值:int,编码后的长度
  1277. ////////////////////////////////////////////////////////////////////////////////
  1278. int CHttpDownload::Base64Encode(IN LPCTSTR lpszEncoding, OUT CString &strEncoded)
  1279. {
  1280. int nDigit;
  1281. int nNumBits = 6;
  1282. int nIndex = 0;
  1283. int nInputSize;
  1284. strEncoded = _T( "" );
  1285. if( lpszEncoding == NULL )
  1286. return 0;
  1287. if( ( nInputSize = lstrlen(lpszEncoding) ) == 0 )
  1288. return 0;
  1289. int nBitsRemaining = 0;
  1290. long lBitsStorage =0;
  1291. long lScratch =0;
  1292. int nBits;
  1293. UCHAR c;
  1294. while( nNumBits > 0 )
  1295. {
  1296. while( ( nBitsRemaining < nNumBits ) &&  ( nIndex < nInputSize ) ) 
  1297. {
  1298. c = lpszEncoding[ nIndex++ ];
  1299. lBitsStorage <<= 8;
  1300. lBitsStorage |= (c & 0xff);
  1301. nBitsRemaining += 8;
  1302. }
  1303. if( nBitsRemaining < nNumBits ) 
  1304. {
  1305. lScratch = lBitsStorage << ( nNumBits - nBitsRemaining );
  1306. nBits    = nBitsRemaining;
  1307. nBitsRemaining = 0;
  1308. }  
  1309. else 
  1310. {
  1311. lScratch = lBitsStorage >> ( nBitsRemaining - nNumBits );
  1312. nBits  = nNumBits;
  1313. nBitsRemaining -= nNumBits;
  1314. }
  1315. nDigit = (int)(lScratch & m_nBase64Mask[nNumBits]);
  1316. nNumBits = nBits;
  1317. if( nNumBits <=0 )
  1318. break;
  1319. strEncoded += m_strBase64TAB[ nDigit ];
  1320. }
  1321. // Pad with '=' as per RFC 1521
  1322. while( strEncoded.GetLength() % 4 != 0 )
  1323. strEncoded += '=';
  1324. return strEncoded.GetLength();
  1325. }
  1326. //////////////////////////////////////////////////////////////////////////////////
  1327. // 函数名:int MakeConnection(
  1328. // CBufSocket* pBufSocket,
  1329. // CString strServer,
  1330. // int nPort ) 
  1331. // 用  途:建立连接
  1332. // 对全局变量的影响:无
  1333. // 参  数:
  1334. // pBufSocket : CBufSocket类指针
  1335. // strServer  : 待连接服务器
  1336. // nPort      : 端口
  1337. // 返回值:int
  1338. ////////////////////////////////////////////////////////////////////////////////
  1339. int CHttpDownload::MakeConnection(CBufSocket* pBufSocket,CString strServer,int nPort)
  1340. {
  1341. CSocksPacket cSocks( pBufSocket );
  1342. DWORD dwIP;
  1343. BYTE byAuth,byAtyp;
  1344. SOCKSREPPACKET pack;
  1345. CString strAuth,strAddr;
  1346. strAuth = _T("");
  1347. strAddr = _T("");
  1348. switch( m_nProxyType )
  1349. {
  1350. case HTTP_PROXY_NONE:
  1351. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1352. Check( !pBufSocket->Connect(strServer,nPort,m_dwConnTimeout,TRUE),HTTP_REQUEST_ERROR);
  1353. break;
  1354. case HTTP_PROXY_HTTPGET:
  1355. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1356. Check( !pBufSocket->Connect(m_strProxyServer,m_nProxyPort,m_dwConnTimeout,TRUE),HTTP_REQUEST_ERROR);
  1357. break;
  1358. case HTTP_PROXY_SOCKS4A:
  1359. dwIP = CBufSocket::GetIP(strServer,TRUE);
  1360. if( dwIP == INADDR_NONE )
  1361. {
  1362. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1363. Check( !pBufSocket->Connect(m_strProxyServer,m_nProxyPort,m_dwConnTimeout,TRUE),HTTP_REQUEST_ERROR);
  1364. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1365. Check( !cSocks.SendSocks4aReq(CMD_CONNECT,nPort,strServer,m_strProxyUsername,m_dwSendTimeout),HTTP_REQUEST_ERROR);
  1366. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1367. Check( !cSocks.RecvPacket(PACKET_SOCKS4AREP,m_dwRecvTimeout),HTTP_REQUEST_ERROR);
  1368. Check( !cSocks.IsSocksOK(),HTTP_REQUEST_FAIL); // 请求有错误,重试可能是没有用的
  1369. break;// NOTICE:如果本地能够解析域名,可以使用SOCKS4 Proxy
  1370. }
  1371. case HTTP_PROXY_SOCKS4:
  1372. // 必须要得到Proxy Server的IP地址(不能为域名)
  1373. dwIP = CBufSocket::GetIP(strServer,TRUE);
  1374. Check( dwIP == INADDR_NONE,HTTP_REQUEST_ERROR);
  1375. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1376. Check( !pBufSocket->Connect(m_strProxyServer,m_nProxyPort,m_dwConnTimeout,TRUE),HTTP_REQUEST_ERROR);
  1377. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1378. Check( !cSocks.SendSocks4Req(CMD_CONNECT,nPort,dwIP,m_strProxyUsername,m_dwSendTimeout),HTTP_REQUEST_ERROR);
  1379. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1380. Check( !cSocks.RecvPacket(PACKET_SOCKS4REP,m_dwRecvTimeout),HTTP_REQUEST_ERROR);
  1381. Check( !cSocks.IsSocksOK(),HTTP_REQUEST_FAIL); // 请求有错误,重试可能是没有用的
  1382. break;
  1383. case HTTP_PROXY_SOCKS5:
  1384. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1385. Check( !pBufSocket->Connect(m_strProxyServer,m_nProxyPort,m_dwConnTimeout,TRUE),HTTP_REQUEST_ERROR);
  1386. if( m_bProxyAuthorization )
  1387. {
  1388. char ch = (char)AUTH_NONE;
  1389. strAuth += ch;
  1390. ch  = (char)AUTH_PASSWD;
  1391. strAuth += ch;
  1392. }
  1393. else
  1394. {
  1395. char ch = (char)AUTH_NONE;
  1396. strAuth += ch;
  1397. }
  1398. byAuth =(BYTE)strAuth.GetLength();
  1399. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1400. Check( !cSocks.SendSocks5AuthReq(byAuth,(LPCTSTR)strAuth,m_dwSendTimeout),HTTP_REQUEST_ERROR);
  1401. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1402. ZeroMemory(&pack,sizeof(SOCKSREPPACKET));
  1403. Check( !cSocks.RecvPacket(&pack,PACKET_SOCKS5AUTHREP,m_dwRecvTimeout),HTTP_REQUEST_ERROR);
  1404. Check( !cSocks.IsSocksOK(&pack,PACKET_SOCKS5AUTHREP),HTTP_REQUEST_FAIL); // 请求有错误,重试可能是没有用的
  1405. switch( pack.socks5AuthRep.byAuth )
  1406. {
  1407. case AUTH_NONE:
  1408. break;
  1409. case AUTH_PASSWD:
  1410. Check( !m_bProxyAuthorization,HTTP_REQUEST_FAIL);
  1411. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1412. Check( !cSocks.SendSocks5AuthPasswdReq(m_strProxyUsername,m_strProxyPassword,m_dwSendTimeout),HTTP_REQUEST_ERROR);
  1413. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1414. Check( !cSocks.RecvPacket(PACKET_SOCKS5AUTHPASSWDREP,m_dwRecvTimeout),HTTP_REQUEST_ERROR);
  1415. Check( !cSocks.IsSocksOK(),HTTP_REQUEST_FAIL); // 请求有错误,重试可能是没有用的
  1416. break;
  1417. case AUTH_GSSAPI:
  1418. case AUTH_CHAP:
  1419. case AUTH_UNKNOWN:
  1420. default:
  1421. return HTTP_REQUEST_FAIL;
  1422. break;
  1423. }
  1424. dwIP = CBufSocket::GetIP(strServer,TRUE);
  1425. if( dwIP != INADDR_NONE )
  1426. {
  1427. byAtyp = ATYP_IPV4ADDR;
  1428. //不用转换字节序
  1429. strAddr += (char)( (dwIP    ) &0x000000ff) ; 
  1430. strAddr += (char)( (dwIP>>8 ) &0x000000ff); 
  1431. strAddr += (char)( (dwIP>>16) &0x000000ff); 
  1432. strAddr += (char)( (dwIP>>24) &0x000000ff); 
  1433. }
  1434. else
  1435. {
  1436. byAtyp = ATYP_HOSTNAME;
  1437. char ch = (char)strServer.GetLength();
  1438. strAddr += ch;
  1439. strAddr += strServer;
  1440. }
  1441. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1442. Check( !cSocks.SendSocks5Req(CMD_CONNECT,byAtyp,strAddr,nPort,m_dwSendTimeout),HTTP_REQUEST_ERROR);
  1443. Check( m_bStopDownload,HTTP_REQUEST_STOP);
  1444. Check( !cSocks.RecvPacket(PACKET_SOCKS5REP,m_dwRecvTimeout),HTTP_REQUEST_ERROR);
  1445. Check( !cSocks.IsSocksOK(),HTTP_REQUEST_FAIL); // 请求有错误,重试可能是没有用的
  1446. break;
  1447. case HTTP_PROXY_HTTPCONNECT:
  1448. default:
  1449. return HTTP_REQUEST_FAIL;
  1450. break;
  1451. }
  1452. return HTTP_REQUEST_SUCCESS;
  1453. }
  1454. //////////////////////////////////////////////////////////////////////////////////
  1455. // 函数名:BOOL GetIEProxy(
  1456. // CString &strProxyServer,
  1457. // int &nProxyPort,
  1458. // int &nProxyType ) 
  1459. // 用  途:获取IE的Proxy设置
  1460. // 对全局变量的影响:无
  1461. // 参  数:
  1462. // strProxyServer : 代理服务器地址
  1463. // nProxyPort     : 代理服务器的端口
  1464. // nProxyType     : 代理服务器的类型
  1465. // 返回值:BOOL
  1466. ////////////////////////////////////////////////////////////////////////////////
  1467. BOOL CHttpDownload::GetIEProxy(CString &strProxyServer, int &nProxyPort, int &nProxyType)
  1468. {
  1469. // 读取注册表
  1470. HKEY hRegKey;
  1471. DWORD dwRet = RegOpenKeyEx(
  1472. HKEY_CURRENT_USER,
  1473. "Software\Microsoft\Windows\CurrentVersion\Internet Settings",
  1474. 0L,
  1475. KEY_QUERY_VALUE,&hRegKey);
  1476. if (dwRet != ERROR_SUCCESS)
  1477. return FALSE;
  1478. TCHAR szAddr[256] = { 0 };
  1479. DWORD dwLen = 256;
  1480. dwRet = RegQueryValueEx(hRegKey,"ProxyServer",NULL,NULL,(LPBYTE)szAddr,&dwLen);
  1481. if (dwRet != ERROR_SUCCESS)
  1482. {
  1483. RegCloseKey(hRegKey);
  1484. return FALSE;
  1485. }
  1486.     RegCloseKey(hRegKey);
  1487.     
  1488.     // 注:可能存在所有代理同一的情况,此时无 http=...ftp=...信息
  1489.     //    comment by Linsuyi, 2002/01/22  23:30
  1490.     // 
  1491.     // 分析Proxy的设置
  1492.     //http=193.168.10.1:80;socks=192.168.10.235:1080
  1493.     //193.168.10.1:1090
  1494.     //ftp=193.168.10.1:1090;gopher=193.168.10.1:1090;https=193.168.10.1:1090;socks=193.168.10.2:1080
  1495.     int nPos = -1;
  1496.     CString strProxy = szAddr;
  1497.     
  1498.     if (strProxy.IsEmpty())
  1499.         return FALSE;
  1500.     
  1501.     strProxy.MakeLower();
  1502.     nProxyType = HTTP_PROXY_HTTPGET;
  1503.     
  1504.     nPos = strProxy.Find(';');
  1505.     if (nPos != -1)
  1506.     {
  1507.         nPos = strProxy.Find("http=");        // HTTP GET Proxy
  1508.         if (nPos != -1)
  1509.             strProxy = strProxy.Mid(nPos+strlen("http="));
  1510.         else if ((nPos = strProxy.Find("socks=")) != -1) // SOCKS Proxy ( SOCKS5 )
  1511.         {
  1512.             strProxy = strProxy.Mid( nPos+strlen("socks="));
  1513.             nProxyType = HTTP_PROXY_SOCKS5;
  1514.         }
  1515.         nPos = strProxy.Find(";");
  1516.         if (nPos != -1)
  1517.          strProxy = strProxy.Left(nPos);
  1518.     }
  1519.     
  1520.     nPos = strProxy.Find(":");
  1521.     strProxyServer = strProxy.Left(nPos);
  1522.     nProxyPort = _ttoi(strProxy.Mid(nPos+1));
  1523.     if (nProxyPort <= 0)
  1524.         return FALSE;
  1525.     
  1526.     return TRUE;
  1527. }
  1528. //////////////////////////////////////////////////////////////////////////////////
  1529. // 函数名:void void SetCookie(
  1530. // LPCTSTR lpszCookie,
  1531. // BOOL bUseIECookie /*= FALSE*/ ) 
  1532. // 用  途:设置Cookie
  1533. // 对全局变量的影响:无
  1534. // 参  数:
  1535. // lpszCookie   : Cookie值 
  1536. // bUseIECookie : 是否使用IE的Cookie值
  1537. // 返回值:void
  1538. ////////////////////////////////////////////////////////////////////////////////
  1539. void CHttpDownload::SetCookie(LPCTSTR lpszCookie,BOOL bUseIECookie /*= FALSE*/ )
  1540. {
  1541. if( bUseIECookie )
  1542. {
  1543. m_bUseIECookie = TRUE;
  1544. /*
  1545. CString strCookie;
  1546. if( GetIECookie(strCookie,m_strDownloadUrl) )
  1547. m_strCookie = strCookie;
  1548. else
  1549. m_strCookie = _T("");
  1550. */
  1551. }
  1552. else
  1553. {
  1554. m_bUseIECookie = FALSE;
  1555. if( lpszCookie != NULL)
  1556. m_strCookie = lpszCookie;
  1557. else
  1558. m_strCookie = _T("");
  1559. }
  1560. }
  1561. //////////////////////////////////////////////////////////////////////////////////
  1562. // 函数名:BOOL GetIECookie(
  1563. // CString& strCookie,
  1564. // LPCTSTR lpszURL )
  1565. // 用  途:获取IE的Cookie设置
  1566. // 对全局变量的影响:无
  1567. // 参  数:
  1568. // strCookie  : 用于保存Cookie
  1569. // lpszURL    : 服务器URL
  1570. // 返回值:BOOL
  1571. ////////////////////////////////////////////////////////////////////////////////
  1572. BOOL CHttpDownload::GetIECookie(CString& strCookie,LPCTSTR lpszURL )
  1573. {
  1574. /*
  1575. Cookies Folder:
  1576. HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionExplorerShell Folders 
  1577. Cookies = ***
  1578. The simpliest way to Get Cookie value is call :
  1579. CInternetSession::GetCookie(***,***,strCookie);
  1580. But this way need the Wininet.dll which i don't want to use,How can i do?
  1581. OR: You can call :
  1582. CInternetSession::GetCookie(***,***,strCookie);
  1583. before you use HttpDownload,and then call SetCookie(***);
  1584. */
  1585. strCookie = _T("");
  1586. return TRUE;
  1587. }
  1588. ////////////////////////////////////////////////////////////////////////////////
  1589. // 函数名:BOOL IsValidFileName( LPCTSTR lpszFileName ) 
  1590. // 用  途:判断文件名是否合法
  1591. // 对全局变量的影响:无
  1592. // 参  数:
  1593. // lpszFileName : 文件名
  1594. // 返回值:BOOL
  1595. ////////////////////////////////////////////////////////////////////////////////
  1596. BOOL CHttpDownload::IsValidFileName(LPCTSTR lpszFileName)
  1597. {
  1598. /*
  1599. Short and long file names must not contain the following characters:
  1600.    ?   |   >  <   :  /  *  "
  1601. In addition, short file names must not contain the following characters:
  1602. +  ,  ;  =  [  ] 
  1603. Short file names may not include a space, although a long file name may. 
  1604. No space is allowed preceding the vertical bar (|) separator for the short 
  1605. file name/long file name syntax. If a space exists after the separator, then 
  1606. the long file name must have a space at the beginning of the file name. No 
  1607. full-path syntax is allowed.
  1608. */
  1609. CString strFileName(lpszFileName);
  1610. if( strFileName.FindOneOf("\?|></"*:") != -1 )
  1611. return FALSE;
  1612. return TRUE;
  1613. }
  1614. //seawind
  1615. BOOL CHttpDownload::IsUserStop()
  1616. {
  1617. ASSERT(m_hStopEvent != NULL);
  1618. if (WaitForSingleObject(m_hStopEvent, 0) == WAIT_OBJECT_0)
  1619. return TRUE;
  1620. else
  1621. return FALSE;
  1622. }