You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw/apps/wizard/unshield/unshieldworker.cpp

1049 lines
29 KiB
C++

#include "unshieldworker.hpp"
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QReadLocker>
#include <QStringList>
#include <fstream>
#include <components/files/qtconversion.hpp>
#include <apps/wizard/inisettings.hpp>
Wizard::UnshieldWorker::UnshieldWorker(qint64 expectedMorrowindBsaSize, QObject* parent)
: QObject(parent)
, mExpectedMorrowindBsaSize(expectedMorrowindBsaSize)
, mIniSettings()
{
unshield_set_log_level(0);
mPath = QString();
mIniPath = QString();
mDiskPath = QString();
// Default to Latin encoding
mIniEncoding = ToUTF8::FromType::WINDOWS_1252;
mInstallMorrowind = false;
mInstallTribunal = false;
mInstallBloodmoon = false;
mMorrowindDone = false;
mTribunalDone = false;
mBloodmoonDone = false;
mStopped = false;
qRegisterMetaType<Wizard::Component>("Wizard::Component");
}
void Wizard::UnshieldWorker::stopWorker()
{
mStopped = true;
mWait.wakeOne();
}
void Wizard::UnshieldWorker::setInstallComponent(Wizard::Component component, bool install)
{
QWriteLocker writeLock(&mLock);
switch (component)
{
case Wizard::Component_Morrowind:
mInstallMorrowind = install;
break;
case Wizard::Component_Tribunal:
mInstallTribunal = install;
break;
case Wizard::Component_Bloodmoon:
mInstallBloodmoon = install;
break;
}
}
bool Wizard::UnshieldWorker::getInstallComponent(Component component)
{
QReadLocker readLock(&mLock);
switch (component)
{
case Wizard::Component_Morrowind:
return mInstallMorrowind;
case Wizard::Component_Tribunal:
return mInstallTribunal;
case Wizard::Component_Bloodmoon:
return mInstallBloodmoon;
}
return false;
}
void Wizard::UnshieldWorker::setComponentDone(Component component, bool done)
{
QWriteLocker writeLock(&mLock);
switch (component)
{
case Wizard::Component_Morrowind:
mMorrowindDone = done;
break;
case Wizard::Component_Tribunal:
mTribunalDone = done;
break;
case Wizard::Component_Bloodmoon:
mBloodmoonDone = done;
break;
}
}
bool Wizard::UnshieldWorker::getComponentDone(Component component)
{
QReadLocker readLock(&mLock);
switch (component)
{
case Wizard::Component_Morrowind:
return mMorrowindDone;
case Wizard::Component_Tribunal:
return mTribunalDone;
case Wizard::Component_Bloodmoon:
return mBloodmoonDone;
}
return false;
}
void Wizard::UnshieldWorker::setPath(const QString& path)
{
QWriteLocker writeLock(&mLock);
mPath = path;
}
void Wizard::UnshieldWorker::setIniPath(const QString& path)
{
QWriteLocker writeLock(&mLock);
mIniPath = path;
}
void Wizard::UnshieldWorker::setDiskPath(const QString& path)
{
QWriteLocker writeLock(&mLock);
mDiskPath = path;
mWait.wakeAll();
}
QString Wizard::UnshieldWorker::getPath()
{
QReadLocker readLock(&mLock);
return mPath;
}
QString Wizard::UnshieldWorker::getIniPath()
{
QReadLocker readLock(&mLock);
return mIniPath;
}
QString Wizard::UnshieldWorker::getDiskPath()
{
QReadLocker readLock(&mLock);
return mDiskPath;
}
void Wizard::UnshieldWorker::setIniEncoding(ToUTF8::FromType encoding)
{
QWriteLocker writeLock(&mLock);
mIniEncoding = encoding;
}
void Wizard::UnshieldWorker::wakeAll()
{
mWait.wakeAll();
}
bool Wizard::UnshieldWorker::setupSettings()
{
// Create Morrowind.ini settings map
if (getIniPath().isEmpty())
return false;
const auto iniPath = Files::pathFromQString(getIniPath());
std::ifstream file(iniPath);
if (file.fail())
{
emit error(tr("Failed to open Morrowind configuration file!"),
tr("Opening %1 failed: %2.").arg(getIniPath(), std::generic_category().message(errno).c_str()));
return false;
}
mIniSettings.readFile(file, mIniEncoding);
return true;
}
bool Wizard::UnshieldWorker::writeSettings()
{
if (getIniPath().isEmpty())
return false;
const auto iniPath = Files::pathFromQString(getIniPath());
std::ifstream file(iniPath);
if (file.fail())
{
emit error(tr("Failed to open Morrowind configuration file!"),
tr("Opening %1 failed: %2.").arg(getIniPath(), std::generic_category().message(errno).c_str()));
return false;
}
if (!mIniSettings.writeFile(getIniPath(), file, mIniEncoding))
{
emit error(tr("Failed to write Morrowind configuration file!"),
tr("Writing to %1 failed: %2.").arg(getIniPath(), std::generic_category().message(errno).c_str()));
return false;
}
return true;
}
bool Wizard::UnshieldWorker::removeDirectory(const QString& dirName)
{
bool result = false;
QDir dir(dirName);
if (dir.exists(dirName))
{
QFileInfoList list(dir.entryInfoList(
QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst));
for (const QFileInfo& info : list)
{
if (info.isDir())
{
result = removeDirectory(info.absoluteFilePath());
}
else
{
result = QFile::remove(info.absoluteFilePath());
}
if (!result)
return result;
}
result = dir.rmdir(dirName);
}
return result;
}
bool Wizard::UnshieldWorker::copyFile(const QString& source, const QString& destination, bool keepSource)
{
QDir dir;
QFile file;
QFileInfo info(destination);
if (info.exists())
{
if (!dir.remove(info.absoluteFilePath()))
return false;
}
if (file.copy(source, destination))
{
if (!keepSource)
{
if (!file.remove(source))
return false;
}
else
{
return true;
}
}
else
{
return false;
}
return true;
}
bool Wizard::UnshieldWorker::copyDirectory(const QString& source, const QString& destination, bool keepSource)
{
QDir sourceDir(source);
QDir destDir(destination);
bool result = true;
if (!destDir.exists())
{
if (!sourceDir.mkpath(destination))
return false;
}
destDir.refresh();
if (!destDir.exists())
return false;
QFileInfoList list(sourceDir.entryInfoList(
QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst));
for (const QFileInfo& info : list)
{
QString relativePath(info.absoluteFilePath());
relativePath.remove(source);
QString destinationPath(destDir.absolutePath() + relativePath);
if (info.isSymLink())
continue;
if (info.isDir())
{
result = copyDirectory(info.absoluteFilePath(), destinationPath);
}
else
{
result = copyFile(info.absoluteFilePath(), destinationPath);
}
}
if (!keepSource)
return result && removeDirectory(sourceDir.absolutePath());
return result;
}
bool Wizard::UnshieldWorker::installFile(
const QString& fileName, const QString& path, Qt::MatchFlags flags, bool keepSource)
{
return installFiles(fileName, path, flags, keepSource, true);
}
bool Wizard::UnshieldWorker::installFiles(
const QString& fileName, const QString& path, Qt::MatchFlags flags, bool keepSource, bool single)
{
QDir dir(path);
if (!dir.exists())
return false;
QStringList files(findFiles(fileName, path, flags));
for (const QString& file : files)
{
QFileInfo info(file);
emit textChanged(tr("Installing: %1").arg(info.fileName()));
if (single)
{
return copyFile(info.absoluteFilePath(), getPath() + QDir::separator() + info.fileName(), keepSource);
}
else
{
if (!copyFile(info.absoluteFilePath(), getPath() + QDir::separator() + info.fileName(), keepSource))
return false;
}
}
return true;
}
bool Wizard::UnshieldWorker::installDirectories(
const QString& dirName, const QString& path, bool recursive, bool keepSource)
{
QDir dir(path);
if (!dir.exists())
return false;
QStringList directories(findDirectories(dirName, path, recursive));
for (const QString& dir : directories)
{
QFileInfo info(dir);
emit textChanged(tr("Installing: %1 directory").arg(info.fileName()));
if (!copyDirectory(info.absoluteFilePath(), getPath() + QDir::separator() + info.fileName(), keepSource))
return false;
}
return true;
}
void Wizard::UnshieldWorker::extract()
{
if (getInstallComponent(Wizard::Component_Morrowind))
{
if (!getComponentDone(Wizard::Component_Morrowind))
if (!setupComponent(Wizard::Component_Morrowind))
return;
}
if (getInstallComponent(Wizard::Component_Tribunal))
{
if (!getComponentDone(Wizard::Component_Tribunal))
if (!setupComponent(Wizard::Component_Tribunal))
return;
}
if (getInstallComponent(Wizard::Component_Bloodmoon))
{
if (!getComponentDone(Wizard::Component_Bloodmoon))
if (!setupComponent(Wizard::Component_Bloodmoon))
return;
}
// Update Morrowind configuration
if (getInstallComponent(Wizard::Component_Tribunal))
{
mIniSettings.setValue(QLatin1String("Archives/Archive 0"), QVariant(QString("Tribunal.bsa")));
mIniSettings.setValue(QLatin1String("Game Files/GameFile1"), QVariant(QString("Tribunal.esm")));
}
if (getInstallComponent(Wizard::Component_Bloodmoon))
{
mIniSettings.setValue(QLatin1String("Archives/Archive 0"), QVariant(QString("Bloodmoon.bsa")));
mIniSettings.setValue(QLatin1String("Game Files/GameFile1"), QVariant(QString("Bloodmoon.esm")));
}
if (getInstallComponent(Wizard::Component_Tribunal) && getInstallComponent(Wizard::Component_Bloodmoon))
{
mIniSettings.setValue(QLatin1String("Archives/Archive 0"), QVariant(QString("Tribunal.bsa")));
mIniSettings.setValue(QLatin1String("Archives/Archive 1"), QVariant(QString("Bloodmoon.bsa")));
mIniSettings.setValue(QLatin1String("Game Files/GameFile1"), QVariant(QString("Tribunal.esm")));
mIniSettings.setValue(QLatin1String("Game Files/GameFile2"), QVariant(QString("Bloodmoon.esm")));
}
// Write the settings to the Morrowind config file
if (!writeSettings())
return;
// Remove the temporary directory
removeDirectory(getPath() + QDir::separator() + QLatin1String("extract-temp"));
// Fill the progress bar
int total = 0;
if (getInstallComponent(Wizard::Component_Morrowind))
total = 100;
if (getInstallComponent(Wizard::Component_Tribunal))
total = total + 100;
if (getInstallComponent(Wizard::Component_Bloodmoon))
total = total + 100;
emit textChanged(tr("Installation finished!"));
emit progressChanged(total);
emit finished();
}
bool Wizard::UnshieldWorker::setupComponent(Component component)
{
QString name;
switch (component)
{
case Wizard::Component_Morrowind:
name = QLatin1String("Morrowind");
break;
case Wizard::Component_Tribunal:
name = QLatin1String("Tribunal");
break;
case Wizard::Component_Bloodmoon:
name = QLatin1String("Bloodmoon");
break;
}
if (name.isEmpty())
{
emit error(tr("Component parameter is invalid!"), tr("An invalid component parameter was supplied."));
return false;
}
bool found = false;
QString cabFile;
QDir disk;
// Keep showing the file dialog until we find the necessary install files
while (!found)
{
if (getDiskPath().isEmpty())
{
QReadLocker readLock(&mLock);
emit requestFileDialog(component);
mWait.wait(&mLock);
if (mStopped)
{
qDebug() << "We are asked to stop !!";
break;
}
disk.setPath(getDiskPath());
}
else
{
disk.setPath(getDiskPath());
}
QStringList list(findFiles(QLatin1String("data1.hdr"), disk.absolutePath()));
for (const QString& file : list)
{
qDebug() << "current archive: " << file;
if (component == Wizard::Component_Morrowind)
{
bool morrowindFound = findInCab(QLatin1String("Morrowind.bsa"), file);
bool tribunalFound = findInCab(QLatin1String("Tribunal.bsa"), file);
bool bloodmoonFound = findInCab(QLatin1String("Bloodmoon.bsa"), file);
if (morrowindFound)
{
// Check if we have correct archive, other archives have Morrowind.bsa too
if (tribunalFound == bloodmoonFound)
{
qint64 actualFileSize = getMorrowindBsaFileSize(file);
if (actualFileSize != mExpectedMorrowindBsaSize)
{
QReadLocker readLock(&mLock);
emit requestOldVersionDialog();
mWait.wait(&mLock);
if (mStopped)
{
qDebug() << "We are asked to stop !!";
break;
}
}
cabFile = file;
found = true; // We have a GoTY disk or a Morrowind-only disk
}
}
}
else
{
if (findInCab(name + QLatin1String(".bsa"), file))
{
cabFile = file;
found = true;
}
}
}
if (cabFile.isEmpty())
{
break;
}
if (!found)
{
emit textChanged(tr("Failed to find a valid archive containing %1.bsa! Retrying.").arg(name));
QReadLocker readLock(&mLock);
emit requestFileDialog(component);
mWait.wait(&mLock);
}
}
if (installComponent(component, cabFile))
{
setComponentDone(component, true);
return true;
}
else
{
return false;
}
return true;
}
bool Wizard::UnshieldWorker::installComponent(Component component, const QString& path)
{
QString name;
switch (component)
{
case Wizard::Component_Morrowind:
name = QLatin1String("Morrowind");
break;
case Wizard::Component_Tribunal:
name = QLatin1String("Tribunal");
break;
case Wizard::Component_Bloodmoon:
name = QLatin1String("Bloodmoon");
break;
}
if (name.isEmpty())
{
emit error(tr("Component parameter is invalid!"), tr("An invalid component parameter was supplied."));
return false;
}
emit textChanged(tr("Installing %1").arg(name));
QFileInfo info(path);
if (!info.exists())
{
emit error(tr("Installation media path not set!"), tr("The source path for %1 was not set.").arg(name));
return false;
}
// Create temporary extract directory
// TODO: Use QTemporaryDir in Qt 5.0
QString tempPath(getPath() + QDir::separator() + QLatin1String("extract-temp"));
QDir temp;
// Make sure the temporary folder is empty
removeDirectory(tempPath);
if (!temp.mkpath(tempPath))
{
emit error(tr("Cannot create temporary directory!"), tr("Failed to create %1.").arg(tempPath));
return false;
}
temp.setPath(tempPath);
if (!temp.mkdir(name))
{
emit error(
tr("Cannot create temporary directory!"), tr("Failed to create %1.").arg(temp.absoluteFilePath(name)));
return false;
}
if (!temp.cd(name))
{
emit error(tr("Cannot move into temporary directory!"),
tr("Failed to move into %1.").arg(temp.absoluteFilePath(name)));
return false;
}
// Extract the installation files
if (!extractCab(info.absoluteFilePath(), temp.absolutePath()))
return false;
// Move the files from the temporary path to the destination folder
emit textChanged(tr("Moving installation files"));
// Install extracted directories
QStringList directories;
directories << QLatin1String("BookArt") << QLatin1String("Fonts") << QLatin1String("Icons")
<< QLatin1String("Meshes") << QLatin1String("Music") << QLatin1String("Sound")
<< QLatin1String("Splash") << QLatin1String("Textures") << QLatin1String("Video");
for (const QString& dir : directories)
{
if (!installDirectories(dir, temp.absolutePath()))
{
emit error(
tr("Could not install directory!"), tr("Installing %1 to %2 failed.").arg(dir, temp.absolutePath()));
return false;
}
}
// Install directories from disk
for (const QString& dir : directories)
{
if (!installDirectories(dir, info.absolutePath(), false, true))
{
emit error(
tr("Could not install directory!"), tr("Installing %1 to %2 failed.").arg(dir, info.absolutePath()));
return false;
}
}
// Install translation files
QStringList extensions;
extensions << QLatin1String(".cel") << QLatin1String(".top") << QLatin1String(".mrk");
for (const QString& extension : extensions)
{
if (!installFiles(extension, info.absolutePath(), Qt::MatchEndsWith))
{
emit error(tr("Could not install translation file!"), tr("Failed to install *%1 files.").arg(extension));
return false;
}
}
if (component == Wizard::Component_Morrowind)
{
QStringList files;
files << QLatin1String("Morrowind.esm") << QLatin1String("Morrowind.bsa");
for (const QString& file : files)
{
if (!installFile(file, temp.absolutePath()))
{
emit error(tr("Could not install Morrowind data file!"), tr("Failed to install %1.").arg(file));
return false;
}
}
// Copy Morrowind configuration file
if (!installFile(QLatin1String("Morrowind.ini"), temp.absolutePath()))
{
emit error(tr("Could not install Morrowind configuration file!"),
tr("Failed to install %1.").arg(QLatin1String("Morrowind.ini")));
return false;
}
// Setup Morrowind configuration
setIniPath(getPath() + QDir::separator() + QLatin1String("Morrowind.ini"));
if (!setupSettings())
return false;
}
if (component == Wizard::Component_Tribunal)
{
QFileInfo sounds(temp.absoluteFilePath(QLatin1String("Sounds")));
QString dest(getPath() + QDir::separator() + QLatin1String("Sound"));
if (sounds.exists())
{
emit textChanged(tr("Installing: Sound directory"));
if (!copyDirectory(sounds.absoluteFilePath(), dest))
{
emit error(tr("Could not install directory!"),
tr("Installing %1 to %2 failed.").arg(sounds.absoluteFilePath(), dest));
return false;
}
}
QStringList files;
files << QLatin1String("Tribunal.esm") << QLatin1String("Tribunal.bsa");
for (const QString& file : files)
{
if (!installFile(file, temp.absolutePath()))
{
emit error(tr("Could not find Tribunal data file!"), tr("Failed to find %1.").arg(file));
return false;
}
}
}
if (component == Wizard::Component_Bloodmoon)
{
QFileInfo original(getPath() + QDir::separator() + QLatin1String("Tribunal.esm"));
if (original.exists())
{
if (!installFile(QLatin1String("Tribunal.esm"), temp.absolutePath()))
{
emit error(tr("Could not find Tribunal patch file!"),
tr("Failed to find %1.").arg(QLatin1String("Tribunal.esm")));
return false;
}
}
QStringList files;
files << QLatin1String("Bloodmoon.esm") << QLatin1String("Bloodmoon.bsa");
for (const QString& file : files)
{
if (!installFile(file, temp.absolutePath()))
{
emit error(tr("Could not find Bloodmoon data file!"), tr("Failed to find %1.").arg(file));
return false;
}
}
// Load Morrowind configuration settings from the setup script
QStringList list(findFiles(QLatin1String("setup.inx"), getDiskPath()));
emit textChanged(tr("Updating Morrowind configuration file"));
for (const QString& inx : list)
{
mIniSettings.parseInx(inx);
}
}
// Finally, install Data Files directories from temp and disk
QStringList datafiles(findDirectories(QLatin1String("Data Files"), temp.absolutePath()));
datafiles.append(findDirectories(QLatin1String("Data Files"), info.absolutePath()));
for (const QString& dir : datafiles)
{
QFileInfo info(dir);
emit textChanged(tr("Installing: %1 directory").arg(info.fileName()));
if (!copyDirectory(info.absoluteFilePath(), getPath()))
{
emit error(tr("Could not install directory!"),
tr("Installing %1 to %2 failed.").arg(info.absoluteFilePath(), getPath()));
return false;
}
}
emit textChanged(tr("%1 installation finished!").arg(name));
return true;
}
bool Wizard::UnshieldWorker::extractFile(
Unshield* unshield, const QString& destination, const QString& prefix, int index, int counter)
{
bool success = false;
QString path(destination);
path.append(QDir::separator());
int directory = unshield_file_directory(unshield, index);
if (!prefix.isEmpty())
path.append(prefix + QDir::separator());
if (directory >= 0)
path.append(QString::fromUtf8(unshield_directory_name(unshield, directory)) + QDir::separator());
// Ensure the path has the right separators
path.replace(QLatin1Char('\\'), QDir::separator());
path = QDir::toNativeSeparators(path);
// Ensure the target path exists
QDir dir;
if (!dir.mkpath(path))
return false;
path.append(QString::fromUtf8(unshield_file_name(unshield, index)));
// Calculate the percentage done
int progress = (((float)counter / (float)unshield_file_count(unshield)) * 100);
if (getComponentDone(Wizard::Component_Morrowind))
progress = progress + 100;
if (getComponentDone(Wizard::Component_Tribunal))
progress = progress + 100;
emit textChanged(tr("Extracting: %1").arg(QString::fromUtf8(unshield_file_name(unshield, index))));
emit progressChanged(progress);
QByteArray array(path.toUtf8());
success = unshield_file_save(unshield, index, array.constData());
if (!success)
{
qDebug() << "error";
dir.remove(path);
}
return success;
}
bool Wizard::UnshieldWorker::extractCab(const QString& cabFile, const QString& destination)
{
bool success = false;
QByteArray array(cabFile.toUtf8());
Unshield* unshield;
unshield = unshield_open(array.constData());
if (!unshield)
{
emit error(tr("Failed to open InstallShield Cabinet File."), tr("Opening %1 failed.").arg(cabFile));
unshield_close(unshield);
return false;
}
int counter = 0;
for (int i = 0; i < unshield_file_group_count(unshield); ++i)
{
UnshieldFileGroup* group = unshield_file_group_get(unshield, i);
for (size_t j = group->first_file; j <= group->last_file; ++j)
{
if (mStopped)
{
qDebug() << "We're asked to stop!";
unshield_close(unshield);
return true;
}
if (unshield_file_is_valid(unshield, j))
{
success = extractFile(unshield, destination, group->name, j, counter);
if (!success)
{
QString name(QString::fromUtf8(unshield_file_name(unshield, j)));
emit error(tr("Failed to extract %1.").arg(name),
tr("Complete path: %1").arg(destination + QDir::separator() + name));
unshield_close(unshield);
return false;
}
++counter;
}
}
}
unshield_close(unshield);
return success;
}
QString Wizard::UnshieldWorker::findFile(const QString& fileName, const QString& path)
{
return findFiles(fileName, path).first();
}
QStringList Wizard::UnshieldWorker::findFiles(
const QString& fileName, const QString& path, int depth, bool recursive, bool directories, Qt::MatchFlags flags)
{
static const int MAXIMUM_DEPTH = 10;
if (depth >= MAXIMUM_DEPTH)
{
qWarning("Maximum directory depth limit reached.");
return QStringList();
}
QStringList result;
QDir dir(path);
// Prevent parsing over the complete filesystem
if (dir == QDir::rootPath())
return QStringList();
if (!dir.exists())
return QStringList();
QFileInfoList list(dir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files, QDir::DirsFirst));
for (const QFileInfo& info : list)
{
if (info.isSymLink())
continue;
if (info.isDir())
{
if (directories)
{
if (!info.fileName().compare(fileName, Qt::CaseInsensitive))
{
result.append(info.absoluteFilePath());
}
else
{
if (recursive)
result.append(findFiles(fileName, info.absoluteFilePath(), depth + 1, recursive, true));
}
}
else
{
if (recursive)
result.append(findFiles(fileName, info.absoluteFilePath(), depth + 1));
}
}
else
{
if (directories)
break;
switch (flags)
{
case Qt::MatchExactly:
if (!info.fileName().compare(fileName, Qt::CaseInsensitive))
result.append(info.absoluteFilePath());
break;
case Qt::MatchEndsWith:
if (info.fileName().endsWith(fileName, Qt::CaseInsensitive))
result.append(info.absoluteFilePath());
break;
}
}
}
return result;
}
QStringList Wizard::UnshieldWorker::findDirectories(const QString& dirName, const QString& path, bool recursive)
{
return findFiles(dirName, path, 0, true, true);
}
bool Wizard::UnshieldWorker::findInCab(const QString& fileName, const QString& cabFile)
{
QByteArray array(cabFile.toUtf8());
Unshield* unshield;
unshield = unshield_open(array.constData());
if (!unshield)
{
emit error(tr("Failed to open InstallShield Cabinet File."), tr("Opening %1 failed.").arg(cabFile));
unshield_close(unshield);
return false;
}
for (int i = 0; i < unshield_file_group_count(unshield); ++i)
{
UnshieldFileGroup* group = unshield_file_group_get(unshield, i);
for (size_t j = group->first_file; j <= group->last_file; ++j)
{
if (unshield_file_is_valid(unshield, j))
{
QString current(QString::fromUtf8(unshield_file_name(unshield, j)));
if (current.toLower() == fileName.toLower())
{
unshield_close(unshield);
return true; // File is found!
}
}
}
}
unshield_close(unshield);
return false;
}
size_t Wizard::UnshieldWorker::getMorrowindBsaFileSize(const QString& cabFile)
{
QString fileName = QString("Morrowind.bsa");
QByteArray array(cabFile.toUtf8());
Unshield* unshield;
unshield = unshield_open(array.constData());
if (!unshield)
{
emit error(tr("Failed to open InstallShield Cabinet File."), tr("Opening %1 failed.").arg(cabFile));
unshield_close(unshield);
return false;
}
for (int i = 0; i < unshield_file_group_count(unshield); ++i)
{
UnshieldFileGroup* group = unshield_file_group_get(unshield, i);
for (size_t j = group->first_file; j <= group->last_file; ++j)
{
if (unshield_file_is_valid(unshield, j))
{
QString current(QString::fromUtf8(unshield_file_name(unshield, j)));
if (current.toLower() == fileName.toLower())
{
size_t fileSize = unshield_file_size(unshield, j);
unshield_close(unshield);
return fileSize; // File is found!
}
}
}
}
unshield_close(unshield);
return 0;
}