]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/url.cpp
Misc validity fixes to samples/xrc/rc/*.xrc.
[wxWidgets.git] / src / common / url.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/url.cpp
3// Purpose: URL parser
4// Author: Guilhem Lavaux
5// Modified by:
6// Created: 20/07/1997
7// Copyright: (c) 1997, 1998 Guilhem Lavaux
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
18#if wxUSE_URL
19
20#include "wx/url.h"
21
22#ifndef WX_PRECOMP
23 #include "wx/list.h"
24 #include "wx/string.h"
25 #include "wx/utils.h"
26 #include "wx/module.h"
27#endif
28
29#include <string.h>
30#include <ctype.h>
31
32IMPLEMENT_CLASS(wxURL, wxURI)
33
34// Protocols list
35wxProtoInfo *wxURL::ms_protocols = NULL;
36
37// Enforce linking of protocol classes:
38USE_PROTOCOL(wxFileProto)
39
40#if wxUSE_PROTOCOL_HTTP
41USE_PROTOCOL(wxHTTP)
42
43 wxHTTP *wxURL::ms_proxyDefault = NULL;
44 bool wxURL::ms_useDefaultProxy = false;
45#endif
46
47#if wxUSE_PROTOCOL_FTP
48USE_PROTOCOL(wxFTP)
49#endif
50
51// --------------------------------------------------------------
52//
53// wxURL
54//
55// --------------------------------------------------------------
56
57// --------------------------------------------------------------
58// Construction
59// --------------------------------------------------------------
60
61wxURL::wxURL(const wxString& url) : wxURI(url)
62{
63 Init(url);
64 ParseURL();
65}
66
67wxURL::wxURL(const wxURI& uri) : wxURI(uri)
68{
69 Init(uri.BuildURI());
70 ParseURL();
71}
72
73wxURL::wxURL(const wxURL& url) : wxURI(url)
74{
75 Init(url.GetURL());
76 ParseURL();
77}
78
79void wxURL::Init(const wxString& url)
80{
81 m_protocol = NULL;
82 m_error = wxURL_NOERR;
83 m_url = url;
84#if wxUSE_URL_NATIVE
85 m_nativeImp = CreateNativeImpObject();
86#endif
87
88#if wxUSE_PROTOCOL_HTTP
89 if ( ms_useDefaultProxy && !ms_proxyDefault )
90 {
91 SetDefaultProxy( wxGetenv(wxT("HTTP_PROXY")) );
92
93 if ( !ms_proxyDefault )
94 {
95 // don't try again
96 ms_useDefaultProxy = false;
97 }
98 }
99
100 m_useProxy = ms_proxyDefault != NULL;
101 m_proxy = ms_proxyDefault;
102#endif // wxUSE_PROTOCOL_HTTP
103
104}
105
106// --------------------------------------------------------------
107// Assignment
108// --------------------------------------------------------------
109
110wxURL& wxURL::operator = (const wxString& url)
111{
112 wxURI::operator = (url);
113 Free();
114 Init(url);
115 ParseURL();
116
117 return *this;
118}
119
120wxURL& wxURL::operator = (const wxURI& uri)
121{
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
143 return *this;
144}
145
146// --------------------------------------------------------------
147// ParseURL
148//
149// Builds the URL and takes care of the old protocol stuff
150// --------------------------------------------------------------
151
152bool wxURL::ParseURL()
153{
154 // If the URL was already parsed (m_protocol != NULL), pass this section.
155 if (!m_protocol)
156 {
157 // Clean up
158 CleanData();
159
160 // Make sure we have a protocol/scheme
161 if (!HasScheme())
162 {
163 m_error = wxURL_SNTXERR;
164 return false;
165 }
166
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 }
184 }
185
186#if wxUSE_PROTOCOL_HTTP
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.
195 if (m_protocol)
196 m_protocol->Destroy();
197 m_protocol = m_proxy; // FIXME: we should clone the protocol
198 }
199#endif // wxUSE_PROTOCOL_HTTP
200
201 m_error = wxURL_NOERR;
202 return true;
203}
204
205// --------------------------------------------------------------
206// Destruction/Cleanup
207// --------------------------------------------------------------
208
209void wxURL::CleanData()
210{
211#if wxUSE_PROTOCOL_HTTP
212 if (!m_useProxy)
213#endif // wxUSE_PROTOCOL_HTTP
214 {
215 if (m_protocol)
216 {
217 // Need to safely delete the socket (pending events)
218 m_protocol->Destroy();
219 m_protocol = NULL;
220 }
221 }
222}
223
224void wxURL::Free()
225{
226 CleanData();
227#if wxUSE_PROTOCOL_HTTP
228 if (m_proxy && m_proxy != ms_proxyDefault)
229 delete m_proxy;
230#endif // wxUSE_PROTOCOL_HTTP
231#if wxUSE_URL_NATIVE
232 delete m_nativeImp;
233#endif
234}
235
236wxURL::~wxURL()
237{
238 Free();
239}
240
241// --------------------------------------------------------------
242// FetchProtocol
243// --------------------------------------------------------------
244
245bool wxURL::FetchProtocol()
246{
247 wxProtoInfo *info = ms_protocols;
248
249 while (info)
250 {
251 if (m_scheme == info->m_protoname)
252 {
253 if ( m_port.empty() )
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;
260 }
261 return false;
262}
263
264// --------------------------------------------------------------
265// GetInputStream
266// --------------------------------------------------------------
267
268wxInputStream *wxURL::GetInputStream()
269{
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)
282 m_protocol->SetUser(Unescape(m_userinfo));
283 else
284 {
285 m_protocol->SetUser(Unescape(m_userinfo(0, dwPasswordPos)));
286 m_protocol->SetPassword(Unescape(m_userinfo(dwPasswordPos+1, m_userinfo.length() + 1)));
287 }
288 }
289
290#if wxUSE_URL_NATIVE
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
301#endif // wxUSE_URL_NATIVE
302
303#if wxUSE_SOCKETS
304 wxIPV4address addr;
305
306 // m_protoinfo is NULL when we use a proxy
307 if (
308#if wxUSE_PROTOCOL_HTTP
309 !m_useProxy &&
310#endif // wxUSE_PROTOCOL_HTTP
311 m_protoinfo->m_needhost )
312 {
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 }
326 }
327#endif // wxUSE_SOCKETS
328
329 wxString fullPath;
330
331#if wxUSE_PROTOCOL_HTTP
332 // When we use a proxy, we have to pass the whole URL to it.
333 if (m_useProxy)
334 fullPath += m_url;
335#endif // wxUSE_PROTOCOL_HTTP
336
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)
351 {
352 m_error = wxURL_PROTOERR;
353 return NULL;
354 }
355
356 return the_i_stream;
357}
358
359#if wxUSE_PROTOCOL_HTTP
360void wxURL::SetDefaultProxy(const wxString& url_proxy)
361{
362 if ( !url_proxy )
363 {
364 if ( ms_proxyDefault )
365 {
366 ms_proxyDefault->Close();
367 wxDELETE(ms_proxyDefault);
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),
378 port = tmp_str(pos+1, tmp_str.length()-pos);
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 }
393}
394
395void wxURL::SetProxy(const wxString& url_proxy)
396{
397 if ( !url_proxy )
398 {
399 if ( m_proxy && m_proxy != ms_proxyDefault )
400 {
401 m_proxy->Close();
402 delete m_proxy;
403 }
404
405 m_useProxy = false;
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.
417 if (pos == wxNOT_FOUND)
418 return;
419
420 hostname = tmp_str(0, pos);
421 port = tmp_str(pos+1, tmp_str.length()-pos);
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();
430 m_proxy->Connect(addr, true); // Watcom needs the 2nd arg for some reason
431
432 CleanData();
433 // Reparse url.
434 m_useProxy = true;
435 ParseURL();
436 }
437}
438#endif // wxUSE_PROTOCOL_HTTP
439
440// ----------------------------------------------------------------------
441// wxURLModule
442//
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:
451 wxURLModule();
452
453 virtual bool OnInit();
454 virtual void OnExit();
455
456private:
457 DECLARE_DYNAMIC_CLASS(wxURLModule)
458};
459
460IMPLEMENT_DYNAMIC_CLASS(wxURLModule, wxModule)
461
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)
466 AddDependency(wxClassInfo::FindClass(wxT("wxSocketModule")));
467}
468
469bool wxURLModule::OnInit()
470{
471#if wxUSE_PROTOCOL_HTTP
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)
476
477 if ( wxGetenv(wxT("HTTP_PROXY")) )
478 {
479 wxURL::ms_useDefaultProxy = true;
480 }
481#endif // wxUSE_PROTOCOL_HTTP
482 return true;
483}
484
485void wxURLModule::OnExit()
486{
487#if wxUSE_PROTOCOL_HTTP
488 wxDELETE(wxURL::ms_proxyDefault);
489#endif // wxUSE_PROTOCOL_HTTP
490}
491
492#endif // wxUSE_SOCKETS
493
494
495#endif // wxUSE_URL