Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/cppalliance/http
8 : //
9 :
10 : #include "src/server/detail/pct_decode.hpp"
11 :
12 : namespace boost {
13 : namespace http {
14 : namespace detail {
15 :
16 : bool
17 0 : ci_is_equal(
18 : core::string_view s0,
19 : core::string_view s1) noexcept
20 : {
21 0 : auto n = s0.size();
22 0 : if(s1.size() != n)
23 0 : return false;
24 0 : auto p1 = s0.data();
25 0 : auto p2 = s1.data();
26 : char a, b;
27 : // fast loop
28 0 : while(n--)
29 : {
30 0 : a = *p1++;
31 0 : b = *p2++;
32 0 : if(a != b)
33 0 : goto slow;
34 : }
35 0 : return true;
36 : do
37 : {
38 0 : a = *p1++;
39 0 : b = *p2++;
40 0 : slow:
41 0 : if( grammar::to_lower(a) !=
42 0 : grammar::to_lower(b))
43 0 : return false;
44 : }
45 0 : while(n--);
46 0 : return true;
47 : }
48 :
49 : std::string
50 179 : pct_decode(
51 : urls::pct_string_view s)
52 : {
53 179 : std::string result;
54 179 : core::string_view sv(s);
55 179 : result.reserve(s.size());
56 179 : auto it = sv.data();
57 179 : auto const end = it + sv.size();
58 : for(;;)
59 : {
60 1043 : if(it == end)
61 179 : break;
62 864 : if(*it != '%')
63 : {
64 863 : result.push_back(*it++);
65 863 : continue;
66 : }
67 1 : ++it;
68 : #if 0
69 : // pct_string_view can never have invalid pct-encodings
70 : if(it == end)
71 : goto invalid;
72 : #endif
73 1 : auto d0 = urls::grammar::hexdig_value(*it++);
74 : #if 0
75 : // pct_string_view can never have invalid pct-encodings
76 : if( d0 < 0 ||
77 : it == end)
78 : goto invalid;
79 : #endif
80 1 : auto d1 = urls::grammar::hexdig_value(*it++);
81 : #if 0
82 : // pct_string_view can never have invalid pct-encodings
83 : if(d1 < 0)
84 : goto invalid;
85 : #endif
86 1 : result.push_back(d0 * 16 + d1);
87 864 : }
88 358 : return result;
89 : #if 0
90 : invalid:
91 : // can't get here, as received a pct_string_view
92 : detail::throw_invalid_argument();
93 : #endif
94 0 : }
95 :
96 : // decode all percent escapes except forward slash '/'
97 : // (backslash is decoded since it's not a path separator in URLs)
98 : std::string
99 107 : pct_decode_path(
100 : urls::pct_string_view s)
101 : {
102 107 : std::string result;
103 107 : core::string_view sv(s);
104 107 : result.reserve(s.size());
105 107 : auto it = sv.data();
106 107 : auto const end = it + sv.size();
107 : for(;;)
108 : {
109 788 : if(it == end)
110 107 : break;
111 681 : if(*it != '%')
112 : {
113 675 : result.push_back(*it++);
114 675 : continue;
115 : }
116 6 : ++it;
117 : #if 0
118 : // pct_string_view can never have invalid pct-encodings
119 : if(it == end)
120 : goto invalid;
121 : #endif
122 6 : auto d0 = urls::grammar::hexdig_value(*it++);
123 : #if 0
124 : // pct_string_view can never have invalid pct-encodings
125 : if( d0 < 0 ||
126 : it == end)
127 : goto invalid;
128 : #endif
129 6 : auto d1 = urls::grammar::hexdig_value(*it++);
130 : #if 0
131 : // pct_string_view can never have invalid pct-encodings
132 : if(d1 < 0)
133 : goto invalid;
134 : #endif
135 6 : char c = d0 * 16 + d1;
136 6 : if(c != '/')
137 : {
138 5 : result.push_back(c);
139 5 : continue;
140 : }
141 1 : result.append(it - 3, 3);
142 681 : }
143 214 : return result;
144 : #if 0
145 : invalid:
146 : // can't get here, as received a pct_string_view
147 : detail::throw_invalid_argument();
148 : #endif
149 0 : }
150 :
151 : } // detail
152 : } // http
153 : } // boost
|