Merge remote-tracking branch 'origin/3.0'

Change-Id: Id2e682dc2698e08f91bee83e2a94de57403545a0
This commit is contained in:
Katja Marttila 2017-09-25 09:00:45 +03:00
commit 741d16a9bd
6 changed files with 196 additions and 27 deletions

View File

@ -126,13 +126,11 @@ DEFINES += NOMINMAX QT_NO_CAST_FROM_ASCII QT_STRICT_ITERATORS QT_USE_QSTRINGBUIL
IFW_VERSION_STR=$$IFW_VERSION_STR IFW_VERSION=$$IFW_VERSION
DEFINES += IFW_REPOSITORY_FORMAT_VERSION=$$IFW_REPOSITORY_FORMAT_VERSION
static {
LIBS += -l7z
win32-g++*: LIBS += -lmpr -luuid
LIBS += -l7z
win32-g++*: LIBS += -lmpr -luuid
equals(TEMPLATE, app) {
msvc:POST_TARGETDEPS += $$IFW_LIB_PATH/installer.lib $$IFW_LIB_PATH/7z.lib
win32-g++*:POST_TARGETDEPS += $$IFW_LIB_PATH/libinstaller.a $$IFW_LIB_PATH/lib7z.a
unix:POST_TARGETDEPS += $$IFW_LIB_PATH/libinstaller.a $$IFW_LIB_PATH/lib7z.a
}
equals(TEMPLATE, app) {
msvc:POST_TARGETDEPS += $$IFW_LIB_PATH/installer.lib $$IFW_LIB_PATH/7z.lib
win32-g++*:POST_TARGETDEPS += $$IFW_LIB_PATH/libinstaller.a $$IFW_LIB_PATH/lib7z.a
unix:POST_TARGETDEPS += $$IFW_LIB_PATH/libinstaller.a $$IFW_LIB_PATH/lib7z.a
}

View File

@ -2,6 +2,8 @@ TEMPLATE = lib
TARGET = installer
INCLUDEPATH += . ..
CONFIG += staticlib
include(../7zip/7zip.pri)
include(../kdtools/kdtools.pri)
include(../../../installerfw.pri)

View File

@ -1439,11 +1439,11 @@ Errore durante lo scaricamento %2</translation>
</message>
<message>
<source>Click Done to exit the %1 Wizard.</source>
<translation>Clicca Fatto per uscire dalla procedura guidatadi %1.</translation>
<translation>Clicca Fatto per uscire dalla procedura guidata di %1.</translation>
</message>
<message>
<source>Click Finish to exit the %1 Wizard.</source>
<translation>Clicca Finito per uscire dalla procedura guidatadi %1.</translation>
<translation>Clicca Finito per uscire dalla procedura guidata di %1.</translation>
</message>
<message>
<source>Restart</source>

View File

@ -870,6 +870,10 @@
<source>&amp;Deselect All</source>
<translation>&amp;Снять отметки выбора со всех компонентов</translation>
</message>
<message>
<source>&amp;Browse QBSP files</source>
<translation>&amp;Обзор файлов QBSP</translation>
</message>
<message>
<source>This component will occupy approximately %1 on your hard disk drive.</source>
<translation>Этот компонент займёт приблизительно %1 на жестком диске.</translation>
@ -891,16 +895,12 @@
<translation>Пожалуйста, выберите компоненты, которые вы хотите удалить.</translation>
</message>
<message>
<source>Select the components to install. Deselect installed components to uninstall them.</source>
<translation>Выберите компоненты для установки.Для удаления уже установленных компонентов снимите отметки выбора.</translation>
<source>Select the components to install. Deselect installed components to uninstall them. Any components already installed will not be updated.</source>
<translation>Выберите компоненты для установки. Для удаления уже установленных компонентов снимите отметки выбора. Уже установленные компоненты не будут обновлены.</translation>
</message>
<message>
<source>To install new compressed repository, browse the repositories from your computer</source>
<translation type="unfinished">Для установки нового хранилища укажите путь к нему на вашем компьютере</translation>
</message>
<message>
<source>&amp;Browse BSP or 7z files...</source>
<translation>&amp;Обзор BSP или 7z файлов...</translation>
<translation>Для установки нового хранилища укажите путь к нему на вашем компьютере</translation>
</message>
<message>
<source>Open File</source>
@ -1155,9 +1155,8 @@ Error while loading %2</source>
<translation>Обнаружено несовпадение контрольной суммы «%1».</translation>
</message>
<message>
<source>Network error while downloading &quot;%1&quot;: %2</source>
<extracomment>%2 is a sentence describing the error</extracomment>
<translation>Возникла ошибка сети при загрузке «%1»: %2</translation>
<source>Network error while downloading &apos;%1&apos;: %2.</source>
<translation>Возникла ошибка сети при загрузке «%1»: %2.</translation>
</message>
<message>
<source>Unknown network error while downloading &quot;%1&quot;.</source>
@ -1463,6 +1462,10 @@ Error while loading %2</source>
<source>Preparing meta information download...</source>
<translation>Подготовка к загрузке метаданных...</translation>
</message>
<message>
<source>Unpacking compressed repositories. This may take a while...</source>
<translation>Распаковка сжатых хранилищ. Это может занять некоторое время...</translation>
</message>
<message>
<source>Meta data download canceled.</source>
<translation>Загрузка метаданных отменена.</translation>
@ -1495,10 +1498,6 @@ Error while loading %2</source>
<source>Extracting meta information...</source>
<translation>Извлечение метаданных...</translation>
</message>
<message>
<source>Unpacking compressed repositories...</source>
<translation>Распаковка сжатых хранилищ...</translation>
</message>
<message>
<source>Error while extracting archive &quot;%1&quot;: %2</source>
<translation>Ошибка извлечения из архива «%1»: %2</translation>

View File

@ -50,6 +50,15 @@
#include <iostream>
#ifdef Q_OS_MACOS
#include <QtCore/QtEndian>
#include <QtCore/QFile>
#include <QtCore/QVersionNumber>
#include <mach-o/fat.h>
#include <mach-o/loader.h>
#endif
using namespace QInstaller;
struct Input {
@ -99,6 +108,159 @@ static void chmod755(const QString &absolutFilePath)
}
#endif
#ifdef Q_OS_MACOS
template <typename T = uint32_t> T readInt(QIODevice *ioDevice, bool *ok,
bool swap, bool peek = false) {
const auto bytes = peek
? ioDevice->peek(sizeof(T))
: ioDevice->read(sizeof(T));
if (bytes.size() != sizeof(T)) {
if (ok)
*ok = false;
return T();
}
if (ok)
*ok = true;
T n = *reinterpret_cast<const T *>(bytes.constData());
return swap ? qbswap(n) : n;
}
static QVersionNumber readMachOMinimumSystemVersion(QIODevice *device)
{
bool ok;
std::vector<qint64> machoOffsets;
qint64 pos = device->pos();
uint32_t magic = readInt(device, &ok, false);
if (magic == FAT_MAGIC || magic == FAT_CIGAM ||
magic == FAT_MAGIC_64 || magic == FAT_CIGAM_64) {
bool swap = magic == FAT_CIGAM || magic == FAT_CIGAM_64;
uint32_t nfat = readInt(device, &ok, swap);
if (!ok)
return QVersionNumber();
for (uint32_t n = 0; n < nfat; ++n) {
const bool is64bit = magic == FAT_MAGIC_64 || magic == FAT_CIGAM_64;
fat_arch_64 fat_arch;
fat_arch.cputype = static_cast<cpu_type_t>(readInt(device, &ok, swap));
if (!ok)
return QVersionNumber();
fat_arch.cpusubtype = static_cast<cpu_subtype_t>(readInt(device, &ok, swap));
if (!ok)
return QVersionNumber();
fat_arch.offset = is64bit
? readInt<uint64_t>(device, &ok, swap) : readInt(device, &ok, swap);
if (!ok)
return QVersionNumber();
fat_arch.size = is64bit
? readInt<uint64_t>(device, &ok, swap) : readInt(device, &ok, swap);
if (!ok)
return QVersionNumber();
fat_arch.align = readInt(device, &ok, swap);
if (!ok)
return QVersionNumber();
fat_arch.reserved = is64bit ? readInt(device, &ok, swap) : 0;
if (!ok)
return QVersionNumber();
machoOffsets.push_back(static_cast<qint64>(fat_arch.offset));
}
} else if (!ok) {
return QVersionNumber();
}
// Wasn't a fat file, so we just read a thin Mach-O from the original offset
if (machoOffsets.empty())
machoOffsets.push_back(pos);
std::vector<QVersionNumber> versions;
for (const auto &offset : machoOffsets) {
if (!device->seek(offset))
return QVersionNumber();
bool swap = false;
mach_header_64 header;
header.magic = readInt(device, nullptr, swap);
switch (header.magic) {
case MH_CIGAM:
case MH_CIGAM_64:
swap = true;
break;
case MH_MAGIC:
case MH_MAGIC_64:
break;
default:
return QVersionNumber();
}
header.cputype = static_cast<cpu_type_t>(readInt(device, &ok, swap));
if (!ok)
return QVersionNumber();
header.cpusubtype = static_cast<cpu_subtype_t>(readInt(device, &ok, swap));
if (!ok)
return QVersionNumber();
header.filetype = readInt(device, &ok, swap);
if (!ok)
return QVersionNumber();
header.ncmds = readInt(device, &ok, swap);
if (!ok)
return QVersionNumber();
header.sizeofcmds = readInt(device, &ok, swap);
if (!ok)
return QVersionNumber();
header.flags = readInt(device, &ok, swap);
if (!ok)
return QVersionNumber();
header.reserved = header.magic == MH_MAGIC_64 || header.magic == MH_CIGAM_64
? readInt(device, &ok, swap) : 0;
if (!ok)
return QVersionNumber();
for (uint32_t i = 0; i < header.ncmds; ++i) {
const uint32_t cmd = readInt(device, nullptr, swap);
const uint32_t cmdsize = readInt(device, nullptr, swap);
if (cmd == 0 || cmdsize == 0)
return QVersionNumber();
switch (cmd) {
case LC_VERSION_MIN_MACOSX:
case LC_VERSION_MIN_IPHONEOS:
case LC_VERSION_MIN_TVOS:
case LC_VERSION_MIN_WATCHOS:
const uint32_t version = readInt(device, &ok, swap, true);
if (!ok)
return QVersionNumber();
versions.push_back(QVersionNumber(
static_cast<int>(version >> 16),
static_cast<int>((version >> 8) & 0xff),
static_cast<int>(version & 0xff)));
break;
}
const qint64 remaining = static_cast<qint64>(cmdsize - sizeof(cmd) - sizeof(cmdsize));
if (device->read(remaining).size() != remaining)
return QVersionNumber();
}
}
std::sort(versions.begin(), versions.end());
return !versions.empty() ? versions.front() : QVersionNumber();
}
#endif
static int assemble(Input input, const QInstaller::Settings &settings, const QString &signingIdentity)
{
#ifdef Q_OS_OSX
@ -124,6 +286,11 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
// output should be a bundle
const QFileInfo fi(input.outputPath);
QString minimumSystemVersion;
QFile file(input.installerExePath);
if (file.open(QIODevice::ReadOnly))
minimumSystemVersion = readMachOMinimumSystemVersion(&file).normalized().toString();
const QString contentsResourcesPath = fi.filePath() + QLatin1String("/Contents/Resources/");
QInstaller::mkpath(fi.filePath() + QLatin1String("/Contents/MacOS"));
@ -182,6 +349,10 @@ static int assemble(Input input, const QInstaller::Settings &settings, const QSt
<< endl;
plistStream << QLatin1String("\t<key>NSPrincipalClass</key>") << endl;
plistStream << QLatin1String("\t<string>NSApplication</string>") << endl;
if (!minimumSystemVersion.isEmpty()) {
plistStream << QLatin1String("\t<key>LSMinimumSystemVersion</key>") << endl;
plistStream << QLatin1String("\t<string>") << minimumSystemVersion << QLatin1String("</string>") << endl;
}
plistStream << QLatin1String("</dict>") << endl;
plistStream << QLatin1String("</plist>") << endl;

View File

@ -1,10 +1,9 @@
TEMPLATE = app
TARGET = devtool
include(../../installerfw.pri)
QT = core network qml xml
QT -= gui
QT += network xml
include(../../installerfw.pri)
CONFIG += console
DESTDIR = $$IFW_APP_PATH