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  pUrl.path = smMatch[6];
95 
96  return true;
97 }
98 
101 {
102  boost::trim(str);
103  return str;
104 }
105 
106 boost::optional<std::uint64_t>
107 to_uint64(std::string const& s)
108 {
109  std::uint64_t result;
110  if (beast::lexicalCastChecked(result, s))
111  return result;
112  return boost::none;
113 }
114 
115 bool
117 {
118  // The domain must be between 4 and 128 characters long
119  if (domain.size() < 4 || domain.size() > 128)
120  return false;
121 
122  // This regular expression should do a decent job of weeding out
123  // obviously wrong domain names but it isn't perfect. It does not
124  // really support IDNs. If this turns out to be an issue, a more
125  // thorough regex can be used or this check can just be removed.
126  static boost::regex const re(
127  "^" // Beginning of line
128  "(" // Beginning of a segment
129  "(?!-)" // - must not begin with '-'
130  "[a-zA-Z0-9-]{1,63}" // - only alphanumeric and '-'
131  "(?<!-)" // - must not end with '-'
132  "\\." // segment separator
133  ")+" // 1 or more segments
134  "[A-Za-z]{2,63}" // TLD
135  "$" // End of line
136  ,
137  boost::regex_constants::optimize);
138 
139  return boost::regex_match(domain, re);
140 }
141 
142 } // namespace ripple
std::string
STL class.
ripple::parsedURL
Definition: StringUtilities.h:100
ripple::parsedURL::password
std::string password
Definition: StringUtilities.h:106
std::string::reserve
T reserve(T... args)
std::vector< unsigned char >
std::vector::size
T size(T... args)
ripple::to_uint64
boost::optional< std::uint64_t > to_uint64(std::string const &s)
std::back_inserter
T back_inserter(T... args)
ripple::parsedURL::username
std::string username
Definition: StringUtilities.h:105
ripple::parsedURL::path
std::string path
Definition: StringUtilities.h:109
ripple::trim_whitespace
std::string trim_whitespace(std::string str)
algorithm
std::string::push_back
T push_back(T... args)
ripple::parseUrl
bool parseUrl(parsedURL &pUrl, std::string const &strUrl)
Definition: StringUtilities.cpp:47
std::uint64_t
ripple::parsedURL::port
boost::optional< std::uint16_t > port
Definition: StringUtilities.h:108
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)
ripple::parsedURL::scheme
std::string scheme
Definition: StringUtilities.h:104
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:107
std::vector::end
T end(T... args)
beast::IP::Endpoint::from_string_checked
static boost::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