summaryrefslogtreecommitdiff
path: root/src/modules/fetcher/winhttp/WinHttpRewindInputStream.cpp
blob: 5ab372c895d9e5029e576d290a44984d62ef71be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#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( );
}