Include wx/utils.h according to precompiled headers of wx/wx.h (with other minor...
[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 #endif
26
27 #if !wxUSE_PROTOCOL_HTTP
28 #include "wx/protocol/protocol.h"
29
30 // empty http protocol replacement (for now)
31 // so that wxUSE_URL_NATIVE can be used with
32 // wxSOCKETS==0 and wxUSE_PROTOCOL_HTTP==0
33 class wxHTTPDummyProto : public wxProtocol
34 {
35 public:
36 wxHTTPDummyProto() : wxProtocol() { }
37
38 wxProtocolError GetError() { return m_error; }
39
40 virtual bool Abort() { return true; }
41
42 wxInputStream *GetInputStream(const wxString& WXUNUSED(path))
43 {
44 return 0; // input stream is returned by wxURLNativeImp
45 }
46
47 protected:
48 wxProtocolError m_error;
49
50 DECLARE_DYNAMIC_CLASS_NO_COPY(wxHTTPDummyProto)
51 DECLARE_PROTOCOL(wxHTTPDummyProto)
52 };
53
54 // the only "reason for being" for this class is to tell
55 // wxURL that there is someone dealing with the http protocol
56 IMPLEMENT_DYNAMIC_CLASS(wxHTTPDummyProto, wxProtocol)
57 IMPLEMENT_PROTOCOL(wxHTTPDummyProto, wxT("http"), NULL, false)
58 USE_PROTOCOL(wxHTTPDummyProto)
59
60 #endif // !wxUSE_PROTOCOL_HTTP
61
62
63 #ifdef __VISUALC__ // be conservative about this pragma
64 // tell the linker to include wininet.lib automatically
65 #pragma comment(lib, "wininet.lib")
66 #endif
67
68 #include "wx/module.h"
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
76 class wxWinINetURL:public wxURLNativeImp
77 {
78 public:
79 wxInputStream *GetInputStream(wxURL *owner);
80
81 protected:
82 // return the WinINet session handle
83 static HINTERNET GetSessionHandle();
84 };
85
86 HINTERNET 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
120 class /*WXDLLIMPEXP_NET */ wxWinINetInputStream : public wxInputStream
121 {
122 public:
123 wxWinINetInputStream(HINTERNET hFile=0);
124 ~wxWinINetInputStream();
125
126 void Attach(HINTERNET hFile);
127
128 wxFileOffset SeekI( wxFileOffset WXUNUSED(pos), wxSeekMode WXUNUSED(mode) )
129 { return -1; }
130 wxFileOffset TellI() const
131 { return -1; }
132
133 protected:
134 void SetError(wxStreamError err) { m_lasterror=err; }
135 HINTERNET m_hFile;
136 size_t OnSysRead(void *buffer, size_t bufsize);
137
138 DECLARE_NO_COPY_CLASS(wxWinINetInputStream)
139 };
140
141 size_t wxWinINetInputStream::OnSysRead(void *buffer, size_t bufsize)
142 {
143 DWORD bytesread = 0;
144 if ( !InternetReadFile(m_hFile, buffer, bufsize, &bytesread) )
145 {
146 DWORD lError = ::GetLastError();
147 if ( lError != ERROR_SUCCESS )
148 SetError(wxSTREAM_READ_ERROR);
149
150 DWORD iError, bLength;
151 InternetGetLastResponseInfo(&iError, NULL, &bLength);
152 if ( bLength > 0 )
153 {
154 wxString errorString;
155 InternetGetLastResponseInfo
156 (
157 &iError,
158 wxStringBuffer(errorString, bLength),
159 &bLength
160 );
161
162 wxLogError(wxT("Read failed with error %d: %s"),
163 iError, errorString);
164 }
165 }
166
167 if ( bytesread == 0 )
168 {
169 SetError(wxSTREAM_EOF);
170 }
171
172 return bytesread;
173 }
174
175 wxWinINetInputStream::wxWinINetInputStream(HINTERNET hFile)
176 : m_hFile(hFile)
177 {
178 }
179
180 void wxWinINetInputStream::Attach(HINTERNET newHFile)
181 {
182 wxCHECK_RET(m_hFile==NULL,
183 wxT("cannot attach new stream when stream already exists"));
184 m_hFile=newHFile;
185 SetError(m_hFile!=NULL ? wxSTREAM_NO_ERROR : wxSTREAM_READ_ERROR);
186 }
187
188 wxWinINetInputStream::~wxWinINetInputStream()
189 {
190 if ( m_hFile )
191 {
192 InternetCloseHandle(m_hFile);
193 m_hFile=0;
194 }
195 }
196
197 wxURLNativeImp *wxURL::CreateNativeImpObject()
198 {
199 return new wxWinINetURL;
200 }
201
202 wxInputStream *wxWinINetURL::GetInputStream(wxURL *owner)
203 {
204 DWORD service;
205 if ( owner->GetScheme() == wxT("http") )
206 {
207 service = INTERNET_SERVICE_HTTP;
208 }
209 else if ( owner->GetScheme() == wxT("ftp") )
210 {
211 service = INTERNET_SERVICE_FTP;
212 }
213 else
214 {
215 // unknown protocol. Let wxURL try another method.
216 return 0;
217 }
218
219 wxWinINetInputStream *newStream = new wxWinINetInputStream;
220 HINTERNET newStreamHandle = InternetOpenUrl
221 (
222 GetSessionHandle(),
223 owner->GetURL(),
224 NULL,
225 0,
226 INTERNET_FLAG_KEEP_CONNECTION |
227 INTERNET_FLAG_PASSIVE,
228 (DWORD_PTR)newStream
229 );
230 newStream->Attach(newStreamHandle);
231
232 return newStream;
233 }
234
235 #endif // wxUSE_URL_NATIVE