#include "WinHttpRewindInputStream.hpp" #include "WinHttpFetcher.hpp" #include "SpoolRewindInputStream.hpp" #include "win32/errormsg.hpp" #include "win32/stringutils.hpp" using namespace std; class winhttp_buffer : public spool_streambuf { public: explicit winhttp_buffer( HINTERNET connect, HINTERNET request, size_t bufSize = 256, size_t putBack = 1, size_t spoolBufSize = 8192 ); protected: virtual streambuf::int_type readFromSource( ); private: HINTERNET m_connect; HINTERNET m_request; }; winhttp_buffer::winhttp_buffer( HINTERNET connect, HINTERNET request, size_t bufSize, size_t putBack, size_t spoolBufSize ) : spool_streambuf( bufSize, putBack, spoolBufSize ), m_connect( connect ), m_request( request ) { } streambuf::int_type winhttp_buffer::readFromSource( ) { DWORD avail = 0; if( !WinHttpQueryDataAvailable( m_request, &avail ) ) { // TODO error handling return traits_type::eof( ); } if( avail == 0 ) { return traits_type::eof( ); } DWORD n; DWORD size = min( avail, m_buf.size( ) - ( m_start - m_base ) ); if( !WinHttpReadData( m_request, (LPVOID)m_start, size, &n ) ) { // TODO error handling return traits_type::eof( ); } return n; } WinHttpRewindInputStream::WinHttpRewindInputStream( const URL &url, WinHttpFetcher *fetcher ) : SpoolRewindInputStream( url ), m_fetcher( fetcher ), m_connect( 0 ), m_request( 0 ) { m_connect = WinHttpConnect( m_fetcher->session( ), s2ws( url.host( ) ).c_str( ), INTERNET_DEFAULT_HTTP_PORT, 0 ); if( !m_connect ) { setstate( badbit ); return; } m_request = WinHttpOpenRequest( m_connect, L"GET", s2ws( url.path( ) ).c_str( ), NULL, WINHTTP_NO_REFERER, NULL, NULL ); if( !m_request ) { setstate( badbit ); return; } if( !WinHttpSendRequest( m_request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0 ) ) { setstate( badbit ); return; } if( !WinHttpReceiveResponse( m_request, NULL ) ) { setstate( badbit ); return; } m_buf = new winhttp_buffer( m_connect, m_request ); rdbuf( m_buf ); } WinHttpRewindInputStream::~WinHttpRewindInputStream( ) { if( m_buf ) delete m_buf; if( m_request ) WinHttpCloseHandle( m_request ); if( m_connect ) WinHttpCloseHandle( m_connect ); } std::string WinHttpRewindInputStream::lastErrMsg( ) const { return getLastError( ); }