]> git.saurik.com Git - wxWidgets.git/blame - src/msw/urlmsw.cpp
#9675: wxDataViewModel::Reset() and scrollbar problem (wxMac)
[wxWidgets.git] / src / msw / urlmsw.cpp
CommitLineData
25959b95 1/////////////////////////////////////////////////////////////////////////////
7ec69821 2// Name: src/msw/urlmsw.cpp
25959b95
VZ
3// Purpose: MS-Windows native URL support based on WinINet
4// Author: Hajo Kirchhoff
5// Modified by:
6// Created: 06/11/2003
7// RCS-ID: $Id$
8// Copyright: (c) 2003 Hajo Kirchhoff
65571936 9// Licence: wxWindows licence
25959b95
VZ
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
19#if wxUSE_URL_NATIVE
20
8ecff181
WS
21#ifndef WX_PRECOMP
22 #include "wx/list.h"
df91131c 23 #include "wx/string.h"
de6185e2 24 #include "wx/utils.h"
02761f6c 25 #include "wx/module.h"
8ecff181
WS
26#endif
27
25959b95 28#if !wxUSE_PROTOCOL_HTTP
7ec69821 29#include "wx/protocol/protocol.h"
25959b95
VZ
30
31// empty http protocol replacement (for now)
32// so that wxUSE_URL_NATIVE can be used with
33// wxSOCKETS==0 and wxUSE_PROTOCOL_HTTP==0
34class wxHTTPDummyProto : public wxProtocol
35{
36public:
37 wxHTTPDummyProto() : wxProtocol() { }
38
39 wxProtocolError GetError() { return m_error; }
40
27d2dbbc 41 virtual bool Abort() { return true; }
25959b95
VZ
42
43 wxInputStream *GetInputStream(const wxString& WXUNUSED(path))
44 {
45 return 0; // input stream is returned by wxURLNativeImp
46 }
47
48protected:
49 wxProtocolError m_error;
50
51 DECLARE_DYNAMIC_CLASS_NO_COPY(wxHTTPDummyProto)
52 DECLARE_PROTOCOL(wxHTTPDummyProto)
53};
54
55// the only "reason for being" for this class is to tell
56// wxURL that there is someone dealing with the http protocol
57IMPLEMENT_DYNAMIC_CLASS(wxHTTPDummyProto, wxProtocol)
7ec69821 58IMPLEMENT_PROTOCOL(wxHTTPDummyProto, wxT("http"), NULL, false)
25959b95
VZ
59USE_PROTOCOL(wxHTTPDummyProto)
60
61#endif // !wxUSE_PROTOCOL_HTTP
62
63
64#ifdef __VISUALC__ // be conservative about this pragma
65 // tell the linker to include wininet.lib automatically
66 #pragma comment(lib, "wininet.lib")
67#endif
68
25959b95
VZ
69#include "wx/url.h"
70
71#include <string.h>
72#include <ctype.h>
73#include <wininet.h>
74
75// this class needn't be exported
76class wxWinINetURL:public wxURLNativeImp
77{
78public:
79 wxInputStream *GetInputStream(wxURL *owner);
80
81protected:
82 // return the WinINet session handle
83 static HINTERNET GetSessionHandle();
84};
85
86HINTERNET wxWinINetURL::GetSessionHandle()
87{
88 // this struct ensures that the session is opened when the
89 // first call to GetSessionHandle is made
90 // it also ensures that the session is closed when the program
91 // terminates
92 static struct INetSession
93 {
94 INetSession()
95 {
96 DWORD rc = InternetAttemptConnect(0);
97
98 m_handle = InternetOpen
99 (
100 wxVERSION_STRING,
101 INTERNET_OPEN_TYPE_PRECONFIG,
102 NULL,
103 NULL,
104 rc == ERROR_SUCCESS ? 0 : INTERNET_FLAG_OFFLINE
105 );
106 }
107
108 ~INetSession()
109 {
110 InternetCloseHandle(m_handle);
111 }
112
113 HINTERNET m_handle;
114 } session;
115
116 return session.m_handle;
117}
118
119// this class needn't be exported
120class /*WXDLLIMPEXP_NET */ wxWinINetInputStream : public wxInputStream
121{
122public:
123 wxWinINetInputStream(HINTERNET hFile=0);
d3c7fc99 124 virtual ~wxWinINetInputStream();
25959b95
VZ
125
126 void Attach(HINTERNET hFile);
127
30984dea 128 wxFileOffset SeekI( wxFileOffset WXUNUSED(pos), wxSeekMode WXUNUSED(mode) )
25959b95 129 { return -1; }
30984dea 130 wxFileOffset TellI() const
25959b95 131 { return -1; }
624f82cc 132 size_t GetSize() const;
25959b95
VZ
133
134protected:
135 void SetError(wxStreamError err) { m_lasterror=err; }
136 HINTERNET m_hFile;
137 size_t OnSysRead(void *buffer, size_t bufsize);
138
139 DECLARE_NO_COPY_CLASS(wxWinINetInputStream)
140};
141
624f82cc
VZ
142size_t wxWinINetInputStream::GetSize() const
143{
144 DWORD contentLength = 0;
145 DWORD dwSize = sizeof(contentLength);
146 DWORD index = 0;
147
148 if ( HttpQueryInfo( m_hFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &contentLength, &dwSize, &index) )
149 return contentLength;
150 else
151 return 0;
152}
153
25959b95
VZ
154size_t wxWinINetInputStream::OnSysRead(void *buffer, size_t bufsize)
155{
156 DWORD bytesread = 0;
157 if ( !InternetReadFile(m_hFile, buffer, bufsize, &bytesread) )
158 {
159 DWORD lError = ::GetLastError();
160 if ( lError != ERROR_SUCCESS )
161 SetError(wxSTREAM_READ_ERROR);
162
163 DWORD iError, bLength;
164 InternetGetLastResponseInfo(&iError, NULL, &bLength);
165 if ( bLength > 0 )
166 {
167 wxString errorString;
168 InternetGetLastResponseInfo
169 (
170 &iError,
171 wxStringBuffer(errorString, bLength),
172 &bLength
173 );
174
175 wxLogError(wxT("Read failed with error %d: %s"),
176 iError, errorString);
177 }
178 }
179
180 if ( bytesread == 0 )
181 {
182 SetError(wxSTREAM_EOF);
183 }
184
185 return bytesread;
186}
187
188wxWinINetInputStream::wxWinINetInputStream(HINTERNET hFile)
189 : m_hFile(hFile)
190{
191}
192
193void wxWinINetInputStream::Attach(HINTERNET newHFile)
194{
195 wxCHECK_RET(m_hFile==NULL,
196 wxT("cannot attach new stream when stream already exists"));
197 m_hFile=newHFile;
198 SetError(m_hFile!=NULL ? wxSTREAM_NO_ERROR : wxSTREAM_READ_ERROR);
199}
200
201wxWinINetInputStream::~wxWinINetInputStream()
202{
203 if ( m_hFile )
204 {
205 InternetCloseHandle(m_hFile);
206 m_hFile=0;
207 }
208}
209
210wxURLNativeImp *wxURL::CreateNativeImpObject()
211{
212 return new wxWinINetURL;
213}
214
215wxInputStream *wxWinINetURL::GetInputStream(wxURL *owner)
216{
217 DWORD service;
c66d0fc3 218 if ( owner->GetScheme() == wxT("http") )
25959b95
VZ
219 {
220 service = INTERNET_SERVICE_HTTP;
221 }
c66d0fc3 222 else if ( owner->GetScheme() == wxT("ftp") )
25959b95
VZ
223 {
224 service = INTERNET_SERVICE_FTP;
225 }
226 else
227 {
228 // unknown protocol. Let wxURL try another method.
229 return 0;
230 }
231
232 wxWinINetInputStream *newStream = new wxWinINetInputStream;
233 HINTERNET newStreamHandle = InternetOpenUrl
234 (
235 GetSessionHandle(),
236 owner->GetURL(),
237 NULL,
238 0,
239 INTERNET_FLAG_KEEP_CONNECTION |
240 INTERNET_FLAG_PASSIVE,
241 (DWORD_PTR)newStream
242 );
243 newStream->Attach(newStreamHandle);
244
245 return newStream;
246}
247
248#endif // wxUSE_URL_NATIVE