summaryrefslogtreecommitdiff
path: root/src/url.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/url.cpp')
-rw-r--r--src/url.cpp237
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
8char Bu::Url::hexcode[] = {
9 '0', '1', '2', '3', '4', '5', '6', '7',
10 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
11};
12
13Bu::Url::Url()
14{
15}
16
17Bu::Url::Url( const Bu::FString &sUrl )
18{
19 parseUrl( sUrl );
20}
21
22Bu::Url::~Url()
23{
24}
25
26void 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
37Bu::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
63Bu::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
92void 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
102void 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
117void 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
137void 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
157void 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
175void 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
223void Bu::Url::addParam( const Bu::FString &n, const Bu::FString &v )
224{
225 lParam.append( Param( n, v ) );
226}
227
228void Bu::Url::clear()
229{
230 sProtocol.clear();
231 sUser.clear();
232 sPass.clear();
233 sHost.clear();
234 sPath.clear();
235 iPort.clear();
236}
237