aboutsummaryrefslogtreecommitdiff
path: root/src/unstable/url.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/unstable/url.cpp')
-rw-r--r--src/unstable/url.cpp285
1 files changed, 285 insertions, 0 deletions
diff --git a/src/unstable/url.cpp b/src/unstable/url.cpp
new file mode 100644
index 0000000..7b4a48e
--- /dev/null
+++ b/src/unstable/url.cpp
@@ -0,0 +1,285 @@
1/*
2 * Copyright (C) 2007-2011 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/url.h"
9#ifndef WIN32
10# include <netdb.h>
11# include <netinet/in.h>
12#endif
13#include <stdlib.h>
14
15char Bu::Url::hexcode[] = {
16 '0', '1', '2', '3', '4', '5', '6', '7',
17 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
18};
19
20Bu::Url::Url()
21{
22}
23
24Bu::Url::Url( const Bu::String &sUrl )
25{
26 parseUrl( sUrl );
27}
28
29Bu::Url::~Url()
30{
31}
32
33void Bu::Url::parseUrl( const Bu::String &sUrl )
34{
35 clear();
36
37 Bu::String::const_iterator i = sUrl.begin();
38 parseProtocol( i );
39 parseUserPass( i );
40 parseHost( i );
41 parsePath( i );
42}
43
44Bu::String Bu::Url::decode( const Bu::String &sStr )
45{
46 Bu::String sRet;
47 char buf[3] = {0, 0, 0};
48 for( Bu::String::const_iterator i = sStr.begin(); i; i++ )
49 {
50 if( *i == '+' )
51 {
52 sRet += ' ';
53 }
54 else if( *i == '%' )
55 {
56 i++;
57 buf[0] = *i;
58 i++;
59 buf[1] = *i;
60 sRet += (char)((unsigned char)strtol( buf, NULL, 16 ));
61 }
62 else
63 {
64 sRet += *i;
65 }
66 }
67 return sRet;
68}
69
70Bu::String Bu::Url::encode( const Bu::String &sStr )
71{
72 Bu::String sRet;
73 for( Bu::String::const_iterator i = sStr.begin(); i; i++ )
74 {
75 if( *i == ' ' )
76 {
77 sRet += '+';
78 }
79 else if(
80 (*i >= 'A' && *i <= 'Z') ||
81 (*i >= 'a' && *i <= 'z') ||
82 (*i >= '0' && *i <= '9') ||
83 (*i == '-' || *i == '_' || *i == '.' || *i == '~')
84 )
85 {
86 sRet += *i;
87 }
88 else
89 {
90 unsigned char b = *i;
91 sRet += '%';
92 sRet += hexcode[(b>>4)&0xF];
93 sRet += hexcode[b&0xF];
94 }
95 }
96 return sRet;
97}
98
99void Bu::Url::parseProtocol( Bu::String::const_iterator &i )
100{
101 Bu::String::const_iterator s = i.find("://", 3);
102 if( !s )
103 throw Bu::ExceptionBase("No :// in url");
104 Bu::String sTmp( i, s );
105 setProtocol( sTmp );
106 i = s + 3;
107}
108
109void Bu::Url::setProtocol( const Bu::String &sNewProto, bool bAutoSetPort )
110{
111 sProtocol = sNewProto;
112#ifndef WIN32
113 if( bAutoSetPort )
114 {
115 struct servent *se = getservbyname( sProtocol.getStr(), "tcp" );
116 if( se )
117 {
118 iPort = ntohs( se->s_port );
119 }
120 }
121#endif
122}
123
124void Bu::Url::parseUserPass( Bu::String::const_iterator &i )
125{
126 Bu::String::const_iterator s = i.find('@');
127 if( !s )
128 return;
129
130 Bu::String::const_iterator p = i.find(':');
131 if( p )
132 {
133 sUser.set( i, p );
134 sPass.set( p+1, s );
135 }
136 else
137 {
138 sUser.set( i, s );
139 }
140
141 i = s + 1;
142}
143
144void Bu::Url::parseHost( Bu::String::const_iterator &i )
145{
146 Bu::String::const_iterator s = i;
147 for( ; s && *s != '/'; s++ )
148 {
149 if( *s == ':' )
150 {
151 sHost.set( i, s );
152 i = s + 1;
153 s = i.find('/');
154 Bu::String sPort( i, s );
155 iPort = strtol( sPort.getStr(), NULL, 10 );
156 i = s;
157 return;
158 }
159 }
160 sHost.set( i, s );
161 i = s;
162}
163
164void Bu::Url::parsePath( const Bu::String &sPath )
165{
166 Bu::String::const_iterator i = sPath.begin();
167 parsePath( i );
168}
169
170void Bu::Url::parsePath( Bu::String::const_iterator &i )
171{
172 if( i )
173 {
174 Bu::String::const_iterator s = i.find('?');
175 sPath.set( i, s );
176 i = s + 1;
177 if( s )
178 {
179 parseParams( i );
180 }
181 }
182 else
183 {
184 sPath = "/";
185 }
186}
187
188void Bu::Url::parseParams( const Bu::String &sQuery )
189{
190 Bu::String::const_iterator i = sQuery.begin();
191 parseParams( i );
192}
193
194void Bu::Url::parseParams( Bu::String::const_iterator &i )
195{
196 bool bName = true;
197 Bu::String sName, sValue;
198 for( Bu::String::const_iterator s = i; s; s++ )
199 {
200 if( bName )
201 {
202 if( *s == '&' )
203 {
204 sName.set( i, s );
205 sValue.clear();
206 i = s + 1;
207 addParam( decode( sName ), decode( sValue ) );
208 }
209 else if( *s == '=' )
210 {
211 sName.set( i, s );
212 i = s + 1;
213 bName = false;
214 }
215 }
216 else
217 {
218 if( *s == '&' )
219 {
220 sValue.set( i, s );
221 i = s + 1;
222 bName = true;
223 addParam( decode( sName ), decode( sValue ) );
224 }
225 }
226 }
227 if( i )
228 {
229 if( bName )
230 {
231 sName.set( i );
232 sValue.clear();
233 }
234 else
235 {
236 sValue.set( i );
237 }
238 addParam( decode( sName ), decode( sValue ) );
239 }
240}
241
242void Bu::Url::addParam( const Bu::String &n, const Bu::String &v )
243{
244 lParam.append( Param( n, v ) );
245}
246
247void Bu::Url::clear()
248{
249 sProtocol.clear();
250 sUser.clear();
251 sPass.clear();
252 sHost.clear();
253 sPath.clear();
254 iPort.clear();
255}
256
257Bu::String Bu::Url::getFullPath() const
258{
259 Bu::String sBuf = sPath;
260 if( !lParam.isEmpty() )
261 {
262 for( ParamList::const_iterator i = lParam.begin(); i; i++ )
263 {
264 if( i == lParam.begin() )
265 sBuf += "?";
266 else
267 sBuf += "&";
268
269 sBuf += encode( (*i).sName );
270 if( !(*i).sValue.isEmpty() )
271 {
272 sBuf += "=" + encode( (*i).sValue );
273 }
274 }
275 }
276
277 return sBuf;
278}
279
280Bu::String Bu::Url::getUrl() const
281{
282 Bu::String sBuf = sProtocol + "://" + sHost + getFullPath();
283 return sBuf;
284}
285