rippled
StringUtilities.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/Slice.h>
21 #include <ripple/basics/StringUtilities.h>
22 #include <ripple/basics/ToString.h>
23 #include <ripple/basics/contract.h>
24 #include <ripple/beast/core/LexicalCast.h>
25 #include <ripple/beast/net/IPEndpoint.h>
26 #include <boost/algorithm/string.hpp>
27 #include <boost/regex.hpp>
28 #include <algorithm>
29 
30 namespace ripple {
31 
33 sqlBlobLiteral(Blob const& blob)
34 {
35  std::string j;
36 
37  j.reserve(blob.size() * 2 + 3);
38  j.push_back('X');
39  j.push_back('\'');
40  boost::algorithm::hex(blob.begin(), blob.end(), std::back_inserter(j));
41  j.push_back('\'');
42 
43  return j;
44 }
45 
46 bool
47 parseUrl(parsedURL& pUrl, std::string const& strUrl)
48 {
49  // scheme://username:password@hostname:port/rest
50  static boost::regex reUrl(
51  "(?i)\\`\\s*"
52  // required scheme
53  "([[:alpha:]][-+.[:alpha:][:digit:]]*?):"
54  // We choose to support only URIs whose `hier-part` has the form
55  // `"//" authority path-abempty`.
56  "//"
57  // optional userinfo
58  "(?:([^:@/]*?)(?::([^@/]*?))?@)?"
59  // optional host
60  "([[:digit:]:]*[[:digit:]]|\\[[^]]+\\]|[^:/?#]*?)"
61  // optional port
62  "(?::([[:digit:]]+))?"
63  // optional path
64  "(/.*)?"
65  "\\s*?\\'");
66  boost::smatch smMatch;
67 
68  // Bail if there is no match.
69  try
70  {
71  if (!boost::regex_match(strUrl, smMatch, reUrl))
72  return false;
73  }
74  catch (...)
75  {
76  return false;
77  }
78 
79  pUrl.scheme = smMatch[1];
80  boost::algorithm::to_lower(pUrl.scheme);
81  pUrl.username = smMatch[2];
82  pUrl.password = smMatch[3];
83  const std::string domain = smMatch[4];
84  // We need to use Endpoint to parse the domain to
85  // strip surrounding brackets from IPv6 addresses,
86  // e.g. [::1] => ::1.
87  const auto result = beast::IP::Endpoint::from_string_checked(domain);
88  pUrl.domain = result ? result->address().to_string() : domain;
89  const std::string port = smMatch[5];
90  if (!port.empty())
91  {
92  pUrl.port = beast::lexicalCast<std::uint16_t>(port);
93 
94  // For inputs larger than 2^32-1 (65535), lexicalCast returns 0.
95  // parseUrl returns false for such inputs.
96  if (pUrl.port == 0)
97  {
98  return false;
99  }
100  }
101  pUrl.path = smMatch[6];
102 
103  return true;
104 }
105 
108 {
109  boost::trim(str);
110  return str;
111 }
112 
114 to_uint64(std::string const& s)
115 {
116  std::uint64_t result;
117  if (beast::lexicalCastChecked(result, s))
118  return result;
119  return std::nullopt;
120 }
121 
122 bool
124 {
125  // The domain must be between 4 and 128 characters long
126  if (domain.size() < 4 || domain.size() > 128)
127  return false;
128 
129  // This regular expression should do a decent job of weeding out
130  // obviously wrong domain names but it isn't perfect. It does not
131  // really support IDNs. If this turns out to be an issue, a more
132  // thorough regex can be used or this check can just be removed.
133  static boost::regex const re(
134  "^" // Beginning of line
135  "(" // Beginning of a segment
136  "(?!-)" // - must not begin with '-'
137  "[a-zA-Z0-9-]{1,63}" // - only alphanumeric and '-'
138  "(?<!-)" // - must not end with '-'
139  "\\." // segment separator
140  ")+" // 1 or more segments
141  "[A-Za-z]{2,63}" // TLD
142  "$" // End of line
143  ,
144  boost::regex_constants::optimize);
145 
146  return boost::regex_match(domain, re);
147 }
148 
149 } // namespace ripple
std::string
STL class.
ripple::parsedURL
Definition: StringUtilities.h:116
ripple::parsedURL::password
std::string password
Definition: StringUtilities.h:122
std::string::reserve
T reserve(T... args)
std::vector< unsigned char >
std::vector::size
T size(T... args)
std::back_inserter
T back_inserter(T... args)
ripple::parsedURL::username
std::string username
Definition: StringUtilities.h:121
ripple::parsedURL::path
std::string path
Definition: StringUtilities.h:125
ripple::trim_whitespace
std::string trim_whitespace(std::string str)
algorithm
std::string::push_back
T push_back(T... args)
ripple::parsedURL::port
std::optional< std::uint16_t > port
Definition: StringUtilities.h:124
ripple::to_uint64
std::optional< std::uint64_t > to_uint64(std::string const &s)
ripple::parseUrl
bool parseUrl(parsedURL &pUrl, std::string const &strUrl)
Definition: StringUtilities.cpp:47
std::uint64_t
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
beast::lexicalCastChecked
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
Definition: LexicalCast.h:266
std::vector::begin
T begin(T... args)
std::string::empty
T empty(T... args)
std::optional
ripple::parsedURL::scheme
std::string scheme
Definition: StringUtilities.h:120
ripple::isProperlyFormedTomlDomain
bool isProperlyFormedTomlDomain(std::string const &domain)
Determines if the given string looks like a TOML-file hosting domain.
ripple::parsedURL::domain
std::string domain
Definition: StringUtilities.h:123
std::vector::end
T end(T... args)
beast::IP::Endpoint::from_string_checked
static std::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
Definition: IPEndpoint.cpp:35
ripple::sqlBlobLiteral
std::string sqlBlobLiteral(Blob const &blob)
Format arbitrary binary data as an SQLite "blob literal".
Definition: StringUtilities.cpp:33