TEAR.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:10k
源码类别:

Windows编程

开发平台:

Visual C++

  1. // tear.cpp : implements the TEAR console application
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1997-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12. #include <afx.h>
  13. #include <afxwin.h>
  14. #include <afxinet.h>
  15. #include "tear.h"
  16. #include <iostream.h>
  17. #include <stdlib.h>
  18. /////////////////////////////////////////////////////////////////////////////
  19. // Globals
  20. LPCTSTR pszURL = NULL;
  21. BOOL    bStripMode = FALSE;
  22. BOOL    bProgressMode = FALSE;
  23. DWORD   dwAccessType = PRE_CONFIG_INTERNET_ACCESS;
  24. DWORD dwHttpRequestFlags =
  25. INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_AUTO_REDIRECT;
  26. const TCHAR szHeaders[] =
  27. _T("Accept: text/*rnUser-Agent: MFC_Tear_Samplern");
  28. /////////////////////////////////////////////////////////////////////////////
  29. // CTearSession object
  30. // TEAR wants to use its own derivative of the CInternetSession class
  31. // just so it can implement an OnStatusCallback() override.
  32. CTearSession::CTearSession(LPCTSTR pszAppName, int nMethod)
  33. : CInternetSession(pszAppName, 1, nMethod)
  34. {
  35. }
  36. void CTearSession::OnStatusCallback(DWORD /* dwContext */, DWORD dwInternetStatus,
  37. LPVOID /* lpvStatusInfomration */, DWORD /* dwStatusInformationLen */)
  38. {
  39. if (!bProgressMode)
  40. return;
  41. if (dwInternetStatus == INTERNET_STATUS_CONNECTED_TO_SERVER)
  42. cerr << _T("Connection made!") << endl;
  43. }
  44. /////////////////////////////////////////////////////////////////////////////
  45. // CTearException -- used if something goes wrong for us
  46. // TEAR will throw its own exception type to handle problems it might
  47. // encounter while fulfilling the user's request.
  48. IMPLEMENT_DYNCREATE(CTearException, CException)
  49. CTearException::CTearException(int nCode)
  50. : m_nErrorCode(nCode)
  51. {
  52. }
  53. void ThrowTearException(int nCode)
  54. {
  55. CTearException* pEx = new CTearException(nCode);
  56. throw pEx;
  57. }
  58. /////////////////////////////////////////////////////////////////////////////
  59. // Routines
  60. void ShowBanner()
  61. {
  62. cerr << _T("TEAR - Tear a Page Off the Internet!") << endl;
  63. cerr << _T("Version 4.2 - Copyright (C) Microsoft Corp 1998") << endl;
  64. cerr << endl;
  65. }
  66. void ShowUsage()
  67. {
  68. cerr << _T("Usage:  TEAR [options] <URL>") << endl << endl;
  69. cerr << _T("t<URL> points at a HTTP resource") << endl;
  70. cerr << _T("t[options] are any of:") << endl;
  71. cerr << _T("tt/F force reload of requested page") << endl;
  72. cerr << _T("tt/P show detailed progress information") << endl;
  73. cerr << _T("tt/S strip HTML tags from stream") << endl << endl;
  74. cerr << _T("tt/L use local Internet access") << endl;
  75. cerr << _T("tt/D use pre-configured Internet access (default)") << endl;
  76. cerr << endl;
  77. exit(1);
  78. }
  79. // ParseOptions() looks for options on the command line and sets global
  80. // flags so the rest of the program knows about them.  ParseOptions()
  81. // also initializes pszURL to point at the URL the user wanted.
  82. BOOL ParseOptions(int argc, char* argv[])
  83. {
  84. int nIndex;
  85. for (nIndex = 1; nIndex < argc; nIndex++)
  86. {
  87. // an option or a URL?
  88. if (*argv[nIndex] == '-' || *argv[nIndex] == '/')
  89. {
  90. if (argv[nIndex][1] == 'D' || argv[nIndex][1] == 'd')
  91. dwAccessType = PRE_CONFIG_INTERNET_ACCESS;
  92. else if (argv[nIndex][1] == 'L' || argv[nIndex][1] == 'l')
  93. dwAccessType = LOCAL_INTERNET_ACCESS;
  94. else if (argv[nIndex][1] == 'S' || argv[nIndex][1] == 's')
  95. bStripMode = TRUE;
  96. else if (argv[nIndex][1] == 'P' || argv[nIndex][1] == 'p')
  97. bProgressMode = TRUE;
  98. else if (argv[nIndex][1] == 'F' || argv[nIndex][1] == 'f')
  99. dwHttpRequestFlags |= INTERNET_FLAG_RELOAD;
  100. else
  101. {
  102. cerr << _T("Error: unrecognized option: ") << argv[nIndex] << endl;
  103. return FALSE;
  104. }
  105. }
  106. else
  107. {
  108. // can't have too many URLs
  109. if (pszURL != NULL)
  110. {
  111. cerr << _T("Error: can only specify one URL!") << endl;
  112. return FALSE;
  113. }
  114. else
  115. pszURL = argv[nIndex];
  116. }
  117. }
  118. return TRUE;
  119. }
  120. // StripTags() rips through a buffer and removes HTML tags from it.
  121. // The function uses a static variable to remember its state in case
  122. // a HTML tag spans a buffer boundary.
  123. void StripTags(LPTSTR pszBuffer)
  124. {
  125. static BOOL bInTag = FALSE;
  126. LPTSTR pszSource = pszBuffer;
  127. LPTSTR pszDest = pszBuffer;
  128. while (*pszSource != '')
  129. {
  130. if (bInTag)
  131. {
  132. if (*pszSource == '>')
  133. bInTag = FALSE;
  134. pszSource++;
  135. }
  136. else
  137. {
  138. if (*pszSource == '<')
  139. bInTag = TRUE;
  140. else
  141. {
  142. *pszDest = *pszSource;
  143. pszDest++;
  144. }
  145. pszSource++;
  146. }
  147. }
  148. *pszDest = '';
  149. }
  150. /////////////////////////////////////////////////////////////////////////////
  151. // The main() Thang
  152. int main(int argc, char* argv[])
  153. {
  154. ShowBanner();
  155. if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
  156. {
  157. cerr << _T("MFC Failed to initialize.n");
  158. return 1;
  159. }
  160. if (argc < 2 || !ParseOptions(argc, argv) || pszURL == NULL)
  161. ShowUsage();
  162. int nRetCode = 0;
  163. CTearSession session(_T("TEAR - MFC Sample App"), dwAccessType);
  164. CHttpConnection* pServer = NULL;
  165. CHttpFile* pFile = NULL;
  166. try
  167. {
  168. // check to see if this is a reasonable URL
  169. CString strServerName;
  170. CString strObject;
  171. INTERNET_PORT nPort;
  172. DWORD dwServiceType;
  173. if (!AfxParseURL(pszURL, dwServiceType, strServerName, strObject, nPort) ||
  174. dwServiceType != INTERNET_SERVICE_HTTP)
  175. {
  176. cerr << _T("Error: can only use URLs beginning with http://") << endl;
  177. ThrowTearException(1);
  178. }
  179. if (bProgressMode)
  180. {
  181. cerr << _T("Opening Internet...");
  182. VERIFY(session.EnableStatusCallback(TRUE));
  183. }
  184. pServer = session.GetHttpConnection(strServerName, nPort);
  185. pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET,
  186. strObject, NULL, 1, NULL, NULL, dwHttpRequestFlags);
  187. pFile->AddRequestHeaders(szHeaders);
  188. pFile->SendRequest();
  189. DWORD dwRet;
  190. pFile->QueryInfoStatusCode(dwRet);
  191. // if access was denied, prompt the user for the password
  192. if (dwRet == HTTP_STATUS_DENIED)
  193. {
  194. DWORD dwPrompt;
  195. dwPrompt = pFile->ErrorDlg(NULL, ERROR_INTERNET_INCORRECT_PASSWORD,
  196. FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, NULL);
  197. // if the user cancelled the dialog, bail out
  198. if (dwPrompt != ERROR_INTERNET_FORCE_RETRY)
  199. {
  200. cerr << _T("Access denied: Invalid passwordn");
  201. ThrowTearException(1);
  202. }
  203. pFile->SendRequest();
  204. pFile->QueryInfoStatusCode(dwRet);
  205. }
  206. CString strNewLocation;
  207. pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strNewLocation);
  208. // were we redirected?
  209. // these response status codes come from WININET.H
  210. if (dwRet == HTTP_STATUS_MOVED ||
  211. dwRet == HTTP_STATUS_REDIRECT ||
  212. dwRet == HTTP_STATUS_REDIRECT_METHOD)
  213. {
  214. CString strNewLocation;
  215. pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strNewLocation);
  216. int nPlace = strNewLocation.Find(_T("Location: "));
  217. if (nPlace == -1)
  218. {
  219. cerr << _T("Error: Site redirects with no new location") << endl;
  220. ThrowTearException(2);
  221. }
  222. strNewLocation = strNewLocation.Mid(nPlace + 10);
  223. nPlace = strNewLocation.Find('n');
  224. if (nPlace > 0)
  225. strNewLocation = strNewLocation.Left(nPlace);
  226. // close up the redirected site
  227. pFile->Close();
  228. delete pFile;
  229. pServer->Close();
  230. delete pServer;
  231. if (bProgressMode)
  232. {
  233. cerr << _T("Caution: redirected to ");
  234. cerr << (LPCTSTR) strNewLocation << endl;
  235. }
  236. // figure out what the old place was
  237. if (!AfxParseURL(strNewLocation, dwServiceType, strServerName, strObject, nPort))
  238. {
  239. cerr << _T("Error: the redirected URL could not be parsed.") << endl;
  240. ThrowTearException(2);
  241. }
  242. if (dwServiceType != INTERNET_SERVICE_HTTP)
  243. {
  244. cerr << _T("Error: the redirected URL does not reference a HTTP resource.") << endl;
  245. ThrowTearException(2);
  246. }
  247. // try again at the new location
  248. pServer = session.GetHttpConnection(strServerName, nPort);
  249. pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET,
  250. strObject, NULL, 1, NULL, NULL, dwHttpRequestFlags);
  251. pFile->AddRequestHeaders(szHeaders);
  252. pFile->SendRequest();
  253. pFile->QueryInfoStatusCode(dwRet);
  254. if (dwRet != HTTP_STATUS_OK)
  255. {
  256. cerr << _T("Error: Got status code ") << dwRet << endl;
  257. ThrowTearException(2);
  258. }
  259. }
  260. cerr << _T("Status Code is ") << dwRet << endl;
  261. TCHAR sz[1024];
  262. while (pFile->ReadString(sz, 1023))
  263. {
  264. if (bStripMode)
  265. StripTags(sz);
  266. cout << sz;
  267. }
  268. // NOTE: Since HTTP servers normally spit back plain text, the
  269. // above code (which reads line by line) is just fine.  However,
  270. // other data sources (eg, FTP servers) might provide binary data
  271. // which should be handled a buffer at a time, like this:
  272. #if 0
  273. while (nRead > 0)
  274. {
  275. sz[nRead] = '';
  276. if (bStripMode)
  277. StripTags(sz);
  278. cout << sz;
  279. nRead = pFile->Read(sz, 1023);
  280. }
  281. #endif
  282. pFile->Close();
  283. pServer->Close();
  284. }
  285. catch (CInternetException* pEx)
  286. {
  287. // catch errors from WinINet
  288. TCHAR szErr[1024];
  289. pEx->GetErrorMessage(szErr, 1024);
  290. cerr << _T("Error: (") << pEx->m_dwError << _T(") ");
  291. cerr << szErr << endl;
  292. nRetCode = 2;
  293. pEx->Delete();
  294. }
  295. catch (CTearException* pEx)
  296. {
  297. // catch things wrong with parameters, etc
  298. nRetCode = pEx->m_nErrorCode;
  299. TRACE1("Error: Exiting with CTearException(%d)n", nRetCode);
  300. pEx->Delete();
  301. }
  302. if (pFile != NULL)
  303. delete pFile;
  304. if (pServer != NULL)
  305. delete pServer;
  306. session.Close();
  307. return nRetCode;
  308. }