DCL 4.0
Loading...
Searching...
No Matches
URI.cpp
Go to the documentation of this file.
1
2#include <ctype.h>
3#include <string.h>
4
5#include <dcl/Object.h>
6
7#if __DCL_HAVE_ALLOC_DEBUG
8#undef __DCL_ALLOC_LEVEL
9#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
10#endif
11
12#include <dcl/Regex.h>
13#include <dcl/Numeric.h>
14#include <dcl/Charset.h>
15
16#include <dcl/URI.h>
17
18#if __DCL_DEBUG
19#undef __THIS_FILE__
20static const char_t* __THIS_FILE__ = __T("dcl/URI.cpp");
21#endif
22
23__DCL_BEGIN_NAMESPACE
24
25static int hextoi(const char* _s)
26{
27 __DCL_ASSERT(_s != NULL);
28
29 __DCL_ASSERT(_s[0] != '\0');
30 int c = _s[0];
31 if (isupper(c))
32 c = tolower(c);
33
34 int r = (('0' <= c && c <= '9') ? c - '0' : c - 'a' + 10) * 16;
35
36 __DCL_ASSERT(_s[1] != '\0');
37 c = _s[1];
38 if (isupper(c))
39 c = tolower(c);
40
41 r += ('0' <= c && c <= '9') ? c - '0' : c - 'a' + 10;
42
43 return r;
44}
45
46ByteString URLDecoder::decode(const char* _begin, const char* _end)
47{
48 ByteStringBuilder r;
49 while (_begin < _end) {
50 if (*_begin == '+')
51 r += ' ';
52 else if (
53 *_begin == '%'
54 && (_begin + 2) < _end
55 && isxdigit(*(_begin +1))
56 && isxdigit(*(_begin + 2))
57 )
58 {
59 r += (char)hextoi(_begin + 1);
60 _begin += 2;
61 }
62 else
63 r += *_begin;
64 _begin++;
65 }
66 return r;
67}
68
69ByteString URLDecoder::decode(const ByteString& _str)
70{
71 return URLDecoder::decode(_str, _str.data() + _str.length());
72}
73
74String URLDecoder::decode(const String& _str)
75{
76 return UTF8Decoder::decode(
78 UTF8Encoder::encode(_str)
79 )
80 );
81}
82
83ByteString URLEncoder::encode(const ByteString& _str)
84{
85 static unsigned char hexchars[] = "0123456789ABCDEF";
86
87 ByteStringBuilder r;
88
89 const char* psz = _str.data();
90 for (; *psz; psz++)
91 {
92 unsigned char c = (unsigned char)*psz;
93 if (c == ' ')
94 r += '+';
95 else if ((c < '0' && c != '-' && c != '.')
96 || (c < 'A' && c > '9')
97 || (c > 'Z' && c < 'a' && c != '_')
98 || (c > 'z'))
99 {
100 r += '%';
101 r += (char)hexchars[c >> 4];
102 r += (char)hexchars[c & 15];
103 }
104 else
105 r += (char)c;
106 }
107 return r;
108}
109
110String URLEncoder::encode(const String& _str)
111{
114 UTF8Encoder::encode(_str)
115 )
116 );
117}
118
120
121URI::URI(const wchar_t* _uri)
123{
124 __port = -1;
125 parse(_uri);
126}
127
128URI::URI(const wchar_t* _scheme,
129 const wchar_t* _schemeSpecificPart,
130 const wchar_t* _fragment
132{
133 __port = -1;
134 assign(
135 _scheme,
136 _schemeSpecificPart,
137 NULL,
138 -1,
139 NULL,
140 NULL,
141 _fragment
142 );
143}
144
145URI::URI(const wchar_t* _scheme,
146 const wchar_t* _userInfo,
147 const wchar_t* _host,
148 int _port,
149 const wchar_t* _path,
150 const wchar_t* _query,
151 const wchar_t* _fragment
153{
154 __port = -1;
155 assign(
156 _scheme,
157 _userInfo,
158 _host,
159 _port,
160 _path,
161 _query,
162 _fragment
163 );
164}
165
166URI::URI(const wchar_t* _scheme,
167 const wchar_t* _host,
168 const wchar_t* _path,
169 const wchar_t* _fragment
171{
172 __port = -1;
173 assign(
174 _scheme,
175 NULL,
176 _host,
177 -1,
178 _path,
179 NULL,
180 _fragment
181 );
182}
183
184URI::URI(const wchar_t* _scheme,
185 const wchar_t* _authority,
186 const wchar_t* _path,
187 const wchar_t* _query,
188 const wchar_t* _fragment
190{
191 __port = -1;
192 assign(
193 _scheme,
194 _authority,
195 NULL,
196 -1,
197 _path,
198 _query,
199 _fragment
200 );
201}
202
204 const wchar_t* _scheme,
205 const wchar_t* _userInfo,
206 const wchar_t* _host,
207 int _port,
208 const wchar_t* _path,
209 const wchar_t* _query,
210 const wchar_t* _fragment
212{
213 StringBuilder r;
214 if (_scheme)
215 {
216 r = _scheme;
217 r += __T(":");
218 }
219
220 if (_userInfo || _host || _port > -1)
221 r += __T("//");
222
223 if (_userInfo)
224 {
225 r += _userInfo;
226 r += __T("@");
227 }
228
229 if (_host)
230 r += _host;
231
232 if (_port > -1)
233 {
234 r +=__T( ":");
235 r += Integer::toString(_port);
236 }
237
238 if (_path)
239 r += _path;
240
241 if (_query)
242 {
243 r += __T("?");
244 r += _query;
245 }
246
247 if (_fragment)
248 {
249 r += __T("#");
250 r += _fragment;
251 }
252
253 parse(r);
254}
255
256static const wchar_t* const __REGEXP_URI =
257 __T("^(([^:/?#]+):)?((//([^/?#]*))?([^?#]*)(\\?([^#]*))?)?(#(.*))?");
258
259static const wchar_t* const __REGEXP_AUTHORITY =
260 __T("^(([^?#]*)@)?([^?#:]*)(:([^?#]*))?");
261
262#define SCHEME_GROUP 2
263#define SCHEME_SPEC_PART_GROUP 3
264#define AUTHORITY_GROUP 5
265#define PATH_GROUP 6
266#define QUERY_GROUP 8
267#define FRAGMENT_GROUP 10
268
269#define AUTHORITY_USERINFO_GROUP 2
270#define AUTHORITY_HOST_GROUP 3
271#define AUTHORITY_PORT_GROUP 5
272
273void URI::parse(const wchar_t* _uri)
275{
276 __DCL_ASSERT(_uri && *_uri);
277
278 Regex re(__REGEXP_URI);
279 {
280 Regex::MatchResults m; // aMatch[11];
281 if (!re.match(_uri, m)) // aMatch, 11))
282 {
283 throw new URISyntaxException(
284 __T("doesn't match URI regular expression"),
285 _uri
286 );
287 }
288
289#define __MATCH_STR(m, index) m[index].first, m[index].second
290
294 __path.assign(__MATCH_STR(m, PATH_GROUP));
295 __query.assign(__MATCH_STR(m, QUERY_GROUP));
297 }
298
299 if (__authority.isEmpty())
300 return;
301
302 re.compile(__REGEXP_AUTHORITY);
303 {
305 if (re.match(__authority, m)) // aMatch, 6))
306 {
309 String port(__MATCH_STR(m, AUTHORITY_PORT_GROUP));
310 __port = Integer::parse(port, 10, __port);
311 }
312 }
313 __uri = _uri;
314}
315
316
318
319URISyntaxException::URISyntaxException(
320 const String& _reason,
321 const String& _source
322 )
323 : Exception(NULL)
324{
325 __message = _reason + __T(": ") + _source;
326}
327
328String URISyntaxException::toString() const
329{
330 return __message;
331}
332
333__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
wchar_t char_t
Definition Config.h:275
#define __DCL_THROWS1(e)
Definition Config.h:167
#define __DCL_ASSERT(expr)
Definition Object.h:371
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
Definition Object.h:228
#define __T(str)
Definition Object.h:44
ByteString r
#define QUERY_GROUP
Definition URI.cpp:266
#define AUTHORITY_USERINFO_GROUP
Definition URI.cpp:269
#define FRAGMENT_GROUP
Definition URI.cpp:267
#define SCHEME_SPEC_PART_GROUP
Definition URI.cpp:263
#define SCHEME_GROUP
Definition URI.cpp:262
#define AUTHORITY_GROUP
Definition URI.cpp:264
#define AUTHORITY_HOST_GROUP
Definition URI.cpp:270
#define AUTHORITY_PORT_GROUP
Definition URI.cpp:271
#define PATH_GROUP
Definition URI.cpp:265
#define __MATCH_STR(m, index)
static String decode(const char *_mbs, size_t _mbslen=(size_t) -1)
virtual String toString() const
Definition Exception.cpp:40
String toString(unsigned _base=10) const
Definition Numeric.inl:21
static int parse(const wchar_t *_number, unsigned _base=10) __DCL_THROWS1(NumericConvertException *)
Definition Numeric.inl:36
Definition Regex.h:32
bool match(const wchar_t *_begin, const wchar_t *_end, unsigned int _flags) __DCL_THROWS1(RegexException *)
Definition Regex.cpp:162
void compile(const wchar_t *_pattern, size_t _n, unsigned int _flags=0) __DCL_THROWS1(RegexException *)
Definition Regex.cpp:105
Definition URI.h:36
int __port
Definition URI.h:89
String __uri
Definition URI.h:94
String __authority
Definition URI.h:86
String __userInfo
Definition URI.h:87
String __fragment
Definition URI.h:92
String __query
Definition URI.h:91
void parse(const wchar_t *_uri) __DCL_THROWS1(URISyntaxException *)
Definition URI.cpp:273
String __scheme
Definition URI.h:84
void assign(const wchar_t *_scheme, const wchar_t *_userInfo, const wchar_t *_host, int _port, const wchar_t *_path, const wchar_t *_query, const wchar_t *_fragment) __DCL_THROWS1(URISyntaxException *)
Definition URI.cpp:203
String __schemeSpecificPart
Definition URI.h:85
String __host
Definition URI.h:88
String __path
Definition URI.h:90
String __message
Definition URI.h:118
static ByteString decode(const char *_begin, const char *_end)
Definition URI.cpp:46
static ByteString encode(const ByteString &_str)
Definition URI.cpp:83