]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/url.cpp
fixed wxXmlDocument::Save() to interpret the indentstep argument correctly
[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// RCS-ID: $Id$
8// Copyright: (c) 1997, 1998 Guilhem Lavaux
9// Licence: wxWindows licence
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
20
21#include "wx/url.h"
22
23#ifndef WX_PRECOMP
24 #include "wx/list.h"
25 #include "wx/string.h"
26 #include "wx/utils.h"
27 #include "wx/module.h"
28#endif
29
30#include <string.h>
31#include <ctype.h>
32
33IMPLEMENT_CLASS(wxURL, wxURI)
34
35// Protocols list
36wxProtoInfo *wxURL::ms_protocols = NULL;
37
38// Enforce linking of protocol classes:
39USE_PROTOCOL(wxFileProto)
40
41#if wxUSE_PROTOCOL_HTTP
42USE_PROTOCOL(wxHTTP)
43
44 wxHTTP *wxURL::ms_proxyDefault = NULL;
45 bool wxURL::ms_useDefaultProxy = false;
46#endif
47
48#if wxUSE_PROTOCOL_FTP
49USE_PROTOCOL(wxFTP)
50#endif
51
52// --------------------------------------------------------------
53//
54// wxURL
55//
56// --------------------------------------------------------------
57
58// --------------------------------------------------------------
59// Construction
60// --------------------------------------------------------------
61
62wxURL::wxURL(const wxString& url) : wxURI(url)
63{
64 Init(url);
65 ParseURL();
66}
67
68wxURL::wxURL(const wxURI& url) : wxURI(url)
69{
70 Init(url.BuildURI());
71 ParseURL();
72}
73
74void wxURL::Init(const wxString& url)
75{
76 m_protocol = NULL;
77 m_error = wxURL_NOERR;
78 m_url = url;
79#if wxUSE_URL_NATIVE
80 m_nativeImp = CreateNativeImpObject();
81#endif
82
83#if wxUSE_PROTOCOL_HTTP
84 if ( ms_useDefaultProxy && !ms_proxyDefault )
85 {
86 SetDefaultProxy( wxGetenv(wxT("HTTP_PROXY")) );
87
88 if ( !ms_proxyDefault )
89 {
90 // don't try again
91 ms_useDefaultProxy = false;
92 }
93 }
94
95 m_useProxy = ms_proxyDefault != NULL;
96 m_proxy = ms_proxyDefault;
97#endif // wxUSE_PROTOCOL_HTTP
98
99}
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
120// --------------------------------------------------------------
121// ParseURL
122//
123// Builds the URL and takes care of the old protocol stuff
124// --------------------------------------------------------------
125
126bool wxURL::ParseURL()
127{
128 // If the URL was already parsed (m_protocol != NULL), pass this section.
129 if (!m_protocol)
130 {
131 // Clean up
132 CleanData();
133
134 // Make sure we have a protocol/scheme
135 if (!HasScheme())
136 {
137 m_error = wxURL_SNTXERR;
138 return false;
139 }
140
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 }
158 }
159
160#if wxUSE_PROTOCOL_HTTP
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 }
171#endif // wxUSE_PROTOCOL_HTTP
172
173 m_error = wxURL_NOERR;
174 return true;
175}
176
177// --------------------------------------------------------------
178// Destruction/Cleanup
179// --------------------------------------------------------------
180
181void wxURL::CleanData()
182{
183#if wxUSE_PROTOCOL_HTTP
184 if (!m_useProxy)
185#endif // wxUSE_PROTOCOL_HTTP
186 if (m_protocol)
187 // Need to safely delete the socket (pending events)
188 m_protocol->Destroy();
189}
190
191wxURL::~wxURL()
192{
193 CleanData();
194#if wxUSE_PROTOCOL_HTTP
195 if (m_proxy && m_proxy != ms_proxyDefault)
196 delete m_proxy;
197#endif // wxUSE_PROTOCOL_HTTP
198#if wxUSE_URL_NATIVE
199 delete m_nativeImp;
200#endif
201}
202
203// --------------------------------------------------------------
204// FetchProtocol
205// --------------------------------------------------------------
206
207bool wxURL::FetchProtocol()
208{
209 wxProtoInfo *info = ms_protocols;
210
211 while (info)
212 {
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;
222 }
223 return false;
224}
225
226// --------------------------------------------------------------
227// GetInputStream
228// --------------------------------------------------------------
229
230wxInputStream *wxURL::GetInputStream()
231{
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)
244 m_protocol->SetUser(Unescape(m_userinfo));
245 else
246 {
247 m_protocol->SetUser(Unescape(m_userinfo(0, dwPasswordPos)));
248 m_protocol->SetPassword(Unescape(m_userinfo(dwPasswordPos+1, m_userinfo.length() + 1)));
249 }
250 }
251
252#if wxUSE_URL_NATIVE
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
263#endif // wxUSE_URL_NATIVE
264
265#if wxUSE_SOCKETS
266 wxIPV4address addr;
267
268 // m_protoinfo is NULL when we use a proxy
269 if (
270#if wxUSE_PROTOCOL_HTTP
271 !m_useProxy &&
272#endif // wxUSE_PROTOCOL_HTTP
273 m_protoinfo->m_needhost )
274 {
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 }
288 }
289#endif // wxUSE_SOCKETS
290
291 wxString fullPath;
292
293#if wxUSE_PROTOCOL_HTTP
294 // When we use a proxy, we have to pass the whole URL to it.
295 if (m_useProxy)
296 fullPath += m_url;
297#endif // wxUSE_PROTOCOL_HTTP
298
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)
313 {
314 m_error = wxURL_PROTOERR;
315 return NULL;
316 }
317
318 return the_i_stream;
319}
320
321#if wxUSE_PROTOCOL_HTTP
322void wxURL::SetDefaultProxy(const wxString& url_proxy)
323{
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),
341 port = tmp_str(pos+1, tmp_str.length()-pos);
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 }
356}
357
358void wxURL::SetProxy(const wxString& url_proxy)
359{
360 if ( !url_proxy )
361 {
362 if ( m_proxy && m_proxy != ms_proxyDefault )
363 {
364 m_proxy->Close();
365 delete m_proxy;
366 }
367
368 m_useProxy = false;
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.
380 if (pos == wxNOT_FOUND)
381 return;
382
383 hostname = tmp_str(0, pos);
384 port = tmp_str(pos+1, tmp_str.length()-pos);
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();
393 m_proxy->Connect(addr, true); // Watcom needs the 2nd arg for some reason
394
395 CleanData();
396 // Reparse url.
397 m_useProxy = true;
398 ParseURL();
399 }
400}
401#endif // wxUSE_PROTOCOL_HTTP
402
403// ----------------------------------------------------------------------
404// wxURLModule
405//
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:
414 wxURLModule();
415
416 virtual bool OnInit();
417 virtual void OnExit();
418
419private:
420 DECLARE_DYNAMIC_CLASS(wxURLModule)
421};
422
423IMPLEMENT_DYNAMIC_CLASS(wxURLModule, wxModule)
424
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)
429 AddDependency(wxClassInfo::FindClass(wxT("wxSocketModule")));
430}
431
432bool wxURLModule::OnInit()
433{
434#if wxUSE_PROTOCOL_HTTP
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)
439
440 if ( wxGetenv(wxT("HTTP_PROXY")) )
441 {
442 wxURL::ms_useDefaultProxy = true;
443 }
444#endif // wxUSE_PROTOCOL_HTTP
445 return true;
446}
447
448void wxURLModule::OnExit()
449{
450#if wxUSE_PROTOCOL_HTTP
451 delete wxURL::ms_proxyDefault;
452 wxURL::ms_proxyDefault = NULL;
453#endif // wxUSE_PROTOCOL_HTTP
454}
455
456#endif // wxUSE_SOCKETS
457
458
459#endif // wxUSE_URL