home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Windows Gam…ming Gurus (2nd Edition)
/
Disc2.iso
/
vc98
/
mfc
/
src
/
inet.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-06-16
|
73KB
|
2,880 lines
// 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;
CString strObject;
INTERNET_PORT nPort;
CStdioFile* pReturn;
BOOL bParsed = AfxParseURL(pstrURL, dwServiceType, strServer, strObject, nPort);
// if it turns out to be a file...
if (bParsed && dwServiceType == AFX_INET_SERVICE_FILE)
{
int nMode = CFile::modeRead | CFile::shareCompat;
if (dwFlags & INTERNET_FLAG_TRANSFER_BINARY)
nMode |= CFile::typeBinary;
else
nMode |= CFile::typeText;
pReturn = new CStdioFile(strObject, nMode);
}
else
{
HINTERNET hOpener;
hOpener = InternetOpenUrl(m_hSession, pstrURL, pstrHeaders,
dwHeadersLength, dwFlags, dwContext);
if (hOpener == NULL)
AfxThrowInternetException(m_dwContext);
if (!bParsed)
dwServiceType = AfxGetInternetHandleType(hOpener);
switch (dwServiceType)
{
case INTERNET_HANDLE_TYPE_GOPHER_FILE:
case AFX_INET_SERVICE_GOPHER:
//WINBUG: WININET supplies no way to
// convert from a URL to a Gopher locator
pReturn = new CGopherFile(hOpener, m_hSession, _T(""),
0, dwContext);
_afxSessionMap.SetAt(hOpener, this);
break;
case INTERNET_HANDLE_TYPE_FTP_FILE:
case AFX_INET_SERVICE_FTP:
pReturn = new CInternetFile(hOpener, m_hSession, strObject,
strServer, dwContext, TRUE);
_afxSessionMap.SetAt(hOpener, this);
break;
case INTERNET_HANDLE_TYPE_HTTP_REQUEST:
case AFX_INET_SERVICE_HTTP:
case AFX_INET_SERVICE_HTTPS:
pReturn = new CHttpFile(hOpener, m_hSession, strObject, strServer,
CHttpConnection::szHtmlVerbs[CHttpConnection::HTTP_VERB_GET],
dwContext);
_afxSessionMap.SetAt(hOpener, this);
break;
default:
TRACE1("Error: Unidentified service type: %8.8X\n", dwServiceType);
pReturn = NULL;
}
}
return pReturn;
}
BOOL CInternetSession::SetOption(DWORD dwOption, LPVOID lpBuffer,
DWORD dwBufferLength, DWORD dwFlags /* = 0 */)
{
ASSERT(AfxIsValidAddress(lpBuffer, dwBufferLength, FALSE));
ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
dwOption <= INTERNET_LAST_OPTION);
ASSERT(dwBufferLength != 0);
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
// bogus flag?
ASSERT(dwFlags == 0 || ((dwFlags & ISO_VALID_FLAGS) == dwFlags));
return InternetSetOptionEx(m_hSession, dwOption,
lpBuffer, dwBufferLength, dwFlags);
}
BOOL CInternetSession::QueryOption(DWORD dwOption, LPVOID lpBuffer,
LPDWORD lpdwBufferLength) const
{
ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
dwOption <= INTERNET_LAST_OPTION);
ASSERT_POINTER(lpdwBufferLength, DWORD);
ASSERT(AfxIsValidAddress(lpBuffer, *lpdwBufferLength));
ASSERT(*lpdwBufferLength != 0);
return InternetQueryOption(m_hSession, dwOption,
lpBuffer, lpdwBufferLength);
}
BOOL CInternetSession::QueryOption(DWORD dwOption, DWORD& dwValue) const
{
DWORD dwLen = sizeof(DWORD);
return InternetQueryOption(m_hSession, dwOption,
&dwValue, &dwLen);
}
BOOL CInternetSession::QueryOption(DWORD dwOption, CString& refString) const
{
ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
dwOption <= INTERNET_LAST_OPTION);
return _AfxQueryCStringInternetOption(m_hSession, dwOption, refString);
}
void CInternetSession::OnStatusCallback(DWORD dwContext,
DWORD dwInternetStatus, LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength)
{
ASSERT(m_bCallbackEnabled != NULL);
if (m_pOldCallback != NULL)
{
(*m_pOldCallback)(m_hSession, dwContext, dwInternetStatus,
lpvStatusInformation, dwStatusInformationLength);
}
}
BOOL CInternetSession::EnableStatusCallback(BOOL bEnable /* = TRUE */)
{
ASSERT(!bEnable || m_hSession != NULL);
if (m_hSession == NULL)
return FALSE;
BOOL bResult = TRUE;
if (bEnable)
{
ASSERT(!m_bCallbackEnabled);
if (!m_bCallbackEnabled)
{
INTERNET_STATUS_CALLBACK pRet =
InternetSetStatusCallback(m_hSession, AfxInternetStatusCallback);
if (pRet != INTERNET_INVALID_STATUS_CALLBACK)
{
m_pOldCallback = pRet;
m_bCallbackEnabled = TRUE;
}
else
AfxThrowInternetException(m_dwContext);
}
}
else
{
ASSERT(m_bCallbackEnabled);
if (m_bCallbackEnabled)
{
InternetSetStatusCallback(m_hSession, NULL);
m_bCallbackEnabled = FALSE;
}
}
return bResult;
}
BOOL CInternetSession::SetCookie(LPCSTR pstrUrl, LPCTSTR pstrCookieName, LPCTSTR pstrCookieData)
{
ASSERT(AfxIsValidString(pstrUrl));
ASSERT(AfxIsValidString(pstrCookieName));
return InternetSetCookie(pstrUrl, pstrCookieName, pstrCookieData);
}
BOOL CInternetSession::GetCookie(LPCSTR pstrUrl, LPCTSTR pstrCookieName, LPTSTR pstrCookieData, DWORD dwBufLen)
{
ASSERT(AfxIsValidString(pstrUrl));
ASSERT(AfxIsValidString(pstrCookieName));
ASSERT(pstrCookieData != NULL);
return InternetGetCookie(pstrUrl, pstrCookieName, pstrCookieData, &dwBufLen);
}
DWORD CInternetSession::GetCookieLength(LPCSTR pstrUrl, LPCTSTR pstrCookieName)
{
ASSERT(AfxIsValidString(pstrUrl));
ASSERT(AfxIsValidString(pstrCookieName));
DWORD dwRet;
if (!InternetGetCookie(pstrUrl, pstrCookieName, NULL, &dwRet))
dwRet = 0;
return dwRet;
}
BOOL CInternetSession::GetCookie(LPCSTR pstrUrl, LPCTSTR pstrCookieName, CString& strCookieData)
{
ASSERT(AfxIsValidString(pstrUrl));
ASSERT(AfxIsValidString(pstrCookieName));
DWORD dwLen = GetCookieLength(pstrUrl, pstrCookieName);
LPTSTR pstrTarget = strCookieData.GetBuffer(dwLen+1);
BOOL bRetVal = InternetGetCookie(pstrUrl, pstrCookieName, pstrTarget, &dwLen);
strCookieData.ReleaseBuffer(dwLen);
if (!bRetVal)
strCookieData.Empty();
return bRetVal;
}
#ifdef _DEBUG
void CInternetSession::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << "m_hSession = " << m_hSession;
dc << "\nm_dwContext = " << m_dwContext;
}
#endif
/////////////////////////////////////////////////////////////////////////////
// Internet Files
CInternetFile::CInternetFile(HINTERNET hFile, HINTERNET /* hSession */,
LPCTSTR pstrFileName, LPCTSTR pstrServer, DWORD dwContext, BOOL bReadMode)
: m_dwContext(dwContext)
{
// caller must set _afxSessionMap()!
ASSERT(AfxIsValidString(pstrServer));
ASSERT(AfxIsValidString(pstrFileName));
ASSERT(hFile != NULL);
m_strFileName = pstrFileName;
m_strServerName = pstrServer;
m_hFile = hFile;
m_bReadMode = bReadMode;
m_pbReadBuffer = NULL;
m_pbWriteBuffer = NULL;
m_nReadBufferSize = 0;
m_nReadBufferPos = 0;
m_nWriteBufferSize = 0;
m_nWriteBufferPos = 0;
m_nReadBufferBytes = 0;
}
CInternetFile::CInternetFile(HINTERNET hFile,
LPCTSTR pstrFileName, CInternetConnection* pConnection, BOOL bReadMode)
{
ASSERT(AfxIsValidString(pstrFileName));
ASSERT(pConnection != NULL);
ASSERT_VALID(pConnection);
ASSERT(hFile != NULL);
_afxSessionMap.SetAt(hFile, pConnection->GetSession());
m_strFileName = pstrFileName;
m_dwContext = pConnection->GetContext();
m_strServerName = pConnection->GetServerName();
m_hFile = hFile;
m_bReadMode = bReadMode;
m_pbReadBuffer = NULL;
m_pbWriteBuffer = NULL;
m_nReadBufferSize = 0;
m_nReadBufferPos = 0;
m_nWriteBufferSize = 0;
m_nWriteBufferPos = 0;
m_nReadBufferBytes = 0;
}
BOOL CInternetFile::QueryOption(DWORD dwOption, LPVOID lpBuffer,
LPDWORD lpdwBufferLength) const
{
ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
dwOption <= INTERNET_LAST_OPTION);
ASSERT_POINTER(lpdwBufferLength, DWORD);
ASSERT(AfxIsValidAddress(lpBuffer, *lpdwBufferLength));
ASSERT(*lpdwBufferLength != 0);
ASSERT(m_hFile != NULL);
return InternetQueryOption(m_hFile, dwOption,
lpBuffer, lpdwBufferLength);
}
BOOL CInternetFile::QueryOption(DWORD dwOption, DWORD& dwValue) const
{
ASSERT(m_hFile != NULL);
DWORD dwLen = sizeof(DWORD);
return InternetQueryOption(m_hFile, dwOption,
&dwValue, &dwLen);
}
BOOL CInternetFile::QueryOption(DWORD dwOption, CString& refString) const
{
ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
dwOption <= INTERNET_LAST_OPTION);
ASSERT(m_hFile != NULL);
return _AfxQueryCStringInternetOption(m_hFile, dwOption, refString);
}
BOOL CInternetFile::SetOption(DWORD dwOption, LPVOID lpBuffer,
DWORD dwBufferLength, DWORD dwFlags /* = 0 */)
{
ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
dwOption <= INTERNET_LAST_OPTION);
ASSERT(AfxIsValidAddress(lpBuffer, dwBufferLength, FALSE));
ASSERT(dwBufferLength != 0);
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
// bogus flag?
ASSERT(dwFlags == 0 || ((dwFlags & ISO_VALID_FLAGS) == dwFlags));
return InternetSetOptionEx(m_hFile, dwOption,
lpBuffer, dwBufferLength, dwFlags);
}
BOOL CInternetFile::SetReadBufferSize(UINT nReadSize)
{
ASSERT_VALID(this);
BOOL bRet = TRUE;
if (nReadSize != -1 && nReadSize != m_nReadBufferSize)
{
if (m_nReadBufferPos > nReadSize)
bRet = FALSE;
else
{
if (nReadSize == 0)
{
delete [] m_pbReadBuffer;
m_pbReadBuffer = NULL;
}
else if (m_pbReadBuffer == NULL)
{
m_pbReadBuffer = new BYTE[nReadSize];
m_nReadBufferPos = nReadSize;
}
else
{
DWORD dwMoved = m_nReadBufferSize - m_nReadBufferPos;
LPBYTE pbTemp = m_pbReadBuffer;
m_pbReadBuffer = new BYTE[nReadSize];
if (dwMoved > 0)
{
memcpy(m_pbReadBuffer, pbTemp + m_nReadBufferPos, dwMoved);
m_nReadBufferPos = 0;
m_nReadBufferBytes = dwMoved;
}
else
{
m_nReadBufferBytes = 0;
m_nReadBufferPos = nReadSize;
}
delete [] pbTemp;
}
m_nReadBufferSize = nReadSize;
}
}
return bRet;
}
BOOL CInternetFile::SetWriteBufferSize(UINT nWriteSize)
{
ASSERT_VALID(this);
BOOL bRet = TRUE;
if (nWriteSize != m_nWriteBufferSize)
{
if (m_nWriteBufferPos > nWriteSize)
Flush();
if (nWriteSize == 0)
{
delete [] m_pbWriteBuffer;
m_pbWriteBuffer = NULL;
}
else if (m_pbWriteBuffer == NULL)
{
m_pbWriteBuffer = new BYTE[nWriteSize];
m_nWriteBufferPos = 0;
}
else
{
LPBYTE pbTemp = m_pbWriteBuffer;
m_pbWriteBuffer = new BYTE[nWriteSize];
memcpy(m_pbWriteBuffer, pbTemp, m_nWriteBufferPos);
delete [] pbTemp;
}
m_nWriteBufferSize = nWriteSize;
}
return bRet;
}
LONG CInternetFile::Seek(LONG lOffset, UINT nFrom)
{
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
ASSERT(m_bReadMode);
ASSERT(m_pbReadBuffer == NULL);
// can't do this on a file for writing
// can't do this on a file that's got a buffer
if (!m_bReadMode || m_pbReadBuffer != NULL)
AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
switch (nFrom)
{
case begin:
nFrom = FILE_BEGIN;
break;
case current:
nFrom = FILE_CURRENT;
break;
case end:
nFrom = FILE_END;
break;
default:
ASSERT(FALSE); // got a bogus nFrom value
AfxThrowInternetException(m_dwContext, ERROR_INVALID_PARAMETER);
break;
}
LONG lRet;
lRet = InternetSetFilePointer(m_hFile, lOffset, NULL, nFrom, m_dwContext);
if (lRet == -1)
AfxThrowInternetException(m_dwContext);
return lRet;
}
CInternetFile::~CInternetFile()
{
if (m_hFile != NULL)
{
#ifdef _DEBUG
USES_CONVERSION;
LPCTSTR pszName = A2CT(GetRuntimeClass()->m_lpszClassName);
TRACE2("Warning: destroying an open %s with handle %8.8X\n",
pszName, m_hFile);
#endif
Close();
}
if (m_pbReadBuffer != NULL)
delete m_pbReadBuffer;
if (m_pbWriteBuffer != NULL)
delete m_pbWriteBuffer;
}
void CInternetFile::Abort()
{
ASSERT_VALID(this);
if (m_hFile != NULL)
Close();
m_strFileName.Empty();
}
void CInternetFile::Flush()
{
if (m_pbWriteBuffer != NULL && m_nWriteBufferPos > 0)
{
DWORD dwBytes;
if (!InternetWriteFile(m_hFile, m_pbWriteBuffer,
m_nWriteBufferPos, &dwBytes))
AfxThrowInternetException(m_dwContext);
if (dwBytes != m_nWriteBufferPos)
AfxThrowInternetException(m_dwContext);
m_nWriteBufferPos = 0;
}
}
void CInternetFile::Close()
{
if (m_hFile != NULL)
{
Flush();
InternetCloseHandle(m_hFile);
_afxSessionMap.RemoveKey(m_hFile);
m_hFile = NULL;
if (m_pbWriteBuffer != NULL)
{
delete [] m_pbWriteBuffer;
m_pbWriteBuffer = NULL;
}
if (m_pbReadBuffer != NULL)
{
delete [] m_pbReadBuffer;
m_pbReadBuffer = NULL;
}
}
}
UINT CInternetFile::Read(LPVOID lpBuf, UINT nCount)
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(lpBuf, nCount));
ASSERT(m_hFile != NULL);
ASSERT(m_bReadMode);
DWORD dwBytes;
if (!m_bReadMode || m_hFile == NULL)
AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
if (m_pbReadBuffer == NULL)
{
if (!InternetReadFile(m_hFile, (LPVOID) lpBuf, nCount, &dwBytes))
AfxThrowInternetException(m_dwContext);
return dwBytes;
}
LPBYTE lpbBuf = (LPBYTE) lpBuf;
// if the requested size is bigger than our buffer,
// then handle it directly
if (nCount >= m_nReadBufferSize)
{
DWORD dwMoved = max(0, (long)m_nReadBufferBytes - (long)m_nReadBufferPos);
memcpy(lpBuf, m_pbReadBuffer + m_nReadBufferPos, dwMoved);
m_nReadBufferPos = m_nReadBufferSize;
if (!InternetReadFile(m_hFile, lpbBuf+dwMoved, nCount-dwMoved, &dwBytes))
AfxThrowInternetException(m_dwContext);
dwBytes += dwMoved;
}
else
{
if (m_nReadBufferPos + nCount >= m_nReadBufferBytes)
{
DWORD dwMoved = max(0, (long)m_nReadBufferBytes - (long)m_nReadBufferPos);
memcpy(lpbBuf, m_pbReadBuffer + m_nReadBufferPos, dwMoved);
DWORD dwRead;
if (!InternetReadFile(m_hFile, m_pbReadBuffer, m_nReadBufferSize,
&dwRead))
AfxThrowInternetException(m_dwContext);
m_nReadBufferBytes = dwRead;
dwRead = min(nCount - dwMoved, m_nReadBufferBytes);
memcpy(lpbBuf + dwMoved, m_pbReadBuffer, dwRead);
m_nReadBufferPos = dwRead;
dwBytes = dwMoved + dwRead;
}
else
{
memcpy(lpbBuf, m_pbReadBuffer + m_nReadBufferPos, nCount);
m_nReadBufferPos += nCount;
dwBytes = nCount;
}
}
return dwBytes;
}
void CInternetFile::Write(const void* lpBuf, UINT nCount)
{
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
ASSERT(m_bReadMode == FALSE || m_bReadMode == -1);
if (m_bReadMode == TRUE || m_hFile == NULL)
AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
DWORD dwBytes;
if (m_pbWriteBuffer == NULL)
{
if (!InternetWriteFile(m_hFile, lpBuf, nCount, &dwBytes))
AfxThrowInternetException(m_dwContext);
if (dwBytes != nCount)
AfxThrowInternetException(m_dwContext);
}
else
{
if ((m_nWriteBufferPos + nCount) >= m_nWriteBufferSize)
{
// write what is in the buffer just now
if (!InternetWriteFile(m_hFile, m_pbWriteBuffer,
m_nWriteBufferPos, &dwBytes))
AfxThrowInternetException(m_dwContext);
// reset the buffer position since it is now clean
m_nWriteBufferPos = 0;
}
// if we can't hope to buffer the write request,
// do it immediately ... otherwise, buffer it!
if (nCount >= m_nWriteBufferSize)
{
if (!InternetWriteFile(m_hFile, (LPVOID) lpBuf, nCount, &dwBytes))
AfxThrowInternetException(m_dwContext);
}
else
{
memcpy(m_nWriteBufferPos + m_pbWriteBuffer, lpBuf, nCount);
m_nWriteBufferPos += nCount;
}
}
}
void CInternetFile::WriteString(LPCTSTR pstr)
{
ASSERT(m_bReadMode == TRUE || m_bReadMode == -1);
ASSERT(AfxIsValidString(pstr));
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
if (m_bReadMode == TRUE)
AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
Write(pstr, lstrlen(pstr));
}
LPTSTR CInternetFile::ReadString(LPTSTR pstr, UINT nMax)
{
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
ASSERT(AfxIsValidAddress(pstr, nMax*sizeof(TCHAR)));
DWORD dwRead;
// if we're reading line-by-line, we must have a buffer
if (m_pbReadBuffer == NULL)
{
if (!SetReadBufferSize(4096)) // arbitrary but reasonable
return NULL;
if (!InternetReadFile(m_hFile, m_pbReadBuffer, m_nReadBufferSize,
&dwRead))
AfxThrowInternetException(m_dwContext);
m_nReadBufferBytes = dwRead;
m_nReadBufferPos = 0;
}
LPTSTR pstrChar = (LPTSTR) (m_pbReadBuffer + m_nReadBufferPos);
LPTSTR pstrTarget = pstr;
while (--nMax)
{
if (m_nReadBufferPos >= m_nReadBufferBytes)
{
if (!InternetReadFile(m_hFile, m_pbReadBuffer, m_nReadBufferSize,
&dwRead))
AfxThrowInternetException(m_dwContext);
m_nReadBufferBytes = dwRead;
if (m_nReadBufferBytes == 0)
{
*pstrTarget = '\0';
if (pstrTarget == pstr)
return NULL;
else
return pstr;
}
else
{
m_nReadBufferPos = 0;
pstrChar = (LPTSTR) m_pbReadBuffer;
}
}
if (*pstrChar != '\r')
*pstrTarget++ = *pstrChar;
m_nReadBufferPos++;
if (*pstrChar++ == '\n')
break;
}
*pstrTarget = '\0';
return pstr;
}
BOOL CInternetFile::ReadString(CString& rString)
{
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
rString = _T(""); // empty string without deallocating
const int nMaxSize = 128;
LPTSTR pstrPlace = rString.GetBuffer(nMaxSize);
LPTSTR pstrResult;
int nLen;
do
{
pstrResult = ReadString(pstrPlace, nMaxSize);
rString.ReleaseBuffer();
// if string is read completely or EOF
if (pstrResult == NULL ||
(nLen = lstrlen(pstrPlace)) < (nMaxSize-1) ||
pstrPlace[nLen-1] == '\n')
break;
nLen = rString.GetLength();
pstrPlace = rString.GetBuffer(nMaxSize + nLen) + nLen;
} while (1);
// remove '\n' from end of string if present
pstrPlace = rString.GetBuffer(0);
nLen = rString.GetLength();
if (nLen != 0 && pstrPlace[nLen-1] == '\n')
pstrPlace[nLen-1] = '\0';
rString.ReleaseBuffer();
return (pstrResult != NULL);
}
DWORD CInternetFile::GetLength() const
{
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
DWORD dwRet = 0;
if (m_hFile != NULL)
{
if (!InternetQueryDataAvailable(m_hFile, &dwRet, 0, 0))
dwRet = 0;
}
return dwRet;
}
void CInternetFile::LockRange(DWORD /* dwPos */, DWORD /* dwCount */)
{
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
AfxThrowNotSupportedException();
}
void CInternetFile::UnlockRange(DWORD /* dwPos */, DWORD /* dwCount */)
{
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
AfxThrowNotSupportedException();
}
void CInternetFile::SetLength(DWORD)
{
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
AfxThrowNotSupportedException();
}
CFile* CInternetFile::Duplicate() const
{
ASSERT_VALID(this);
ASSERT(m_pStream != NULL);
AfxThrowNotSupportedException();
return NULL;
}
#ifdef _DEBUG
void CInternetFile::AssertValid() const
{
// Don't call CStdioFile's AsssertValid()
CFile::AssertValid();
ASSERT(m_hConnection != NULL);
// make sure we really have a decent handle
if (m_hFile != NULL)
{
DWORD dwResult = AfxGetInternetHandleType(m_hFile);
if (IsKindOf(RUNTIME_CLASS(CHttpFile)))
{
ASSERT(dwResult == INTERNET_HANDLE_TYPE_HTTP_REQUEST);
}
else if (IsKindOf(RUNTIME_CLASS(CGopherFile)))
{
ASSERT(dwResult == INTERNET_HANDLE_TYPE_GOPHER_FILE ||
dwResult == INTERNET_HANDLE_TYPE_GOPHER_FIND_HTML ||
dwResult == INTERNET_HANDLE_TYPE_GOPHER_FILE_HTML ||
dwResult == INTERNET_HANDLE_TYPE_HTTP_REQUEST);
}
else if (IsKindOf(RUNTIME_CLASS(CInternetFile)))
{
ASSERT(dwResult == INTERNET_HANDLE_TYPE_FTP_FILE ||
dwResult == INTERNET_HANDLE_TYPE_FTP_FILE_HTML ||
dwResult == INTERNET_HANDLE_TYPE_FTP_FIND_HTML ||
dwResult == INTERNET_HANDLE_TYPE_HTTP_REQUEST);
}
else
ASSERT(FALSE); // some bogus object!
}
}
void CInternetFile::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << "\na " << GetRuntimeClass()->m_lpszClassName;
dc << " with handle " << (UINT)m_hFile;
}
#endif
/////////////////////////////////////////////////////////////////////////////
// CInternetConnection
CInternetConnection::CInternetConnection(CInternetSession* pSession,
LPCTSTR pstrServerName,
INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
DWORD dwContext /* = 1 */)
: m_strServerName(pstrServerName)
{
ASSERT(pSession != NULL);
ASSERT_VALID(pSession);
ASSERT(pstrServerName != NULL);
m_nPort = nPort;
m_pSession = pSession;
m_hConnection = NULL;
if (dwContext == 1)
dwContext = pSession->GetContext();
m_dwContext = dwContext;
}
CInternetConnection::~CInternetConnection()
{
if (m_hConnection != NULL)
{
#ifdef _DEBUG
USES_CONVERSION;
LPCTSTR pszName = A2CT(GetRuntimeClass()->m_lpszClassName);
TRACE3("Warning: Disconnecting %s handle %8.8X in context %8.8X at destruction.\n",
pszName, m_hConnection, m_dwContext);
#endif
Close();
}
}
BOOL CInternetConnection::SetOption(DWORD dwOption, LPVOID lpBuffer,
DWORD dwBufferLength, DWORD dwFlags /* = 0 */)
{
ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
dwOption <= INTERNET_LAST_OPTION);
ASSERT(AfxIsValidAddress(lpBuffer, dwBufferLength, FALSE));
ASSERT(dwBufferLength != 0);
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
// bogus flag?
ASSERT(dwFlags == 0 || ((dwFlags & ISO_VALID_FLAGS) == dwFlags));
return InternetSetOptionEx(m_hConnection, dwOption,
lpBuffer, dwBufferLength, dwFlags);
}
BOOL CInternetConnection::QueryOption(DWORD dwOption, LPVOID lpBuffer,
LPDWORD lpdwBufferLength) const
{
ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
dwOption <= INTERNET_LAST_OPTION);
ASSERT_POINTER(lpdwBufferLength, DWORD);
ASSERT(AfxIsValidAddress(lpBuffer, *lpdwBufferLength));
ASSERT(*lpdwBufferLength != 0);
return InternetQueryOption(m_hConnection, dwOption,
lpBuffer, lpdwBufferLength);
}
BOOL CInternetConnection::QueryOption(DWORD dwOption, DWORD& dwValue) const
{
DWORD dwLen = sizeof(DWORD);
return InternetQueryOption(m_hConnection, dwOption,
&dwValue, &dwLen);
}
BOOL CInternetConnection::QueryOption(DWORD dwOption, CString& refString) const
{
ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
dwOption <= INTERNET_LAST_OPTION);
return _AfxQueryCStringInternetOption(m_hConnection, dwOption, refString);
}
void CInternetConnection::Close()
{
if (m_hConnection != NULL)
{
InternetCloseHandle(m_hConnection);
_afxSessionMap.RemoveKey(m_hConnection);
m_hConnection = NULL;
}
}
#ifdef _DEBUG
void CInternetConnection::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << "m_hConnection = " << m_hConnection;
}
void CInternetConnection::AssertValid() const
{
CObject::AssertValid();
}
#endif
/////////////////////////////////////////////////////////////////////////////
// CFtpConnection
CFtpConnection::~CFtpConnection()
{
}
CFtpConnection::CFtpConnection(CInternetSession* pSession,
HINTERNET hConnected, LPCTSTR pstrServer, DWORD dwContext)
: CInternetConnection(pSession, pstrServer, INTERNET_INVALID_PORT_NUMBER,
dwContext)
{
ASSERT(pSession != NULL);
ASSERT(AfxIsValidString(pstrServer));
BOOL bBadType = FALSE;
if (AfxGetInternetHandleType(hConnected) != INTERNET_HANDLE_TYPE_CONNECT_FTP)
{
ASSERT(FALSE); // used the wrong handle type
bBadType = TRUE;
}
m_strServerName = pstrServer;
m_hConnection = hConnected;
if (m_hConnection == NULL || bBadType)
AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
else
_afxSessionMap.SetAt(m_hConnection, m_pSession);
}
CFtpConnection::CFtpConnection(CInternetSession* pSession,
LPCTSTR pstrServer, LPCTSTR pstrUserName /* = NULL */,
LPCTSTR pstrPassword /* = NULL */, DWORD dwContext /* = 0 */,
INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
BOOL bPassive /* = FALSE */)
: CInternetConnection(pSession, pstrServer, nPort, dwContext)
{
ASSERT(pSession != NULL);
ASSERT_KINDOF(CInternetSession, pSession);
ASSERT(AfxIsValidString(pstrServer));
m_strServerName = pstrServer;
m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_FTP,
(bPassive ? INTERNET_FLAG_PASSIVE : 0), m_dwContext);
if (m_hConnection == NULL)
AfxThrowInternetException(m_dwContext, ::GetLastError());
else
_afxSessionMap.SetAt(m_hConnection, m_pSession);
}
void CFtpConnection::Close()
{
CInternetConnection::Close();
}
BOOL CFtpConnection::Remove(LPCTSTR pstrFileName)
{
ASSERT_VALID(this);
ASSERT(m_hConnection != NULL);
ASSERT(AfxIsValidString(pstrFileName));
return FtpDeleteFile(m_hConnection, pstrFileName);
}
BOOL CFtpConnection::Rename(LPCTSTR pstrExisting, LPCTSTR pstrNew)
{
ASSERT_VALID(this);
ASSERT(m_hConnection != NULL);
ASSERT(AfxIsValidString(pstrExisting));
ASSERT(AfxIsValidString(pstrNew));
return FtpRenameFile(m_hConnection, pstrExisting, pstrNew);
}
BOOL CFtpConnection::CreateDirectory(LPCTSTR pstrDirName)
{
ASSERT_VALID(this);
ASSERT(m_hConnection != NULL);
ASSERT(AfxIsValidString(pstrDirName));
return FtpCreateDirectory(m_hConnection, pstrDirName);
}
BOOL CFtpConnection::RemoveDirectory(LPCTSTR pstrDirName)
{
ASSERT_VALID(this);
ASSERT(m_hConnection != NULL);
ASSERT(AfxIsValidString(pstrDirName));
return FtpRemoveDirectory(m_hConnection, pstrDirName);
}
BOOL CFtpConnection::SetCurrentDirectory(LPCTSTR pstrDirName)
{
ASSERT_VALID(this);
ASSERT(m_hConnection != NULL);
ASSERT(AfxIsValidString(pstrDirName));
return FtpSetCurrentDirectory(m_hConnection, pstrDirName);
}
BOOL CFtpConnection::GetCurrentDirectory(LPTSTR pstrDirName,
LPDWORD lpdwLen) const
{
ASSERT_VALID(this);
ASSERT(m_hConnection != NULL);
ASSERT(AfxIsValidAddress(pstrDirName, *lpdwLen));
ASSERT(lpdwLen != 0);
return FtpGetCurrentDirectory(m_hConnection, pstrDirName, lpdwLen);
}
BOOL CFtpConnection::GetCurrentDirectoryAsURL(CString& strDirName) const
{
CString strDirectory;
if (!GetCurrentDirectory(strDirectory))
return FALSE;
strDirName = _afxURLftp;
strDirName += GetServerName();
if (strDirectory[0] != '/')
strDirName += '/';
strDirName += strDirectory;
return TRUE;
}
BOOL CFtpConnection::GetCurrentDirectoryAsURL(LPTSTR pstrName,
LPDWORD lpdwLen) const
{
ASSERT(lpdwLen != NULL);
ASSERT_POINTER(lpdwLen, DWORD);
ASSERT(AfxIsValidAddress(pstrName, *lpdwLen));
ASSERT(*lpdwLen != 0);
CString strTemp;
if (lpdwLen == NULL || !GetCurrentDirectoryAsURL(strTemp))
return FALSE;
if (pstrName == NULL)
*lpdwLen = strTemp.GetLength();
else
lstrcpyn(pstrName, (LPCTSTR) strTemp, max(0, *lpdwLen -1));
return TRUE;
}
BOOL CFtpConnection::GetCurrentDirectory(CString& strDirName) const
{
ASSERT_VALID(this);
ASSERT(m_hConnection != NULL);
DWORD dwLen = INTERNET_MAX_PATH_LENGTH;
LPTSTR pstrTarget = strDirName.GetBufferSetLength(dwLen);
BOOL bRet = FtpGetCurrentDirectory(m_hConnection, pstrTarget, &dwLen);
if (bRet)
strDirName.ReleaseBuffer(dwLen);
else
strDirName.ReleaseBuffer(0);
return bRet;
}
CInternetFile* CFtpConnection::OpenFile(LPCTSTR pstrFileName,
DWORD dwAccess /* = GENERIC_READ */,
DWORD dwFlags /* = FTP_TRANSFER_TYPE_BINARY */,
DWORD dwContext /* = 1 */)
{
ASSERT_VALID(this);
ASSERT(m_hConnection != NULL);
ASSERT(dwAccess != (GENERIC_READ | GENERIC_WRITE));
ASSERT(dwAccess == GENERIC_READ || dwAccess == GENERIC_WRITE);
ASSERT(AfxIsValidString(pstrFileName));
HINTERNET hFile;
if (dwContext == 1)
dwContext = m_dwContext;
hFile = FtpOpenFile(m_hConnection, pstrFileName, dwAccess,
dwFlags, dwContext);
if (hFile == NULL)
AfxThrowInternetException(dwContext);
CInternetFile* pFile = new CInternetFile(hFile, pstrFileName, this,
(dwAccess == GENERIC_READ));
return pFile;
}
BOOL CFtpConnection::PutFile(LPCTSTR pstrLocalFile, LPCTSTR pstrRemoteFile,
DWORD dwFlags /* = FTP_TRANSFER_TYPE_BINARY */,
DWORD dwContext /* = 1 */)
{
ASSERT_VALID(this);
ASSERT(m_hConnection != NULL);
ASSERT(AfxIsValidString(pstrRemoteFile));
ASSERT(AfxIsValidString(pstrLocalFile));
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
if (dwContext == 1)
dwContext = m_dwContext;
return FtpPutFile(m_hConnection, pstrLocalFile, pstrRemoteFile,
dwFlags, dwContext);
}
BOOL CFtpConnection::GetFile(LPCTSTR pstrRemoteFile, LPCTSTR pstrLocalFile,
BOOL bFailIfExists /* = TRUE */,
DWORD dwAttributes /* = FILE_ATTRIBUTE_NORMAL */,
DWORD dwFlags /* = FTP_TRANSFER_TYPE_BINARY */, DWORD dwContext /* = 1 */)
{
ASSERT_VALID(this);
ASSERT(m_hConnection != NULL);
ASSERT(AfxIsValidString(pstrRemoteFile));
ASSERT(AfxIsValidString(pstrLocalFile));
ASSERT(!(dwAttributes & FILE_ATTRIBUTE_DIRECTORY));
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
if (dwContext == 1)
dwContext = m_dwContext;
return FtpGetFile(m_hConnection, pstrRemoteFile, pstrLocalFile,
bFailIfExists, dwAttributes, dwFlags, dwContext);
}
#ifdef _DEBUG
void CFtpConnection::Dump(CDumpContext& dc) const
{
CInternetConnection::Dump(dc);
dc << "\nm_strServerName = " << m_strServerName;
}
void CFtpConnection::AssertValid() const
{
ASSERT(m_pSession != NULL);
if (m_hConnection != NULL)
{
ASSERT(AfxGetInternetHandleType(m_hConnection)
== INTERNET_HANDLE_TYPE_CONNECT_FTP);
}
}
#endif
/////////////////////////////////////////////////////////////////////////////
// CGopherConnection
CGopherConnection::~CGopherConnection()
{
}
CGopherConnection::CGopherConnection(CInternetSession* pSession,
LPCTSTR pstrServer, LPCTSTR pstrUserName /* = NULL */,
LPCTSTR pstrPassword /* = NULL */, DWORD dwContext /* = 0 */,
INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */)
: CInternetConnection(pSession, pstrServer, nPort, dwContext)
{
ASSERT(pSession != NULL);
ASSERT_KINDOF(CInternetSession, pSession);
ASSERT(AfxIsValidString(pstrServer));
m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_GOPHER,
0, m_dwContext);
if (m_hConnection == NULL)
AfxThrowInternetException(m_dwContext);
else
_afxSessionMap.SetAt(m_hConnection, m_pSession);
}
CGopherConnection::CGopherConnection(CInternetSession* pSession,
HINTERNET hConnected, LPCTSTR pstrServer, DWORD dwContext)
: CInternetConnection(pSession, pstrServer,
INTERNET_INVALID_PORT_NUMBER, dwContext)
{
ASSERT(pSession != NULL);
ASSERT(AfxIsValidString(pstrServer));
BOOL bBadType = FALSE;
if (AfxGetInternetHandleType(hConnected) != INTERNET_HANDLE_TYPE_CONNECT_GOPHER)
{
ASSERT(FALSE); // used the wrong handle type
bBadType = TRUE;
}
m_hConnection = hConnected;
if (m_hConnection == NULL || bBadType)
AfxThrowInternetException(m_dwContext);
else
_afxSessionMap.SetAt(m_hConnection, m_pSession);
}
CGopherLocator CGopherConnection::CreateLocator(LPCTSTR pstrLocator)
{
CGopherLocator ret(pstrLocator, lstrlen(pstrLocator));
return ret;
}
CGopherLocator CGopherConnection::CreateLocator(LPCTSTR pstrServerName,
LPCTSTR pstrDisplayString, LPCTSTR pstrSelectorString, DWORD dwGopherType,
INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */)
{
TCHAR szLocator[MAX_GOPHER_LOCATOR_LENGTH];
DWORD dwLocLen = MAX_GOPHER_LOCATOR_LENGTH;
ASSERT(AfxIsValidString(pstrDisplayString));
ASSERT(AfxIsValidString(pstrServerName));
ASSERT(AfxIsValidString(pstrSelectorString));
if (!GopherCreateLocator(pstrServerName, nPort,
pstrDisplayString, pstrSelectorString, dwGopherType,
szLocator, &dwLocLen))
AfxThrowInternetException(0);
CGopherLocator ret(szLocator, dwLocLen);
return ret;
}
CGopherLocator CGopherConnection::CreateLocator(
LPCTSTR pstrDisplayString, LPCTSTR pstrSelectorString, DWORD dwGopherType)
{
TCHAR szLocator[MAX_GOPHER_LOCATOR_LENGTH];
DWORD dwLocLen = MAX_GOPHER_LOCATOR_LENGTH;
ASSERT(AfxIsValidString(pstrDisplayString));
ASSERT(AfxIsValidString(pstrSelectorString));
if (!GopherCreateLocator(m_strServerName, m_nPort,
pstrDisplayString, pstrSelectorString, dwGopherType,
szLocator, &dwLocLen))
AfxThrowInternetException(m_dwContext);
CGopherLocator ret(szLocator, dwLocLen);
return ret;
}
BOOL CGopherConnection::GetAttribute(CGopherLocator& refLocator,
CString strRequestedAttributes, CString& strResult)
{
DWORD dwLen = 4*MIN_GOPHER_ATTRIBUTE_LENGTH; // more than the minimum
BOOL bRet;
LPTSTR pstrResult = strResult.GetBuffer(dwLen);
if (!GopherGetAttribute(m_hConnection, (LPCTSTR) refLocator,
pstrResult, NULL, dwLen, &dwLen,
NULL, m_dwContext))
{
bRet = FALSE;
strResult.ReleaseBuffer(0);
}
else
{
bRet = TRUE;
strResult.ReleaseBuffer(dwLen);
}
return bRet;
}
CGopherFile* CGopherConnection::OpenFile(CGopherLocator& refLocator,
DWORD dwFlags /* = 0 */, LPCTSTR pstrView /* = NULL */,
DWORD dwContext /* = 1 */)
{
ASSERT_VALID(this);
ASSERT(m_hConnection != NULL);
HINTERNET hFile;
if (dwContext == 1)
dwContext = m_dwContext;
hFile = GopherOpenFile(m_hConnection, (LPCTSTR) refLocator, pstrView,
dwFlags, dwContext);
if (hFile == NULL)
AfxThrowInternetException(dwContext);
CGopherFile* pFile = new CGopherFile(hFile, refLocator, this);
return pFile;
}
void CGopherConnection::Close()
{
CInternetConnection::Close();
}
#ifdef _DEBUG
void CGopherConnection::Dump(CDumpContext& dc) const
{
CInternetConnection::Dump(dc);
dc << "\nm_strServerName = " << m_strServerName;
}
void CGopherConnection::AssertValid() const
{
ASSERT(m_pSession != NULL);
if (m_hConnection != NULL)
{
ASSERT(AfxGetInternetHandleType(m_hConnection)
== INTERNET_HANDLE_TYPE_CONNECT_GOPHER);
}
}
#endif
/////////////////////////////////////////////////////////////////////////////
// CHttpConnection
CHttpConnection::~CHttpConnection()
{
}
CHttpConnection::CHttpConnection(CInternetSession* pSession,
HINTERNET hConnected, LPCTSTR pstrServer, DWORD dwContext /* = 0 */)
: CInternetConnection(pSession, pstrServer, INTERNET_INVALID_PORT_NUMBER, dwContext)
{
ASSERT(pSession != NULL);
ASSERT(AfxIsValidString(pstrServer));
BOOL bBadType = FALSE;
if (AfxGetInternetHandleType(hConnected) != INTERNET_HANDLE_TYPE_CONNECT_HTTP)
{
ASSERT(FALSE); // used the wrong handle type
bBadType = TRUE;
}
m_hConnection = hConnected;
if (m_hConnection == NULL || bBadType)
AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
else
_afxSessionMap.SetAt(m_hConnection, m_pSession);
}
CHttpConnection::CHttpConnection(CInternetSession* pSession,
LPCTSTR pstrServer,
INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
LPCTSTR pstrUserName /* = NULL */,
LPCTSTR pstrPassword /* = NULL */, DWORD dwContext /* = 1 */)
: CInternetConnection(pSession, pstrServer, nPort, dwContext)
{
ASSERT(pSession != NULL);
ASSERT_KINDOF(CInternetSession, pSession);
ASSERT(AfxIsValidString(pstrServer));
m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_HTTP,
0, m_dwContext);
if (m_hConnection == NULL)
AfxThrowInternetException(m_dwContext);
else
_afxSessionMap.SetAt(m_hConnection, m_pSession);
}
CHttpConnection::CHttpConnection(CInternetSession* pSession,
LPCTSTR pstrServer, DWORD dwFlags,
INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
LPCTSTR pstrUserName /* = NULL */,
LPCTSTR pstrPassword /* = NULL */,
DWORD dwContext /* = 1 */)
: CInternetConnection(pSession, pstrServer, nPort, dwContext)
{
ASSERT(pSession != NULL);
ASSERT_KINDOF(CInternetSession, pSession);
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
ASSERT(AfxIsValidString(pstrServer));
m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_HTTP,
dwFlags, m_dwContext);
if (m_hConnection == NULL)
AfxThrowInternetException(m_dwContext);
else
_afxSessionMap.SetAt(m_hConnection, m_pSession);
}
void CHttpConnection::Close()
{
CInternetConnection::Close();
}
CHttpFile* CHttpConnection::OpenRequest(LPCTSTR pstrVerb,
LPCTSTR pstrObjectName, LPCTSTR pstrReferer, DWORD dwContext,
LPCTSTR* ppstrAcceptTypes, LPCTSTR pstrVersion, DWORD dwFlags)
{
ASSERT_VALID(this);
ASSERT(m_hConnection != NULL);
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
if (dwContext == 1)
dwContext = m_dwContext;
if (pstrVersion == NULL)
pstrVersion = HTTP_VERSION;
HINTERNET hFile;
hFile = HttpOpenRequest(m_hConnection, pstrVerb, pstrObjectName,
pstrVersion, pstrReferer, ppstrAcceptTypes, dwFlags, dwContext);
CHttpFile* pRet = new CHttpFile(hFile, pstrVerb, pstrObjectName, this);
pRet->m_dwContext = dwContext;
return pRet;
}
CHttpFile* CHttpConnection::OpenRequest(int nVerb,
LPCTSTR pstrObjectName, LPCTSTR pstrReferer /* = NULL */, DWORD dwContext,
LPCTSTR* ppstrAcceptTypes /* = NULL */,
LPCTSTR pstrVersion /* = NULL */, DWORD dwFlags)
{
ASSERT_VALID(this);
ASSERT(m_hConnection != NULL);
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
ASSERT(AfxIsValidString(pstrObjectName));
ASSERT(nVerb >= _HTTP_VERB_MIN && nVerb <= _HTTP_VERB_MAX);
LPCTSTR pstrVerb;
if (nVerb >= _HTTP_VERB_MIN && nVerb <= _HTTP_VERB_MAX)
pstrVerb = szHtmlVerbs[nVerb];
else
pstrVerb = _T("");
return OpenRequest(pstrVerb, pstrObjectName, pstrReferer,
dwContext, ppstrAcceptTypes, pstrVersion, dwFlags);
}
#ifdef _DEBUG
void CHttpConnection::Dump(CDumpContext& dc) const
{
CInternetConnection::Dump(dc);
dc << "\nm_strServerName = " << m_strServerName;
}
void CHttpConnection::AssertValid() const
{
ASSERT(m_pSession != NULL);
if (m_hConnection != NULL)
{
ASSERT(AfxGetInternetHandleType(m_hConnection)
== INTERNET_HANDLE_TYPE_CONNECT_HTTP);
}
}
#endif
/////////////////////////////////////////////////////////////////////////////
// CHttpFile
CHttpFile::CHttpFile(HINTERNET hFile, HINTERNET hSession, LPCTSTR pstrObject,
LPCTSTR pstrServer, LPCTSTR pstrVerb, DWORD dwContext)
: CInternetFile(hFile, hSession, pstrObject, pstrServer, dwContext, TRUE),
m_strVerb(pstrVerb), m_strObject(pstrObject)
{
// caller must set _afxSessionMap!
ASSERT(AfxIsValidString(pstrVerb));
}
CHttpFile::CHttpFile(HINTERNET hFile, LPCTSTR pstrVerb, LPCTSTR pstrObject,
CHttpConnection* pConnection)
: CInternetFile(hFile, pstrObject, pConnection, TRUE),
m_strVerb(pstrVerb), m_strObject(pstrObject)
{
ASSERT(pstrVerb != NULL);
ASSERT(pstrObject != NULL);
ASSERT(pConnection != NULL);
ASSERT_VALID(pConnection);
}
CHttpFile::~CHttpFile()
{
}
void CHttpFile::Close()
{
CInternetFile::Close();
}
DWORD CHttpFile::ErrorDlg(CWnd* pParent /* = NULL */,
DWORD dwError /* = ERROR_INTERNET_INCORRECT_PASSWORD */,
DWORD dwFlags /* = FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS*/,
LPVOID* lppvData /* = NULL */)
{
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
HWND hWnd;
LPVOID lpEmpty;
LPVOID* lppvHolder;
if (lppvData == NULL)
{
lpEmpty = NULL;
lppvHolder = &lpEmpty;
}
else
lppvHolder = lppvData;
if (pParent == NULL || pParent->m_hWnd == NULL)
hWnd = GetDesktopWindow();
else
hWnd = pParent->m_hWnd;
return InternetErrorDlg(hWnd, m_hFile, dwError, dwFlags, lppvHolder);
}
CString CHttpFile::GetVerb() const
{
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
return m_strVerb;
}
CString CHttpFile::GetObject() const
{
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
return m_strObject;
}
CString CHttpFile::GetFileURL() const
{
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
CString str(_afxURLhttp);
if (m_hConnection != NULL)
{
str += m_strServerName;
int nLen = m_strObject.GetLength();
if (nLen > 0)
{
if (m_strObject[0] != '/' && m_strObject[0] != '\\')
str += '/';
str += m_strObject;
}
}
return str;
}
BOOL CHttpFile::AddRequestHeaders(LPCTSTR pstrHeaders,
DWORD dwModifiers /* = HTTP_ADDREQ_FLAG_ADD */,
int dwHeadersLen /* = -1 */)
{
ASSERT(AfxIsValidString(pstrHeaders));
ASSERT(dwHeadersLen == 0 || pstrHeaders != NULL);
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
if (dwHeadersLen == -1)
if (pstrHeaders == NULL)
dwHeadersLen = 0;
else
dwHeadersLen = lstrlen(pstrHeaders);
return HttpAddRequestHeaders(m_hFile, pstrHeaders, dwHeadersLen,
dwModifiers);
}
BOOL CHttpFile::AddRequestHeaders(CString& str,
DWORD dwModifiers /* = HTTP_ADDREQ_FLAG_ADD */)
{
return AddRequestHeaders((LPCTSTR) str, dwModifiers, str.GetLength());
}
BOOL CHttpFile::SendRequest(LPCTSTR pstrHeaders /* = NULL */,
DWORD dwHeadersLen /* = 0 */, LPVOID lpOptional /* = NULL */,
DWORD dwOptionalLen /* = 0 */)
{
ASSERT(dwOptionalLen == 0 || lpOptional != NULL);
ASSERT(dwHeadersLen == 0 || pstrHeaders != NULL);
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
BOOL bRet = HttpSendRequest(m_hFile,
pstrHeaders, dwHeadersLen, lpOptional, dwOptionalLen);
if (!bRet)
AfxThrowInternetException(m_dwContext);
return bRet;
}
BOOL CHttpFile::EndRequest(
DWORD dwFlags /* = 0 */,
LPINTERNET_BUFFERS lpBuffIn /* = NULL */, DWORD dwContext /* = 1 */)
{
ASSERT(m_hFile != NULL);
ASSERT(m_bReadMode == -1);
if (dwContext == 1)
dwContext = m_dwContext;
BOOL bRet = HttpEndRequest(m_hFile, lpBuffIn, dwFlags, dwContext);
if (!bRet)
AfxThrowInternetException(m_dwContext);
return bRet;
}
BOOL CHttpFile::SendRequestEx(DWORD dwTotalLen,
DWORD dwFlags /* = HSR_INITIATE */, DWORD dwContext /* = 1 */)
{
ASSERT(m_hFile != NULL);
INTERNET_BUFFERS buffer;
memset(&buffer, 0, sizeof(buffer));
buffer.dwStructSize = sizeof(buffer);
buffer.dwBufferTotal = dwTotalLen;
if (dwContext == 1)
dwContext = m_dwContext;
return SendRequestEx(&buffer, NULL, dwFlags, dwContext);
}
BOOL CHttpFile::SendRequestEx(LPINTERNET_BUFFERS lpBuffIn,
LPINTERNET_BUFFERS lpBuffOut, DWORD dwFlags /* = HSR_INITIATE */,
DWORD dwContext /* = 1 */)
{
ASSERT(m_hFile != NULL);
ASSERT_NULL_OR_POINTER(lpBuffIn, INTERNET_BUFFERS);
ASSERT_NULL_OR_POINTER(lpBuffOut, INTERNET_BUFFERS);
if (dwContext == 1)
dwContext = m_dwContext;
BOOL bRet = HttpSendRequestEx(m_hFile, lpBuffIn, lpBuffOut,
dwFlags, dwContext);
if (!bRet)
AfxThrowInternetException(m_dwContext);
m_bReadMode = -1;
return bRet;
}
BOOL CHttpFile::SendRequest(CString& strHeaders,
LPVOID lpOptional /* = NULL */, DWORD dwOptionalLen /* = 0 */)
{
ASSERT(dwOptionalLen == 0 || lpOptional != NULL);
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
return SendRequest((LPCTSTR) strHeaders, strHeaders.GetLength(),
lpOptional, dwOptionalLen);
}
BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel,
LPVOID lpvBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex) const
{
ASSERT((HTTP_QUERY_HEADER_MASK & dwInfoLevel) <= HTTP_QUERY_MAX &&
dwInfoLevel != 0);
ASSERT(lpvBuffer != NULL && *lpdwBufferLength > 0);
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
return HttpQueryInfo(m_hFile, dwInfoLevel, lpvBuffer,
lpdwBufferLength, lpdwIndex);
}
BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel, DWORD& dwResult,
LPDWORD lpdwIndex /* = NULL */) const
{
dwInfoLevel |= HTTP_QUERY_FLAG_NUMBER;
DWORD dwDWSize = sizeof(DWORD);
return QueryInfo(dwInfoLevel, &dwResult, &dwDWSize, lpdwIndex);
}
BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel, SYSTEMTIME* pSystemTime,
LPDWORD lpdwIndex /* = NULL */) const
{
dwInfoLevel |= HTTP_QUERY_FLAG_SYSTEMTIME;
DWORD dwTimeSize = sizeof(SYSTEMTIME);
return QueryInfo(dwInfoLevel, pSystemTime, &dwTimeSize, lpdwIndex);
}
BOOL CHttpFile::QueryInfoStatusCode(DWORD& dwStatusCode) const
{
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
TCHAR szBuffer[80];
DWORD dwLen = _countof(szBuffer);
BOOL bRet;
bRet = HttpQueryInfo(m_hFile, HTTP_QUERY_STATUS_CODE,
szBuffer, &dwLen, NULL);
if (bRet)
dwStatusCode = (DWORD) _ttol(szBuffer);
return bRet;
}
BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel, CString& str,
LPDWORD lpdwIndex) const
{
ASSERT(dwInfoLevel <= HTTP_QUERY_MAX && dwInfoLevel >= 0);
ASSERT_VALID(this);
ASSERT(m_hFile != NULL);
BOOL bRet;
DWORD dwLen = 0;
// ask for nothing to see how long the return really is
str.Empty();
if (HttpQueryInfo(m_hFile, dwInfoLevel, NULL, &dwLen, 0))
bRet = TRUE;
else
{
// now that we know how long it is, ask for exactly that much
// space and really request the header from the API
LPTSTR pstr = str.GetBufferSetLength(dwLen);
bRet = HttpQueryInfo(m_hFile, dwInfoLevel, pstr, &dwLen, lpdwIndex);
if (bRet)
str.ReleaseBuffer(dwLen);
else
str.ReleaseBuffer(0);
}
return bRet;
}
#ifdef _DEBUG
void CHttpFile::Dump(CDumpContext& dc) const
{
dc << "\nm_strFileName = " << m_strFileName;
dc << "\nm_strVerb = " << m_strVerb;
}
void CHttpFile::AssertValid() const
{
CInternetFile::AssertValid();
}
#endif
/////////////////////////////////////////////////////////////////////////////
// CGopherFile
CGopherFile::CGopherFile(HINTERNET hFile, CGopherLocator& refLocator,
CGopherConnection* pConnection)
: CInternetFile(hFile, _T(""), pConnection, TRUE),
m_Locator(refLocator)
{
ASSERT(pConnection != NULL);
ASSERT_VALID(pConnection);
}
CGopherFile::CGopherFile(HINTERNET hFile, HINTERNET hSession,
LPCTSTR pstrLocator, DWORD dwLocLen, DWORD dwContext)
: CInternetFile(hFile, hSession, _T(""), _T(""), dwContext, TRUE),
m_Locator(pstrLocator, dwLocLen)
{
// caller muset set _afxSessionMap!
}
CGopherFile::~CGopherFile()
{
}
void CGopherFile::Close()
{
CInternetFile::Close();
}
void CGopherFile::Write(const void* lpBuf, UINT nCount)
{
UNUSED_ALWAYS(lpBuf);
UNUSED_ALWAYS(nCount);
ASSERT(FALSE);
AfxThrowNotSupportedException();
}
void CGopherFile::WriteString(LPCTSTR pstr)
{
UNUSED_ALWAYS(pstr);
ASSERT(FALSE);
AfxThrowNotSupportedException();
}
#ifdef _DEBUG
void CGopherFile::Dump(CDumpContext& dc) const
{
CInternetFile::Dump(dc);
}
void CGopherFile::AssertValid() const
{
CInternetFile::AssertValid();
}
#endif
/////////////////////////////////////////////////////////////////////////////
// CFtpFileFind
CFtpFileFind::CFtpFileFind(CFtpConnection* pConnection, DWORD dwContext)
{
ASSERT(pConnection != NULL);
ASSERT_KINDOF(CFtpConnection, pConnection);
m_pConnection = pConnection;
if (dwContext == 1)
dwContext = pConnection->GetContext();
m_dwContext = dwContext;
m_chDirSeparator = '/';
}
CFtpFileFind::~CFtpFileFind()
{
}
BOOL CFtpFileFind::FindFile(LPCTSTR pstrName /* = NULL */,
DWORD dwFlags /* = INTERNET_FLAG_RELOAD */)
{
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
ASSERT(m_pConnection != NULL);
ASSERT_VALID(m_pConnection);
if (m_pConnection == NULL)
return FALSE;
Close();
m_pNextInfo = new WIN32_FIND_DATA;
m_bGotLast = FALSE;
if (pstrName == NULL)
pstrName = _T("*");
lstrcpy(((LPWIN32_FIND_DATA) m_pNextInfo)->cFileName, pstrName);
m_hContext = FtpFindFirstFile((HINTERNET) *m_pConnection,
pstrName, (LPWIN32_FIND_DATA) m_pNextInfo, dwFlags, m_dwContext);
if (m_hContext == NULL)
{
Close();
return FALSE;
}
LPCTSTR pstrRoot = _tcspbrk(pstrName, _T("\\/"));
CString strCWD;
m_pConnection->GetCurrentDirectory(strCWD);
if (pstrRoot == NULL)
{
if (m_pConnection->SetCurrentDirectory(pstrName))
{
m_pConnection->GetCurrentDirectory(m_strRoot);
m_pConnection->SetCurrentDirectory(strCWD);
}
else
m_strRoot = strCWD;
}
else
{
// find the last forward or backward whack
int nLast;
LPCTSTR pstrOther = _tcsrchr(pstrName, '\\');
pstrRoot = _tcsrchr(pstrName, '/');
if (pstrRoot == NULL)
pstrRoot = pstrName;
if (pstrOther == NULL)
pstrOther = pstrName;
if (pstrRoot >= pstrOther)
nLast = pstrRoot - pstrName;
else
nLast = pstrOther - pstrName;
// from the start to the last whack is the root
if (nLast == 0)
nLast++;
m_strRoot = pstrName;
m_strRoot = m_strRoot.Left(nLast);
}
return TRUE;
}
BOOL CFtpFileFind::FindNextFile()
{
ASSERT(m_hContext != NULL);
if (m_hContext == NULL)
return FALSE;
if (m_pFoundInfo == NULL)
m_pFoundInfo = new WIN32_FIND_DATA;
ASSERT_VALID(this);
void* pTemp = m_pFoundInfo;
m_pFoundInfo = m_pNextInfo;
m_pNextInfo = pTemp;
return InternetFindNextFile(m_hContext, m_pNextInfo);
}
void CFtpFileFind::CloseContext()
{
if (m_hContext != NULL && m_hContext != INVALID_HANDLE_VALUE)
{
InternetCloseHandle(m_hContext);
m_hContext = NULL;
}
return;
}
CString CFtpFileFind::GetFileURL() const
{
ASSERT_VALID(this);
ASSERT(m_hContext != NULL);
CString str;
if (m_hContext != NULL)
{
str += _afxURLftp;
str += m_pConnection->GetServerName();
str += GetFilePath();
}
return str;
}
#ifdef _DEBUG
void CFtpFileFind::Dump(CDumpContext& dc) const
{
CFileFind::Dump(dc);
dc << "m_hContext = " << m_hContext;
}
void CFtpFileFind::AssertValid() const
{
CFileFind::AssertValid();
}
#endif
/////////////////////////////////////////////////////////////////////////////
// CGopherFileFind
CGopherFileFind::CGopherFileFind(CGopherConnection* pConnection,
DWORD dwContext)
{
ASSERT(pConnection != NULL);
ASSERT_KINDOF(CGopherConnection, pConnection);
m_pConnection = pConnection;
if (dwContext == 1)
dwContext = pConnection->GetContext();
m_dwContext = dwContext;
}
CGopherFileFind::~CGopherFileFind()
{
}
BOOL CGopherFileFind::FindFile(LPCTSTR pstrString,
DWORD dwFlags /* = INTERNET_FLAG_RELOAD */)
{
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
Close();
m_pNextInfo = new GOPHER_FIND_DATA;
m_bGotLast = FALSE;
m_hContext = GopherFindFirstFile((HINTERNET) *m_pConnection,
NULL, pstrString,
(GOPHER_FIND_DATA*) m_pNextInfo, dwFlags, m_dwContext);
if (m_hContext == NULL)
Close();
return (m_hContext != NULL);
}
BOOL CGopherFileFind::FindFile(CGopherLocator& refLocator,
LPCTSTR pstrString, DWORD dwFlags /* = INTERNET_FLAG_RELOAD */)
{
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
Close();
m_pNextInfo = new GOPHER_FIND_DATA;
m_pFoundInfo = new GOPHER_FIND_DATA;
m_bGotLast = FALSE;
m_hContext = GopherFindFirstFile((HINTERNET) *m_pConnection,
(LPCTSTR) refLocator, pstrString,
(GOPHER_FIND_DATA*) m_pNextInfo, dwFlags, m_dwContext);
if (m_hContext == NULL)
Close();
return (m_hContext != NULL);
}
BOOL CGopherFileFind::FindNextFile()
{
ASSERT(m_hContext != NULL);
if (m_hContext == NULL)
return FALSE;
if (m_pFoundInfo == NULL)
m_pFoundInfo = new GOPHER_FIND_DATA;
ASSERT_VALID(this);
void* pTemp = m_pFoundInfo;
m_pFoundInfo = m_pNextInfo;
m_pNextInfo = pTemp;
return InternetFindNextFile(m_hContext, m_pNextInfo);
}
void CGopherFileFind::CloseContext()
{
if (m_hContext != NULL && m_hContext != INVALID_HANDLE_VALUE)
{
InternetCloseHandle(m_hContext);
m_hContext = NULL;
}
return;
}
CString CGopherFileFind::GetFileName() const
{
AfxThrowNotSupportedException();
return CString();
}
CString CGopherFileFind::GetFilePath() const
{
AfxThrowNotSupportedException();
return CString();
}
CString CGopherFileFind::GetFileTitle() const
{
AfxThrowNotSupportedException();
return CString();
}
BOOL CGopherFileFind::IsDots() const
{
// gophers never have dots
return FALSE;
}
BOOL CGopherFileFind::GetLastWriteTime(FILETIME* pTimeStamp) const
{
ASSERT(m_hContext != NULL);
ASSERT_POINTER(pTimeStamp, FILETIME);
ASSERT_VALID(this);
if (m_pFoundInfo != NULL && pTimeStamp != NULL)
{
*pTimeStamp = ((LPGOPHER_FIND_DATA) m_pFoundInfo)->LastModificationTime;
return TRUE;
}
else
return FALSE;
}
BOOL CGopherFileFind::GetLastAccessTime(FILETIME* pTimeStamp) const
{
ASSERT_POINTER(pTimeStamp, FILETIME);
return GetLastWriteTime(pTimeStamp);
}
BOOL CGopherFileFind::GetCreationTime(FILETIME* pTimeStamp) const
{
ASSERT_POINTER(pTimeStamp, FILETIME);
return GetLastWriteTime(pTimeStamp);
}
BOOL CGopherFileFind::GetLastWriteTime(CTime& refTime) const
{
ASSERT(m_hContext != NULL);
ASSERT_VALID(this);
if (m_pFoundInfo != NULL)
{
refTime = CTime(((LPGOPHER_FIND_DATA) m_pFoundInfo)->LastModificationTime);
return TRUE;
}
else
return FALSE;
}
BOOL CGopherFileFind::GetCreationTime(CTime& refTime) const
{
return GetLastWriteTime(refTime);
}
BOOL CGopherFileFind::GetLastAccessTime(CTime& refTime) const
{
return GetLastWriteTime(refTime);
}
CString CGopherFileFind::GetFileURL() const
{
AfxThrowNotSupportedException();
return CString();
}
CString CGopherFileFind::GetRoot() const
{
AfxThrowNotSupportedException();
return CString();
}
CGopherLocator CGopherFileFind::GetLocator() const
{
ASSERT_VALID(this);
ASSERT(m_pConnection != NULL && m_hContext != NULL);
return m_pConnection->CreateLocator(
((LPGOPHER_FIND_DATA) m_pFoundInfo)->Locator);
}
CString CGopherFileFind::GetScreenName() const
{
ASSERT_VALID(this);
ASSERT(m_hContext != NULL);
CString str;
if (m_pFoundInfo != NULL)
str = ((LPGOPHER_FIND_DATA) m_pFoundInfo)->DisplayString;
return str;
}
DWORD CGopherFileFind::GetLength() const
{
ASSERT_VALID(this);
if (m_pFoundInfo != NULL)
return ((LPGOPHER_FIND_DATA) m_pFoundInfo)->SizeLow;
else
return 0;
}
#if defined(_X86_) || defined(_ALPHA_)
__int64 CGopherFileFind::GetLength64() const
{
ASSERT_VALID(this);
if (m_pFoundInfo != NULL)
return ((LPGOPHER_FIND_DATA) m_pFoundInfo)->SizeLow +
(((LPGOPHER_FIND_DATA) m_pFoundInfo)->SizeHigh << 32);
else
return 0;
}
#endif
#ifdef _DEBUG
void CGopherFileFind::Dump(CDumpContext& dc) const
{
CFileFind::Dump(dc);
dc << "m_hContext = " << m_hContext;
}
void CGopherFileFind::AssertValid() const
{
CFileFind::AssertValid();
}
#endif
/////////////////////////////////////////////////////////////////////////////
// CGopherLocator
CGopherLocator::CGopherLocator(LPCTSTR pstrLocator, DWORD dwLocLen)
{
ASSERT(AfxIsValidString(pstrLocator));
LPTSTR pstr = m_Locator.GetBufferSetLength(dwLocLen);
memcpy(pstr, pstrLocator, dwLocLen);
m_Locator.ReleaseBuffer(dwLocLen);
m_dwBufferLength = dwLocLen;
}
CGopherLocator::~CGopherLocator()
{
}
/////////////////////////////////////////////////////////////////////////////
// exception handling
void AFXAPI AfxThrowInternetException(DWORD dwContext, DWORD dwError /* = 0 */)
{
if (dwError == 0)
dwError = ::GetLastError();
CInternetException* pException = new CInternetException(dwError);
pException->m_dwContext = dwContext;
TRACE1("Warning: throwing CInternetException for error %d\n", dwError);
THROW(pException);
}
BOOL CInternetException::GetErrorMessage(LPTSTR pstrError, UINT nMaxError,
PUINT pnHelpContext)
{
ASSERT(pstrError != NULL && AfxIsValidString(pstrError, nMaxError));
if (pnHelpContext != NULL)
*pnHelpContext = 0;
LPTSTR lpBuffer;
BOOL bRet = TRUE;
HINSTANCE hWinINetLibrary;
hWinINetLibrary = ::LoadLibraryA("WININET.DLL");
if (hWinINetLibrary == NULL ||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
hWinINetLibrary, m_dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
(LPTSTR) &lpBuffer, 0, NULL) == 0)
{
// it failed! try Windows...
bRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, m_dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
(LPTSTR) &lpBuffer, 0, NULL);
}
if (!bRet)
*pstrError = '\0';
else
{
if (m_dwError == ERROR_INTERNET_EXTENDED_ERROR)
{
LPTSTR lpExtended;
DWORD dwLength = 0;
DWORD dwError;
// find the length of the error
if (!InternetGetLastResponseInfo(&dwError, NULL, &dwLength) &&
GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
lpExtended = (LPTSTR) LocalAlloc(LPTR, dwLength);
InternetGetLastResponseInfo(&dwError, lpExtended, &dwLength);
lstrcpyn(pstrError, lpExtended, nMaxError);
pstrError += dwLength;
nMaxError -= dwLength;
if (nMaxError < 0)
nMaxError = 0;
LocalFree(lpExtended);
}
else
TRACE0("Warning: Extended error reported with no response info\n");
bRet = TRUE;
}
else
{
lstrcpyn(pstrError, lpBuffer, nMaxError);
bRet = TRUE;
}
LocalFree(lpBuffer);
}
#ifndef _AFXDLL
::FreeLibrary(hWinINetLibrary);
#endif
return bRet;
}
CInternetException::CInternetException(DWORD dwError)
{
m_dwError = dwError;
}
CInternetException::~CInternetException()
{
}
#ifdef _DEBUG
void CInternetException::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << "m_dwError = " << m_dwError;
dc << "\nm_dwContext = " << m_dwContext;
}
#endif
/////////////////////////////////////////////////////////////////////////////
// Inline function declarations expanded out-of-line
#ifndef _AFX_ENABLE_INLINES
// expand inlines for OLE dialog APIs
static char _szAfxInetInl[] = "afxinet.inl";
#undef THIS_FILE
#define THIS_FILE _szAfxInetInl
#define _AFXINET_INLINE
#include "afxinet.inl"
#endif //!_AFX_ENABLE_INLINES
/////////////////////////////////////////////////////////////////////////////
// Pre-startup code
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
IMPLEMENT_DYNAMIC(CInternetException, CException)
IMPLEMENT_DYNAMIC(CInternetFile, CStdioFile)
IMPLEMENT_DYNAMIC(CHttpFile, CInternetFile)
IMPLEMENT_DYNAMIC(CGopherFile, CInternetFile)
IMPLEMENT_DYNAMIC(CInternetSession, CObject)
IMPLEMENT_DYNAMIC(CInternetConnection, CObject)
IMPLEMENT_DYNAMIC(CFtpConnection, CInternetConnection)
IMPLEMENT_DYNAMIC(CHttpConnection, CInternetConnection)
IMPLEMENT_DYNAMIC(CGopherConnection, CInternetConnection)
IMPLEMENT_DYNAMIC(CFtpFileFind, CFileFind)
IMPLEMENT_DYNAMIC(CGopherFileFind, CFileFind)
#pragma warning(disable: 4074)
#pragma init_seg(compiler)
CSessionMapPtrToPtr _afxSessionMap;