]> git.saurik.com Git - wxWidgets.git/blame - src/msw/urlmsw.cpp
Fix memory leak by letting the base class version handle the
[wxWidgets.git] / src / msw / urlmsw.cpp
CommitLineData
25959b95
VZ
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
77ffb593 9// Licence: wxWidgets 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
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
27class wxHTTPDummyProto : public wxProtocol
28{
29public:
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
41protected:
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
50IMPLEMENT_DYNAMIC_CLASS(wxHTTPDummyProto, wxProtocol)
51IMPLEMENT_PROTOCOL(wxHTTPDummyProto, wxT("http"), NULL, FALSE)
52USE_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
73class wxWinINetURL:public wxURLNativeImp
74{
75public:
76 wxInputStream *GetInputStream(wxURL *owner);
77
78protected:
79 // return the WinINet session handle
80 static HINTERNET GetSessionHandle();
81};
82
83HINTERNET 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
117class /*WXDLLIMPEXP_NET */ wxWinINetInputStream : public wxInputStream
118{
119public:
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
130protected:
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
138size_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
172wxWinINetInputStream::wxWinINetInputStream(HINTERNET hFile)
173 : m_hFile(hFile)
174{
175}
176
177void 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
185wxWinINetInputStream::~wxWinINetInputStream()
186{
187 if ( m_hFile )
188 {
189 InternetCloseHandle(m_hFile);
190 m_hFile=0;
191 }
192}
193
194wxURLNativeImp *wxURL::CreateNativeImpObject()
195{
196 return new wxWinINetURL;
197}
198
199wxInputStream *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