FireBreath  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Pages
axstream.cpp
1 /**********************************************************\
2 Original Author: Matthias (nitrogenycs)
3 
4 Created: Feb 28, 2010
5 License: Dual license model; choose one of two:
6  New BSD License
7  http://www.opensource.org/licenses/bsd-license.php
8  - or -
9  GNU Lesser General Public License, version 2.1
10  http://www.gnu.org/licenses/lgpl-2.1.html
11 
12 Copyright 2010 Richard Bateman, Firebreath development team
13 \**********************************************************/
14 
15 #include "axstream.h"
16 #include "axstream_impl.h"
17 #include "PluginEvents/StreamEvents.h"
18 #include "precompiled_headers.h" // On windows, everything above this line in PCH
19 
20 using namespace FB;
21 using namespace FB::ActiveX;
22 
23 ActiveXStream::ActiveXStream( const std::string& url, bool cache, bool seekableRequested, size_t internalBufferSize ) : FB::BrowserStream( url, cache, seekableRequested, internalBufferSize ), closing(false)
24 {
25 }
26 
27 ActiveXStream::ActiveXStream( const std::string& url, bool cache, bool seekableRequested, size_t internalBufferSize, const std::string& verbdata ) : FB::BrowserStream( url, cache, seekableRequested, internalBufferSize ), closing(false), data(verbdata)
28 {
29 }
30 
31 ActiveXStream::~ActiveXStream()
32 {
33  close();
34 }
35 
36 bool ActiveXStream::readRanges( const std::vector<Range>& ranges )
37 {
38  if ( !isSeekable() || !isOpen() ) return false;
39  if ( !ranges.size() ) return true;
40 
41  addRequest( ActiveXStreamRequest( FB::ptr_cast<ActiveXStream>(shared_from_this()), ranges ) );
42  return true;
43 }
44 
45 bool ActiveXStream::write(const char* data, size_t dataLength, size_t& written)
46 {
47  return false;
48 }
49 
50 bool ActiveXStream::close()
51 {
52  if ( closing ) return true; // prevent re-entrant calls
53  closing = true;
54 
55  if ( !isOpen() ) return false;
56 
57  setOpen( false );
58 
59  bool result = true;
60  std::set<ActiveXStreamRequestPtr> copiedRequests( requests );
61 
62  for ( std::set<ActiveXStreamRequestPtr>::const_iterator it = copiedRequests.begin(); it != copiedRequests.end(); ++it )
63  {
64  result &= (*it)->stop();
65  }
66  requests.clear();
67 
68  closing = false;
69  return result;
70 }
71 
72 bool ActiveXStream::init()
73 {
74  if ( isSeekable() ) return true; // if seekable, wait for the user to pull data ...
75  else return addRequest( ActiveXStreamRequest( FB::ptr_cast<ActiveXStream>(shared_from_this()) ) ); // ... otherwise start downloading the whole thing
76 }
77 
78 bool ActiveXStream::addRequest( const ActiveXStreamRequest& Request )
79 {
80  ActiveXStreamRequestPtr request( new ActiveXStreamRequest( Request ) );
81  bool result = request->start();
82  if ( result ) requests.insert( request );
83  return result;
84 }
85 
86 
87 size_t ActiveXStream::signalDataArrived(void* buffer, size_t len, size_t offset)
88 {
89  size_t effectiveLen = len; //min( getInternalBufferSize(), static_cast<size_t>(len) );
90  if ( effectiveLen )
91  {
92  //memcpy( &internalBuffer[0], buffer, effectiveLen );
93 
94  float progress = 0;
95  if ( getLength() )
96  {
97  progress = float( offset + len ) / float( getLength() ) * 100.f;
98  }
99  if ( isOpen() || (getCacheFilename() != L"") )
100  {
101  StreamDataArrivedEvent ev(this, buffer, effectiveLen, offset, progress);
102  SendEvent( &ev );
103  }
104  }
105  return effectiveLen;
106 }
107 
108 void ActiveXStream::signalOpened()
109 {
110  setOpen( true );
111  StreamOpenedEvent ev(this);
112  SendEvent( &ev );
113 }
114 
115 void ActiveXStream::signalFailedOpen()
116 {
117  StreamFailedOpenEvent ev(this);
118  SendEvent( &ev );
119 }
120 
121 void ActiveXStream::signalCompleted(bool success)
122 {
123  setCompleted( true );
124 
125  if ( !isOpen() && !success )
126  {
127  signalFailedOpen();
128  }
129 
130  close();
131 
132  StreamCompletedEvent ev(this, success);
133  SendEvent( &ev );
134 }
135 
136 void ActiveXStream::signalRequestCompleted(ActiveXStreamRequestPtr request, bool success)
137 {
138  requests.erase( request );
139  if ( !requests.size() )
140  {
141  signalCompleted( success );
142  close();
143  }
144 }
145 
146 void ActiveXStream::signalCacheFilename(const std::wstring& cacheFilename)
147 {
148  setCacheFilename( cacheFilename );
149 }
150 
151 std::string ActiveXStream::getVerbData() const
152 {
153  return data;
154 }
155 
156 #if 0
157 #ifdef USE_WINHTTP
158 
159 // WinHTTP - Excerpt from MSDN docs on WinHttpOpen:
160 // INHTTP_ACCESS_TYPE_DEFAULT_PROXY does not inherit browser proxy settings. WinHTTP does not share any proxy settings with Internet Explorer.
161 // The WinHTTP proxy configuration is set by one of these mechanisms:
162 // - The proxycfg.exe utility on Windows XP and Windows Server 2003 or earlier.
163 // - The netsh.exe utility on Windows Vista and Windows Server 2008 or later.
164 // - WinHttpSetDefaultProxyConfiguration on all platforms.
165 //
166 // Checked this with Wireshark and indeed this method does not use any proxy, even if set in internet explorer.
167 // Not good. Not sure about the automatic proxy stuff.
168 void UseWinHTTP(const WCHAR* URL)
169 {
170  BOOL bResults = FALSE;
171  HINTERNET hSession = NULL,
172  hConnect = NULL,
173  hRequest = NULL;
174 
175  // Use WinHttpOpen to obtain a session handle.
176  hSession = WinHttpOpen( L"DCWebClient/1.0",
177  WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
178  WINHTTP_NO_PROXY_NAME,
179  WINHTTP_NO_PROXY_BYPASS, 0);
180 
181  URL_COMPONENTS comps;
182  ZeroMemory(&comps, sizeof(comps));
183  comps.dwStructSize = sizeof(comps);
184 
185  // Set required component lengths to non-zero
186  // so that they are cracked.
187  comps.dwSchemeLength = -1;
188  comps.dwHostNameLength = -1;
189  comps.dwUrlPathLength = -1;
190  comps.dwExtraInfoLength = -1;
191  comps.dwUrlPathLength = -1;
192 
193  ::WinHttpCrackUrl( URL, 0, 0, &comps );
194 
195  // Specify an HTTP server.
196  if (hSession)
197  hConnect = WinHttpConnect( hSession, L"www.myurl.com",
198  comps.nPort, 0);
199 
200  // Create an HTTP Request handle.
201  if (hConnect)
202  hRequest = WinHttpOpenRequest( hConnect, L"GET",
203  comps.lpszUrlPath,
204  NULL, WINHTTP_NO_REFERER,
205  WINHTTP_DEFAULT_ACCEPT_TYPES,
206  0);
207 
208  const WCHAR headers[] =
209  L"Request-Range: bytes=2-5\r\n";
210  // Send a Request.
211  if (hRequest)
212  bResults = WinHttpSendRequest( hRequest,
213  headers,
214  0, WINHTTP_NO_REQUEST_DATA, 0,
215  0, 0);
216 
217  if (bResults)
218  bResults = WinHttpReceiveResponse( hRequest, 0 );
219 
220 
221  char buffer[1000];
222  DWORD readBytes, availBytes;
223 
224  if (bResults)
225  bResults = WinHttpQueryDataAvailable( hRequest, &availBytes );
226 
227  if (bResults && availBytes)
228  bResults = WinHttpReadData( hRequest, buffer, availBytes, &readBytes );
229 
230  // PLACE ADDITIONAL CODE HERE.
231 
232  // Report any errors.
233  if (!bResults)
234  ShowMessage( 0, "Error %d has occurred." + toString(GetLastError()) );
235 
236  // Close any open handles.
237  if (hRequest) WinHttpCloseHandle(hRequest);
238  if (hConnect) WinHttpCloseHandle(hConnect);
239  if (hSession) WinHttpCloseHandle(hSession);
240 }
241 
242 #endif
243 
244 // WinInet - This one seems to work with Internet Explorer's proxies. It also uses internet explorer's default user agent and additional headers.
245 /* Wireshark example (with proxy enabled)
246  GET /Resources.zip HTTP/1.0
247  Accept: *//*
248  Request-Range: bytes=2-5
249  Accept-Encoding: gzip, deflate
250  User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)
251  Host: www.myurl.com
252  Pragma: no-cache
253  Via: 1.1 myproxy.com:3128 (squid/2.7.STABLE7)
254  X-Forwarded-For: 192.168.0.2
255  Cache-Control: max-age=259200
256  Connection: keep-alive
257 
258  Wireshark example (no proxy, direct connection):
259  GET /Resources.zip HTTP/1.1
260  Accept: *//*
261  Request-Range: bytes=2-5
262  Accept-Encoding: gzip, deflate
263  User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)
264  Host: www.myurl.com
265  Connection: Keep-Alive
266  Cache-Control: no-cache
267 */
268 void UseWinInet(const WCHAR* URL)
269 {
270  HRESULT hr;
271 
272  IBindStatusCallback* ibscb(0);
273  ::CBindStatusCallback::Create( &ibscb );
274  /*HRESULT uoshr = URLOpenStream( 0, L"http://www.myurl.com/Resources.zip", 0, ibscb );
275  ShowMessage( hwnd, "URLOpenStream: " + toString(uoshr) );*/
276  IMoniker* FMoniker;
277  CreateURLMonikerEx(0, URL, &FMoniker, URL_MK_UNIFORM );
278 
279  IBindCtx* FBindCtx;
280  CreateAsyncBindCtx(0, ibscb, 0, &FBindCtx);
281 
282  hr = IsValidURL(FBindCtx, URL, 0);
283  if ( hr != S_OK )
284  {
285  ShowMessage( 0, "Invalid url" );
286  }
287 
288  IStream* fstream;
289  hr = FMoniker->BindToStorage(FBindCtx, 0, IID_IStream, (void**)&fstream);
290 
291  if ( (hr != S_OK) && (hr != MK_S_ASYNCHRONOUS) )
292  {
293  ShowMessage( 0, "error" );
294  }
295 }
296 
297 
298 // WinInet2 - This one seems to work with Internet Explorer's proxies. It does not use internet explorer's default user agent and only sends its own headers.
299 /* Wireshark example (with proxy enabled)
300  GET /Resources.zip HTTP/1.0
301  Request-Range: bytes=2-5
302  User-Agent: DCWebPlayer/1.0
303  Host: www.myurl.com
304  Via: 1.1 myproxy.com:3128 (squid/2.7.STABLE7)
305  X-Forwarded-For: 192.168.0.2
306  Cache-Control: max-age=259200
307  Connection: keep-alive
308 
309  Wireshark example (no proxy, direct connection):
310  GET /Resources.zip HTTP/1.1
311  Request-Range: bytes=2-5
312  User-Agent: DCWebPlayer/1.0
313  Host: www.myurl.com
314  Connection: Keep-Alive
315 */
316 void UseWinInet2(const WCHAR* URL)
317 {
318  HINTERNET hSession = InternetOpen( L"DCWebPlayer/1.0", INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0 /*INTERNET_FLAG_ASYNC*/ );
319  if ( !hSession ) ShowMessage( 0, "could not open internet" );
320  const WCHAR headers[] = L"Request-Range: bytes=2-5\r\n";
321  HINTERNET handleurl = InternetOpenUrl( hSession, URL, headers, -1, INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_CACHE_WRITE, 0 );
322  if ( !handleurl ) ShowMessage( 0, "could not open internet url" );
323 
324  char buf[1000];
325  DWORD noBytes;
326  InternetReadFile( handleurl, buf, 100, &noBytes );
327 
328  ShowMessage( 0, "WinInet2: "+ toString(noBytes) );
329 }
330 #endif
331 
This is the abstract base class (interface class) for a browser stream.
Definition: BrowserStream.h:41
This event is fired when a stream failed to open, e.g. the url was invalid or a seekable stream was r...
Definition: StreamEvents.h:120
This event is fired when a stream has completed downloading.
Definition: StreamEvents.h:148