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