Branch data Line data Source code
1 : : // Copyright (c) 2015-present The Bitcoin Core developers
2 : : // Distributed under the MIT software license, see the accompanying
3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 : :
5 : : #include <common/url.h>
6 : :
7 : : #include <charconv>
8 : : #include <cstddef>
9 : : #include <string>
10 : : #include <string_view>
11 : : #include <system_error>
12 : :
13 : 16095 : std::string UrlDecode(std::string_view url_encoded)
14 : : {
15 [ + - ]: 16095 : std::string res;
16 [ + - ]: 16095 : res.reserve(url_encoded.size());
17 : :
18 [ + + ]: 234680 : for (size_t i = 0; i < url_encoded.size(); ++i) {
19 [ + + ]: 218585 : char c = url_encoded[i];
20 : : // Special handling for percent which should be followed by two hex digits
21 : : // representing an octet values, see RFC 3986, Section 2.1 Percent-Encoding
22 [ + + + + ]: 218585 : if (c == '%' && i + 2 < url_encoded.size()) {
23 : 404 : unsigned int decoded_value{0};
24 : 404 : auto [p, ec] = std::from_chars(url_encoded.data() + i + 1, url_encoded.data() + i + 3, decoded_value, 16);
25 : :
26 : : // Only if there is no error and the pointer is set to the end of
27 : : // the string, we can be sure both characters were valid hex
28 [ + + + + ]: 404 : if (ec == std::errc{} && p == url_encoded.data() + i + 3) {
29 [ + - ]: 381 : res += static_cast<char>(decoded_value);
30 : : // Next two characters are part of the percent encoding
31 : 381 : i += 2;
32 : 381 : continue;
33 : : }
34 : : // In case of invalid percent encoding, add the '%' and continue
35 : : }
36 [ + - ]: 436789 : res += c;
37 : : }
38 : :
39 : 16095 : return res;
40 : 0 : }
41 : :
42 : 140 : std::string UrlEncode(std::string_view str)
43 : : {
44 [ + - ]: 140 : std::string res;
45 [ + - ]: 140 : res.reserve(str.size() * 3); // worst case: every char needs encoding
46 : :
47 [ + + ]: 1423 : for (char ch : str) {
48 : 1283 : auto c = static_cast<unsigned char>(ch);
49 : : // Unreserved characters per RFC 3986, Section 2.3
50 [ + + ]: 1283 : if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
51 [ + + + + : 593 : (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~') {
+ + ]
52 [ + - ]: 1003 : res += ch;
53 : : } else {
54 : : // Percent-encode all other characters
55 [ + - ]: 280 : res += '%';
56 : 280 : constexpr char hex_chars[] = "0123456789ABCDEF";
57 [ + - ]: 280 : res += hex_chars[(c >> 4) & 0xF];
58 [ + - ]: 1563 : res += hex_chars[c & 0xF];
59 : : }
60 : : }
61 : 140 : return res;
62 : 0 : }
|