<commit_before>/* Chrome Linux plugin
*
* This software is released under either the GNU Library General Public
* License (see LICENSE.LGPL).
*
* Note that the only valid version of the LGPL license as far as this
* project is concerned is the original GNU Library General Public License
* Version 2.1, February 1999
*/

#pragma once

#include "PKCS11CardManager.h"
#include "BinaryUtils.h"
#include "Labels.h"

#include <QDebug>
#include <QDialog>
#include <QDialogButtonBox>
#include <QLabel>
#include <QLineEdit>
#include <QProgressBar>
#include <QPushButton>
#include <QRegExpValidator>
#include <QTimeLine>
#include <QVBoxLayout>

#include <future>
#include <string>

class Signer: public QDialog {
public:
    static QVariantMap sign(const QString &hash, const QString &cert) {
        switch(hash.length())
        {
        case BINARY_SHA1_LENGTH * 2:
        case BINARY_SHA224_LENGTH * 2:
        case BINARY_SHA256_LENGTH * 2:
        case BINARY_SHA384_LENGTH * 2:
        case BINARY_SHA512_LENGTH * 2: break;
        default:
            return {{"result", "invalid_argument"}};
        }

        std::unique_ptr<PKCS11CardManager> manager;
        try {
            for (auto &token : PKCS11CardManager::instance()->getAvailableTokens()) {
                manager.reset(PKCS11CardManager::instance()->getManagerForReader(token));
                if (manager->getSignCert() == BinaryUtils::hex2bin(cert.toStdString())) {
                    break;
                }
                manager.reset();
            }

            if(!manager)
                return {{"result", "invalid_argument"}};
        } catch (const std::runtime_error &a) {
            return {{"result", "technical_error"}};
        }

        bool isInitialCheck = true;
        for (int retriesLeft = manager->getPIN2RetryCount(); retriesLeft > 0; ) {
            Signer dialog(manager->isPinpad());
            if (retriesLeft < 3) {
                dialog.errorLabel->setText(QString("<font color='red'><b>%1%2 %3</b></font>")
                     .arg((!isInitialCheck ? Labels::l10n.get("incorrect PIN2") : "").c_str())
                     .arg(Labels::l10n.get("tries left").c_str())
                     .arg(retriesLeft));
            }
            isInitialCheck = false;
            dialog.nameLabel->setText((manager->getCardName() + ", " + manager->getPersonalCode()).c_str());
            std::future< std::vector<unsigned char> > signature;

            if (manager->isPinpad()) {
                signature = std::async(std::launch::async, [&](){
                    std::vector<unsigned char> result;
                    try {
                        result = manager->sign(BinaryUtils::hex2bin(hash.toStdString()), nullptr);
                        dialog.accept();
                    } catch (const AuthenticationError &) {
                        --retriesLeft;
                        dialog.done(-2);
                    } catch (const AuthenticationBadInput &) {
                        dialog.done(-2);
                    } catch (const UserCanceledError &) {
                        dialog.reject();
                    } catch (const std::runtime_error &) {
                        dialog.done(-1);
                    }
                    return result;
                });
            }

            switch (dialog.exec())
            {
            case 0:
                return {{"result", "user_cancel"}};
            case -2:
                continue;
            case -1:
                return {{"result", "technical_error"}};
            default:
                if (manager->isPinpad()) {
                    return {{"signature", BinaryUtils::bin2hex(signature.get()).c_str()}};
                }
            }

            try {
                if (!manager->isPinpad()) {
                    std::vector<unsigned char> result = manager->sign(
                        BinaryUtils::hex2bin(hash.toStdString()),
                        dialog.pin->text().toUtf8().constData());
                    return {{"signature", BinaryUtils::bin2hex(result).c_str()}};
                }
            } catch (const AuthenticationBadInput &) {
            } catch (const AuthenticationError &) {
                --retriesLeft;
            } catch (const UserCanceledError &) {
                return {{"result", "user_cancel"}};
            } catch (const std::runtime_error &) {
                return {{"result", "technical_error"}};
            }
        }
        return {{"result", "pin_blocked"}};
    }

private:
    Signer(bool isPinpad)
        : nameLabel(new QLabel(this))
        , pinLabel(new QLabel(this))
        , errorLabel(new QLabel(this))
    {
        QVBoxLayout *layout = new QVBoxLayout(this);
        layout->addWidget(errorLabel);
        layout->addWidget(nameLabel);
        layout->addWidget(pinLabel);

        setMinimumWidth(350);
        setWindowFlags(Qt::WindowStaysOnTopHint);
        setWindowTitle(Labels::l10n.get("signing").c_str());
        pinLabel->setText(Labels::l10n.get(isPinpad ? "enter PIN2 pinpad" : "enter PIN2").c_str());
        errorLabel->setTextFormat(Qt::RichText);<commit_msg>Hide error label by default<commit_after>/* Chrome Linux plugin
*
* This software is released under either the GNU Library General Public
* License (see LICENSE.LGPL).
*
* Note that the only valid version of the LGPL license as far as this
* project is concerned is the original GNU Library General Public License
* Version 2.1, February 1999
*/

#pragma once

#include "PKCS11CardManager.h"
#include "BinaryUtils.h"
#include "Labels.h"

#include <QDebug>
#include <QDialog>
#include <QDialogButtonBox>
#include <QLabel>
#include <QLineEdit>
#include <QProgressBar>
#include <QPushButton>
#include <QRegExpValidator>
#include <QTimeLine>
#include <QVBoxLayout>

#include <future>
#include <string>

class Signer: public QDialog {
public:
    static QVariantMap sign(const QString &hash, const QString &cert) {
        switch(hash.length())
        {
        case BINARY_SHA1_LENGTH * 2:
        case BINARY_SHA224_LENGTH * 2:
        case BINARY_SHA256_LENGTH * 2:
        case BINARY_SHA384_LENGTH * 2:
        case BINARY_SHA512_LENGTH * 2: break;
        default:
            return {{"result", "invalid_argument"}};
        }

        std::unique_ptr<PKCS11CardManager> manager;
        try {
            for (auto &token : PKCS11CardManager::instance()->getAvailableTokens()) {
                manager.reset(PKCS11CardManager::instance()->getManagerForReader(token));
                if (manager->getSignCert() == BinaryUtils::hex2bin(cert.toStdString())) {
                    break;
                }
                manager.reset();
            }

            if(!manager)
                return {{"result", "invalid_argument"}};
        } catch (const std::runtime_error &a) {
            return {{"result", "technical_error"}};
        }

        bool isInitialCheck = true;
        for (int retriesLeft = manager->getPIN2RetryCount(); retriesLeft > 0; ) {
            Signer dialog(manager->isPinpad());
            if (retriesLeft < 3) {
                dialog.errorLabel->show();
                dialog.errorLabel->setText(QString("<font color='red'><b>%1%2 %3</b></font>")
                     .arg((!isInitialCheck ? Labels::l10n.get("incorrect PIN2") : "").c_str())
                     .arg(Labels::l10n.get("tries left").c_str())
                     .arg(retriesLeft));
            }
            isInitialCheck = false;
            dialog.nameLabel->setText((manager->getCardName() + ", " + manager->getPersonalCode()).c_str());
            std::future< std::vector<unsigned char> > signature;

            if (manager->isPinpad()) {
                signature = std::async(std::launch::async, [&](){
                    std::vector<unsigned char> result;
                    try {
                        result = manager->sign(BinaryUtils::hex2bin(hash.toStdString()), nullptr);
                        dialog.accept();
                    } catch (const AuthenticationError &) {
                        --retriesLeft;
                        dialog.done(-2);
                    } catch (const AuthenticationBadInput &) {
                        dialog.done(-2);
                    } catch (const UserCanceledError &) {
                        dialog.reject();
                    } catch (const std::runtime_error &) {
                        dialog.done(-1);
                    }
                    return result;
                });
            }

            switch (dialog.exec())
            {
            case 0:
                return {{"result", "user_cancel"}};
            case -2:
                continue;
            case -1:
                return {{"result", "technical_error"}};
            default:
                if (manager->isPinpad()) {
                    return {{"signature", BinaryUtils::bin2hex(signature.get()).c_str()}};
                }
            }

            try {
                if (!manager->isPinpad()) {
                    std::vector<unsigned char> result = manager->sign(
                        BinaryUtils::hex2bin(hash.toStdString()),
                        dialog.pin->text().toUtf8().constData());
                    return {{"signature", BinaryUtils::bin2hex(result).c_str()}};
                }
            } catch (const AuthenticationBadInput &) {
            } catch (const AuthenticationError &) {
                --retriesLeft;
            } catch (const UserCanceledError &) {
                return {{"result", "user_cancel"}};
            } catch (const std::runtime_error &) {
                return {{"result", "technical_error"}};
            }
        }
        return {{"result", "pin_blocked"}};
    }

private:
    Signer(bool isPinpad)
        : nameLabel(new QLabel(this))
        , pinLabel(new QLabel(this))
        , errorLabel(new QLabel(this))
    {
        QVBoxLayout *layout = new QVBoxLayout(this);
        layout->addWidget(errorLabel);
        layout->addWidget(nameLabel);
        layout->addWidget(pinLabel);

        setMinimumWidth(350);
        setWindowFlags(Qt::WindowStaysOnTopHint);
        setWindowTitle(Labels::l10n.get("signing").c_str());
        pinLabel->setText(Labels::l10n.get(isPinpad ? "enter PIN2 pinpad" : "enter PIN2").c_str());
        errorLabel->setTextFormat(Qt::RichText);
        errorLabel->hide();
{'fraction_non_alphanumeric': 0.12970630717380838, 'fraction_numerical': 0.012325469427058257, 'mean_word_length': 1.8207495926127104, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 89, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2714474', 'n_tokens_mistral': 2960, 'n_tokens_neox': 2784, 'n_words': 567}