/ src / qt / bitcoinaddressvalidator.cpp
bitcoinaddressvalidator.cpp
 1  // Copyright (c) 2011-2018 The Bitcoin Core 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/bitcoinaddressvalidator.h>
 6  
 7  #include <key_io.h>
 8  
 9  /* Base58 characters are:
10       "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
11  
12    This is:
13    - All numbers except for '0'
14    - All upper-case letters except for 'I' and 'O'
15    - All lower-case letters except for 'l'
16  */
17  
18  BitcoinAddressEntryValidator::BitcoinAddressEntryValidator(QObject *parent) :
19      QValidator(parent)
20  {
21  }
22  
23  QValidator::State BitcoinAddressEntryValidator::validate(QString &input, int &pos) const
24  {
25      Q_UNUSED(pos);
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              state = QValidator::Invalid;
77          }
78      }
79  
80      return state;
81  }
82  
83  BitcoinAddressCheckValidator::BitcoinAddressCheckValidator(QObject *parent) :
84      QValidator(parent)
85  {
86  }
87  
88  QValidator::State BitcoinAddressCheckValidator::validate(QString &input, int &pos) const
89  {
90      Q_UNUSED(pos);
91      // Validate the passed Bitcoin address
92      if (IsValidDestinationString(input.toStdString())) {
93          return QValidator::Acceptable;
94      }
95  
96      return QValidator::Invalid;
97  }