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