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: