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