2017-07-03 09:30:10 +02:00
|
|
|
/*!
|
2018-03-28 15:10:51 +02:00
|
|
|
* \copyright Copyright (c) 2014-2018 Governikus GmbH & Co. KG, Germany
|
2017-07-03 09:30:10 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "SelfAuthenticationData.h"
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
#include "LanguageLoader.h"
|
|
|
|
|
2017-07-03 09:30:10 +02:00
|
|
|
#include <QDomDocument>
|
|
|
|
#include <QLoggingCategory>
|
|
|
|
|
|
|
|
Q_DECLARE_LOGGING_CATEGORY(secure)
|
|
|
|
|
|
|
|
using namespace governikus;
|
|
|
|
|
|
|
|
|
|
|
|
SelfAuthenticationData::SelfAuthenticationData(const QByteArray& pData)
|
2017-12-20 14:54:05 +01:00
|
|
|
: d(new SelfData(pData))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SelfAuthenticationData::isValid() const
|
|
|
|
{
|
|
|
|
return d->mValid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString SelfAuthenticationData::getValue(SelfAuthData pData) const
|
|
|
|
{
|
|
|
|
return d->getValue(pData);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const QDateTime& SelfAuthenticationData::getDateTime() const
|
2017-07-03 09:30:10 +02:00
|
|
|
{
|
2017-12-20 14:54:05 +01:00
|
|
|
return d->mDateTime;
|
2017-07-03 09:30:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
SelfAuthenticationData::OrderedSelfData SelfAuthenticationData::getOrderedSelfData() const
|
2017-07-03 09:30:10 +02:00
|
|
|
{
|
2017-12-20 14:54:05 +01:00
|
|
|
return d->getOrderedSelfInfo();
|
2017-07-03 09:30:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
SelfAuthenticationData::SelfData::SelfData(const QByteArray& pData)
|
|
|
|
: mValid(false)
|
|
|
|
, mDateTime(QDateTime::currentDateTime())
|
|
|
|
, mOperationsAllowed()
|
|
|
|
, mSelfAuthData()
|
2017-07-03 09:30:10 +02:00
|
|
|
{
|
2017-12-20 14:54:05 +01:00
|
|
|
if (pData.isEmpty())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2017-07-03 09:30:10 +02:00
|
|
|
qCDebug(secure) << "parsing data:" << pData;
|
|
|
|
|
|
|
|
QDomDocument doc(QStringLiteral("dataXML"));
|
|
|
|
|
|
|
|
QString errorMsg;
|
|
|
|
int errorLine;
|
|
|
|
int errorColumn;
|
|
|
|
if (!doc.setContent(pData, true, &errorMsg, &errorLine, &errorColumn))
|
|
|
|
{
|
|
|
|
qDebug() << "XML parsing failed. No valid values to parse. Error in line" << errorLine << "column"
|
|
|
|
<< errorColumn << ":" << errorMsg;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
const auto& parseOperations = std::bind(&SelfAuthenticationData::SelfData::parseOperationsAllowedByUser, this, std::placeholders::_1);
|
|
|
|
const auto& parsePersonal = std::bind(&SelfAuthenticationData::SelfData::parsePersonalData, this, std::placeholders::_1);
|
2017-07-03 09:30:10 +02:00
|
|
|
mValid = parse(doc, QStringLiteral("OperationsAllowedByUser"), parseOperations) && parse(doc, QStringLiteral("PersonalData"), parsePersonal);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
QString SelfAuthenticationData::SelfData::getValue(SelfAuthData pData) const
|
|
|
|
{
|
|
|
|
if (mOperationsAllowed.value(pData) == SelfAuthDataPermission::ALLOWED)
|
|
|
|
{
|
|
|
|
return mSelfAuthData.value(pData);
|
|
|
|
}
|
|
|
|
else if (mOperationsAllowed.value(pData) == SelfAuthDataPermission::NOTONCHIP)
|
|
|
|
{
|
|
|
|
if (pData == SelfAuthData::Nationality && getValue(SelfAuthData::DocumentType) == QLatin1String("ID"))
|
|
|
|
{
|
|
|
|
return QStringLiteral("D");
|
|
|
|
}
|
|
|
|
|
|
|
|
return tr("This data has not been stored in this chip generation.");
|
|
|
|
}
|
|
|
|
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool SelfAuthenticationData::SelfData::parseOperationsAllowedByUser(const QDomElement& pElement)
|
2017-07-03 09:30:10 +02:00
|
|
|
{
|
|
|
|
for (auto elem = pElement; !elem.isNull(); elem = elem.nextSiblingElement())
|
|
|
|
{
|
|
|
|
auto authData = Enum<SelfAuthData>::fromString(elem.tagName(), SelfAuthData::UNKNOWN);
|
|
|
|
if (authData == SelfAuthData::UNKNOWN)
|
|
|
|
{
|
|
|
|
qWarning() << "SelfAuthData is unknown:" << elem.tagName();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto permission = Enum<SelfAuthDataPermission>::fromString(elem.text(), SelfAuthDataPermission::UNKNOWN);
|
|
|
|
if (permission == SelfAuthDataPermission::UNKNOWN)
|
|
|
|
{
|
|
|
|
qWarning() << "SelfAuthDataPermission is unknown:" << elem.tagName();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
mOperationsAllowed.insert(authData, permission);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
bool SelfAuthenticationData::SelfData::parsePersonalData(const QDomElement& pElement)
|
2017-07-03 09:30:10 +02:00
|
|
|
{
|
|
|
|
for (auto elem = pElement; !elem.isNull(); elem = elem.nextSiblingElement())
|
|
|
|
{
|
|
|
|
auto authData = Enum<SelfAuthData>::fromString(elem.tagName(), SelfAuthData::UNKNOWN);
|
|
|
|
if (authData == SelfAuthData::UNKNOWN)
|
|
|
|
{
|
|
|
|
qWarning() << "PersonalData is unknown:" << elem.tagName();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (authData == SelfAuthData::DateOfBirth)
|
|
|
|
{
|
|
|
|
tryToInsertChild(elem.firstChildElement(QStringLiteral("DateValue")), authData);
|
|
|
|
}
|
|
|
|
else if (authData == SelfAuthData::PlaceOfBirth)
|
|
|
|
{
|
|
|
|
tryToInsertChild(elem.firstChildElement(QStringLiteral("FreetextPlace")), authData);
|
|
|
|
}
|
|
|
|
else if (authData == SelfAuthData::PlaceOfResidence)
|
|
|
|
{
|
|
|
|
if (tryToInsertChild(elem.firstChildElement(QStringLiteral("NoPlaceInfo")), SelfAuthData::PlaceOfResidenceNoPlaceInfo))
|
|
|
|
{
|
|
|
|
mOperationsAllowed.insert(SelfAuthData::PlaceOfResidenceNoPlaceInfo, mOperationsAllowed.value(authData));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
static const QMap<QString, SelfAuthData> placeInfo = {
|
|
|
|
{QStringLiteral("City"), SelfAuthData::PlaceOfResidenceCity},
|
|
|
|
{QStringLiteral("Country"), SelfAuthData::PlaceOfResidenceCountry},
|
|
|
|
{QStringLiteral("Street"), SelfAuthData::PlaceOfResidenceStreet},
|
|
|
|
{QStringLiteral("ZipCode"), SelfAuthData::PlaceOfResidenceZipCode}
|
|
|
|
};
|
|
|
|
|
|
|
|
auto structuredPlace = elem.firstChildElement(QStringLiteral("StructuredPlace"));
|
|
|
|
for (auto iter = placeInfo.constBegin(); iter != placeInfo.constEnd(); ++iter)
|
|
|
|
{
|
|
|
|
if (tryToInsertChild(structuredPlace.firstChildElement(iter.key()), iter.value()))
|
|
|
|
{
|
|
|
|
mOperationsAllowed.insert(iter.value(), mOperationsAllowed.value(authData));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tryToInsertChild(elem, authData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
bool SelfAuthenticationData::SelfData::tryToInsertChild(const QDomElement& pElement, SelfAuthData pAuthData)
|
2017-07-03 09:30:10 +02:00
|
|
|
{
|
|
|
|
if (pElement.isNull() || pElement.text().isNull())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mSelfAuthData.insert(pAuthData, pElement.text());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
bool SelfAuthenticationData::SelfData::parse(const QDomDocument& pDoc, const QString& pElementName, const std::function<bool(const QDomElement&)>& pParserFunc)
|
2017-07-03 09:30:10 +02:00
|
|
|
{
|
|
|
|
const QDomNodeList nodeList = pDoc.documentElement().elementsByTagName(pElementName);
|
|
|
|
if (nodeList.size() == 0)
|
|
|
|
{
|
|
|
|
qCritical() << "XML parsing failed. No valid values to parse for:" << pElementName;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pParserFunc(nodeList.at(0).toElement().firstChildElement());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
SelfAuthenticationData::OrderedSelfData SelfAuthenticationData::SelfData::getOrderedSelfInfo() const
|
2017-07-03 09:30:10 +02:00
|
|
|
{
|
2017-12-20 14:54:05 +01:00
|
|
|
OrderedSelfData orderedSelfData;
|
2017-07-03 09:30:10 +02:00
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
if (!mValid)
|
|
|
|
{
|
|
|
|
return orderedSelfData;
|
|
|
|
}
|
2017-07-03 09:30:10 +02:00
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
const auto& formatDate = [](const QString& pIn){
|
|
|
|
QDateTime dateTime = QDateTime::fromString(pIn, QStringLiteral("yyyy-MM-dd+hh:mm"));
|
|
|
|
return LanguageLoader::getInstance().getUsedLocale().toString(dateTime, tr("dd.MM.yyyy"));
|
|
|
|
};
|
|
|
|
|
|
|
|
const auto& add = [&](const QString& pKey, const QString& pValue){
|
|
|
|
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
|
|
|
|
if (!pKey.isEmpty())
|
|
|
|
{
|
|
|
|
orderedSelfData << qMakePair(pKey + QLatin1Char(':'), pValue);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
orderedSelfData << qMakePair(pKey, pValue);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//fill layout with new data, see 18 Personalausweisgesetz (PAuswG)
|
|
|
|
if (!getValue(SelfAuthData::FamilyNames).isNull())
|
2017-07-03 09:30:10 +02:00
|
|
|
{
|
2017-12-20 14:54:05 +01:00
|
|
|
add(tr("Family name"), getValue(SelfAuthData::FamilyNames));
|
2017-07-03 09:30:10 +02:00
|
|
|
}
|
2017-12-20 14:54:05 +01:00
|
|
|
if (!getValue(SelfAuthData::BirthName).isNull())
|
2017-07-03 09:30:10 +02:00
|
|
|
{
|
2017-12-20 14:54:05 +01:00
|
|
|
add(tr("Birth name"), getValue(SelfAuthData::BirthName));
|
|
|
|
}
|
|
|
|
if (!getValue(SelfAuthData::GivenNames).isNull())
|
|
|
|
{
|
|
|
|
add(tr("Given name(s)"), getValue(SelfAuthData::GivenNames));
|
|
|
|
}
|
|
|
|
if (!getValue(SelfAuthData::AcademicTitle).isNull())
|
|
|
|
{
|
|
|
|
add(tr("Doctoral degree"), getValue(SelfAuthData::AcademicTitle));
|
|
|
|
}
|
|
|
|
if (!getValue(SelfAuthData::DateOfBirth).isNull())
|
|
|
|
{
|
|
|
|
add(tr("Date of birth"), formatDate(getValue(SelfAuthData::DateOfBirth)));
|
|
|
|
}
|
|
|
|
if (!getValue(SelfAuthData::PlaceOfBirth).isNull())
|
|
|
|
{
|
|
|
|
add(tr("Place of birth"), getValue(SelfAuthData::PlaceOfBirth));
|
|
|
|
}
|
|
|
|
if (!getValue(SelfAuthData::PlaceOfResidenceNoPlaceInfo).isNull())
|
|
|
|
{
|
|
|
|
add(tr("Address"), getValue(SelfAuthData::PlaceOfResidenceNoPlaceInfo));
|
|
|
|
}
|
|
|
|
if (!getValue(SelfAuthData::PlaceOfResidenceStreet).isNull())
|
|
|
|
{
|
|
|
|
add(getValue(SelfAuthData::PlaceOfResidenceNoPlaceInfo).isNull() ? tr("Address") : QString(), getValue(SelfAuthData::PlaceOfResidenceStreet));
|
|
|
|
}
|
|
|
|
if (!getValue(SelfAuthData::PlaceOfResidenceZipCode).isNull() || !getValue(SelfAuthData::PlaceOfResidenceCity).isNull())
|
|
|
|
{
|
|
|
|
add(getValue(SelfAuthData::PlaceOfResidenceStreet).isNull() ? tr("Address") : QString(), getValue(SelfAuthData::PlaceOfResidenceZipCode) + QLatin1Char(' ') + getValue(SelfAuthData::PlaceOfResidenceCity));
|
|
|
|
}
|
|
|
|
if (!getValue(SelfAuthData::PlaceOfResidenceCountry).isNull())
|
|
|
|
{
|
|
|
|
add(QString(), getValue(SelfAuthData::PlaceOfResidenceCountry));
|
|
|
|
}
|
2017-07-03 09:30:10 +02:00
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
const auto& documentType = getValue(SelfAuthData::DocumentType);
|
|
|
|
if (!documentType.isNull())
|
|
|
|
{
|
|
|
|
add(tr("Document type"), documentType);
|
|
|
|
}
|
|
|
|
if (!getValue(SelfAuthData::Nationality).isNull())
|
|
|
|
{
|
|
|
|
add(tr("Nationality"), getValue(SelfAuthData::Nationality));
|
|
|
|
}
|
|
|
|
if (!getValue(SelfAuthData::ArtisticName).isNull())
|
|
|
|
{
|
|
|
|
add(tr("Religious / artistic name"), getValue(SelfAuthData::ArtisticName));
|
|
|
|
}
|
|
|
|
if (!getValue(SelfAuthData::IssuingState).isNull())
|
|
|
|
{
|
|
|
|
add(tr("Issuing country"), getValue(SelfAuthData::IssuingState));
|
2017-07-03 09:30:10 +02:00
|
|
|
}
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
// Show "Residence Permit" for eAT- and Test-Cards only
|
|
|
|
// AR, AS, AF --> see TR-03127 (v1.16) chapter 3.2.3
|
|
|
|
// TA --> Used by Test-Cards
|
|
|
|
if (!getValue(SelfAuthData::ResidencePermitI).isNull() && (
|
|
|
|
documentType == QLatin1String("AR") ||
|
|
|
|
documentType == QLatin1String("AS") ||
|
|
|
|
documentType == QLatin1String("AF") ||
|
|
|
|
documentType == QLatin1String("TA")))
|
|
|
|
{
|
|
|
|
add(tr("Residence permit I"), getValue(SelfAuthData::ResidencePermitI));
|
|
|
|
}
|
|
|
|
|
|
|
|
return orderedSelfData;
|
2017-07-03 09:30:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-12-20 14:54:05 +01:00
|
|
|
#include "moc_SelfAuthenticationData.cpp"
|