limenkaaddressvalidator.cpp raw
1 // Copyright (c) 2011-2018 The Limenka 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 <qt/limenkaaddressvalidator.h>
6
7 #include <key_io.h>
8
9 #include <vector>
10
11 /* Base58 characters are:
12 "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
13
14 This is:
15 - All numbers except for '0'
16 - All upper-case letters except for 'I' and 'O'
17 - All lower-case letters except for 'l'
18 */
19
20 LimenkaAddressEntryValidator::LimenkaAddressEntryValidator(QObject *parent) :
21 QValidator(parent)
22 {
23 }
24
25 QValidator::State LimenkaAddressEntryValidator::validate(QString &input, std::vector<int>&error_locations) const
26 {
27 // Empty address is "intermediate" input
28 if (input.isEmpty())
29 return QValidator::Intermediate;
30
31 // Correction
32 for (int idx = 0; idx < input.size();)
33 {
34 bool removeChar = false;
35 QChar ch = input.at(idx);
36 // Corrections made are very conservative on purpose, to avoid
37 // users unexpectedly getting away with typos that would normally
38 // be detected, and thus sending to the wrong address.
39 switch(ch.unicode())
40 {
41 // Qt categorizes these as "Other_Format" not "Separator_Space"
42 case 0x200B: // ZERO WIDTH SPACE
43 case 0xFEFF: // ZERO WIDTH NO-BREAK SPACE
44 removeChar = true;
45 break;
46 default:
47 break;
48 }
49
50 // Remove whitespace
51 if (ch.isSpace())
52 removeChar = true;
53
54 // To next character
55 if (removeChar)
56 input.remove(idx, 1);
57 else
58 ++idx;
59 }
60
61 // Validation
62 QValidator::State state = QValidator::Acceptable;
63 for (int idx = 0; idx < input.size(); ++idx)
64 {
65 int ch = input.at(idx).unicode();
66
67 if (((ch >= '0' && ch<='9') ||
68 (ch >= 'a' && ch<='z') ||
69 (ch >= 'A' && ch<='Z')) &&
70 ch != 'I' && ch != 'O') // Characters invalid in both Base58 and Bech32
71 {
72 // Alphanumeric and not a 'forbidden' character
73 }
74 else
75 {
76 error_locations.push_back(idx);
77 state = QValidator::Invalid;
78 }
79 }
80
81 return state;
82 }
83
84 QValidator::State LimenkaAddressEntryValidator::validate(QString &input, int &pos) const
85 {
86 std::vector<int> error_locations;
87 const auto ret = validate(input, error_locations);
88 if (!error_locations.empty()) pos = error_locations.at(0);
89 return ret;
90 }
91
92 LimenkaAddressCheckValidator::LimenkaAddressCheckValidator(QObject *parent) :
93 LimenkaAddressEntryValidator(parent)
94 {
95 }
96
97 QValidator::State LimenkaAddressCheckValidator::validate(QString &input, std::vector<int>&error_locations) const
98 {
99 // Validate the passed Limenka address
100 std::string error_msg;
101 CTxDestination dest = DecodeDestination(input.toStdString(), error_msg, &error_locations);
102 if (IsValidDestination(dest)) {
103 return QValidator::Acceptable;
104 }
105
106 return QValidator::Invalid;
107 }
108