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