Files
2026-06-01 12:46:52 +02:00

347 lines
8.7 KiB
C++

#include "../../include/internet/XInternetSession2.h"
#include "../../include/toolkit/safe_function.h"
#include <cstdio>
#include <cassert>
#include <shlwapi.h>
const int URL_STRING_LENGTH = 256;
std::string XInternetSession2Factory::s_strDefaultScheme = "http://";
XInternetSession2::XInternetSession2(void)
: m_hSession( NULL )
, m_hConnection( NULL )
, m_dwLastError( 0 )
{
m_hSession = InternetOpen( "XModule", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
if( m_hSession == NULL )
{
m_dwLastError = ::GetLastError();
}
memset( &m_urlComponent, 0, sizeof( m_urlComponent ) );
m_urlComponent.dwStructSize = sizeof( m_urlComponent );
m_urlComponent.lpszHostName = new char[URL_STRING_LENGTH];
m_urlComponent.dwHostNameLength = URL_STRING_LENGTH;
m_urlComponent.lpszUserName = new char[URL_STRING_LENGTH];
m_urlComponent.dwUserNameLength = URL_STRING_LENGTH;
m_urlComponent.lpszPassword = new char[URL_STRING_LENGTH];
m_urlComponent.dwPasswordLength = URL_STRING_LENGTH;
}
XInternetSession2::~XInternetSession2(void)
{
Close();
delete [] m_urlComponent.lpszHostName;
delete [] m_urlComponent.lpszUserName;
delete [] m_urlComponent.lpszPassword;
if( m_hSession != NULL )
{
InternetCloseHandle( m_hSession );
m_hSession = NULL;
}
}
int XInternetSession2::DownloadFile( HINTERNET hService, XInternetFileWriter2* pStream )
{
int nSize = 0;
while( true )
{
DWORD dwBytesAvailable = 0;
if( InternetQueryDataAvailable( hService, &dwBytesAvailable, 0, 0 ) == FALSE )
{
DWORD last_error = ::GetLastError();
if( last_error != ERROR_NO_MORE_FILES )
{
m_dwLastError = last_error;
nSize = -1;
}
break;
}
if( dwBytesAvailable == 0 )
break;
char* lpBuffer = new char[dwBytesAvailable];
DWORD dwBytesRead = 0;
if( InternetReadFile( hService, lpBuffer, dwBytesAvailable, &dwBytesRead ) == FALSE )
{
m_dwLastError = ::GetLastError();
delete [] lpBuffer;
break;
}
if( dwBytesRead == 0 )
{
delete [] lpBuffer;
break;
}
nSize += dwBytesRead;
if( pStream->Write( lpBuffer, dwBytesRead ) == false )
{
delete [] lpBuffer;
break;
}
delete [] lpBuffer;
}
return nSize;
}
int XHTTPSession::Connect( const char *szServerAddr, int nPort, const char* szAccount, const char* szPassword )
{
if( m_hSession == NULL )
{
return -1;
}
m_urlComponent.nPort = static_cast< INTERNET_PORT >( nPort );
s_strcpy( m_urlComponent.lpszHostName, URL_STRING_LENGTH, szServerAddr );
s_strcpy( m_urlComponent.lpszUserName, URL_STRING_LENGTH, szAccount );
s_strcpy( m_urlComponent.lpszPassword, URL_STRING_LENGTH, szPassword );
m_hConnection = InternetConnect( m_hSession,
m_urlComponent.lpszHostName,
m_urlComponent.nPort,
m_urlComponent.lpszUserName,
m_urlComponent.lpszPassword,
INTERNET_SERVICE_HTTP, 0, NULL );
if( m_hConnection == NULL )
{
m_dwLastError = ::GetLastError();
return -1;
}
return 0;
}
template< typename _Elem >
void url_encode( std::basic_string< _Elem > *pString )
{
for( size_t i = 0; i < pString->size(); ++i )
{
bool bEncode = false;
int nChar = (*pString)[i];
// ASCII Control characters
if( ( nChar >= 0x00 && nChar <= 0x1F ) || ( nChar == 0x7F ) ) bEncode = true;
// Non-ASCII characters
else if( nChar >= 0x80 && nChar <= 0xFF ) bEncode = true;
// Resserved characters
else if( ( nChar == 0x24 ) || ( nChar == 0x26 ) ||
( nChar == 0x2B ) || ( nChar == 0x2C ) ||
( nChar == 0x27 ) || ( nChar == 0x3A ) ||
( nChar == 0x28 ) || ( nChar == 0x29 ) ||
( nChar == 0x3B ) || ( nChar == 0x3D ) ||
( nChar == 0x3F ) || ( nChar == 0x40 ) ) bEncode = true;
// Unsafe characters
else if( ( nChar == 0x20 ) || ( nChar == 0x22 ) ||
( nChar == 0x3C ) || ( nChar == 0x3E ) ||
( nChar == 0x23 ) || ( nChar == 0x25 ) ) bEncode = true;
// Misc
else if( ( nChar == 0x7B ) || ( nChar == 0x7D ) ||
( nChar == 0x7C ) || ( nChar == 0x5C ) ||
( nChar == 0x5E ) || ( nChar == 0x7E ) ||
( nChar == 0x5B ) || ( nChar == 0x5D ) ||
( nChar == 0x60 ) ) bEncode = true;
if( bEncode )
{
(*pString)[i++] = '%';
int nHigh = nChar / 16;
int nLow = nChar % 16;
nHigh = nHigh > 9 ? 'A' + nHigh - 10 : '0' + nHigh;
nLow = nLow > 9 ? 'A' + nLow - 10 : '0' + nLow;
pString->insert( i++, 1, static_cast< _Elem >( nHigh ) );
pString->insert( i, 1, static_cast< _Elem >( nLow ) );
}
}
}
int XHTTPSession::GetFile( const char* szObject, XInternetFileWriter2* pStream, std::string& real_query )
{
std::string strObject = szObject;
url_encode( &strObject );
real_query = strObject;
HINTERNET hRequest = HttpOpenRequest( m_hConnection, m_strVerb.c_str(), strObject.c_str(), NULL, NULL, NULL,
INTERNET_FLAG_RELOAD | INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_PRAGMA_NOCACHE, NULL );
if( hRequest == NULL )
{
m_dwLastError = ::GetLastError();
return -1;
}
// char *szHeader = "Content-Type: application/x-www-form-urlencoded\nKeep-Alive: 300\nProxy-Connection: keep-alive\n";
if( HttpSendRequest( hRequest, NULL, 0, NULL, 0 ) == FALSE )
{
m_dwLastError = ::GetLastError();
InternetCloseHandle( hRequest );
hRequest = NULL;
return -2;
}
DWORD dwStatusCode = 0;
DWORD dwStatusCodeSize = sizeof( dwStatusCode );
if( HttpQueryInfo( hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwStatusCode, &dwStatusCodeSize, 0 ) == FALSE )
{
m_dwLastError = ::GetLastError();
InternetCloseHandle( hRequest );
hRequest = NULL;
return -3;
}
if( dwStatusCode != HTTP_STATUS_OK )
{
m_dwLastError = dwStatusCode;
InternetCloseHandle( hRequest );
hRequest = NULL;
return -4;
}
/*
DWORD dwContentLen = 0;
DWORD dwContentLenSize = sizeof( dwContentLen );
if( HttpQueryInfo( hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwContentLen, &dwContentLenSize, 0 ) == FALSE )
{
dwContentLen = 0;
}
*/
int size = DownloadFile( hRequest, pStream );
/*
if( dwContentLen != 0 && static_cast< int >( dwContentLen ) != size )
{
return -5;
}
*/
InternetCloseHandle( hRequest );
hRequest = NULL;
return size;
}
int XFTPSession::Connect( const char *szServerAddr, int nPort, const char* szAccount, const char* szPassword )
{
if( m_hSession == NULL )
{
return -1;
}
m_urlComponent.nPort = static_cast< INTERNET_PORT >( nPort );
s_strcpy( m_urlComponent.lpszHostName, URL_STRING_LENGTH, szServerAddr );
s_strcpy( m_urlComponent.lpszUserName, URL_STRING_LENGTH, szAccount );
s_strcpy( m_urlComponent.lpszPassword, URL_STRING_LENGTH, szPassword );
m_hConnection = InternetConnect( m_hSession,
m_urlComponent.lpszHostName,
m_urlComponent.nPort,
m_urlComponent.lpszUserName,
m_urlComponent.lpszPassword,
INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0 );
if( m_hConnection == NULL )
{
m_dwLastError = ::GetLastError();
return -1;
}
return 0;
}
int XFTPSession::GetFile( const char* szObject, XInternetFileWriter2* pStream, std::string& real_query )
{
real_query = szObject;
HINTERNET hRequest = FtpOpenFile( m_hConnection, szObject, GENERIC_READ, INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_RELOAD, 0 );
if( !hRequest )
{
m_dwLastError = ::GetLastError();
return -1;
}
int size = DownloadFile( hRequest, pStream );
if( hRequest )
InternetCloseHandle( hRequest );
return size;
}
XInternetSession2* XInternetSession2Factory::CreateSessionAndConnect( const char* szURL )
{
std::string strURL = szURL;
XInternetSession2* pSession = NULL;
std::string::size_type nPos = 0;
nPos = strURL.find( "'ftp'" );
if ( nPos != std::string::npos )
strURL.replace( nPos, 5, "ftp://" );
nPos = strURL.find( "'http'" );
if ( nPos != std::string::npos )
strURL.replace( nPos, 6, "http://" );
if ( strURL.find( "://" ) == std::string::npos )
{
strURL = GetDefaultScheme();
strURL += szURL;
}
URL_COMPONENTS urlComp;
memset( &urlComp, 0, sizeof( urlComp ) );
urlComp.dwStructSize = sizeof( urlComp );
urlComp.lpszHostName = new char[URL_STRING_LENGTH];
urlComp.dwHostNameLength = URL_STRING_LENGTH;
urlComp.lpszUserName = new char[URL_STRING_LENGTH];
urlComp.dwUserNameLength = URL_STRING_LENGTH;
urlComp.lpszPassword = new char[URL_STRING_LENGTH];
urlComp.dwPasswordLength = URL_STRING_LENGTH;
if ( InternetCrackUrl( strURL.c_str(), static_cast< DWORD >( strURL.size() ), ICU_ESCAPE, &urlComp ) )
{
switch ( urlComp.nScheme )
{
case INTERNET_SCHEME_FTP :
pSession = new XFTPSession(); break;
case INTERNET_SCHEME_HTTP :
pSession = new XHTTPSession(); break;
}
if( pSession != NULL )
{
if( pSession->Connect( urlComp.lpszHostName, urlComp.nPort, urlComp.lpszUserName, urlComp.lpszPassword ) != 0 )
{
delete pSession;
pSession = NULL;
}
}
}
delete [] urlComp.lpszHostName;
delete [] urlComp.lpszUserName;
delete [] urlComp.lpszPassword;
return pSession;
}