]> git.saurik.com Git - wxWidgets.git/blame - src/common/url.cpp
Fix wxFileSystem::FileNameToURL() for Unicode file names.
[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.
be103d4a
VZ
169 if (m_protocol)
170 m_protocol->Destroy();
fd725bce
WS
171 m_protocol = m_proxy; // FIXME: we should clone the protocol
172 }
ce195ee6 173#endif // wxUSE_PROTOCOL_HTTP
f4ada568 174
fd725bce
WS
175 m_error = wxURL_NOERR;
176 return true;
f4ada568
GL
177}
178
ce321570
RN
179// --------------------------------------------------------------
180// Destruction/Cleanup
181// --------------------------------------------------------------
182
f4ada568
GL
183void wxURL::CleanData()
184{
ce195ee6 185#if wxUSE_PROTOCOL_HTTP
fd725bce 186 if (!m_useProxy)
ce195ee6 187#endif // wxUSE_PROTOCOL_HTTP
be103d4a 188 {
5f3742c2 189 if (m_protocol)
be103d4a 190 {
5f3742c2
KH
191 // Need to safely delete the socket (pending events)
192 m_protocol->Destroy();
be103d4a
VZ
193 m_protocol = NULL;
194 }
195 }
f4ada568
GL
196}
197
198wxURL::~wxURL()
199{
25959b95 200 CleanData();
ce195ee6 201#if wxUSE_PROTOCOL_HTTP
25959b95
VZ
202 if (m_proxy && m_proxy != ms_proxyDefault)
203 delete m_proxy;
ce195ee6 204#endif // wxUSE_PROTOCOL_HTTP
25959b95
VZ
205#if wxUSE_URL_NATIVE
206 delete m_nativeImp;
8a4df159 207#endif
f4ada568
GL
208}
209
ce321570
RN
210// --------------------------------------------------------------
211// FetchProtocol
212// --------------------------------------------------------------
f4ada568
GL
213
214bool wxURL::FetchProtocol()
215{
fd725bce 216 wxProtoInfo *info = ms_protocols;
f4ada568 217
fd725bce 218 while (info)
f6bcfd97 219 {
fd725bce
WS
220 if (m_scheme == info->m_protoname)
221 {
222 if (m_port.IsNull())
223 m_port = info->m_servname;
224 m_protoinfo = info;
225 m_protocol = (wxProtocol *)m_protoinfo->m_cinfo->CreateObject();
226 return true;
227 }
228 info = info->next;
f4ada568 229 }
fd725bce 230 return false;
f4ada568
GL
231}
232
fae05df5 233// --------------------------------------------------------------
ce321570 234// GetInputStream
fae05df5
GL
235// --------------------------------------------------------------
236
58c837a4 237wxInputStream *wxURL::GetInputStream()
f4ada568 238{
fd725bce
WS
239 if (!m_protocol)
240 {
241 m_error = wxURL_NOPROTO;
242 return NULL;
243 }
244
245 m_error = wxURL_NOERR;
246 if (HasUserInfo())
247 {
248 size_t dwPasswordPos = m_userinfo.find(':');
249
250 if (dwPasswordPos == wxString::npos)
e03e94b0 251 m_protocol->SetUser(Unescape(m_userinfo));
fd725bce
WS
252 else
253 {
e03e94b0
VZ
254 m_protocol->SetUser(Unescape(m_userinfo(0, dwPasswordPos)));
255 m_protocol->SetPassword(Unescape(m_userinfo(dwPasswordPos+1, m_userinfo.length() + 1)));
fd725bce
WS
256 }
257 }
856d2e52 258
25959b95 259#if wxUSE_URL_NATIVE
fd725bce
WS
260 // give the native implementation to return a better stream
261 // such as the native WinINet functionality under MS-Windows
262 if (m_nativeImp)
263 {
264 wxInputStream *rc;
265 rc = m_nativeImp->GetInputStream(this);
266 if (rc != 0)
267 return rc;
268 }
269 // else use the standard behaviour
25959b95
VZ
270#endif // wxUSE_URL_NATIVE
271
8a4df159 272#if wxUSE_SOCKETS
19e0e04b
RD
273 wxIPV4address addr;
274
fd725bce 275 // m_protoinfo is NULL when we use a proxy
283965f0
VZ
276 if (
277#if wxUSE_PROTOCOL_HTTP
278 !m_useProxy &&
279#endif // wxUSE_PROTOCOL_HTTP
280 m_protoinfo->m_needhost )
f6bcfd97 281 {
fd725bce
WS
282 if (!addr.Hostname(m_server))
283 {
284 m_error = wxURL_NOHOST;
285 return NULL;
286 }
287
288 addr.Service(m_port);
289
290 if (!m_protocol->Connect(addr, true)) // Watcom needs the 2nd arg for some reason
291 {
292 m_error = wxURL_CONNERR;
293 return NULL;
294 }
f4ada568 295 }
283965f0 296#endif // wxUSE_SOCKETS
fd725bce
WS
297
298 wxString fullPath;
f4ada568 299
283965f0 300#if wxUSE_PROTOCOL_HTTP
fd725bce
WS
301 // When we use a proxy, we have to pass the whole URL to it.
302 if (m_useProxy)
303 fullPath += m_url;
283965f0 304#endif // wxUSE_PROTOCOL_HTTP
f4ada568 305
fd725bce
WS
306 if(m_path.empty())
307 fullPath += wxT("/");
308 else
309 fullPath += m_path;
310
311 if (HasQuery())
312 fullPath += wxT("?") + m_query;
313
314 if (HasFragment())
315 fullPath += wxT("#") + m_fragment;
316
317 wxInputStream *the_i_stream = m_protocol->GetInputStream(fullPath);
318
319 if (!the_i_stream)
8a2c6ef8 320 {
fd725bce
WS
321 m_error = wxURL_PROTOERR;
322 return NULL;
f4ada568 323 }
f4ada568 324
fd725bce 325 return the_i_stream;
f4ada568
GL
326}
327
ce195ee6 328#if wxUSE_PROTOCOL_HTTP
f4ada568
GL
329void wxURL::SetDefaultProxy(const wxString& url_proxy)
330{
fd725bce
WS
331 if ( !url_proxy )
332 {
333 if ( ms_proxyDefault )
334 {
335 ms_proxyDefault->Close();
336 delete ms_proxyDefault;
337 ms_proxyDefault = NULL;
338 }
339 }
340 else
341 {
342 wxString tmp_str = url_proxy;
343 int pos = tmp_str.Find(wxT(':'));
344 if (pos == wxNOT_FOUND)
345 return;
346
347 wxString hostname = tmp_str(0, pos),
8ecff181 348 port = tmp_str(pos+1, tmp_str.length()-pos);
fd725bce
WS
349 wxIPV4address addr;
350
351 if (!addr.Hostname(hostname))
352 return;
353 if (!addr.Service(port))
354 return;
355
356 if (ms_proxyDefault)
357 // Finally, when all is right, we connect the new proxy.
358 ms_proxyDefault->Close();
359 else
360 ms_proxyDefault = new wxHTTP();
361 ms_proxyDefault->Connect(addr, true); // Watcom needs the 2nd arg for some reason
362 }
f4ada568
GL
363}
364
365void wxURL::SetProxy(const wxString& url_proxy)
366{
b2b35524
VZ
367 if ( !url_proxy )
368 {
369 if ( m_proxy && m_proxy != ms_proxyDefault )
370 {
371 m_proxy->Close();
372 delete m_proxy;
373 }
f4ada568 374
cb719f2e 375 m_useProxy = false;
b2b35524
VZ
376 }
377 else
378 {
379 wxString tmp_str;
380 wxString hostname, port;
381 int pos;
382 wxIPV4address addr;
383
384 tmp_str = url_proxy;
385 pos = tmp_str.Find(wxT(':'));
386 // This is an invalid proxy name.
cb719f2e 387 if (pos == wxNOT_FOUND)
b2b35524
VZ
388 return;
389
390 hostname = tmp_str(0, pos);
8ecff181 391 port = tmp_str(pos+1, tmp_str.length()-pos);
b2b35524
VZ
392
393 addr.Hostname(hostname);
394 addr.Service(port);
395
396 // Finally, create the whole stuff.
397 if (m_proxy && m_proxy != ms_proxyDefault)
398 delete m_proxy;
399 m_proxy = new wxHTTP();
cb719f2e 400 m_proxy->Connect(addr, true); // Watcom needs the 2nd arg for some reason
b2b35524
VZ
401
402 CleanData();
403 // Reparse url.
cb719f2e 404 m_useProxy = true;
b2b35524
VZ
405 ParseURL();
406 }
f4ada568 407}
ce195ee6 408#endif // wxUSE_PROTOCOL_HTTP
35a4dab7 409
b2b35524 410// ----------------------------------------------------------------------
ce321570
RN
411// wxURLModule
412//
b2b35524
VZ
413// A module which deletes the default proxy if we created it
414// ----------------------------------------------------------------------
415
416#if wxUSE_SOCKETS
417
418class wxURLModule : public wxModule
419{
420public:
7921a093
VZ
421 wxURLModule();
422
b2b35524
VZ
423 virtual bool OnInit();
424 virtual void OnExit();
425
426private:
427 DECLARE_DYNAMIC_CLASS(wxURLModule)
428};
429
430IMPLEMENT_DYNAMIC_CLASS(wxURLModule, wxModule)
431
7921a093
VZ
432wxURLModule::wxURLModule()
433{
434 // we must be cleaned up before wxSocketModule as otherwise deleting
435 // ms_proxyDefault from our OnExit() won't work (and can actually crash)
9a83f860 436 AddDependency(wxClassInfo::FindClass(wxT("wxSocketModule")));
7921a093
VZ
437}
438
b2b35524
VZ
439bool wxURLModule::OnInit()
440{
ce195ee6 441#if wxUSE_PROTOCOL_HTTP
b2b35524
VZ
442 // env var HTTP_PROXY contains the address of the default proxy to use if
443 // set, but don't try to create this proxy right now because it will slow
444 // down the program startup (especially if there is no DNS server
445 // available, in which case it may take up to 1 minute)
f6bcfd97 446
9a83f860 447 if ( wxGetenv(wxT("HTTP_PROXY")) )
b2b35524 448 {
cb719f2e 449 wxURL::ms_useDefaultProxy = true;
b2b35524 450 }
ce195ee6 451#endif // wxUSE_PROTOCOL_HTTP
cb719f2e 452 return true;
b2b35524
VZ
453}
454
455void wxURLModule::OnExit()
456{
ce195ee6 457#if wxUSE_PROTOCOL_HTTP
b2b35524
VZ
458 delete wxURL::ms_proxyDefault;
459 wxURL::ms_proxyDefault = NULL;
ce195ee6 460#endif // wxUSE_PROTOCOL_HTTP
b2b35524
VZ
461}
462
463#endif // wxUSE_SOCKETS
a5d46b73 464
97d8fe87 465
a5d46b73 466#endif // wxUSE_URL