aboutsummaryrefslogtreecommitdiff
path: root/src/url.cpp
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2009-02-08 00:44:10 +0000
committerMike Buland <eichlan@xagasoft.com>2009-02-08 00:44:10 +0000
commit366a8063730aa7ae696bcb9cf56eafd13d43dfc0 (patch)
tree42e3597edfde0c183506ad0d452f045cb7726137 /src/url.cpp
parent4f59dec6bad120b72f1bc075715d79bfbe881f7e (diff)
downloadlibbu++-366a8063730aa7ae696bcb9cf56eafd13d43dfc0.tar.gz
libbu++-366a8063730aa7ae696bcb9cf56eafd13d43dfc0.tar.bz2
libbu++-366a8063730aa7ae696bcb9cf56eafd13d43dfc0.tar.xz
libbu++-366a8063730aa7ae696bcb9cf56eafd13d43dfc0.zip
So many updates. I recommend using the new FString iterators instead of direct
indexing. It is now many times faster, and requires less overhead. Also, more stuff iterator related in every class. More on that later.
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