* Big memory bug fixed in socket/getline fixed.
[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 #ifndef WX_PRECOMP
24 #endif
25
26 #include <string.h>
27 #include <ctype.h>
28
29 // wxWindows headers
30 #include <wx/string.h>
31 #include <wx/list.h>
32 #include <wx/utils.h>
33
34 // wxSocket header
35 #include "wx/url.h"
36
37 #if !USE_SHARED_LIBRARY
38 IMPLEMENT_CLASS(wxProtoInfo, wxObject)
39 IMPLEMENT_CLASS(wxURL, wxObject)
40 #endif
41
42 // Protocols list
43 wxProtoInfo *wxURL::g_protocols = NULL;
44 wxHTTP *wxURL::g_proxy;
45
46 /////////////////////////////////////////////////////////////////
47 // wxURL ////////////////////////////////////////////////////////
48 /////////////////////////////////////////////////////////////////
49
50 /*
51 * --------------------------------------------------------------
52 * --------- wxURL CONSTRUCTOR DESTRUCTOR -----------------------
53 * --------------------------------------------------------------
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 != "proxy")
111 delete m_protocol;
112 }
113
114 wxURL::~wxURL()
115 {
116 CleanData();
117 }
118
119 /*
120 * --------------------------------------------------------------
121 * --------- wxURL urls decoders --------------------------------
122 * --------------------------------------------------------------
123 */
124 bool wxURL::PrepProto(wxString& url)
125 {
126 int pos;
127
128 // Find end
129 pos = url.Find(':');
130 if (pos == -1)
131 return FALSE;
132
133 m_protoname = url(0, pos);
134
135 url = url(pos+1, url.Length());
136
137 return TRUE;
138 }
139
140 bool wxURL::PrepHost(wxString& url)
141 {
142 wxString temp_url;
143 int pos, pos2;
144
145 if ((url.GetChar(0) != '/') || (url.GetChar(1) != '/'))
146 return FALSE;
147
148 url = url(2, url.Length());
149
150 pos = url.Find('/');
151 if (pos == -1)
152 pos = url.Length();
153
154 if (pos == 0)
155 return FALSE;
156
157 temp_url = url(0, pos);
158 url = url(url.Find('/'), url.Length());
159
160 // Retrieve service number
161 pos2 = temp_url.Find(':', TRUE);
162 if (pos2 != -1 && pos2 < pos) {
163 m_servname = url(pos2, pos);
164 if (!m_servname.IsNumber())
165 return FALSE;
166 pos2 = pos;
167 temp_url = temp_url(0, pos2);
168 }
169
170 // Retrieve user and password.
171 pos2 = temp_url.Find('@');
172 // Even if pos2 equals -1, this code is right.
173 m_hostname = temp_url(pos2+1, temp_url.Length());
174
175 m_user = "";
176 m_password = "";
177
178 if (pos2 == -1)
179 return TRUE;
180
181 temp_url = temp_url(0, pos2);
182 pos2 = temp_url.Find(':');
183
184 if (pos2 == -1)
185 return FALSE;
186
187 m_user = temp_url(0, pos2);
188 m_password = temp_url(pos2+1, url.Length());
189
190 return TRUE;
191 }
192
193 bool wxURL::PrepPath(wxString& url)
194 {
195 if (url.Length() != 0)
196 m_path = url;
197 else
198 m_path = "/";
199 return TRUE;
200 }
201
202 bool wxURL::FetchProtocol()
203 {
204 wxProtoInfo *info = g_protocols;
205
206 while (info) {
207 if (m_protoname == info->m_protoname) {
208 if (m_servname.IsNull())
209 m_servname = info->m_servname;
210
211 m_protoinfo = info;
212 m_protocol = (wxProtocol *)m_protoinfo->m_cinfo->CreateObject();
213 wxSocketHandler::Master().Register(m_protocol);
214 return TRUE;
215 }
216 info = info->next;
217 }
218 return FALSE;
219 }
220
221 /*
222 * --------------------------------------------------------------
223 * --------- wxURL get ------------------------------------------
224 * --------------------------------------------------------------
225 */
226 wxInputStream *wxURL::GetInputStream(void)
227 {
228 wxIPV4address addr;
229 wxInputStream *the_i_stream = NULL;
230
231 if (!m_protocol)
232 if (!ParseURL())
233 return NULL;
234
235 if (!m_protocol) {
236 m_error = wxURL_NOPROTO;
237 return NULL;
238 }
239
240 m_error = wxURL_NOERR;
241 if (m_user != "") {
242 m_protocol->SetUser(m_user);
243 m_protocol->SetPassword(m_password);
244 }
245
246 if (m_protoinfo->m_needhost) {
247 if (!addr.Hostname(m_hostname)) {
248 m_error = wxURL_NOHOST;
249 return NULL;
250 }
251
252 addr.Service(m_servname);
253
254 if (!m_protocol->Connect(addr, TRUE)) // Watcom needs the 2nd arg for some reason
255 {
256 m_error = wxURL_CONNERR;
257 return NULL;
258 }
259 }
260
261 the_i_stream = m_protocol->GetInputStream(m_path);
262 if (!the_i_stream) {
263 m_error = wxURL_PROTOERR;
264 return NULL;
265 }
266
267 return the_i_stream;
268 }
269
270 void wxURL::SetDefaultProxy(const wxString& url_proxy)
271 {
272 g_proxy->Close();
273
274 if (url_proxy.IsNull())
275 return;
276
277 wxString tmp_str = url_proxy;
278 int pos = tmp_str.Find(':');
279 wxString hostname = tmp_str(0, pos),
280 port = tmp_str(pos, tmp_str.Length()-pos);
281 wxIPV4address addr;
282
283 addr.Hostname(hostname);
284 addr.Service(port);
285
286 g_proxy->Connect(addr, TRUE); // Watcom needs the 2nd arg for some reason
287 }
288
289 void wxURL::SetProxy(const wxString& url_proxy)
290 {
291 if (url_proxy.IsNull()) {
292 m_proxy.Close();
293 return;
294 }
295
296 CleanData();
297
298 wxString tmp_str;
299 wxString hostname, port;
300 int pos;
301 wxIPV4address addr;
302
303 tmp_str = url_proxy;
304 pos = tmp_str.Find(':');
305 hostname = tmp_str(0, pos);
306 port = tmp_str(pos, tmp_str.Length()-pos);
307
308 addr.Hostname(hostname);
309 addr.Service(port);
310
311 m_proxy.Connect(addr, TRUE); // Watcom needs the 2nd arg for some reason
312
313 m_protocol = &m_proxy;
314 m_protoname = "proxy";
315 m_path = url_proxy;
316 }