Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2880 lines
71 KiB
C++
2880 lines
71 KiB
C++
// 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;
|