diff options
Diffstat (limited to 'src/unstable/url.cpp')
-rw-r--r-- | src/unstable/url.cpp | 285 |
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 | |||
15 | char Bu::Url::hexcode[] = { | ||
16 | '0', '1', '2', '3', '4', '5', '6', '7', | ||
17 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' | ||
18 | }; | ||
19 | |||
20 | Bu::Url::Url() | ||
21 | { | ||
22 | } | ||
23 | |||
24 | Bu::Url::Url( const Bu::String &sUrl ) | ||
25 | { | ||
26 | parseUrl( sUrl ); | ||
27 | } | ||
28 | |||
29 | Bu::Url::~Url() | ||
30 | { | ||
31 | } | ||
32 | |||
33 | void 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 | |||
44 | Bu::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 | |||
70 | Bu::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 | |||
99 | void 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 | |||
109 | void 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 | |||
124 | void 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 | |||
144 | void 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 | |||
164 | void Bu::Url::parsePath( const Bu::String &sPath ) | ||
165 | { | ||
166 | Bu::String::const_iterator i = sPath.begin(); | ||
167 | parsePath( i ); | ||
168 | } | ||
169 | |||
170 | void 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 | |||
188 | void Bu::Url::parseParams( const Bu::String &sQuery ) | ||
189 | { | ||
190 | Bu::String::const_iterator i = sQuery.begin(); | ||
191 | parseParams( i ); | ||
192 | } | ||
193 | |||
194 | void 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 | |||
242 | void Bu::Url::addParam( const Bu::String &n, const Bu::String &v ) | ||
243 | { | ||
244 | lParam.append( Param( n, v ) ); | ||
245 | } | ||
246 | |||
247 | void Bu::Url::clear() | ||
248 | { | ||
249 | sProtocol.clear(); | ||
250 | sUser.clear(); | ||
251 | sPass.clear(); | ||
252 | sHost.clear(); | ||
253 | sPath.clear(); | ||
254 | iPort.clear(); | ||
255 | } | ||
256 | |||
257 | Bu::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 | |||
280 | Bu::String Bu::Url::getUrl() const | ||
281 | { | ||
282 | Bu::String sBuf = sProtocol + "://" + sHost + getFullPath(); | ||
283 | return sBuf; | ||
284 | } | ||
285 | |||