Skip to content

Commit e68ac19

Browse files
committed
Added some functions that allow encoding and decoding of URI strings.
1 parent 372c3bf commit e68ac19

File tree

7 files changed

+325
-9
lines changed

7 files changed

+325
-9
lines changed

boost/network/uri/decode.hpp

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright (c) Glyn Matthews 2011.
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE_1_0.txt or copy at
4+
// http://www.boost.org/LICENSE_1_0.txt)
5+
6+
7+
#ifndef __BOOST_NETWORK_URI_DECODE_INC__
8+
# define __BOOST_NETWORK_URI_DECODE_INC__
9+
10+
11+
# include <boost/iterator/iterator_traits.hpp>
12+
# include <boost/range/begin.hpp>
13+
# include <boost/range/end.hpp>
14+
# include <cassert>
15+
16+
17+
namespace boost {
18+
namespace network {
19+
namespace uri {
20+
namespace detail {
21+
template <
22+
typename CharT
23+
>
24+
CharT letter_to_hex(CharT in)
25+
{
26+
switch (in)
27+
{
28+
case '0':
29+
case '1':
30+
case '2':
31+
case '3':
32+
case '4':
33+
case '5':
34+
case '6':
35+
case '7':
36+
case '8':
37+
case '9':
38+
return in - '0';
39+
case 'a':
40+
case 'b':
41+
case 'c':
42+
case 'd':
43+
case 'e':
44+
case 'f':
45+
return in + 10 - 'a';
46+
case 'A':
47+
case 'B':
48+
case 'C':
49+
case 'D':
50+
case 'E':
51+
case 'F':
52+
return in + 10 - 'A';
53+
}
54+
return CharT();
55+
}
56+
} // namespace detail
57+
58+
template <
59+
class InputIterator,
60+
class OutputIterator
61+
>
62+
OutputIterator decode(const InputIterator &in_begin, const InputIterator &in_end, const OutputIterator &out_begin) {
63+
typedef typename boost::iterator_value<InputIterator>::type value_type;
64+
65+
InputIterator it = in_begin;
66+
OutputIterator out = out_begin;
67+
while (it != in_end) {
68+
if (*it == '%')
69+
{
70+
++it;
71+
value_type v0 = detail::letter_to_hex(*it);
72+
++it;
73+
value_type v1 = detail::letter_to_hex(*it);
74+
++it;
75+
*out++ = 0x10 * v0 + v1;
76+
}
77+
else
78+
{
79+
*out++ = *it++;
80+
}
81+
}
82+
return out;
83+
}
84+
85+
template <
86+
class SinglePassRange,
87+
class OutputIterator
88+
>
89+
inline
90+
OutputIterator decode(const SinglePassRange &range, const OutputIterator &out) {
91+
return decode(boost::begin(range), boost::end(range), out);
92+
}
93+
} // namespace uri
94+
} // namespace network
95+
} // namespace boost
96+
97+
98+
#endif // __BOOST_NETWORK_URI_DECODE_INC__

boost/network/uri/encode.hpp

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
// Copyright (c) Glyn Matthews 2011.
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE_1_0.txt or copy at
4+
// http://www.boost.org/LICENSE_1_0.txt)
5+
6+
7+
#ifndef __BOOST_NETWORK_URI_ENCODE_INC__
8+
# define __BOOST_NETWORK_URI_ENCODE_INC__
9+
10+
11+
# include <boost/iterator/iterator_traits.hpp>
12+
# include <boost/range/begin.hpp>
13+
# include <boost/range/end.hpp>
14+
# include <cassert>
15+
16+
17+
namespace boost {
18+
namespace network {
19+
namespace uri {
20+
namespace detail {
21+
template <
22+
typename CharT
23+
>
24+
inline
25+
CharT hex_to_letter(CharT in) {
26+
switch (in)
27+
{
28+
case 0:
29+
case 1:
30+
case 2:
31+
case 3:
32+
case 4:
33+
case 5:
34+
case 6:
35+
case 7:
36+
case 8:
37+
case 9:
38+
return in + '0';
39+
case 10:
40+
case 11:
41+
case 12:
42+
case 13:
43+
case 14:
44+
default:
45+
return in - 10 + 'A';
46+
}
47+
return CharT();
48+
}
49+
50+
51+
template <
52+
typename CharT,
53+
class OutputIterator
54+
>
55+
void encode_char(CharT in, OutputIterator &out) {
56+
switch (in)
57+
{
58+
case 'a':
59+
case 'A':
60+
case 'b':
61+
case 'B':
62+
case 'c':
63+
case 'C':
64+
case 'd':
65+
case 'D':
66+
case 'e':
67+
case 'E':
68+
case 'f':
69+
case 'F':
70+
case 'g':
71+
case 'G':
72+
case 'h':
73+
case 'H':
74+
case 'i':
75+
case 'I':
76+
case 'j':
77+
case 'J':
78+
case 'k':
79+
case 'K':
80+
case 'l':
81+
case 'L':
82+
case 'm':
83+
case 'M':
84+
case 'n':
85+
case 'N':
86+
case 'o':
87+
case 'O':
88+
case 'p':
89+
case 'P':
90+
case 'q':
91+
case 'Q':
92+
case 'r':
93+
case 'R':
94+
case 's':
95+
case 'S':
96+
case 't':
97+
case 'T':
98+
case 'u':
99+
case 'U':
100+
case 'v':
101+
case 'V':
102+
case 'w':
103+
case 'W':
104+
case 'x':
105+
case 'X':
106+
case 'y':
107+
case 'Y':
108+
case 'z':
109+
case 'Z':
110+
case '0':
111+
case '1':
112+
case '2':
113+
case '3':
114+
case '4':
115+
case '5':
116+
case '6':
117+
case '7':
118+
case '8':
119+
case '9':
120+
case '-':
121+
case '.':
122+
case '_':
123+
case '~':
124+
out++ = in;
125+
break;
126+
default:
127+
out++ = '%';
128+
out++ = hex_to_letter(in >> 4);
129+
out++ = hex_to_letter(in & 0x0f);
130+
;
131+
}
132+
}
133+
} // namespace detail
134+
135+
template <
136+
class InputIterator,
137+
class OutputIterator
138+
>
139+
OutputIterator encode(const InputIterator &in_begin, const InputIterator &in_end, const OutputIterator &out_begin) {
140+
typedef typename boost::iterator_value<InputIterator>::type value_type;
141+
142+
InputIterator it = in_begin;
143+
OutputIterator out = out_begin;
144+
while (it != in_end) {
145+
detail::encode_char(*it, out);
146+
++it;
147+
}
148+
return out;
149+
}
150+
151+
template <
152+
class SinglePassRange,
153+
class OutputIterator
154+
>
155+
inline
156+
OutputIterator encode(const SinglePassRange &range, const OutputIterator &out) {
157+
return encode(boost::begin(range), boost::end(range), out);
158+
}
159+
} // namespace uri
160+
} // namespace network
161+
} // namespace boost
162+
163+
164+
#endif // __BOOST_NETWORK_URI_ENCODE_INC__

boost/network/uri/uri.hpp

+8
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,14 @@ typename basic_uri<Tag>::string_type authority(const basic_uri<Tag> &uri) {
324324
return typename basic_uri<Tag>::string_type(user_info.begin(), port.end());
325325
}
326326

327+
template <
328+
class Tag
329+
>
330+
inline
331+
typename basic_uri<Tag>::string_type netloc(const basic_uri<Tag> &uri) {
332+
return authority(uri);
333+
}
334+
327335
template <
328336
class Tag
329337
>

libs/network/test/http/server_async_less_copy.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
// Copyright 2010 Dean Michael Berris.
2+
// Copyright 2010 Dean Michael Berris.
33
// Distributed under the Boost Software License, Version 1.0.
44
// (See accompanying file LICENSE_1_0.txt or copy at
55
// http://www.boost.org/LICENSE_1_0.txt)
@@ -50,11 +50,10 @@ struct async_hello_world {
5050
};
5151

5252
int main(int argc, char * argv[]) {
53-
utils::thread_pool thread_pool(2);
53+
utils::thread_pool thread_pool(2);
5454
async_hello_world handler;
5555
std::string port = "8000";
5656
if (argc > 1) port = argv[1];
57-
std::cerr << "Configuration: port = " << port << std::endl;
5857
server instance("127.0.0.1", port, handler, thread_pool, http::_reuse_address=true);
5958
instance.run();
6059
return 0;

libs/network/test/uri/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ if (Boost_FOUND)
1717
url_test
1818
url_http_test
1919
url_mailto_test
20+
url_encoding_test
2021
builder_test
2122
)
2223
foreach (test ${TESTS})

libs/network/test/uri/builder_test.cpp

+4-6
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,17 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types)
2626
{
2727
typedef uri::basic_uri<T> uri_type;
2828
typedef typename uri_type::string_type string_type;
29+
namespace urib = uri::builder;
2930

3031
const std::string scheme("http");
3132
const std::string host("www.example.com");
3233
const std::string path("/");
3334

3435
uri_type instance;
3536
uri::basic_builder<T> builder(instance);
36-
builder << uri::builder::scheme(string_type(boost::begin(scheme),
37-
boost::end(scheme)))
38-
<< uri::builder::host(string_type(boost::begin(host),
39-
boost::end(host)))
40-
<< uri::builder::path(string_type(boost::begin(path),
41-
boost::end(path)))
37+
builder << urib::scheme(string_type(boost::begin(scheme), boost::end(scheme)))
38+
<< urib::host(string_type(boost::begin(host), boost::end(host)))
39+
<< urib::path(string_type(boost::begin(path), boost::end(path)))
4240
;
4341
BOOST_REQUIRE(uri::is_valid(instance));
4442
BOOST_CHECK(boost::equal(uri::scheme(instance), scheme));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) Glyn Matthews 2011.
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE_1_0.txt or copy at
4+
// http://www.boost.org/LICENSE_1_0.txt)
5+
6+
#define BOOST_TEST_MODULE URL encoding test
7+
#include <boost/config/warning_disable.hpp>
8+
#include <boost/test/unit_test.hpp>
9+
#include <boost/network/uri/encode.hpp>
10+
#include <boost/network/uri/decode.hpp>
11+
#include <boost/network/tags.hpp>
12+
#include <boost/network/traits/string.hpp>
13+
#include <boost/mpl/list.hpp>
14+
#include <boost/range/algorithm/equal.hpp>
15+
#include <boost/range/algorithm/copy.hpp>
16+
#include <iterator>
17+
18+
19+
using namespace boost::network;
20+
21+
typedef boost::mpl::list<
22+
tags::default_string
23+
, tags::default_wstring
24+
> tag_types;
25+
26+
27+
BOOST_AUTO_TEST_CASE_TEMPLATE(encoding_test, T, tag_types) {
28+
typedef typename string<T>::type string_type;
29+
30+
const std::string unencoded(" !\"#$%&\'()*");
31+
const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A");
32+
33+
string_type instance;
34+
uri::encode(unencoded, std::back_inserter(instance));
35+
BOOST_CHECK(boost::equal(instance, encoded));
36+
}
37+
38+
39+
BOOST_AUTO_TEST_CASE_TEMPLATE(decoding_test, T, tag_types) {
40+
typedef typename string<T>::type string_type;
41+
42+
const std::string unencoded(" !\"#$%&\'()*");
43+
const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A");
44+
45+
string_type instance;
46+
uri::decode(encoded, std::back_inserter(instance));
47+
BOOST_CHECK(boost::equal(instance, unencoded));
48+
}

0 commit comments

Comments
 (0)