Skip to content

Commit d24ffb2

Browse files
authored
Merge pull request #1720 from evoskuil/master
Re-implement URI parser using boost.url (dependency), remove "strict".
2 parents b97deca + 120f89e commit d24ffb2

File tree

13 files changed

+396
-379
lines changed

13 files changed

+396
-379
lines changed

include/bitcoin/system/boost.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,14 @@
2626

2727
// Include boost only from here, so exception disable works.
2828
#include <boost/asio.hpp>
29+
#include <boost/beast.hpp>
2930
#include <boost/format.hpp>
3031
#include <boost/iostreams/stream.hpp>
3132
#include <boost/json.hpp>
3233
#include <boost/locale.hpp>
3334
#include <boost/multiprecision/cpp_int.hpp>
3435
#include <boost/program_options.hpp>
36+
#include <boost/url.hpp>
3537

3638
// ADL free functions for use with boost-json.
3739
#define DECLARE_JSON_VALUE_CONVERTORS(name) \

include/bitcoin/system/impl/unicode/ascii.ipp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ constexpr bool is_ascii_alpha(char32_t point) NOEXCEPT
5454
return is_ascii_lower(point) || is_ascii_upper(point);
5555
}
5656

57+
constexpr bool is_ascii_alphanumeric(char32_t point) NOEXCEPT
58+
{
59+
return is_ascii_alpha(point) || is_ascii_number(point);
60+
}
61+
5762
// see char32_separators[]
5863
constexpr bool is_ascii_separator(char32_t point) NOEXCEPT
5964
{

include/bitcoin/system/unicode/ascii.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ constexpr bool is_ascii_number(char32_t point) NOEXCEPT;
3030
constexpr bool is_ascii_lower(char32_t point) NOEXCEPT;
3131
constexpr bool is_ascii_upper(char32_t point) NOEXCEPT;
3232
constexpr bool is_ascii_alpha(char32_t point) NOEXCEPT;
33+
constexpr bool is_ascii_alphanumeric(char32_t point) NOEXCEPT;
3334
constexpr bool is_ascii_separator(char32_t point) NOEXCEPT;
3435
constexpr bool is_ascii_whitespace(char32_t point) NOEXCEPT;
3536

include/bitcoin/system/wallet/addresses/bitcoin_uri.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class BC_API bitcoin_uri
3939

4040
/// Constructors.
4141
bitcoin_uri() NOEXCEPT;
42-
bitcoin_uri(const std::string& uri, bool strict=true) NOEXCEPT;
42+
bitcoin_uri(const std::string& uri) NOEXCEPT;
4343

4444
/// Operators.
4545
bool operator<(const bitcoin_uri& other) const NOEXCEPT;
@@ -75,7 +75,6 @@ class BC_API bitcoin_uri
7575
void set_address(const stealth_address& stealth) NOEXCEPT;
7676

7777
/// uri_reader implementation.
78-
void set_strict(bool strict) NOEXCEPT;
7978
bool set_scheme(const std::string& scheme) NOEXCEPT;
8079
bool set_authority(const std::string& authority) NOEXCEPT;
8180
bool set_path(const std::string& path) NOEXCEPT;
@@ -87,7 +86,6 @@ class BC_API bitcoin_uri
8786
bool set_amount(const std::string& satoshis) NOEXCEPT;
8887

8988
/// Member state.
90-
bool strict_;
9189
std::string scheme_;
9290
std::string address_;
9391
std::map<std::string, std::string> query_;

include/bitcoin/system/wallet/addresses/uri.hpp

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,42 +30,42 @@ namespace wallet {
3030
class BC_API uri
3131
{
3232
public:
33+
typedef std::map<std::string, std::string> query_map;
34+
3335
DEFAULT_COPY_MOVE_DESTRUCT(uri);
3436
uri() NOEXCEPT {}
3537

3638
/// Decodes a URI from a string.
37-
/// @param strict set to false to tolerate unescaped special characters.
38-
bool decode(const std::string& encoded, bool strict=true) NOEXCEPT;
39+
bool decode(const std::string& encoded) NOEXCEPT;
3940
std::string encoded() const NOEXCEPT;
4041

41-
/// Returns the lowercased URI scheme.
42+
/// Returns the lowercased URI scheme (set empty to remove).
4243
std::string scheme() const NOEXCEPT;
43-
void set_scheme(const std::string& scheme) NOEXCEPT;
44+
bool has_scheme() const NOEXCEPT;
45+
bool set_scheme(const std::string& scheme) NOEXCEPT;
4446

4547
/// Obtains the unescaped authority part, if any (user@server:port).
4648
std::string authority() const NOEXCEPT;
4749
bool has_authority() const NOEXCEPT;
48-
void set_authority(const std::string& authority) NOEXCEPT;
50+
bool set_authority(const std::string& authority) NOEXCEPT;
4951
void remove_authority() NOEXCEPT;
5052

5153
/// Obtains the unescaped path part.
5254
std::string path() const NOEXCEPT;
53-
void set_path(const std::string& path) NOEXCEPT;
55+
bool set_path(const std::string& path) NOEXCEPT;
5456

5557
/// Returns the unescaped query string, if any.
5658
std::string query() const NOEXCEPT;
5759
bool has_query() const NOEXCEPT;
58-
void set_query(const std::string& query) NOEXCEPT;
60+
bool set_query(const std::string& query) NOEXCEPT;
5961
void remove_query() NOEXCEPT;
6062

6163
/// Returns the unescaped fragment string, if any.
6264
std::string fragment() const NOEXCEPT;
6365
bool has_fragment() const NOEXCEPT;
64-
void set_fragment(const std::string& fragment) NOEXCEPT;
66+
bool set_fragment(const std::string& fragment) NOEXCEPT;
6567
void remove_fragment() NOEXCEPT;
6668

67-
typedef std::map<std::string, std::string> query_map;
68-
6969
/// Interprets the query string as a sequence of key-value pairs.
7070
/// All query strings are valid, so this function cannot fail.
7171
/// The results are unescaped. Both keys and values can be zero-length,
@@ -74,16 +74,8 @@ class BC_API uri
7474
void encode_query(const query_map& map) NOEXCEPT;
7575

7676
private:
77-
// All parts are stored with their original escaping.
78-
std::string scheme_;
79-
std::string authority_;
80-
std::string path_;
81-
std::string query_;
82-
std::string fragment_;
83-
84-
bool has_authority_ = false;
85-
bool has_query_ = false;
86-
bool has_fragment_ = false;
77+
// Mutable URL object to store the parsed URI.
78+
boost::urls::url url_;
8779
};
8880

8981
} // namespace wallet

include/bitcoin/system/wallet/addresses/uri_reader.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,16 @@ class BC_API uri_reader
3939
/// @return The parsed URI or a default instance if the `uri` is malformed
4040
/// according to the `UriReader`.
4141
template <class UriReader>
42-
static UriReader parse(const std::string& uri, bool strict=true) NOEXCEPT
42+
static UriReader parse(const std::string& uri) NOEXCEPT
4343
{
4444
wallet::uri parsed;
45-
if (!parsed.decode(uri, strict))
45+
if (!parsed.decode(uri))
46+
return {};
47+
48+
UriReader out{};
49+
if (!out.set_scheme(parsed.scheme()))
4650
return {};
4751

48-
UriReader out;
49-
out.set_strict(strict);
50-
out.set_scheme(parsed.scheme());
5152
if (parsed.has_authority() && !out.set_authority(parsed.authority()))
5253
return {};
5354

@@ -70,7 +71,6 @@ class BC_API uri_reader
7071
}
7172

7273
/// uri_reader interface.
73-
virtual void set_strict(bool strict) NOEXCEPT = 0;
7474
virtual bool set_scheme(const std::string& scheme) NOEXCEPT = 0;
7575
virtual bool set_authority(const std::string& authority) NOEXCEPT = 0;
7676
virtual bool set_path(const std::string& path) NOEXCEPT = 0;

src/chain/script.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@ BC_PUSH_WARNING(NO_ARRAY_INDEXING)
4545
// that indicates height size. This is inconsistent with an extreme future
4646
// where the size byte overflows. However satoshi actually requires nominal
4747
// encoding.
48-
//*************************************************************************
48+
//*****************************************************************************
4949
bool script::is_coinbase_pattern(const operations& ops, size_t height) NOEXCEPT
5050
{
5151
using namespace machine::number;
5252
return !ops.empty()
5353
&& ops[0].is_nominal_push()
54-
&& ops[0].data() == chunk::from_integer(to_unsigned(height));
54+
&& ops[0].data() == chunk::from_integer(to_signed(height));
5555
}
5656

5757
// Constructors.

src/wallet/addresses/bitcoin_uri.cpp

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,11 @@ static const auto parameter_req_ = "req-";
3838
static constexpr size_t parameter_req_length = 4;
3939

4040
bitcoin_uri::bitcoin_uri() NOEXCEPT
41-
: strict_(true)
4241
{
4342
}
4443

45-
bitcoin_uri::bitcoin_uri(const std::string& uri, bool strict) NOEXCEPT
46-
: bitcoin_uri(uri_reader::parse<bitcoin_uri>(uri, strict))
44+
bitcoin_uri::bitcoin_uri(const std::string& uri) NOEXCEPT
45+
: bitcoin_uri(uri_reader::parse<bitcoin_uri>(uri))
4746
{
4847
}
4948

@@ -171,7 +170,7 @@ void bitcoin_uri::set_address(const stealth_address& stealth) NOEXCEPT
171170
bool bitcoin_uri::set_amount(const std::string& satoshis) NOEXCEPT
172171
{
173172
uint64_t decoded;
174-
if (!decode_base10(decoded, satoshis, btc_decimal_places, strict_))
173+
if (!decode_base10(decoded, satoshis, btc_decimal_places, true))
175174
return false;
176175

177176
// Normalize the encoding for string-based getter (parameter).
@@ -182,11 +181,6 @@ bool bitcoin_uri::set_amount(const std::string& satoshis) NOEXCEPT
182181
// uri_reader implementation.
183182
// ----------------------------------------------------------------------------
184183

185-
void bitcoin_uri::set_strict(bool strict) NOEXCEPT
186-
{
187-
strict_ = strict;
188-
}
189-
190184
bool bitcoin_uri::set_scheme(const std::string& scheme) NOEXCEPT
191185
{
192186
if (scheme == bitcoin_scheme)
@@ -201,8 +195,8 @@ bool bitcoin_uri::set_scheme(const std::string& scheme) NOEXCEPT
201195
bool bitcoin_uri::set_authority(const std::string& authority) NOEXCEPT
202196
{
203197
// Using "bitcoin://" instead of "bitcoin:" is a common mistake, so we
204-
// allow the authority in place of the path when not strict.
205-
return !strict_ && set_path(authority);
198+
// allow the authority in place of the path.
199+
return set_path(authority);
206200
}
207201

208202
bool bitcoin_uri::set_path(const std::string& path) NOEXCEPT
@@ -248,8 +242,8 @@ bool bitcoin_uri::operator<(const bitcoin_uri& other) const NOEXCEPT
248242

249243
bool bitcoin_uri::operator==(const bitcoin_uri& other) const NOEXCEPT
250244
{
251-
return strict_ == other.strict_ && scheme_ == other.scheme_ &&
252-
address_ == other.address_ && query_ == other.query_;
245+
return scheme_ == other.scheme_ && address_ == other.address_ &&
246+
query_ == other.query_;
253247
}
254248

255249
bool bitcoin_uri::operator!=(const bitcoin_uri& other) const NOEXCEPT

0 commit comments

Comments
 (0)