xrpld
Toggle main menu visibility
Loading...
Searching...
No Matches
libxrpl
basics
libxrpl/basics/StringUtilities.cpp
1
#include <xrpl/basics/StringUtilities.h>
2
3
#include <xrpl/basics/Blob.h>
4
#include <xrpl/beast/core/LexicalCast.h>
5
#include <xrpl/beast/net/IPEndpoint.h>
6
7
#include <boost/algorithm/hex.hpp>
8
#include <boost/regex/v5/regbase.hpp>
9
#include <boost/regex/v5/regex.hpp>
10
#include <boost/regex/v5/regex_match.hpp>
11
12
#include <
algorithm
>
13
#include <
cstdint
>
14
#include <
iterator
>
15
#include <
optional
>
16
#include <
ranges
>
17
#include <
string
>
18
#include <
string_view
>
19
20
namespace
xrpl
{
21
22
std::string
23
sqlBlobLiteral
(
Blob
const
& blob)
24
{
25
std::string
j;
26
27
j.
reserve
((blob.
size
() * 2) + 3);
28
j.
push_back
(
'X'
);
29
j.
push_back
(
'\''
);
30
boost::algorithm::hex(blob.
begin
(), blob.
end
(),
std::back_inserter
(j));
31
j.
push_back
(
'\''
);
32
33
return
j;
34
}
35
36
bool
37
parseUrl
(
ParsedUrl
& pUrl,
std::string
const
& strUrl)
38
{
39
// scheme://username:password@hostname:port/rest
40
static
boost::regex
const
kReUrl(
41
"(?i)\\`\\s*"
42
// required scheme
43
"([[:alpha:]][-+.[:alpha:][:digit:]]*?):"
44
// We choose to support only URIs whose `hier-part` has the form
45
// `"//" authority path-abempty`.
46
"//"
47
// optional userinfo
48
"(?:([^:@/]*?)(?::([^@/]*?))?@)?"
49
// optional host
50
"([[:digit:]:]*[[:digit:]]|\\[[^]]+\\]|[^:/?#]*?)"
51
// optional port
52
"(?::([[:digit:]]+))?"
53
// optional path
54
"(/.*)?"
55
"\\s*?\\'"
);
56
boost::smatch smMatch;
57
58
// Bail if there is no match.
59
try
60
{
61
if
(!boost::regex_match(strUrl, smMatch, kReUrl))
62
return
false
;
63
}
64
catch
(...)
65
{
66
return
false
;
67
}
68
69
pUrl.
scheme
= smMatch[1];
70
pUrl.
scheme
=
toLower
(pUrl.
scheme
);
71
pUrl.
username
= smMatch[2];
72
pUrl.
password
= smMatch[3];
73
std::string
const
domain = smMatch[4];
74
// We need to use Endpoint to parse the domain to
75
// strip surrounding brackets from IPv6 addresses,
76
// e.g. [::1] => ::1.
77
auto
const
result =
beast::ip::Endpoint::fromStringChecked
(domain);
78
pUrl.
domain
= result ? result->address().to_string() : domain;
79
std::string
const
port = smMatch[5];
80
if
(!port.
empty
())
81
{
82
pUrl.
port
=
beast::lexicalCast<std::uint16_t>
(port);
83
84
// For inputs larger than 2^32-1 (65535), lexicalCast returns 0.
85
// parseUrl returns false for such inputs.
86
if
(pUrl.
port
== 0)
87
{
88
return
false
;
89
}
90
}
91
pUrl.
path
= smMatch[6];
92
93
return
true
;
94
}
95
96
namespace
{
97
98
// Deliberately not std::isspace / std::tolower: those consult the current C
99
// locale, so the same input could trim or fold differently depending on
100
// process-wide state set by something else entirely. Everything these helpers
101
// are used on (config keys and values, URL schemes, hex digests) is ASCII, and
102
// the callers want a fixed answer, so spell the ASCII rules out.
103
104
constexpr
bool
105
isAsciiSpace(
char
c)
106
{
107
return
c ==
' '
|| c ==
'\t'
|| c ==
'\n'
|| c ==
'\v'
|| c ==
'\f'
|| c ==
'\r'
;
108
}
109
110
constexpr
char
111
toAsciiLower(
char
c)
112
{
113
return
(c >=
'A'
&& c <=
'Z'
) ?
static_cast<
char
>
(c -
'A'
+
'a'
) : c;
114
}
115
116
}
// namespace
117
118
std::string
119
trimWhitespace
(
std::string
str)
120
{
121
auto
const
end =
std::ranges::find_if_not
(str | std::views::reverse, isAsciiSpace).base();
122
str.
erase
(end, str.
end
());
123
str.
erase
(str.
begin
(),
std::ranges::find_if_not
(str, isAsciiSpace));
124
125
return
str;
126
}
127
128
std::string
129
toLower
(
std::string
str)
130
{
131
std::ranges::transform
(str, str.
begin
(), toAsciiLower);
132
return
str;
133
}
134
135
std::optional<std::uint64_t>
136
toUInt64
(
std::string
const
& s)
137
{
138
std::uint64_t
result = 0;
139
if
(
beast::lexicalCastChecked
(result, s))
140
return
result;
141
return
std::nullopt;
142
}
143
144
bool
145
isProperlyFormedTomlDomain
(
std::string_view
domain)
146
{
147
// The domain must be between 4 and 128 characters long
148
if
(domain.
size
() < 4 || domain.
size
() > 128)
149
return
false
;
150
151
// This regular expression should do a decent job of weeding out
152
// obviously wrong domain names but it isn't perfect. It does not
153
// really support IDNs. If this turns out to be an issue, a more
154
// thorough regex can be used or this check can just be removed.
155
static
boost::regex
const
kRE(
156
"^"
// Beginning of line
157
"("
// Beginning of a segment
158
"(?!-)"
// - must not begin with '-'
159
"[a-zA-Z0-9-]{1,63}"
// - only alphanumeric and '-'
160
"(?<!-)"
// - must not end with '-'
161
"\\."
// segment separator
162
")+"
// 1 or more segments
163
"[A-Za-z]{2,63}"
// TLD
164
"$"
// End of line
165
,
166
boost::regex_constants::optimize);
167
168
return
boost::regex_match(domain.
begin
(), domain.
end
(), kRE);
169
}
170
171
}
// namespace xrpl
algorithm
std::back_inserter
T back_inserter(T... args)
std::string
std::string_view
std::vector::begin
T begin(T... args)
beast::ip::Endpoint::fromStringChecked
static std::optional< Endpoint > fromStringChecked(std::string const &s)
Create an Endpoint from a string.
Definition
IPEndpoint.cpp:28
cstdint
std::string::empty
T empty(T... args)
std::vector::end
T end(T... args)
std::string::erase
T erase(T... args)
std::ranges::find_if_not
T find_if_not(T... args)
std::uint64_t
iterator
beast::lexicalCastChecked
constexpr bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
Definition
LexicalCast.h:181
beast::lexicalCast
constexpr Out lexicalCast(In in, Out defaultValue=Out())
Convert from one type to another.
Definition
LexicalCast.h:211
xrpl
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition
algorithm.h:5
xrpl::toLower
std::string toLower(std::string str)
Fold ASCII upper case letters to lower case.
Definition
libxrpl/basics/StringUtilities.cpp:129
xrpl::isProperlyFormedTomlDomain
bool isProperlyFormedTomlDomain(std::string_view domain)
Determines if the given string looks like a TOML-file hosting domain.
Definition
libxrpl/basics/StringUtilities.cpp:145
xrpl::trimWhitespace
std::string trimWhitespace(std::string str)
Remove leading and trailing ASCII whitespace.
Definition
libxrpl/basics/StringUtilities.cpp:119
xrpl::toUInt64
std::optional< std::uint64_t > toUInt64(std::string const &s)
Definition
libxrpl/basics/StringUtilities.cpp:136
xrpl::sqlBlobLiteral
std::string sqlBlobLiteral(Blob const &blob)
Format arbitrary binary data as an SQLite "blob literal".
Definition
libxrpl/basics/StringUtilities.cpp:23
xrpl::Blob
std::vector< unsigned char > Blob
Storage for linear binary data.
Definition
Blob.h:11
xrpl::parseUrl
bool parseUrl(ParsedUrl &pUrl, std::string const &strUrl)
Definition
libxrpl/basics/StringUtilities.cpp:37
optional
std::string::push_back
T push_back(T... args)
ranges
std::string::reserve
T reserve(T... args)
std::vector::size
T size(T... args)
string
string_view
xrpl::ParsedUrl
Definition
StringUtilities.h:106
xrpl::ParsedUrl::port
std::optional< std::uint16_t > port
Definition
StringUtilities.h:113
xrpl::ParsedUrl::password
std::string password
Definition
StringUtilities.h:111
xrpl::ParsedUrl::scheme
std::string scheme
Definition
StringUtilities.h:109
xrpl::ParsedUrl::domain
std::string domain
Definition
StringUtilities.h:112
xrpl::ParsedUrl::path
std::string path
Definition
StringUtilities.h:114
xrpl::ParsedUrl::username
std::string username
Definition
StringUtilities.h:110
std::ranges::transform
T transform(T... args)
Generated by
1.17.0