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 37 : ci_is_equal(
18 : core::string_view s0,
19 : core::string_view s1) noexcept
20 : {
21 37 : auto n = s0.size();
22 37 : if(s1.size() != n)
23 0 : return false;
24 37 : auto p1 = s0.data();
25 37 : auto p2 = s1.data();
26 : char a, b;
27 : // fast loop
28 155 : while(n--)
29 : {
30 126 : a = *p1++;
31 126 : b = *p2++;
32 126 : if(a != b)
33 8 : goto slow;
34 : }
35 29 : return true;
36 : do
37 : {
38 5 : a = *p1++;
39 5 : b = *p2++;
40 13 : slow:
41 26 : if( grammar::to_lower(a) !=
42 13 : grammar::to_lower(b))
43 5 : return false;
44 : }
45 8 : while(n--);
46 3 : return true;
47 : }
48 :
49 : std::string
50 116 : pct_decode(
51 : urls::pct_string_view s)
52 : {
53 116 : std::string result;
54 116 : core::string_view sv(s);
55 116 : result.reserve(s.size());
56 116 : auto it = sv.data();
57 116 : auto const end = it + sv.size();
58 : for(;;)
59 : {
60 377 : if(it == end)
61 116 : break;
62 261 : if(*it != '%')
63 : {
64 260 : result.push_back(*it++);
65 260 : 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 261 : }
88 232 : 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 slashes '/' and '\'
97 : std::string
98 58 : pct_decode_path(
99 : urls::pct_string_view s)
100 : {
101 58 : std::string result;
102 58 : core::string_view sv(s);
103 58 : result.reserve(s.size());
104 58 : auto it = sv.data();
105 58 : auto const end = it + sv.size();
106 : for(;;)
107 : {
108 227 : if(it == end)
109 58 : break;
110 169 : if(*it != '%')
111 : {
112 167 : result.push_back(*it++);
113 167 : continue;
114 : }
115 2 : ++it;
116 : #if 0
117 : // pct_string_view can never have invalid pct-encodings
118 : if(it == end)
119 : goto invalid;
120 : #endif
121 2 : auto d0 = urls::grammar::hexdig_value(*it++);
122 : #if 0
123 : // pct_string_view can never have invalid pct-encodings
124 : if( d0 < 0 ||
125 : it == end)
126 : goto invalid;
127 : #endif
128 2 : auto d1 = urls::grammar::hexdig_value(*it++);
129 : #if 0
130 : // pct_string_view can never have invalid pct-encodings
131 : if(d1 < 0)
132 : goto invalid;
133 : #endif
134 2 : char c = d0 * 16 + d1;
135 2 : if( c != '/' &&
136 : c != '\\')
137 : {
138 1 : result.push_back(c);
139 1 : continue;
140 : }
141 1 : result.append(it - 3, 3);
142 169 : }
143 116 : 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
|