]> git.saurik.com Git - wxWidgets.git/blame - src/common/url.cpp
serbase.cpp added to the list of files
[wxWidgets.git] / src / common / url.cpp
CommitLineData
f4ada568
GL
1/////////////////////////////////////////////////////////////////////////////
2// Name: 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 license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "url.h"
14#endif
fcc6dddd
JS
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
f4ada568
GL
23#include <string.h>
24#include <ctype.h>
25
f4ada568
GL
26#include <wx/string.h>
27#include <wx/list.h>
28#include <wx/utils.h>
f61815af 29#include <wx/url.h>
f4ada568 30
f4ada568
GL
31#if !USE_SHARED_LIBRARY
32IMPLEMENT_CLASS(wxProtoInfo, wxObject)
33IMPLEMENT_CLASS(wxURL, wxObject)
34#endif
35
36// Protocols list
37wxProtoInfo *wxURL::g_protocols = NULL;
8a4df159
RR
38
39#if wxUSE_SOCKETS
f61815af 40wxHTTP *wxURL::g_proxy = NULL;
8a4df159 41#endif
f4ada568 42
fae05df5
GL
43// --------------------------------------------------------------
44// wxURL
45// --------------------------------------------------------------
f4ada568 46
fae05df5
GL
47// --------------------------------------------------------------
48// --------- wxURL CONSTRUCTOR DESTRUCTOR -----------------------
49// --------------------------------------------------------------
f4ada568
GL
50
51wxURL::wxURL(const wxString& url)
52{
53 m_protocol = NULL;
f4ada568 54 m_error = wxURL_NOERR;
f61815af 55 m_url = url;
8a4df159 56#if wxUSE_SOCKETS
f61815af
GL
57 m_useProxy = (g_proxy != NULL);
58 m_proxy = g_proxy;
8a4df159 59#endif
41895a05 60 ParseURL();
f4ada568
GL
61}
62
63bool wxURL::ParseURL()
64{
65 wxString last_url = m_url;
66
f61815af
GL
67 // If the URL was already parsed (so m_protocol != NULL), we pass this section.
68 if (!m_protocol) {
f4ada568 69
f61815af
GL
70 // Clean up
71 CleanData();
f4ada568 72
f61815af
GL
73 // Extract protocol name
74 if (!PrepProto(last_url)) {
f4ada568
GL
75 m_error = wxURL_SNTXERR;
76 return FALSE;
77 }
f61815af
GL
78
79 // Find and create the protocol object
80 if (!FetchProtocol()) {
81 m_error = wxURL_NOPROTO;
82 return FALSE;
83 }
84
85 // Do we need a host name ?
86 if (m_protoinfo->m_needhost) {
87 // Extract it
88 if (!PrepHost(last_url)) {
89 m_error = wxURL_SNTXERR;
90 return FALSE;
91 }
92 }
93
94 // Extract full path
95 if (!PrepPath(last_url)) {
96 m_error = wxURL_NOPATH;
97 return FALSE;
98 }
f4ada568 99 }
f61815af 100 // URL parse finished.
f4ada568 101
8a4df159 102#if wxUSE_SOCKETS
f61815af
GL
103 if (m_useProxy) {
104 // We destroy the newly created protocol.
105 CleanData();
106
107 // Third, we rebuild the URL.
108 m_url = m_protoname + _T(":");
109 if (m_protoinfo->m_needhost)
110 m_url = m_url + _T("//") + m_hostname;
111
112 m_url += m_path;
113
114 // We initialize specific variables.
115 m_protocol = m_proxy; // FIXME: we should clone the protocol
f4ada568 116 }
8a4df159 117#endif
f4ada568
GL
118
119 m_error = wxURL_NOERR;
120 return TRUE;
121}
122
123void wxURL::CleanData()
124{
8a4df159 125#if wxUSE_SOCKETS
f61815af 126 if (!m_useProxy)
8a4df159 127#endif
f4ada568
GL
128 delete m_protocol;
129}
130
131wxURL::~wxURL()
132{
133 CleanData();
8a4df159 134#if wxUSE_SOCKETS
f61815af
GL
135 if (m_proxy && m_proxy != g_proxy)
136 delete m_proxy;
8a4df159 137#endif
f4ada568
GL
138}
139
fae05df5
GL
140// --------------------------------------------------------------
141// --------- wxURL urls decoders --------------------------------
142// --------------------------------------------------------------
143
f4ada568
GL
144bool wxURL::PrepProto(wxString& url)
145{
146 int pos;
147
148 // Find end
f61815af 149 pos = url.Find(_T(':'));
f4ada568
GL
150 if (pos == -1)
151 return FALSE;
152
153 m_protoname = url(0, pos);
154
155 url = url(pos+1, url.Length());
156
157 return TRUE;
158}
159
160bool wxURL::PrepHost(wxString& url)
161{
856d2e52 162 wxString temp_url;
f4ada568
GL
163 int pos, pos2;
164
fcc6dddd 165 if ((url.GetChar(0) != '/') || (url.GetChar(1) != '/'))
f4ada568
GL
166 return FALSE;
167
168 url = url(2, url.Length());
169
f61815af 170 pos = url.Find(_T('/'));
f4ada568 171 if (pos == -1)
b7db6f0b 172 pos = url.Length();
f4ada568 173
856d2e52
GL
174 if (pos == 0)
175 return FALSE;
176
177 temp_url = url(0, pos);
f61815af 178 url = url(url.Find(_T('/')), url.Length());
856d2e52
GL
179
180 // Retrieve service number
f61815af 181 pos2 = temp_url.Find(_T(':'), TRUE);
f4ada568 182 if (pos2 != -1 && pos2 < pos) {
375abe3d 183 m_servname = temp_url(pos2+1, pos);
f4ada568
GL
184 if (!m_servname.IsNumber())
185 return FALSE;
856d2e52 186 temp_url = temp_url(0, pos2);
f4ada568
GL
187 }
188
856d2e52 189 // Retrieve user and password.
f61815af 190 pos2 = temp_url.Find(_T('@'));
856d2e52
GL
191 // Even if pos2 equals -1, this code is right.
192 m_hostname = temp_url(pos2+1, temp_url.Length());
f4ada568 193
f61815af
GL
194 m_user = _T("");
195 m_password = _T("");
856d2e52
GL
196
197 if (pos2 == -1)
198 return TRUE;
199
200 temp_url = temp_url(0, pos2);
f61815af 201 pos2 = temp_url.Find(_T(':'));
856d2e52
GL
202
203 if (pos2 == -1)
204 return FALSE;
205
206 m_user = temp_url(0, pos2);
207 m_password = temp_url(pos2+1, url.Length());
f4ada568
GL
208
209 return TRUE;
210}
211
212bool wxURL::PrepPath(wxString& url)
213{
214 if (url.Length() != 0)
f61815af 215 m_path = ConvertToValidURI(url);
f4ada568 216 else
f61815af 217 m_path = _T("/");
f4ada568
GL
218 return TRUE;
219}
220
221bool wxURL::FetchProtocol()
222{
223 wxProtoInfo *info = g_protocols;
224
225 while (info) {
226 if (m_protoname == info->m_protoname) {
227 if (m_servname.IsNull())
228 m_servname = info->m_servname;
229
230 m_protoinfo = info;
231 m_protocol = (wxProtocol *)m_protoinfo->m_cinfo->CreateObject();
f4ada568
GL
232 return TRUE;
233 }
234 info = info->next;
235 }
236 return FALSE;
237}
238
fae05df5
GL
239// --------------------------------------------------------------
240// --------- wxURL get ------------------------------------------
241// --------------------------------------------------------------
242
f4ada568
GL
243wxInputStream *wxURL::GetInputStream(void)
244{
f4ada568
GL
245 wxInputStream *the_i_stream = NULL;
246
f4ada568
GL
247 if (!m_protocol) {
248 m_error = wxURL_NOPROTO;
249 return NULL;
250 }
251
252 m_error = wxURL_NOERR;
00421206 253 if (m_user != _T("")) {
856d2e52
GL
254 m_protocol->SetUser(m_user);
255 m_protocol->SetPassword(m_password);
256 }
257
8a4df159 258#if wxUSE_SOCKETS
19e0e04b
RD
259 wxIPV4address addr;
260
f61815af
GL
261 // m_protoinfo is NULL when we use a proxy
262 if (!m_useProxy && m_protoinfo->m_needhost) {
f4ada568
GL
263 if (!addr.Hostname(m_hostname)) {
264 m_error = wxURL_NOHOST;
265 return NULL;
266 }
267
268 addr.Service(m_servname);
269
8a2c6ef8
JS
270 if (!m_protocol->Connect(addr, TRUE)) // Watcom needs the 2nd arg for some reason
271 {
f4ada568
GL
272 m_error = wxURL_CONNERR;
273 return NULL;
274 }
275 }
8a4df159 276#endif
f4ada568 277
f61815af
GL
278 // When we use a proxy, we have to pass the whole URL to it.
279 if (m_useProxy)
280 the_i_stream = m_protocol->GetInputStream(m_url);
281 else
282 the_i_stream = m_protocol->GetInputStream(m_path);
283
f4ada568
GL
284 if (!the_i_stream) {
285 m_error = wxURL_PROTOERR;
286 return NULL;
287 }
288
289 return the_i_stream;
290}
291
8a4df159 292#if wxUSE_SOCKETS
f4ada568
GL
293void wxURL::SetDefaultProxy(const wxString& url_proxy)
294{
f61815af
GL
295 if (url_proxy.IsNull()) {
296 g_proxy->Close();
297 delete g_proxy;
298 g_proxy = NULL;
f4ada568 299 return;
f61815af 300 }
f4ada568
GL
301
302 wxString tmp_str = url_proxy;
f61815af
GL
303 int pos = tmp_str.Find(_T(':'));
304 if (pos == -1)
305 return;
306
f4ada568 307 wxString hostname = tmp_str(0, pos),
f61815af 308 port = tmp_str(pos+1, tmp_str.Length()-pos);
f4ada568
GL
309 wxIPV4address addr;
310
f61815af
GL
311 if (!addr.Hostname(hostname))
312 return;
313 if (!addr.Service(port))
314 return;
315
316 if (g_proxy)
317 // Finally, when all is right, we connect the new proxy.
318 g_proxy->Close();
319 else
320 g_proxy = new wxHTTP();
8a2c6ef8 321 g_proxy->Connect(addr, TRUE); // Watcom needs the 2nd arg for some reason
f4ada568
GL
322}
323
324void wxURL::SetProxy(const wxString& url_proxy)
325{
326 if (url_proxy.IsNull()) {
f61815af
GL
327 if (m_proxy) {
328 m_proxy->Close();
329 delete m_proxy;
330 }
331 m_useProxy = FALSE;
f4ada568
GL
332 return;
333 }
334
f4ada568
GL
335 wxString tmp_str;
336 wxString hostname, port;
337 int pos;
338 wxIPV4address addr;
339
340 tmp_str = url_proxy;
f61815af
GL
341 pos = tmp_str.Find(_T(':'));
342 // This is an invalid proxy name.
343 if (pos == -1)
344 return;
345
f4ada568
GL
346 hostname = tmp_str(0, pos);
347 port = tmp_str(pos, tmp_str.Length()-pos);
348
349 addr.Hostname(hostname);
350 addr.Service(port);
351
f61815af
GL
352 // Finally, create the whole stuff.
353 if (m_proxy && m_proxy != g_proxy)
354 delete m_proxy;
355 m_proxy = new wxHTTP();
356 m_proxy->Connect(addr, TRUE); // Watcom needs the 2nd arg for some reason
f4ada568 357
f61815af
GL
358 CleanData();
359 // Reparse url.
360 m_useProxy = TRUE;
361 ParseURL();
f4ada568 362}
8a4df159 363#endif
35a4dab7 364
14906731
GL
365wxString wxURL::ConvertToValidURI(const wxString& uri)
366{
fae05df5
GL
367 wxString out_str;
368 wxString hexa_code;
369 size_t i;
370
371 for (i=0;i<uri.Len();i++) {
372 wxChar c = uri.GetChar(i);
373
5a96d2f4
GL
374 if (c == _T(' '))
375 out_str += _T('+');
376 else {
19e0e04b 377 if (!isalpha(c) && c != _T('.') && c != _T('+') && c != _T('/')) {
5a96d2f4
GL
378 hexa_code.Printf(_T("%%%02X"), c);
379 out_str += hexa_code;
380 } else
381 out_str += c;
382 }
fae05df5 383 }
19e0e04b 384
fae05df5 385 return out_str;
14906731
GL
386}
387
aa6d9706
GL
388wxString wxURL::ConvertFromURI(const wxString& uri)
389{
390 int code;
391 int i;
392 wxString new_uri;
393
394 new_uri.Empty();
395
396 i = 0;
397 while (i<uri.Len()) {
398 if (uri[i] == _T('%')) {
399 i++;
400 if (uri[i] >= _T('A') && uri[i] <= _T('F'))
401 code = (uri[i] - _T('A') + 10) * 16;
402 else
403 code = (uri[i] - _T('0')) * 16;
404 i++;
405 if (uri[i] >= _T('A') && uri[i] <= _T('F'))
406 code += (uri[i] - _T('A')) + 10;
407 else
408 code += (uri[i] - _T('0'));
409 i++;
410 new_uri += (wxChar)code;
411 continue;
412 }
413 new_uri += uri[i];
414 i++;
415 }
416 return new_uri;
417}