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