TEAR.CPP
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:10k
源码类别:
Windows编程
开发平台:
Visual C++
- // tear.cpp : implements the TEAR console application
- //
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1997-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
- #include <afx.h>
- #include <afxwin.h>
- #include <afxinet.h>
- #include "tear.h"
- #include <iostream.h>
- #include <stdlib.h>
- /////////////////////////////////////////////////////////////////////////////
- // Globals
- LPCTSTR pszURL = NULL;
- BOOL bStripMode = FALSE;
- BOOL bProgressMode = FALSE;
- DWORD dwAccessType = PRE_CONFIG_INTERNET_ACCESS;
- DWORD dwHttpRequestFlags =
- INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_NO_AUTO_REDIRECT;
- const TCHAR szHeaders[] =
- _T("Accept: text/*rnUser-Agent: MFC_Tear_Samplern");
- /////////////////////////////////////////////////////////////////////////////
- // CTearSession object
- // TEAR wants to use its own derivative of the CInternetSession class
- // just so it can implement an OnStatusCallback() override.
- CTearSession::CTearSession(LPCTSTR pszAppName, int nMethod)
- : CInternetSession(pszAppName, 1, nMethod)
- {
- }
- void CTearSession::OnStatusCallback(DWORD /* dwContext */, DWORD dwInternetStatus,
- LPVOID /* lpvStatusInfomration */, DWORD /* dwStatusInformationLen */)
- {
- if (!bProgressMode)
- return;
- if (dwInternetStatus == INTERNET_STATUS_CONNECTED_TO_SERVER)
- cerr << _T("Connection made!") << endl;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CTearException -- used if something goes wrong for us
- // TEAR will throw its own exception type to handle problems it might
- // encounter while fulfilling the user's request.
- IMPLEMENT_DYNCREATE(CTearException, CException)
- CTearException::CTearException(int nCode)
- : m_nErrorCode(nCode)
- {
- }
- void ThrowTearException(int nCode)
- {
- CTearException* pEx = new CTearException(nCode);
- throw pEx;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Routines
- void ShowBanner()
- {
- cerr << _T("TEAR - Tear a Page Off the Internet!") << endl;
- cerr << _T("Version 4.2 - Copyright (C) Microsoft Corp 1998") << endl;
- cerr << endl;
- }
- void ShowUsage()
- {
- cerr << _T("Usage: TEAR [options] <URL>") << endl << endl;
- cerr << _T("t<URL> points at a HTTP resource") << endl;
- cerr << _T("t[options] are any of:") << endl;
- cerr << _T("tt/F force reload of requested page") << endl;
- cerr << _T("tt/P show detailed progress information") << endl;
- cerr << _T("tt/S strip HTML tags from stream") << endl << endl;
- cerr << _T("tt/L use local Internet access") << endl;
- cerr << _T("tt/D use pre-configured Internet access (default)") << endl;
- cerr << endl;
- exit(1);
- }
- // ParseOptions() looks for options on the command line and sets global
- // flags so the rest of the program knows about them. ParseOptions()
- // also initializes pszURL to point at the URL the user wanted.
- BOOL ParseOptions(int argc, char* argv[])
- {
- int nIndex;
- for (nIndex = 1; nIndex < argc; nIndex++)
- {
- // an option or a URL?
- if (*argv[nIndex] == '-' || *argv[nIndex] == '/')
- {
- if (argv[nIndex][1] == 'D' || argv[nIndex][1] == 'd')
- dwAccessType = PRE_CONFIG_INTERNET_ACCESS;
- else if (argv[nIndex][1] == 'L' || argv[nIndex][1] == 'l')
- dwAccessType = LOCAL_INTERNET_ACCESS;
- else if (argv[nIndex][1] == 'S' || argv[nIndex][1] == 's')
- bStripMode = TRUE;
- else if (argv[nIndex][1] == 'P' || argv[nIndex][1] == 'p')
- bProgressMode = TRUE;
- else if (argv[nIndex][1] == 'F' || argv[nIndex][1] == 'f')
- dwHttpRequestFlags |= INTERNET_FLAG_RELOAD;
- else
- {
- cerr << _T("Error: unrecognized option: ") << argv[nIndex] << endl;
- return FALSE;
- }
- }
- else
- {
- // can't have too many URLs
- if (pszURL != NULL)
- {
- cerr << _T("Error: can only specify one URL!") << endl;
- return FALSE;
- }
- else
- pszURL = argv[nIndex];
- }
- }
- return TRUE;
- }
- // StripTags() rips through a buffer and removes HTML tags from it.
- // The function uses a static variable to remember its state in case
- // a HTML tag spans a buffer boundary.
- void StripTags(LPTSTR pszBuffer)
- {
- static BOOL bInTag = FALSE;
- LPTSTR pszSource = pszBuffer;
- LPTSTR pszDest = pszBuffer;
- while (*pszSource != ' ')
- {
- if (bInTag)
- {
- if (*pszSource == '>')
- bInTag = FALSE;
- pszSource++;
- }
- else
- {
- if (*pszSource == '<')
- bInTag = TRUE;
- else
- {
- *pszDest = *pszSource;
- pszDest++;
- }
- pszSource++;
- }
- }
- *pszDest = ' ';
- }
- /////////////////////////////////////////////////////////////////////////////
- // The main() Thang
- int main(int argc, char* argv[])
- {
- ShowBanner();
- if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
- {
- cerr << _T("MFC Failed to initialize.n");
- return 1;
- }
- if (argc < 2 || !ParseOptions(argc, argv) || pszURL == NULL)
- ShowUsage();
- int nRetCode = 0;
- CTearSession session(_T("TEAR - MFC Sample App"), dwAccessType);
- CHttpConnection* pServer = NULL;
- CHttpFile* pFile = NULL;
- try
- {
- // check to see if this is a reasonable URL
- CString strServerName;
- CString strObject;
- INTERNET_PORT nPort;
- DWORD dwServiceType;
- if (!AfxParseURL(pszURL, dwServiceType, strServerName, strObject, nPort) ||
- dwServiceType != INTERNET_SERVICE_HTTP)
- {
- cerr << _T("Error: can only use URLs beginning with http://") << endl;
- ThrowTearException(1);
- }
- if (bProgressMode)
- {
- cerr << _T("Opening Internet...");
- VERIFY(session.EnableStatusCallback(TRUE));
- }
- pServer = session.GetHttpConnection(strServerName, nPort);
- pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET,
- strObject, NULL, 1, NULL, NULL, dwHttpRequestFlags);
- pFile->AddRequestHeaders(szHeaders);
- pFile->SendRequest();
- DWORD dwRet;
- pFile->QueryInfoStatusCode(dwRet);
- // if access was denied, prompt the user for the password
- if (dwRet == HTTP_STATUS_DENIED)
- {
- DWORD dwPrompt;
- dwPrompt = pFile->ErrorDlg(NULL, ERROR_INTERNET_INCORRECT_PASSWORD,
- FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, NULL);
- // if the user cancelled the dialog, bail out
- if (dwPrompt != ERROR_INTERNET_FORCE_RETRY)
- {
- cerr << _T("Access denied: Invalid passwordn");
- ThrowTearException(1);
- }
- pFile->SendRequest();
- pFile->QueryInfoStatusCode(dwRet);
- }
- CString strNewLocation;
- pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strNewLocation);
- // were we redirected?
- // these response status codes come from WININET.H
- if (dwRet == HTTP_STATUS_MOVED ||
- dwRet == HTTP_STATUS_REDIRECT ||
- dwRet == HTTP_STATUS_REDIRECT_METHOD)
- {
- CString strNewLocation;
- pFile->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF, strNewLocation);
- int nPlace = strNewLocation.Find(_T("Location: "));
- if (nPlace == -1)
- {
- cerr << _T("Error: Site redirects with no new location") << endl;
- ThrowTearException(2);
- }
- strNewLocation = strNewLocation.Mid(nPlace + 10);
- nPlace = strNewLocation.Find('n');
- if (nPlace > 0)
- strNewLocation = strNewLocation.Left(nPlace);
- // close up the redirected site
- pFile->Close();
- delete pFile;
- pServer->Close();
- delete pServer;
- if (bProgressMode)
- {
- cerr << _T("Caution: redirected to ");
- cerr << (LPCTSTR) strNewLocation << endl;
- }
- // figure out what the old place was
- if (!AfxParseURL(strNewLocation, dwServiceType, strServerName, strObject, nPort))
- {
- cerr << _T("Error: the redirected URL could not be parsed.") << endl;
- ThrowTearException(2);
- }
- if (dwServiceType != INTERNET_SERVICE_HTTP)
- {
- cerr << _T("Error: the redirected URL does not reference a HTTP resource.") << endl;
- ThrowTearException(2);
- }
- // try again at the new location
- pServer = session.GetHttpConnection(strServerName, nPort);
- pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_GET,
- strObject, NULL, 1, NULL, NULL, dwHttpRequestFlags);
- pFile->AddRequestHeaders(szHeaders);
- pFile->SendRequest();
- pFile->QueryInfoStatusCode(dwRet);
- if (dwRet != HTTP_STATUS_OK)
- {
- cerr << _T("Error: Got status code ") << dwRet << endl;
- ThrowTearException(2);
- }
- }
- cerr << _T("Status Code is ") << dwRet << endl;
- TCHAR sz[1024];
- while (pFile->ReadString(sz, 1023))
- {
- if (bStripMode)
- StripTags(sz);
- cout << sz;
- }
- // NOTE: Since HTTP servers normally spit back plain text, the
- // above code (which reads line by line) is just fine. However,
- // other data sources (eg, FTP servers) might provide binary data
- // which should be handled a buffer at a time, like this:
- #if 0
- while (nRead > 0)
- {
- sz[nRead] = ' ';
- if (bStripMode)
- StripTags(sz);
- cout << sz;
- nRead = pFile->Read(sz, 1023);
- }
- #endif
- pFile->Close();
- pServer->Close();
- }
- catch (CInternetException* pEx)
- {
- // catch errors from WinINet
- TCHAR szErr[1024];
- pEx->GetErrorMessage(szErr, 1024);
- cerr << _T("Error: (") << pEx->m_dwError << _T(") ");
- cerr << szErr << endl;
- nRetCode = 2;
- pEx->Delete();
- }
- catch (CTearException* pEx)
- {
- // catch things wrong with parameters, etc
- nRetCode = pEx->m_nErrorCode;
- TRACE1("Error: Exiting with CTearException(%d)n", nRetCode);
- pEx->Delete();
- }
- if (pFile != NULL)
- delete pFile;
- if (pServer != NULL)
- delete pServer;
- session.Close();
- return nRetCode;
- }