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