📄 inet.cpp
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-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 "stdafx.h"
#include <afxtempl.h>
#include <afxinet.h>
#pragma warning(disable: 4706) // assignment within conditional
#ifdef AFX_INET_SEG
#pragma code_seg(AFX_INET_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define new DEBUG_NEW
#ifdef _AFXDLL
#pragma comment(lib, "wininet.lib")
#endif
/////////////////////////////////////////////////////////////////////////////
// non-localized useful strings
typedef struct tagServiceTable {
DWORD dwService;
LPCTSTR pstrIdentifier;
} SvcTable;
AFX_STATIC_DATA const TCHAR _afxURLftp[] = _T("ftp://");
AFX_STATIC_DATA const TCHAR _afxURLgopher[] = _T("gopher://");
AFX_STATIC_DATA const TCHAR _afxURLhttp[] = _T("http://");
const LPCTSTR CHttpConnection::szHtmlVerbs[] = {
_T("POST"),
_T("GET"),
_T("HEAD"),
_T("PUT"),
_T("LINK"),
_T("DELETE"),
_T("UNLINK"),
};
/////////////////////////////////////////////////////////////////////////////
// map of HINTERNETs to CInternetSessions* for callbacks
// forward declared because we need a #pragma -- see end of this file
class CSessionMapPtrToPtr : public CMapPtrToPtr
{
private:
CCriticalSection m_sect;
public:
CSessionMapPtrToPtr() { }
~CSessionMapPtrToPtr() { }
void SetAt(HINTERNET hInternet, CInternetSession* pSess)
{
m_sect.Lock();
CMapPtrToPtr::SetAt(hInternet, pSess);
m_sect.Unlock();
}
void RemoveKey(HINTERNET hInternet)
{
m_sect.Lock();
CMapPtrToPtr::RemoveKey(hInternet);
m_sect.Unlock();
}
BOOL Lookup(HINTERNET hInternet, CInternetSession*& refpSession)
{
BOOL bRet;
m_sect.Lock();
bRet = CMapPtrToPtr::Lookup(hInternet, (void*&) refpSession);
m_sect.Unlock();
return bRet;
}
};
extern CSessionMapPtrToPtr _afxSessionMap;
/////////////////////////////////////////////////////////////////////////////
// Global Functions
AFX_STATIC BOOL AFXAPI _AfxParseURLWorker(LPCTSTR pstrURL,
LPURL_COMPONENTS lpComponents, DWORD& dwServiceType,
INTERNET_PORT& nPort, DWORD dwFlags)
{
// this function will return bogus stuff if lpComponents
// isn't set up to copy the components
ASSERT(lpComponents != NULL && pstrURL != NULL);
if (lpComponents == NULL || pstrURL == NULL)
return FALSE;
ASSERT(lpComponents->dwHostNameLength == 0 ||
lpComponents->lpszHostName != NULL);
ASSERT(lpComponents->dwUrlPathLength == 0 ||
lpComponents->lpszUrlPath != NULL);
ASSERT(lpComponents->dwUserNameLength == 0 ||
lpComponents->lpszUserName != NULL);
ASSERT(lpComponents->dwPasswordLength == 0 ||
lpComponents->lpszPassword != NULL);
ASSERT(AfxIsValidAddress(lpComponents, sizeof(URL_COMPONENTS), TRUE));
LPTSTR pstrCanonicalizedURL;
TCHAR szCanonicalizedURL[INTERNET_MAX_URL_LENGTH];
DWORD dwNeededLength = INTERNET_MAX_URL_LENGTH;
BOOL bRetVal;
BOOL bMustFree = FALSE;
DWORD dwCanonicalizeFlags = dwFlags &
(ICU_NO_ENCODE | ICU_DECODE | ICU_NO_META |
ICU_ENCODE_SPACES_ONLY | ICU_BROWSER_MODE);
DWORD dwCrackFlags = dwFlags & (ICU_ESCAPE | ICU_USERNAME);
bRetVal = InternetCanonicalizeUrl(pstrURL, szCanonicalizedURL,
&dwNeededLength, dwCanonicalizeFlags);
if (!bRetVal)
{
if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
return FALSE;
pstrCanonicalizedURL = new TCHAR[dwNeededLength];
bMustFree = TRUE;
bRetVal = InternetCanonicalizeUrl(pstrURL, pstrCanonicalizedURL,
&dwNeededLength, dwCanonicalizeFlags);
if (!bRetVal)
{
delete [] pstrCanonicalizedURL;
return FALSE;
}
}
else
pstrCanonicalizedURL = szCanonicalizedURL;
// now that it's safely canonicalized, crack it
bRetVal = InternetCrackUrl(pstrCanonicalizedURL, 0,
dwCrackFlags, lpComponents);
if (bMustFree)
delete [] pstrCanonicalizedURL;
// convert to MFC-style service ID
if (!bRetVal)
dwServiceType = AFX_INET_SERVICE_UNK;
else
{
nPort = lpComponents->nPort;
switch (lpComponents->nScheme)
{
case INTERNET_SCHEME_FTP:
dwServiceType = AFX_INET_SERVICE_FTP;
break;
case INTERNET_SCHEME_GOPHER:
dwServiceType = AFX_INET_SERVICE_GOPHER;
break;
case INTERNET_SCHEME_HTTP:
dwServiceType = AFX_INET_SERVICE_HTTP;
break;
case INTERNET_SCHEME_HTTPS:
dwServiceType = AFX_INET_SERVICE_HTTPS;
break;
case INTERNET_SCHEME_FILE:
dwServiceType = AFX_INET_SERVICE_FILE;
break;
case INTERNET_SCHEME_NEWS:
dwServiceType = AFX_INET_SERVICE_NNTP;
break;
case INTERNET_SCHEME_MAILTO:
dwServiceType = AFX_INET_SERVICE_MAILTO;
break;
default:
dwServiceType = AFX_INET_SERVICE_UNK;
}
}
return bRetVal;
}
BOOL AFXAPI AfxParseURLEx(LPCTSTR pstrURL, DWORD& dwServiceType,
CString& strServer, CString& strObject, INTERNET_PORT& nPort,
CString& strUsername, CString& strPassword, DWORD dwFlags/* = 0*/)
{
dwServiceType = AFX_INET_SERVICE_UNK;
ASSERT(pstrURL != NULL);
if (pstrURL == NULL)
return FALSE;
URL_COMPONENTS urlComponents;
memset(&urlComponents, 0, sizeof(URL_COMPONENTS));
urlComponents.dwStructSize = sizeof(URL_COMPONENTS);
urlComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
urlComponents.lpszHostName = strServer.GetBuffer(INTERNET_MAX_HOST_NAME_LENGTH+1);
urlComponents.dwUrlPathLength = INTERNET_MAX_PATH_LENGTH;
urlComponents.lpszUrlPath = strObject.GetBuffer(INTERNET_MAX_PATH_LENGTH+1);
urlComponents.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH;
urlComponents.lpszUserName = strUsername.GetBuffer(INTERNET_MAX_USER_NAME_LENGTH+1);
urlComponents.dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH;
urlComponents.lpszPassword = strPassword.GetBuffer(INTERNET_MAX_PASSWORD_LENGTH+1);
BOOL bRetVal = _AfxParseURLWorker(pstrURL, &urlComponents,
dwServiceType, nPort, dwFlags);
strServer.ReleaseBuffer();
strObject.ReleaseBuffer();
strUsername.ReleaseBuffer();
strPassword.ReleaseBuffer();
return bRetVal;
}
BOOL AFXAPI AfxParseURL(LPCTSTR pstrURL, DWORD& dwServiceType,
CString& strServer, CString& strObject, INTERNET_PORT& nPort)
{
dwServiceType = AFX_INET_SERVICE_UNK;
ASSERT(pstrURL != NULL);
if (pstrURL == NULL)
return FALSE;
URL_COMPONENTS urlComponents;
memset(&urlComponents, 0, sizeof(URL_COMPONENTS));
urlComponents.dwStructSize = sizeof(URL_COMPONENTS);
urlComponents.dwHostNameLength = INTERNET_MAX_URL_LENGTH;
urlComponents.lpszHostName = strServer.GetBuffer(INTERNET_MAX_URL_LENGTH+1);
urlComponents.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;
urlComponents.lpszUrlPath = strObject.GetBuffer(INTERNET_MAX_URL_LENGTH+1);
BOOL bRetVal = _AfxParseURLWorker(pstrURL, &urlComponents,
dwServiceType, nPort, ICU_BROWSER_MODE);
strServer.ReleaseBuffer();
strObject.ReleaseBuffer();
return bRetVal;
}
DWORD AFXAPI AfxGetInternetHandleType(HINTERNET hQuery)
{
DWORD dwServiceType;
DWORD dwTypeLen = sizeof(dwServiceType);
if (hQuery == NULL ||
!InternetQueryOption(hQuery, INTERNET_OPTION_HANDLE_TYPE,
&dwServiceType, &dwTypeLen))
return AFX_INET_SERVICE_UNK;
else
return dwServiceType;
}
AFX_STATIC BOOL AFXAPI
_AfxQueryCStringInternetOption(HINTERNET hHandle, DWORD dwOption, CString& refString)
{
DWORD dwLength = 0;
LPTSTR pstrBuffer;
if (hHandle == NULL)
return FALSE;
if (!InternetQueryOption(hHandle, dwOption, NULL, &dwLength) &&
GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
refString.Empty();
return FALSE;
}
pstrBuffer = refString.GetBuffer(dwLength);
BOOL bRet = InternetQueryOption(hHandle, dwOption, pstrBuffer, &dwLength);
refString.ReleaseBuffer();
return bRet;
}
#ifdef _DEBUG
void AFXAPI AfxInternetStatusCallbackDebug(HINTERNET hInternet,
DWORD dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength)
{
UNUSED_ALWAYS(hInternet);
TRACE1("Internet ctxt=%d: ", dwContext);
switch (dwInternetStatus)
{
case INTERNET_STATUS_RESOLVING_NAME:
TRACE1("resolving name for %s\n", lpvStatusInformation);
break;
case INTERNET_STATUS_NAME_RESOLVED:
TRACE1("resolved name for %s!\n", lpvStatusInformation);
break;
case INTERNET_STATUS_HANDLE_CREATED:
TRACE1("handle %8.8X created\n", hInternet);
break;
case INTERNET_STATUS_CONNECTING_TO_SERVER:
{
sockaddr* pSockAddr = (sockaddr*) lpvStatusInformation;
TRACE1("connecting to socket address \"%s\"\n", pSockAddr->sa_data);
}
break;
case INTERNET_STATUS_REQUEST_SENT:
TRACE0("request sent!\n");
break;
case INTERNET_STATUS_SENDING_REQUEST:
TRACE0("sending request...\n");
break;
case INTERNET_STATUS_CONNECTED_TO_SERVER:
TRACE0("connected to socket address!\n");
break;
case INTERNET_STATUS_RECEIVING_RESPONSE:
TRACE0("receiving response...\n");
break;
case INTERNET_STATUS_RESPONSE_RECEIVED:
TRACE0("response received!\n");
break;
case INTERNET_STATUS_CLOSING_CONNECTION:
TRACE1("closing connection %8.8X\n", hInternet);
break;
case INTERNET_STATUS_CONNECTION_CLOSED:
TRACE1("connection %8.8X closed!\n", hInternet);
break;
case INTERNET_STATUS_HANDLE_CLOSING:
TRACE1("handle %8.8X closed!\n", hInternet);
break;
case INTERNET_STATUS_REQUEST_COMPLETE:
if (dwStatusInformationLength == sizeof(INTERNET_ASYNC_RESULT))
{
INTERNET_ASYNC_RESULT* pResult = (INTERNET_ASYNC_RESULT*) lpvStatusInformation;
TRACE2("request complete, dwResult = %8.8X, dwError = %8.8X\n",
pResult->dwResult, pResult->dwError);
}
else
TRACE0("request complete.\n");
break;
case INTERNET_STATUS_CTL_RESPONSE_RECEIVED:
case INTERNET_STATUS_REDIRECT:
default:
TRACE1("Unknown status: %d\n", dwInternetStatus);
break;
}
return;
}
#endif // _DEBUG
void AFXAPI AfxInternetStatusCallback(HINTERNET hInternet, DWORD dwContext,
DWORD dwInternetStatus, LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength)
{
CInternetSession* pSession;
#ifdef _DEBUG
if (afxTraceFlags & traceInternet)
AfxInternetStatusCallbackDebug(hInternet, dwContext,
dwInternetStatus, lpvStatusInformation, dwStatusInformationLength);
#endif
if (_afxSessionMap.Lookup(hInternet, pSession))
{
pSession->OnStatusCallback(dwContext, dwInternetStatus,
lpvStatusInformation, dwStatusInformationLength);
}
// note that an entry we can't match is simply ignored as
// WININET can send notifications for handles that we can't
// see -- such as when using InternetOpenURL()
}
/////////////////////////////////////////////////////////////////////////////
// CInternetSession
CInternetSession::~CInternetSession()
{
Close();
}
CInternetSession::CInternetSession(LPCTSTR pstrAgent /* = NULL */,
DWORD dwContext /* = 1 */,
DWORD dwAccessType /* = PRE_CONFIG_INTERNET_ACCESS */,
LPCTSTR pstrProxyName /* = NULL */,
LPCTSTR pstrProxyBypass /* = NULL */,
DWORD dwFlags /* = 0 */)
{
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
m_bCallbackEnabled = FALSE;
m_pOldCallback = NULL;
m_dwContext = dwContext;
if (pstrAgent == NULL)
pstrAgent = AfxGetAppName();
m_hSession = InternetOpen(pstrAgent, dwAccessType,
pstrProxyName, pstrProxyBypass, dwFlags);
if (m_hSession == NULL)
AfxThrowInternetException(m_dwContext);
else
_afxSessionMap.SetAt(m_hSession, this);
}
void CInternetSession::Close()
{
if (m_bCallbackEnabled)
EnableStatusCallback(FALSE);
if (m_hSession != NULL)
{
InternetCloseHandle(m_hSession);
_afxSessionMap.RemoveKey(m_hSession);
m_hSession = NULL;
}
}
CGopherConnection* CInternetSession::GetGopherConnection(LPCTSTR pstrServer,
LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */,
INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */)
{
ASSERT(AfxIsValidString(pstrServer));
CGopherConnection* pReturn = new CGopherConnection(this,
pstrServer, pstrUserName, pstrPassword, m_dwContext, nPort);
return pReturn;
}
CFtpConnection* CInternetSession::GetFtpConnection(LPCTSTR pstrServer,
LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */,
INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
BOOL bPassive /* = FALSE */)
{
ASSERT(AfxIsValidString(pstrServer));
CFtpConnection* pReturn = new CFtpConnection(this,
pstrServer, pstrUserName, pstrPassword, m_dwContext,
nPort, bPassive);
return pReturn;
}
CHttpConnection* CInternetSession::GetHttpConnection(LPCTSTR pstrServer,
INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */)
{
ASSERT(AfxIsValidString(pstrServer));
CHttpConnection* pReturn = new CHttpConnection(this,
pstrServer, nPort, pstrUserName, pstrPassword, m_dwContext);
return pReturn;
}
CHttpConnection* CInternetSession::GetHttpConnection(LPCTSTR pstrServer,
DWORD dwFlags, INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */)
{
ASSERT(AfxIsValidString(pstrServer));
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
CHttpConnection* pReturn = new CHttpConnection(this, pstrServer,
dwFlags, nPort, pstrUserName, pstrPassword, m_dwContext);
return pReturn;
}
CStdioFile* CInternetSession::OpenURL(LPCTSTR pstrURL,
DWORD dwContext /* = 0 */, DWORD dwFlags /* = INTERNET_FLAG_TRANSFER_BINARY */,
LPCTSTR pstrHeaders /* = NULL */, DWORD dwHeadersLength /* = 0 */)
{
ASSERT(AfxIsValidString(pstrURL));
ASSERT(dwHeadersLength == 0 || pstrHeaders != NULL);
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
// must have TRANSFER_BINARY or TRANSFER_ASCII but not both
#define _AFX_TRANSFER_MASK (INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_TRANSFER_ASCII)
ASSERT((dwFlags & _AFX_TRANSFER_MASK) != 0);
ASSERT((dwFlags & _AFX_TRANSFER_MASK) != _AFX_TRANSFER_MASK);
if (dwContext == 1)
dwContext = m_dwContext;
DWORD dwServiceType;
CString strServer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -