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