* Bug fix in wxFilter*Stream
[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 }
68
69 bool wxURL::ParseURL()
70 {
71 wxString last_url = m_url;
72
73 // Clean up
74 CleanData();
75
76 // Extract protocol name
77 if (!PrepProto(last_url)) {
78 m_error = wxURL_SNTXERR;
79 return FALSE;
80 }
81
82 // Find and create the protocol object
83 if (!FetchProtocol()) {
84 m_error = wxURL_NOPROTO;
85 return FALSE;
86 }
87
88 // Do we need a host name ?
89 if (m_protoinfo->m_needhost) {
90 // Extract it
91 if (!PrepHost(last_url)) {
92 m_error = wxURL_SNTXERR;
93 return FALSE;
94 }
95 }
96
97 // Extract full path
98 if (!PrepPath(last_url)) {
99 m_error = wxURL_NOPATH;
100 return FALSE;
101 }
102
103 m_error = wxURL_NOERR;
104 return TRUE;
105 }
106
107 void wxURL::CleanData()
108 {
109 if (m_protoname != "proxy")
110 delete m_protocol;
111 }
112
113 wxURL::~wxURL()
114 {
115 CleanData();
116 }
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 int pos, pos2;
142
143 if ((url.GetChar(0) != '/') || (url.GetChar(1) != '/'))
144 return FALSE;
145
146 url = url(2, url.Length());
147
148 pos = url.Find('/');
149 if (pos == -1)
150 pos = url.Length();
151
152 pos2 = url.Find(':');
153 if (pos2 != -1 && pos2 < pos) {
154 m_servname = url(pos2, pos);
155 if (!m_servname.IsNumber())
156 return FALSE;
157 pos2 = pos;
158 }
159
160 m_hostname = url(0, pos);
161
162 url = url(url.Find('/'), url.Length());
163
164 return TRUE;
165 }
166
167 bool wxURL::PrepPath(wxString& url)
168 {
169 if (url.Length() != 0)
170 m_path = url;
171 else
172 m_path = "/";
173 return TRUE;
174 }
175
176 bool wxURL::FetchProtocol()
177 {
178 wxProtoInfo *info = g_protocols;
179
180 while (info) {
181 if (m_protoname == info->m_protoname) {
182 if (m_servname.IsNull())
183 m_servname = info->m_servname;
184
185 m_protoinfo = info;
186 m_protocol = (wxProtocol *)m_protoinfo->m_cinfo->CreateObject();
187 wxSocketHandler::Master().Register(m_protocol);
188 return TRUE;
189 }
190 info = info->next;
191 }
192 return FALSE;
193 }
194
195 /*
196 * --------------------------------------------------------------
197 * --------- wxURL get ------------------------------------------
198 * --------------------------------------------------------------
199 */
200 wxInputStream *wxURL::GetInputStream(void)
201 {
202 wxIPV4address addr;
203 wxInputStream *the_i_stream = NULL;
204
205 if (!m_protocol)
206 if (!ParseURL())
207 return NULL;
208
209 if (!m_protocol) {
210 m_error = wxURL_NOPROTO;
211 return NULL;
212 }
213
214 m_error = wxURL_NOERR;
215 if (m_protoinfo->m_needhost) {
216 if (!addr.Hostname(m_hostname)) {
217 m_error = wxURL_NOHOST;
218 return NULL;
219 }
220
221 addr.Service(m_servname);
222
223 if (!m_protocol->Connect(addr)) {
224 m_error = wxURL_CONNERR;
225 return NULL;
226 }
227 }
228
229 the_i_stream = m_protocol->GetInputStream(m_path);
230 if (!the_i_stream) {
231 m_error = wxURL_PROTOERR;
232 return NULL;
233 }
234
235 return the_i_stream;
236 }
237
238 void wxURL::SetDefaultProxy(const wxString& url_proxy)
239 {
240 g_proxy.Close();
241
242 if (url_proxy.IsNull())
243 return;
244
245 wxString tmp_str = url_proxy;
246 int pos = tmp_str.Find(':');
247 wxString hostname = tmp_str(0, pos),
248 port = tmp_str(pos, tmp_str.Length()-pos);
249 wxIPV4address addr;
250
251 addr.Hostname(hostname);
252 addr.Service(port);
253
254 g_proxy.Connect(addr);
255 }
256
257 void wxURL::SetProxy(const wxString& url_proxy)
258 {
259 if (url_proxy.IsNull()) {
260 m_proxy.Close();
261 return;
262 }
263
264 CleanData();
265
266 wxString tmp_str;
267 wxString hostname, port;
268 int pos;
269 wxIPV4address addr;
270
271 tmp_str = url_proxy;
272 pos = tmp_str.Find(':');
273 hostname = tmp_str(0, pos);
274 port = tmp_str(pos, tmp_str.Length()-pos);
275
276 addr.Hostname(hostname);
277 addr.Service(port);
278
279 m_proxy.Connect(addr);
280
281 m_protocol = &m_proxy;
282 m_protoname = "proxy";
283 m_path = url_proxy;
284 }