/tmp/bitcoin/src/common/url.cpp
Line | Count | Source |
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 <string> |
9 | | #include <string_view> |
10 | | #include <system_error> |
11 | | |
12 | | std::string UrlDecode(std::string_view url_encoded) |
13 | 14.8k | { |
14 | 14.8k | std::string res; |
15 | 14.8k | res.reserve(url_encoded.size()); |
16 | | |
17 | 216k | for (size_t i = 0; i < url_encoded.size(); ++i) { |
18 | 201k | char c = url_encoded[i]; |
19 | | // Special handling for percent which should be followed by two hex digits |
20 | | // representing an octet values, see RFC 3986, Section 2.1 Percent-Encoding |
21 | 201k | if (c == '%' && i + 2 < url_encoded.size()) { |
22 | 410 | unsigned int decoded_value{0}; |
23 | 410 | auto [p, ec] = std::from_chars(url_encoded.data() + i + 1, url_encoded.data() + i + 3, decoded_value, 16); |
24 | | |
25 | | // Only if there is no error and the pointer is set to the end of |
26 | | // the string, we can be sure both characters were valid hex |
27 | 410 | if (ec == std::errc{} && p == url_encoded.data() + i + 3) { |
28 | 391 | res += static_cast<char>(decoded_value); |
29 | | // Next two characters are part of the percent encoding |
30 | 391 | i += 2; |
31 | 391 | continue; |
32 | 391 | } |
33 | | // In case of invalid percent encoding, add the '%' and continue |
34 | 410 | } |
35 | 200k | res += c; |
36 | 200k | } |
37 | | |
38 | 14.8k | return res; |
39 | 14.8k | } |
40 | | |
41 | | std::string UrlEncode(std::string_view str) |
42 | 168 | { |
43 | 168 | std::string res; |
44 | 168 | res.reserve(str.size() * 3); // worst case: every char needs encoding |
45 | | |
46 | 1.62k | for (char ch : str) { |
47 | 1.62k | auto c = static_cast<unsigned char>(ch); |
48 | | // Unreserved characters per RFC 3986, Section 2.3 |
49 | 1.62k | if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || |
50 | 1.62k | (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~') { |
51 | 1.32k | res += ch; |
52 | 1.32k | } else { |
53 | | // Percent-encode all other characters |
54 | 295 | res += '%'; |
55 | 295 | constexpr char hex_chars[] = "0123456789ABCDEF"; |
56 | 295 | res += hex_chars[(c >> 4) & 0xF]; |
57 | 295 | res += hex_chars[c & 0xF]; |
58 | 295 | } |
59 | 1.62k | } |
60 | 168 | return res; |
61 | 168 | } |