AusweisApp2/src/global/BuildHelper.cpp

207 lines
4.6 KiB
C++

/*
* \copyright Copyright (c) 2014-2019 Governikus GmbH & Co. KG, Germany
*/
#include "BuildHelper.h"
#include "DeviceInfo.h"
#ifdef Q_OS_ANDROID
#include "VersionNumber.h"
#include <QAndroidJniEnvironment>
#include <QAndroidJniObject>
#include <QtAndroid>
#endif
#include <openssl/crypto.h>
#include <QSysInfo>
using namespace governikus;
#ifdef Q_OS_ANDROID
namespace
{
QAndroidJniObject getPackageInfo(const QString& pPackageName, int pFlags = 0)
{
QAndroidJniEnvironment env;
auto context = QtAndroid::androidContext();
auto manager = context.callObjectMethod("getPackageManager",
"()Landroid/content/pm/PackageManager;");
if (manager.isValid())
{
const auto& str = QAndroidJniObject::fromString(pPackageName);
return manager.callObjectMethod("getPackageInfo",
"(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;",
str.object<jstring>(), pFlags);
}
if (env->ExceptionCheck())
{
env->ExceptionDescribe();
env->ExceptionClear();
}
return QAndroidJniObject();
}
} // namespace
int BuildHelper::getVersionCode()
{
static int version_code = -1;
if (version_code == -1)
{
version_code = getVersionCode(getPackageName());
}
return version_code;
}
int BuildHelper::getVersionCode(const QString& pPackageName)
{
const auto info = getPackageInfo(pPackageName);
if (info.isValid())
{
return info.getField<jint>("versionCode");
}
return -1;
}
QString BuildHelper::getPackageName()
{
auto context = QtAndroid::androidContext();
auto name = context.callObjectMethod("getPackageName", "()Ljava/lang/String;");
if (name.isValid())
{
return name.toString();
}
return QString();
}
QByteArrayList BuildHelper::getAppCertificates()
{
return getAppCertificates(getPackageName());
}
QByteArrayList BuildHelper::getAppCertificates(const QString& pPackageName)
{
const int flags = 0x00000040; // GET_SIGNATURES
const auto info = getPackageInfo(pPackageName, flags);
if (!info.isValid())
{
return QByteArrayList();
}
const auto signatures = info.getObjectField("signatures", "[Landroid/content/pm/Signature;");
if (!signatures.isValid())
{
return QByteArrayList();
}
QAndroidJniEnvironment env;
jobjectArray obj = signatures.object<jobjectArray>();
const jsize elementCount = env->GetArrayLength(obj);
QByteArrayList list;
list.reserve(elementCount);
for (jsize i = 0; i < elementCount; ++i)
{
QAndroidJniObject elem = env->GetObjectArrayElement(obj, i);
if (!elem.isValid())
{
continue;
}
auto bytes = elem.callObjectMethod("toByteArray", "()[B");
if (!bytes.isValid())
{
continue;
}
jbyteArray data = bytes.object<jbyteArray>();
const auto size = env->GetArrayLength(data);
jbyte* buffer = env->GetByteArrayElements(data, 0);
list << QByteArray(reinterpret_cast<const char* const>(buffer), size).toHex();
}
if (env->ExceptionCheck())
{
env->ExceptionDescribe();
env->ExceptionClear();
}
return list;
}
#endif
QVector<QPair<QLatin1String, QString> > BuildHelper::getInformationHeader()
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define OpenSSL_version SSLeay_version
#define OPENSSL_VERSION SSLEAY_VERSION
#endif
QVector<QPair<QLatin1String, QString> > data;
const auto& add = [&data](const char* pKey, const QString& pStr)
{
data << qMakePair(QLatin1String(pKey), pStr);
};
add(QT_TR_NOOP("Application"), QCoreApplication::applicationName());
add(QT_TR_NOOP("Application Version"), QCoreApplication::applicationVersion());
add(QT_TR_NOOP("Organization"), QCoreApplication::organizationName());
add(QT_TR_NOOP("Organization Domain"), QCoreApplication::organizationDomain());
add(QT_TR_NOOP("System"), QSysInfo::prettyProductName());
add(QT_TR_NOOP("Kernel"), QSysInfo::kernelVersion());
QString architecture = QSysInfo::currentCpuArchitecture();
#ifdef Q_OS_ANDROID
if (architecture != QSysInfo::buildCpuArchitecture())
{
architecture += QStringLiteral(" (%1)").arg(QSysInfo::buildCpuArchitecture());
}
#endif
add(QT_TR_NOOP("Architecture"), architecture);
#ifdef Q_OS_ANDROID
add(QT_TR_NOOP("Device"), DeviceInfo::getPrettyInfo());
add(QT_TR_NOOP("VersionCode"), QString::number(getVersionCode()));
#else
add(QT_TR_NOOP("Device"), DeviceInfo::getName());
#endif
add(QT_TR_NOOP("Qt Version"), QString::fromLatin1(qVersion()));
add(QT_TR_NOOP("OpenSSL Version"), QString::fromLatin1(OpenSSL_version(OPENSSL_VERSION)));
return data;
}
void BuildHelper::processInformationHeader(const std::function<void(const QString&, const QString&)>& pFunc, bool pTranslate)
{
const auto& info = getInformationHeader();
for (const auto& entry : info)
{
const auto& key = entry.first;
pFunc(pTranslate ? tr(key.data()) : QString(key), entry.second);
}
}