diff --git a/client/Diagnostics.cpp b/client/Diagnostics.cpp index 7d1edbd2..c2c8b9aa 100644 --- a/client/Diagnostics.cpp +++ b/client/Diagnostics.cpp @@ -122,7 +122,6 @@ void Diagnostics::generalInfo(QTextStream &s) continue; s << "ATR - " << reader.atr() << "
"; - reader.beginTransaction(); constexpr auto APDU = &QByteArray::fromHex; auto printAID = [&](QLatin1String label, const QByteArray &apdu) { diff --git a/client/MainWindow.cpp b/client/MainWindow.cpp index 92b97c1b..f2e56c49 100644 --- a/client/MainWindow.cpp +++ b/client/MainWindow.cpp @@ -86,18 +86,16 @@ MainWindow::MainWindow( QWidget *parent ) // Refresh ID card info in card widget connect(qApp->signer(), &QSigner::cacheChanged, this, &MainWindow::updateSelector); - connect(&QPCSC::instance(), &QPCSC::statusChanged, this, &MainWindow::updateSelector); connect(qApp->signer(), &QSigner::signDataChanged, this, [this](const TokenData &token) { - updateSelectorData(token); + updateSelector(); updateMyEID(token); ui->signContainerPage->cardChanged(token.cert(), token.data(QStringLiteral("blocked")).toBool()); }); connect(qApp->signer(), &QSigner::authDataChanged, this, [this](const TokenData &token) { - updateSelectorData(token); + updateSelector(); updateMyEID(token); ui->cryptoContainerPage->cardChanged(token.cert(), token.data(QStringLiteral("blocked")).toBool()); }); - QPCSC::instance().start(); // Refresh card info on "My EID" page connect(qApp->signer()->smartcard(), &QSmartCard::dataChanged, this, &MainWindow::updateMyEid); @@ -124,7 +122,7 @@ MainWindow::MainWindow( QWidget *parent ) connect(ui->accordion, &Accordion::changePinClicked, this, &MainWindow::changePinClicked); connect(ui->cardInfo, &CardWidget::selected, ui->selector, &QToolButton::toggle); - updateSelectorData(qApp->signer()->tokensign()); + updateSelector(); updateMyEID(qApp->signer()->tokensign()); ui->signContainerPage->cardChanged(qApp->signer()->tokensign().cert()); ui->cryptoContainerPage->cardChanged(qApp->signer()->tokenauth().cert()); @@ -846,11 +844,7 @@ bool MainWindow::wrapContainer(bool signing) void MainWindow::updateSelector() { - updateSelectorData({}); -} - -void MainWindow::updateSelectorData(TokenData data) -{ + TokenData selected; enum Filter: uint8_t { Signing, Decrypting, @@ -860,24 +854,24 @@ void MainWindow::updateSelectorData(TokenData data) { case SignIntro: case SignDetails: - if(data.isNull()) data = qApp->signer()->tokensign(); + selected = qApp->signer()->tokensign(); filter = Signing; break; case CryptoIntro: case CryptoDetails: - if(data.isNull()) data = qApp->signer()->tokenauth(); + selected = qApp->signer()->tokenauth(); filter = Decrypting; break; case MyEid: default: - if(data.isNull()) data = qApp->signer()->smartcard()->tokenData(); + selected = qApp->signer()->smartcard()->tokenData(); filter = MyEID; break; } QVector list; for(const TokenData &token: qApp->signer()->cache()) { - if(token.card() == data.card()) + if(token.card() == selected.card()) continue; if(std::any_of(list.cbegin(), list.cend(), [token](const TokenData &item) { return token.card() == item.card(); })) continue; @@ -891,12 +885,12 @@ void MainWindow::updateSelectorData(TokenData data) continue; list.append(token); } - ui->noCardInfo->setVisible(ui->cardInfo->token().isNull()); + ui->noCardInfo->setVisible(selected.isNull()); ui->selector->setHidden(list.isEmpty()); ui->selector->setChecked(false); ui->cardInfo->setVisible(ui->noCardInfo->isHidden()); ui->cardInfo->setCursor(ui->selector->isVisible() ? Qt::PointingHandCursor : Qt::ArrowCursor); - ui->cardInfo->update(data, list.size() > 1); + ui->cardInfo->update(selected, list.size() > 1); if (!QPCSC::instance().serviceRunning()) ui->noCardInfo->update(NoCardInfo::NoPCSC); else if(QPCSC::instance().readers().isEmpty()) @@ -910,7 +904,7 @@ void MainWindow::updateSelectorData(TokenData data) if(show) { auto *cardPopup = new CardPopup(list, this); - connect(cardPopup, &CardPopup::activated, qApp->signer(), &QSigner::selectCard, Qt::QueuedConnection); + connect(cardPopup, &CardPopup::activated, qApp->signer(), &QSigner::selectCard); connect(cardPopup, &CardPopup::activated, this, [this] { ui->selector->setChecked(false); }); cardPopup->show(); } diff --git a/client/MainWindow.h b/client/MainWindow.h index f8c83865..38782dc2 100644 --- a/client/MainWindow.h +++ b/client/MainWindow.h @@ -83,7 +83,6 @@ class MainWindow final : public QWidget void sign(F &&sign); bool validateFiles(const QString &container, const QStringList &files); void updateSelector(); - void updateSelectorData(TokenData data); void updateMyEID(const TokenData &t); void updateMyEid(const QSmartCardData &data); bool wrap(const QString& wrappedFile, bool enclose); diff --git a/client/QCNG.cpp b/client/QCNG.cpp index 1162a9a7..7107299e 100644 --- a/client/QCNG.cpp +++ b/client/QCNG.cpp @@ -23,7 +23,9 @@ #include "SslCertificate.h" #include "TokenData.h" +#include #include +#include #include using namespace Qt::Literals::StringLiterals; @@ -220,7 +222,9 @@ QList QCNG::tokens() const if(QByteArray tmp = prop(key, NCRYPT_READER_PROPERTY); !tmp.isEmpty()) reader = QString::fromUtf16((const char16_t*)tmp.data()); } - QString guid = prop(h, NCRYPT_SMARTCARD_GUID_PROPERTY).trimmed(); + QByteArray guidData = prop(h, NCRYPT_SMARTCARD_GUID_PROPERTY); + static const QRegularExpression reg(QStringLiteral("\\w{1,2}\\d{7} *")); + QString guid = reg.match(guidData).hasMatch() ? guidData.trimmed() : QUuid(*((GUID*)guidData.data())).toString(QUuid::WithBraces); TokenData &t = result.emplaceBack(); t.setReader(reader); t.setCard(cert.type() & SslCertificate::EstEidType || cert.type() & SslCertificate::DigiIDType ? @@ -232,7 +236,8 @@ QList QCNG::tokens() const qCWarning(CNG) << "key" << t.data(u"provider"_s) << "spec" << t.data(u"spec"_s) << "alg" << QStringView(keyname->pszAlgid) - << "flags" << keyname->dwFlags; + << "flags" << keyname->dwFlags + << t.card(); if(cert.publicKey().algorithm() != QSsl::Rsa || reader.isEmpty()) continue; diff --git a/client/QPCSC.cpp b/client/QPCSC.cpp index 3ea63220..c16f9f9d 100644 --- a/client/QPCSC.cpp +++ b/client/QPCSC.cpp @@ -76,7 +76,7 @@ QHash QPCSCReader::Private::features() for(const auto &f: feature) { if(f.tag) - featuresList[DRIVER_FEATURES(f.tag)] = qFromBigEndian(f.value); + featuresList[f.tag] = qFromBigEndian(f.value); } return featuresList; } @@ -94,10 +94,12 @@ QPCSC::QPCSC() QPCSC::~QPCSC() { requestInterruption(); + d->sleepCond.wakeAll(); + if(d->thread) + SC(Cancel, d->thread); wait(); - if( d->context ) + if(d->context) SC(ReleaseContext, d->context); - qDeleteAll(d->lock); delete d; } @@ -138,16 +140,14 @@ void QPCSC::run() std::vector list; while(!isInterruptionRequested()) { - if(!pcsc.serviceRunning()) - { - sleep(5); - continue; - } // "\\?PnP?\Notification" does not work on macOS QByteArray data = pcsc.rawReaders(); if(data.isEmpty()) { - sleep(5); + QMutexLocker locker(&d->sleepMutex); + if (isInterruptionRequested()) + break; + d->sleepCond.wait(&d->sleepMutex, 5000); continue; } for(const char *name = data.constData(); *name; name += strlen(name) + 1) @@ -155,6 +155,15 @@ void QPCSC::run() if(std::none_of(list.cbegin(), list.cend(), [&name](const SCARD_READERSTATE &state) { return strcmp(state.szReader, name) == 0; })) list.push_back({ strdup(name), nullptr, 0, 0, 0, {} }); } + if(list.empty()) + { + QMutexLocker locker(&d->sleepMutex); + if (isInterruptionRequested()) + break; + d->sleepCond.wait(&d->sleepMutex, 5000); + continue; + } + d->thread = pcsc.d->context; if(SC(GetStatusChange, pcsc.d->context, 5*1000U, list.data(), DWORD(list.size())) != SCARD_S_SUCCESS) continue; for(auto i = list.begin(); i != list.end(); ) @@ -164,6 +173,8 @@ void QPCSC::run() ++i; continue; } + if((i->dwCurrentState & SCARD_STATE_PRESENT) != (i->dwEventState & SCARD_STATE_PRESENT)) + Q_EMIT cardChanged(); i->dwCurrentState = i->dwEventState; qCDebug(SCard) << "New state: " << QString::fromLocal8Bit(i->szReader) << stateToString(i->dwCurrentState); Q_EMIT statusChanged(QString::fromLocal8Bit(i->szReader), stateToString(i->dwCurrentState)); @@ -176,6 +187,7 @@ void QPCSC::run() ++i; } } + d->thread = {}; } bool QPCSC::serviceRunning() const @@ -191,19 +203,19 @@ bool QPCSC::serviceRunning() const QPCSCReader::QPCSCReader( const QString &reader, QPCSC *parent ) : d(new Private) { - if(!parent->d->lock.contains(reader)) - parent->d->lock[reader] = new QMutex(); - parent->d->lock[reader]->lock(); d->d = parent->d; d->reader = reader.toUtf8(); d->state.szReader = d->reader.constData(); - updateState(); + if(parent->d->context) + SC(GetStatusChange, d->d->context, 0, &d->state, 1U); } QPCSCReader::~QPCSCReader() { - disconnect(); - d->d->lock[d->reader]->unlock(); + if(d->isTransacted) + SC(EndTransaction, d->card, SCARD_LEAVE_CARD); + if(d->card) + SC(Disconnect, d->card, SCARD_LEAVE_CARD); delete d; } @@ -212,29 +224,12 @@ QByteArray QPCSCReader::atr() const return QByteArray::fromRawData((const char*)d->state.rgbAtr, int(d->state.cbAtr)).toHex().toUpper(); } -bool QPCSCReader::beginTransaction() -{ - return d->isTransacted = SC(BeginTransaction, d->card) == SCARD_S_SUCCESS; -} - bool QPCSCReader::connect(Connect connect, Mode mode) { - LONG err = SC(Connect, d->d->context, d->state.szReader, connect, mode, &d->card, &d->io.dwProtocol); - updateState(); - return err == SCARD_S_SUCCESS; -} - -void QPCSCReader::disconnect( Reset reset ) -{ - if(d->isTransacted) - SC(EndTransaction, d->card, reset); - d->isTransacted = false; - if( d->card ) - SC(Disconnect, d->card, reset); - d->io.dwProtocol = SCARD_PROTOCOL_UNDEFINED; - d->card = {}; - d->featuresList.clear(); - updateState(); + if(SC(Connect, d->d->context, d->state.szReader, connect, mode, &d->card, &d->io.dwProtocol) != SCARD_S_SUCCESS) + return false; + d->isTransacted = SC(BeginTransaction, d->card) == SCARD_S_SUCCESS; + return true; } bool QPCSCReader::isPinPad() const @@ -272,7 +267,7 @@ QHash QPCSCReader::properties() const int tag = *p++, len = *p++, value = 0; for(int i = 0; i < len; ++i) value |= *p++ << 8 * i; - properties[Properties(tag)] = value; + properties.emplace(Properties(tag), value); } } return properties; @@ -303,7 +298,7 @@ QPCSCReader::Result QPCSCReader::transfer( const QByteArray &apdu ) const case 0x6100: // Read more { QByteArray cmd( "\x00\xC0\x00\x00\x00", 5 ); - cmd[4] = data.at(int(size - 1)); + cmd[4] = char(result.SW); Result result2 = transfer( cmd ); result2.data.prepend(result.data); return result2; @@ -397,16 +392,3 @@ QPCSCReader::Result QPCSCReader::transferCTL(const QByteArray &apdu, bool verify if(!result.data.isEmpty()) qCDebug(APDU).nospace().noquote() << result.data.toHex(); return result; } - -bool QPCSCReader::updateState( quint32 msec ) -{ - if(!d->d->context) - return false; - d->state.dwCurrentState = d->state.dwEventState; - switch(SC(GetStatusChange, d->d->context, msec, &d->state, 1U)) - { - case LONG(SCARD_S_SUCCESS): return true; - case LONG(SCARD_E_TIMEOUT): return msec == 0; - default: return false; - } -} diff --git a/client/QPCSC.h b/client/QPCSC.h index 4bbef764..772b46a2 100644 --- a/client/QPCSC.h +++ b/client/QPCSC.h @@ -36,6 +36,7 @@ class QPCSC final: public QThread Q_SIGNALS: void statusChanged(const QString &reader, const QStringList &state); + void cardChanged(); private: QPCSC(); @@ -44,7 +45,7 @@ class QPCSC final: public QThread QByteArray rawReaders() const; void run() final; - class Private; + struct Private; Private *d; friend class QPCSCReader; @@ -61,7 +62,7 @@ class QPCSCReader final: public QObject constexpr operator bool() const { return SW == 0x9000; } }; - enum Properties { + enum Properties : quint8 { wLcdLayout = 0x01, bEntryValidationCondition = 0x02, bTimeOut2 = 0x03, @@ -76,21 +77,20 @@ class QPCSCReader final: public QObject wIdProduct = 0x0C }; - enum Connect { + enum Connect : quint8 { Exclusive = 1, Shared = 2, Direct = 3 }; - enum Reset - { + enum Reset : quint8 { LeaveCard = 0, ResetCard = 1, UnpowerCard = 2, EjectCard = 3 }; - enum Mode { + enum Mode : quint8 { Undefined = 0, T0 = 1, T1 = 2 @@ -105,17 +105,14 @@ class QPCSCReader final: public QObject QString name() const; QHash properties() const; QStringList state() const; - bool updateState( quint32 msec = 0 ); bool connect( Connect connect = Shared, Mode mode = Mode(T0|T1) ); - void disconnect( Reset reset = LeaveCard ); - bool beginTransaction(); Result transfer( const QByteArray &apdu ) const; Result transferCTL(const QByteArray &apdu, bool verify, quint16 lang = 0, quint8 minlen = 4, quint8 newPINOffset = 0, bool requestCurrentPIN = true) const; private: Q_DISABLE_COPY(QPCSCReader) - class Private; + struct Private; Private *d; }; diff --git a/client/QPCSC_p.h b/client/QPCSC_p.h index 4ffa83b5..7fd830fe 100644 --- a/client/QPCSC_p.h +++ b/client/QPCSC_p.h @@ -23,6 +23,7 @@ #include #include +#include #ifdef Q_OS_WIN #undef UNICODE @@ -73,7 +74,7 @@ FEATURE_CCID_ESC_COMMAND = 0x13 struct PCSC_TLV_STRUCTURE { - quint8 tag; + DRIVER_FEATURES tag; quint8 length; quint32 value; }; @@ -178,16 +179,16 @@ struct DISPLAY_PROPERTIES_STRUCTURE #pragma pack(pop) -class QPCSC::Private +struct QPCSC::Private { -public: SCARDCONTEXT context {}; - QHash lock; + SCARDCONTEXT thread {}; + QMutex sleepMutex; + QWaitCondition sleepCond; }; -class QPCSCReader::Private +struct QPCSCReader::Private { -public: QHash features(); QPCSC::Private *d {}; diff --git a/client/QSigner.cpp b/client/QSigner.cpp index 94b5e604..a7b57e00 100644 --- a/client/QSigner.cpp +++ b/client/QSigner.cpp @@ -20,6 +20,7 @@ #include "QSigner.h" #include "Application.h" +#include "QPCSC.h" #include "QSmartCard.h" #include "TokenData.h" #ifdef Q_OS_WIN @@ -34,8 +35,9 @@ #include #include +#include #include -#include +#include #include #include @@ -52,6 +54,8 @@ class QSigner::Private final TokenData auth, sign; QList cache; QReadWriteLock lock; + QMutex sleepMutex; + QWaitCondition sleepCond; static ECDSA_SIG* ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey); @@ -135,12 +139,18 @@ QSigner::QSigner(QObject *parent) } setMethod(method); }); + connect(&QPCSC::instance(), &QPCSC::cardChanged, this, [this] { + qCDebug(SLog) << "Card change detected"; + d->sleepCond.wakeAll(); + }); start(); + QPCSC::instance().start(); } QSigner::~QSigner() { requestInterruption(); + d->sleepCond.wakeAll(); wait(); delete d->smartcard; RSA_meth_free(d->rsamethod); @@ -150,42 +160,6 @@ QSigner::~QSigner() QList QSigner::cache() const { return d->cache; } -bool QSigner::cardsOrder(const TokenData &s1, const TokenData &s2) -{ - static auto cardsOrderScore = [](QChar c) -> quint8 { - switch(c.toLatin1()) - { - case 'N': return 6; - case 'A': return 5; - case 'P': return 4; - case 'E': return 3; - case 'F': return 2; - case 'B': return 1; - default: return 0; - } - }; - static const QRegularExpression reg(QStringLiteral("(\\w{1,2})(\\d{7})")); - QRegularExpressionMatch r1 = reg.match(s1.card()); - QRegularExpressionMatch r2 = reg.match(s2.card()); - if(r1.hasMatch() || r2.hasMatch()) - return false; - QStringList cap1 = r1.capturedTexts(); - QStringList cap2 = r1.capturedTexts(); - if(cap1.isEmpty() || cap2.isEmpty()) - return false; - // new cards to front - if(cap1[1].size() != cap2[1].size()) - return cap1[1].size() > cap2[1].size(); - // card type order - if(cap1[1][0] != cap2[1][0]) - return cardsOrderScore(cap1[1][0]) > cardsOrderScore(cap2[1][0]); - // card version order - if(cap1[1].size() > 1 && cap2[1].size() > 1 && cap1[1][1] != cap2[1][1]) - return cap1[1][1] > cap2[1][1]; - // serial number order - return cap1[2].toUInt() > cap2[2].toUInt(); -} - X509Cert QSigner::cert() const { if( d->sign.cert().isNull() ) @@ -265,7 +239,7 @@ quint8 QSigner::login(const TokenData &cert) const default: d->lock.unlock(); // QSmartCard should also know that PIN is blocked. - std::thread(&QSmartCard::reloadCard, d->smartcard, d->smartcard->tokenData(), true).detach(); + d->smartcard->reloadCard(d->smartcard->tokenData(), true); return status; } } @@ -275,7 +249,7 @@ void QSigner::logout() const d->backend->logout(); d->lock.unlock(); // QSmartCard should also know that PIN1 info is updated - std::thread(&QSmartCard::reloadCard, d->smartcard, d->smartcard->tokenData(), true).detach(); + d->smartcard->reloadCard(d->smartcard->tokenData(), true); } QCryptographicHash::Algorithm QSigner::methodToNID(const std::string &method) @@ -322,7 +296,6 @@ void QSigner::run() QList acards, scards; QList cache = d->backend->tokens(); - std::sort(cache.begin(), cache.end(), cardsOrder); if(cache != d->cache) { d->cache = std::move(cache); @@ -370,13 +343,16 @@ void QSigner::run() d->lock.unlock(); } - if(!isInterruptionRequested()) - sleep( 5 ); + QMutexLocker locker(&d->sleepMutex); + if (isInterruptionRequested()) + break; + d->sleepCond.wait(&d->sleepMutex, 5000); } } void QSigner::selectCard(const TokenData &token) { + d->smartcard->reloadCard(token, false); bool isSign = SslCertificate(token.cert()).keyUsage().contains(SslCertificate::NonRepudiation); if(isSign) Q_EMIT signDataChanged(d->sign = token); @@ -394,7 +370,6 @@ void QSigner::selectCard(const TokenData &token) Q_EMIT signDataChanged(d->sign = other); break; } - std::thread(&QSmartCard::reloadCard, d->smartcard, token, false).detach(); } std::vector QSigner::sign(const std::string &method, const std::vector &digest ) const diff --git a/client/QSigner.h b/client/QSigner.h index e15d2e01..1e03d397 100644 --- a/client/QSigner.h +++ b/client/QSigner.h @@ -58,7 +58,6 @@ class QSigner final: public QThread, public digidoc::Signer void error( const QString &msg ); private: - static bool cardsOrder(const TokenData &s1, const TokenData &s2); quint8 login(const TokenData &cert) const; static QCryptographicHash::Algorithm methodToNID(const std::string &method); void run() final; diff --git a/client/QSmartCard.cpp b/client/QSmartCard.cpp index 4f9eb5b1..b5338c69 100644 --- a/client/QSmartCard.cpp +++ b/client/QSmartCard.cpp @@ -546,7 +546,7 @@ bool QSmartCard::pinChange(QSmartCardData::PinType type, QSmartCard::PinAction a } QPCSCReader reader(d->t.reader(), &QPCSC::instance()); - if(!reader.connect() || !reader.beginTransaction()) + if(!reader.connect()) { FadeInNotification::warning(parent, tr("Changing %1 failed").arg(QSmartCardData::typeString(type))); return false; @@ -614,61 +614,63 @@ void QSmartCard::reloadCard(const TokenData &token, bool reloadCounters) { qCDebug(CLog) << "Polling"; d->token = token; - if(!reloadCounters && !d->t.isNull() && !d->t.card().isEmpty() && d->t.card() == token.card()) + if(!reloadCounters && !d->t.isNull() && !d->t.card().isEmpty() && d->t.card() == d->token.card()) return; - // check if selected card is same as signer - if(!d->t.card().isEmpty() && token.card() != d->t.card()) - d->t.d = new QSmartCardDataPrivate(); + std::thread([&] { + // check if selected card is same as signer + if(!d->t.card().isEmpty() && d->token.card() != d->t.card()) + d->t.d = new QSmartCardDataPrivate(); - // select signer card - if(d->t.card().isEmpty() || d->t.card() != token.card()) - { - QSharedDataPointer t = d->t.d; - t->card = token.card(); - t->data.clear(); - t->authCert.clear(); - t->signCert.clear(); - d->t.d = std::move(t); - } + // select signer card + if(d->t.card().isEmpty() || d->t.card() != d->token.card()) + { + QSharedDataPointer t = d->t.d; + t->card = d->token.card(); + t->data.clear(); + t->authCert.clear(); + t->signCert.clear(); + d->t.d = std::move(t); + } - if(!reloadCounters && (!d->t.isNull() || token.reader().isEmpty())) - return; + if(!reloadCounters && (!d->t.isNull() || d->token.reader().isEmpty())) + return; - QString reader = token.reader(); - if(token.reader().endsWith(QLatin1String("..."))) { - for(const QString &test: QPCSC::instance().readers()) { - if(test.startsWith(token.reader().left(token.reader().size() - 3))) - reader = test; + QString reader = d->token.reader(); + if(d->token.reader().endsWith(QLatin1String("..."))) { + for(const QString &test: QPCSC::instance().readers()) { + if(test.startsWith(d->token.reader().left(d->token.reader().size() - 3))) + reader = test; + } } - } - qCDebug(CLog) << "Read" << reader; - QPCSCReader selectedReader(reader, &QPCSC::instance()); - if(!selectedReader.connect() || !selectedReader.beginTransaction()) - return; + qCDebug(CLog) << "Read" << reader; + QPCSCReader selectedReader(reader, &QPCSC::instance()); + if(!selectedReader.connect()) + return; - if(auto atr = selectedReader.atr(); - IDEMIACard::isSupported(atr)) - d->card = std::make_unique(); - else if(THALESCard::isSupported(atr)) - d->card = std::make_unique(); - else { - qCDebug(CLog) << "Unsupported card"; - return; - } + if(auto atr = selectedReader.atr(); + IDEMIACard::isSupported(atr)) + d->card = std::make_unique(); + else if(THALESCard::isSupported(atr)) + d->card = std::make_unique(); + else { + qCDebug(CLog) << "Unsupported card"; + return; + } - qCDebug(CLog) << "Read card" << token.card() << "info"; - QSharedDataPointer t = d->t.d; - t->reader = selectedReader.name(); - t->pinpad = selectedReader.isPinPad(); - if(d->card->loadPerso(&selectedReader, t)) - { - d->t.d = std::move(t); - emit dataChanged(d->t); - } - else - qCDebug(CLog) << "Failed to read card info, try again next round"; + qCDebug(CLog) << "Read card" << d->token.card() << "info"; + QSharedDataPointer t = d->t.d; + t->reader = selectedReader.name(); + t->pinpad = selectedReader.isPinPad(); + if(d->card->loadPerso(&selectedReader, t)) + { + d->t.d = std::move(t); + emit dataChanged(d->t); + } + else + qCDebug(CLog) << "Failed to read card info, try again next round"; + }).detach(); } TokenData QSmartCard::tokenData() const { return d->token; } diff --git a/client/TokenData.cpp b/client/TokenData.cpp index b695e5e6..cfca1e6b 100644 --- a/client/TokenData.cpp +++ b/client/TokenData.cpp @@ -58,8 +58,6 @@ bool TokenData::isNull() const { TokenData& TokenData::operator =( const TokenData &other ) = default; TokenData& TokenData::operator =(TokenData &&other) Q_DECL_NOEXCEPT = default; -bool TokenData::operator !=( const TokenData &other ) const { return !(operator==(other)); } - bool TokenData::operator ==( const TokenData &other ) const { return d == other.d || ( diff --git a/client/TokenData.h b/client/TokenData.h index 1a471413..1a3176fb 100644 --- a/client/TokenData.h +++ b/client/TokenData.h @@ -48,7 +48,6 @@ class TokenData TokenData& operator =( const TokenData &other ); TokenData& operator =(TokenData &&other) Q_DECL_NOEXCEPT; - bool operator !=( const TokenData &other ) const; bool operator ==( const TokenData &other ) const; private: