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