]>
Commit | Line | Data |
---|---|---|
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 |
34 | IMPLEMENT_CLASS(wxProtoInfo, wxObject) | |
35 | IMPLEMENT_CLASS(wxURL, wxObject) | |
36 | #endif | |
37 | ||
38 | // Protocols list | |
39 | wxProtoInfo *wxURL::g_protocols = NULL; | |
f61815af | 40 | wxHTTP *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 | |
50 | wxURL::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 | ||
60 | bool 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 | ||
118 | void wxURL::CleanData() | |
119 | { | |
f61815af | 120 | if (!m_useProxy) |
f4ada568 GL |
121 | delete m_protocol; |
122 | } | |
123 | ||
124 | wxURL::~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 |
135 | bool 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 | ||
151 | bool 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 | ||
203 | bool 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 | ||
212 | bool 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 |
234 | wxInputStream *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 | ||
280 | void 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 | ||
311 | void 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 |
351 | wxString 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 |