First commit

This commit is contained in:
giomba 2019-08-13 08:23:37 +02:00
commit da07035f17
9 changed files with 314 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
build/
old/
*.o

61
CNS.cpp Normal file
View File

@ -0,0 +1,61 @@
#include "CNS.h"
int read_CNS_hex_8(std::istringstream& stream) {
char what[2];
stream.read(what, 2);
std::string hexstring(what, 2);
int actual_number = std::stoi(hexstring, nullptr, 16);
return actual_number;
}
CNS dati_CNS_to_cpp() {
CNS data;
char* buffer;
size_t len;
int rv = read_dati_personali_c(&buffer, &len);
std::clog << "[D] " << rv << std::endl;
if (rv != 0) throw ExPCSC("can not read_dati_personali_c()");
//std::clog << "[D] " << len << '\t' << buffer << std::endl;
std::vector<std::string> field;
for (int i = 12; i < len; ) {
if (buffer[i] == '\0') break;
std::string hexstring(&buffer[i], 2);
int len = std::stoi(hexstring, nullptr, 16);
i += 2;
std::string fieldData(&buffer[i], len);
i += len;
field.push_back(fieldData);
}
free(buffer);
for (int i = 0; i < field.size(); ++i) {
std::clog << i << '\t' << field[i] << std::endl;
switch (i) {
case 0: data.dataRilascio = QDate::fromString(QString(field[i].data()), "ddMMyyyy"); break;
case 1: data.dataScadenza = QDate::fromString(QString(field[i].data()), "ddMMyyyy"); break;
case 2: data.cognome = QString(field[i].data()); break;
case 3: data.nome = QString(field[i].data()); break;
case 4: data.dataNascita = QDate::fromString(QString(field[i].data()), "ddMMyyyy"); break;
case 5: data.sesso = field[i] == "F" ? Sex::F : Sex::M; break; /* TODO what about other genders? */
case 7: data.codiceFiscale = QString(field[i].data()); break;
case 9: data.comuneNascita = QString(field[i].data()); break;
case 12: data.comuneResidenza = QString(field[i].data()); break;
default: break;
}
}
return data;
}

38
CNS.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef CONVERT_H
#define CONVERT_H
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <QDate>
#include <QString>
#include "Ex.h"
#include "read_dati_personali.h"
namespace Sex {
enum Sex {
F,
M
};
}
struct CNS {
QString nome;
QString cognome;
QDate dataNascita;
QString comuneNascita;
QString comuneResidenza;
QString codiceFiscale;
Sex::Sex sesso;
QDate dataRilascio;
QDate dataScadenza;
};
CNS dati_CNS_to_cpp(void);
#endif

21
Ex.cpp Normal file
View File

@ -0,0 +1,21 @@
#include "Ex.h"
Ex::Ex() {
this->msg = std::string("generic exception");
}
Ex::Ex(const char* msg) {
this->msg = std::string(msg);
}
/*
Ex::Ex(const char* msg, int n) {
this->msg = std::string(msg) + ": " + strerror(n);
}
*/
std::ostream& operator<<(std::ostream& os, const Ex& e) {
os << e.msg;
return os;
}

21
Ex.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef EXCEPTION_H
#define EXCEPTION_H
#include <iostream>
#include <string>
/* `explicit` specifier forces constructors to not being implicitly called */
class Ex {
private:
std::string msg;
public:
explicit Ex();
explicit Ex(const char* msg);
explicit Ex(const char* msg, int errn);
friend std::ostream& operator<<(std::ostream&, const Ex&);
};
/* Parent::Parent makes classes inherit their constructors from parents (C++11) */
class ExPCSC : public Ex { using Ex::Ex; };
#endif

43
cnsparser.pro Normal file
View File

@ -0,0 +1,43 @@
#----------------------------------------------------
# CNS-Parser for Italian Carta Nazionale dei Servizi
# adapted by giomba
#----------------------------------------------------
QT += core
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = cnsparser
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += c++11
SOURCES += \
main.cpp \
CNS.cpp \
Ex.cpp \
read_dati_personali.cpp
HEADERS += \
CNS.h \
Ex.h \
read_dati_personali.h
QMAKE_CXXFLAGS += $(shell pkg-config --cflags libpcsclite)
QMAKE_LFLAGS += $(shell pkg-config --libs libpcsclite)
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

24
main.cpp Normal file
View File

@ -0,0 +1,24 @@
#include <iostream>
#include "CNS.h"
int main(void) {
CNS cns;
int r = 0;
try {
cns = dati_CNS_to_cpp();
std::clog << "Data Rilascio:\t";
std::clog << cns.dataRilascio.year() << '-' << cns.dataRilascio.month() << '-' << cns.dataRilascio.day() << std::endl;
std::clog << "Data Scadenza:\t";
std::clog << cns.dataScadenza.year() << '-' << cns.dataScadenza.month() << '-' << cns.dataScadenza.day() << std::endl;
r = 0;
} catch (Ex e) {
std::cerr << "[E] exception: " << e << std::endl;
r = 1;
}
return r;
}

90
read_dati_personali.cpp Normal file
View File

@ -0,0 +1,90 @@
#include "read_dati_personali.h"
#define CHECK(f, rv) \
if (SCARD_S_SUCCESS != rv) \
{ \
printf("[E] " f ": %s\n", pcsc_stringify_error(rv)); \
return -1; \
}
int read_dati_personali_c(char** output_buffer, size_t* len) {
LONG rv;
SCARDCONTEXT hContext;
LPTSTR mszReaders;
SCARDHANDLE hCard;
DWORD dwReaders, dwActiveProtocol, dwRecvLength;
SCARD_IO_REQUEST pioSendPci;
BYTE pbRecvBuffer[1024];
BYTE cmd[4][7];
memcpy(cmd[0], "\x00\xA4\x00\x00\x02\03f\x00", 7);
memcpy(cmd[1], "\x00\xA4\x00\x00\x02\x11\x00", 7);
memcpy(cmd[2], "\x00\xA4\x00\x00\x02\x11\x02", 7);
memcpy(cmd[3], "\x00\xB0\x00\x00\x00\x00", 6);
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
CHECK("SCardEstablishContext", rv)
#ifdef SCARD_AUTOALLOCATE
dwReaders = SCARD_AUTOALLOCATE;
rv = SCardListReaders(hContext, NULL, (LPTSTR)&mszReaders, &dwReaders);
CHECK("SCardListReaders", rv)
#else
rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
CHECK("SCardListReaders", rv)
mszReaders = calloc(dwReaders, sizeof(char));
rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
CHECK("SCardListReaders", rv)
#endif
/* printf("reader name: %s\n", mszReaders); */
rv = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
CHECK("SCardConnect", rv)
switch(dwActiveProtocol) {
case SCARD_PROTOCOL_T0:
pioSendPci = *SCARD_PCI_T0;
break;
case SCARD_PROTOCOL_T1:
pioSendPci = *SCARD_PCI_T1;
break;
}
for (int j = 0; j < 4; ++j) {
dwRecvLength = sizeof(pbRecvBuffer);
/* TODO: hardcoded packet length*/
rv = SCardTransmit(hCard, &pioSendPci, cmd[j], ((j == 3) ? 6 : 7), NULL, pbRecvBuffer, &dwRecvLength);
CHECK("SCardTransmit", rv)
/*
printf("response %d\tlen %d\t", j, dwRecvLength);
printf("%.*s", dwRecvLength, pbRecvBuffer);
printf("\n");
*/
}
/* send back last buffer read */
*output_buffer = (char*)malloc(dwRecvLength);
memcpy(*output_buffer, pbRecvBuffer, dwRecvLength);
*len = dwRecvLength;
rv = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
CHECK("SCardDisconnect", rv)
#ifdef SCARD_AUTOALLOCATE
rv = SCardFreeMemory(hContext, mszReaders);
CHECK("SCardFreeMemory", rv)
#else
free(mszReaders);
#endif
rv = SCardReleaseContext(hContext);
CHECK("SCardReleaseContext", rv)
return 0;
}

12
read_dati_personali.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef READ_DATI_PERSONALI_H
#define READ_DATI_PERSONALI_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winscard.h>
int read_dati_personali_c(char** output_buffer, size_t* len);
#endif