]> git.saurik.com Git - wxWidgets.git/blame - src/common/url.cpp
Avoid defining COMPILER_PREFIX for autoconf format.
[wxWidgets.git] / src / common / url.cpp
CommitLineData
f4ada568 1/////////////////////////////////////////////////////////////////////////////
8ecff181 2// Name: src/common/url.cpp
f4ada568
GL
3// Purpose: URL parser
4// Author: Guilhem Lavaux
5// Modified by:
6// Created: 20/07/1997
7// RCS-ID: $Id$
8// Copyright: (c) 1997, 1998 Guilhem Lavaux
65571936 9// Licence: wxWindows licence
f4ada568
GL
10/////////////////////////////////////////////////////////////////////////////
11
fcc6dddd
JS
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
8ecff181 16 #pragma hdrstop
fcc6dddd
JS
17#endif
18
a5d46b73 19#if wxUSE_URL
f4ada568 20
df91131c
WS
21#include "wx/url.h"
22
8ecff181
WS
23#ifndef WX_PRECOMP
24 #include "wx/list.h"
df91131c 25 #include "wx/string.h"
de6185e2 26 #include "wx/utils.h"
02761f6c 27 #include "wx/module.h"
8ecff181
WS
28#endif
29
a5d46b73
VZ
30#include <string.h>
31#include <ctype.h>
32
b60b2ec8 33IMPLEMENT_CLASS(wxURL, wxURI)
f4ada568
GL
34
35// Protocols list
b2b35524 36wxProtoInfo *wxURL::ms_protocols = NULL;
8a4df159 37
f92f546c 38// Enforce linking of protocol classes:
f92f546c
VS
39USE_PROTOCOL(wxFileProto)
40
ce195ee6 41#if wxUSE_PROTOCOL_HTTP
f80eabe5 42USE_PROTOCOL(wxHTTP)
f80eabe5 43
b2b35524 44 wxHTTP *wxURL::ms_proxyDefault = NULL;
cb719f2e 45 bool wxURL::ms_useDefaultProxy = false;
8a4df159 46#endif
f4ada568 47
ce195ee6
MB
48#if wxUSE_PROTOCOL_FTP
49USE_PROTOCOL(wxFTP)
50#endif
51
fae05df5 52// --------------------------------------------------------------
b60b2ec8
RN
53//
54// wxURL
55//
fae05df5 56// --------------------------------------------------------------
f4ada568 57
ce321570
RN
58// --------------------------------------------------------------
59// Construction
60// --------------------------------------------------------------
61
b60b2ec8
RN
62wxURL::wxURL(const wxString& url) : wxURI(url)
63{
64 Init(url);
65 ParseURL();
66}
67
68wxURL::wxURL(const wxURI& url) : wxURI(url)
69{
86470d43 70 Init(url.BuildURI());
b60b2ec8
RN
71 ParseURL();
72}
73
b60b2ec8 74void wxURL::Init(const wxString& url)
f4ada568 75{
b2b35524
VZ
76 m_protocol = NULL;
77 m_error = wxURL_NOERR;
78 m_url = url;
25959b95
VZ
79#if wxUSE_URL_NATIVE
80 m_nativeImp = CreateNativeImpObject();
81#endif
b2b35524 82
ce195ee6 83#if wxUSE_PROTOCOL_HTTP
b2b35524
VZ
84 if ( ms_useDefaultProxy && !ms_proxyDefault )
85 {
2b5f62a0 86 SetDefaultProxy( wxGetenv(wxT("HTTP_PROXY")) );
b2b35524
VZ
87
88 if ( !ms_proxyDefault )
89 {
90 // don't try again
cb719f2e 91 ms_useDefaultProxy = false;
b2b35524
VZ
92 }
93 }
94
95 m_useProxy = ms_proxyDefault != NULL;
96 m_proxy = ms_proxyDefault;
ce195ee6 97#endif // wxUSE_PROTOCOL_HTTP
b2b35524 98
f4ada568 99}
ce321570
RN
100
101// --------------------------------------------------------------
102// Assignment
103// --------------------------------------------------------------
104
105wxURL& wxURL::operator = (const wxURI& url)
106{
107 wxURI::operator = (url);
108 Init(url.BuildURI());
109 ParseURL();
110 return *this;
111}
112wxURL& wxURL::operator = (const wxString& url)
113{
114 wxURI::operator = (url);
115 Init(url);
116 ParseURL();
117 return *this;
118}
119
b60b2ec8
RN
120// --------------------------------------------------------------
121// ParseURL
122//
123// Builds the URL and takes care of the old protocol stuff
124// --------------------------------------------------------------
f4ada568
GL
125
126bool wxURL::ParseURL()
127{
fd725bce
WS
128 // If the URL was already parsed (m_protocol != NULL), pass this section.
129 if (!m_protocol)
f6bcfd97 130 {
fd725bce
WS
131 // Clean up
132 CleanData();
f61815af 133
fd725bce
WS
134 // Make sure we have a protocol/scheme
135 if (!HasScheme())
136 {
137 m_error = wxURL_SNTXERR;
138 return false;
139 }
f61815af 140
fd725bce
WS
141 // Find and create the protocol object
142 if (!FetchProtocol())
143 {
144 m_error = wxURL_NOPROTO;
145 return false;
146 }
147
148 // Do we need a host name ?
149 if (m_protoinfo->m_needhost)
150 {
151 // Make sure we have one, then
152 if (!HasServer())
153 {
154 m_error = wxURL_SNTXERR;
155 return false;
156 }
157 }
f61815af 158 }
f4ada568 159
ce195ee6 160#if wxUSE_PROTOCOL_HTTP
fd725bce
WS
161 if (m_useProxy)
162 {
163 // Third, we rebuild the URL.
164 m_url = m_scheme + wxT(":");
165 if (m_protoinfo->m_needhost)
166 m_url = m_url + wxT("//") + m_server;
167
168 // We initialize specific variables.
169 m_protocol = m_proxy; // FIXME: we should clone the protocol
170 }
ce195ee6 171#endif // wxUSE_PROTOCOL_HTTP
f4ada568 172
fd725bce
WS
173 m_error = wxURL_NOERR;
174 return true;
f4ada568
GL
175}
176
ce321570
RN
177// --------------------------------------------------------------
178// Destruction/Cleanup
179// --------------------------------------------------------------
180
f4ada568
GL
181void wxURL::CleanData()
182{
ce195ee6 183#if wxUSE_PROTOCOL_HTTP
fd725bce 184 if (!m_useProxy)
ce195ee6 185#endif // wxUSE_PROTOCOL_HTTP
5f3742c2
KH
186 if (m_protocol)
187 // Need to safely delete the socket (pending events)
188 m_protocol->Destroy();
f4ada568
GL
189}
190
191wxURL::~wxURL()
192{
25959b95 193 CleanData();
ce195ee6 194#if wxUSE_PROTOCOL_HTTP
25959b95
VZ
195 if (m_proxy && m_proxy != ms_proxyDefault)
196 delete m_proxy;
ce195ee6 197#endif // wxUSE_PROTOCOL_HTTP
25959b95
VZ
198#if wxUSE_URL_NATIVE
199 delete m_nativeImp;
8a4df159 200#endif
f4ada568
GL
201}
202
ce321570
RN
203// --------------------------------------------------------------
204// FetchProtocol
205// --------------------------------------------------------------
f4ada568
GL
206
207bool wxURL::FetchProtocol()
208{
fd725bce 209 wxProtoInfo *info = ms_protocols;
f4ada568 210
fd725bce 211 while (info)
f6bcfd97 212 {
fd725bce
WS
213 if (m_scheme == info->m_protoname)
214 {
215 if (m_port.IsNull())
216 m_port = info->m_servname;
217 m_protoinfo = info;
218 m_protocol = (wxProtocol *)m_protoinfo->m_cinfo->CreateObject();
219 return true;
220 }
221 info = info->next;
f4ada568 222 }
fd725bce 223 return false;
f4ada568
GL
224}
225
fae05df5 226// --------------------------------------------------------------
ce321570 227// GetInputStream
fae05df5
GL
228// --------------------------------------------------------------
229
58c837a4 230wxInputStream *wxURL::GetInputStream()
f4ada568 231{
fd725bce
WS
232 if (!m_protocol)
233 {
234 m_error = wxURL_NOPROTO;
235 return NULL;
236 }
237
238 m_error = wxURL_NOERR;
239 if (HasUserInfo())
240 {
241 size_t dwPasswordPos = m_userinfo.find(':');
242
243 if (dwPasswordPos == wxString::npos)
e03e94b0 244 m_protocol->SetUser(Unescape(m_userinfo));
fd725bce
WS
245 else
246 {
e03e94b0
VZ
247 m_protocol->SetUser(Unescape(m_userinfo(0, dwPasswordPos)));
248 m_protocol->SetPassword(Unescape(m_userinfo(dwPasswordPos+1, m_userinfo.length() + 1)));
fd725bce
WS
249 }
250 }
856d2e52 251
25959b95 252#if wxUSE_URL_NATIVE
fd725bce
WS
253 // give the native implementation to return a better stream
254 // such as the native WinINet functionality under MS-Windows
255 if (m_nativeImp)
256 {
257 wxInputStream *rc;
258 rc = m_nativeImp->GetInputStream(this);
259 if (rc != 0)
260 return rc;
261 }
262 // else use the standard behaviour
25959b95
VZ
263#endif // wxUSE_URL_NATIVE
264
8a4df159 265#if wxUSE_SOCKETS
19e0e04b
RD
266 wxIPV4address addr;
267
fd725bce 268 // m_protoinfo is NULL when we use a proxy
283965f0
VZ
269 if (
270#if wxUSE_PROTOCOL_HTTP
271 !m_useProxy &&
272#endif // wxUSE_PROTOCOL_HTTP
273 m_protoinfo->m_needhost )
f6bcfd97 274 {
fd725bce
WS
275 if (!addr.Hostname(m_server))
276 {
277 m_error = wxURL_NOHOST;
278 return NULL;
279 }
280
281 addr.Service(m_port);
282
283 if (!m_protocol->Connect(addr, true)) // Watcom needs the 2nd arg for some reason
284 {
285 m_error = wxURL_CONNERR;
286 return NULL;
287 }
f4ada568 288 }
283965f0 289#endif // wxUSE_SOCKETS
fd725bce
WS
290
291 wxString fullPath;
f4ada568 292
283965f0 293#if wxUSE_PROTOCOL_HTTP
fd725bce
WS
294 // When we use a proxy, we have to pass the whole URL to it.
295 if (m_useProxy)
296 fullPath += m_url;
283965f0 297#endif // wxUSE_PROTOCOL_HTTP
f4ada568 298
fd725bce
WS
299 if(m_path.empty())
300 fullPath += wxT("/");
301 else
302 fullPath += m_path;
303
304 if (HasQuery())
305 fullPath += wxT("?") + m_query;
306
307 if (HasFragment())
308 fullPath += wxT("#") + m_fragment;
309
310 wxInputStream *the_i_stream = m_protocol->GetInputStream(fullPath);
311
312 if (!the_i_stream)
8a2c6ef8 313 {
fd725bce
WS
314 m_error = wxURL_PROTOERR;
315 return NULL;
f4ada568 316 }
f4ada568 317
fd725bce 318 return the_i_stream;
f4ada568
GL
319}
320
ce195ee6 321#if wxUSE_PROTOCOL_HTTP
f4ada568
GL
322void wxURL::SetDefaultProxy(const wxString& url_proxy)
323{
fd725bce
WS
324 if ( !url_proxy )
325 {
326 if ( ms_proxyDefault )
327 {
328 ms_proxyDefault->Close();
329 delete ms_proxyDefault;
330 ms_proxyDefault = NULL;
331 }
332 }
333 else
334 {
335 wxString tmp_str = url_proxy;
336 int pos = tmp_str.Find(wxT(':'));
337 if (pos == wxNOT_FOUND)
338 return;
339
340 wxString hostname = tmp_str(0, pos),
8ecff181 341 port = tmp_str(pos+1, tmp_str.length()-pos);
fd725bce
WS
342 wxIPV4address addr;
343
344 if (!addr.Hostname(hostname))
345 return;
346 if (!addr.Service(port))
347 return;
348
349 if (ms_proxyDefault)
350 // Finally, when all is right, we connect the new proxy.
351 ms_proxyDefault->Close();
352 else
353 ms_proxyDefault = new wxHTTP();
354 ms_proxyDefault->Connect(addr, true); // Watcom needs the 2nd arg for some reason
355 }
f4ada568
GL
356}
357
358void wxURL::SetProxy(const wxString& url_proxy)
359{
b2b35524
VZ
360 if ( !url_proxy )
361 {
362 if ( m_proxy && m_proxy != ms_proxyDefault )
363 {
364 m_proxy->Close();
365 delete m_proxy;
366 }
f4ada568 367
cb719f2e 368 m_useProxy = false;
b2b35524
VZ
369 }
370 else
371 {
372 wxString tmp_str;
373 wxString hostname, port;
374 int pos;
375 wxIPV4address addr;
376
377 tmp_str = url_proxy;
378 pos = tmp_str.Find(wxT(':'));
379 // This is an invalid proxy name.
cb719f2e 380 if (pos == wxNOT_FOUND)
b2b35524
VZ
381 return;
382
383 hostname = tmp_str(0, pos);
8ecff181 384 port = tmp_str(pos+1, tmp_str.length()-pos);
b2b35524
VZ
385
386 addr.Hostname(hostname);
387 addr.Service(port);
388
389 // Finally, create the whole stuff.
390 if (m_proxy && m_proxy != ms_proxyDefault)
391 delete m_proxy;
392 m_proxy = new wxHTTP();
cb719f2e 393 m_proxy->Connect(addr, true); // Watcom needs the 2nd arg for some reason
b2b35524
VZ
394
395 CleanData();
396 // Reparse url.
cb719f2e 397 m_useProxy = true;
b2b35524
VZ
398 ParseURL();
399 }
f4ada568 400}
ce195ee6 401#endif // wxUSE_PROTOCOL_HTTP
35a4dab7 402
b2b35524 403// ----------------------------------------------------------------------
ce321570
RN
404// wxURLModule
405//
b2b35524
VZ
406// A module which deletes the default proxy if we created it
407// ----------------------------------------------------------------------
408
409#if wxUSE_SOCKETS
410
411class wxURLModule : public wxModule
412{
413public:
7921a093
VZ
414 wxURLModule();
415
b2b35524
VZ
416 virtual bool OnInit();
417 virtual void OnExit();
418
419private:
420 DECLARE_DYNAMIC_CLASS(wxURLModule)
421};
422
423IMPLEMENT_DYNAMIC_CLASS(wxURLModule, wxModule)
424
7921a093
VZ
425wxURLModule::wxURLModule()
426{
427 // we must be cleaned up before wxSocketModule as otherwise deleting
428 // ms_proxyDefault from our OnExit() won't work (and can actually crash)
9a83f860 429 AddDependency(wxClassInfo::FindClass(wxT("wxSocketModule")));
7921a093
VZ
430}
431
b2b35524
VZ
432bool wxURLModule::OnInit()
433{
ce195ee6 434#if wxUSE_PROTOCOL_HTTP
b2b35524
VZ
435 // env var HTTP_PROXY contains the address of the default proxy to use if
436 // set, but don't try to create this proxy right now because it will slow
437 // down the program startup (especially if there is no DNS server
438 // available, in which case it may take up to 1 minute)
f6bcfd97 439
9a83f860 440 if ( wxGetenv(wxT("HTTP_PROXY")) )
b2b35524 441 {
cb719f2e 442 wxURL::ms_useDefaultProxy = true;
b2b35524 443 }
ce195ee6 444#endif // wxUSE_PROTOCOL_HTTP
cb719f2e 445 return true;
b2b35524
VZ
446}
447
448void wxURLModule::OnExit()
449{
ce195ee6 450#if wxUSE_PROTOCOL_HTTP
b2b35524
VZ
451 delete wxURL::ms_proxyDefault;
452 wxURL::ms_proxyDefault = NULL;
ce195ee6 453#endif // wxUSE_PROTOCOL_HTTP
b2b35524
VZ
454}
455
456#endif // wxUSE_SOCKETS
a5d46b73 457
97d8fe87 458
a5d46b73 459#endif // wxUSE_URL