diff --git a/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp b/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp index 10ea322a2..38c945ade 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/configfile.cpp @@ -749,6 +749,26 @@ bool CConfigFile::shouldCreateMenuShortcut() const return !shortcut.isEmpty() && !NLMISC::CFile::isExists(qToUtf8(shortcut)); } +bool CConfigFile::shouldCopyInstaller() const +{ + const CProfile &p = getProfile(); + const CServer &s = getServer(p.server); + + QString installerDst = getInstallationDirectory() + "/" + s.installerFilename; + + // if installer not found in installation directory, extract it from BNP + if (!QFile::exists(installerDst)) return true; + + QString installedVersion = getVersionFromExecutable(installerDst); + QString newVersion = QApplication::applicationVersion(); + + QVersionNumber installedVer = QVersionNumber::fromString(installedVersion); + QVersionNumber newVer = QVersionNumber::fromString(newVersion); + + // if version is greater, copy it + return newVer > installedVer; +} + QString CConfigFile::getInstallerCurrentFilePath() const { // installer is always run from TEMP under Windows @@ -955,23 +975,7 @@ OperationStep CConfigFile::getInstallNextStep() const } } - QString installerDst = getInstallationDirectory() + "/" + server.installerFilename; - - // if installer not found in installation directory, extract it from BNP - if (QFile::exists(installerDst)) - { - QString installerSrc = getInstallerCurrentFilePath(); - - // copy it too if destination one if older than new one - uint64 srcDate = QFileInfo(installerSrc).lastModified().toTime_t(); - uint64 dstDate = QFileInfo(installerDst).lastModified().toTime_t(); - - if (srcDate > dstDate) return CopyInstaller; - } - else - { - return CopyInstaller; - } + if (shouldCopyInstaller()) return CopyInstaller; // no default profile if (profile.id.isEmpty()) diff --git a/code/ryzom/tools/client/ryzom_installer/src/configfile.h b/code/ryzom/tools/client/ryzom_installer/src/configfile.h index 70ca6a6a0..a279e6d7a 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/configfile.h +++ b/code/ryzom/tools/client/ryzom_installer/src/configfile.h @@ -103,6 +103,7 @@ public: bool foundTemporaryFiles(const QString &directory) const; bool shouldCreateDesktopShortcut() const; bool shouldCreateMenuShortcut() const; + bool shouldCopyInstaller() const; // installation choices bool use64BitsClient() const; diff --git a/code/ryzom/tools/client/ryzom_installer/src/main.cpp b/code/ryzom/tools/client/ryzom_installer/src/main.cpp index c20b40efe..9e4bdf8a0 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/main.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/main.cpp @@ -114,6 +114,34 @@ int main(int argc, char *argv[]) QApplication::installTranslator(&qtTranslator); } + // define commandline arguments + QCommandLineParser parser; + parser.setApplicationDescription(QApplication::tr("Instalation and launcher tool for Ryzom")); + parser.addHelpOption(); + + QCommandLineOption uninstallOption(QStringList() << "u" << "uninstall", QApplication::tr("Uninstall")); + parser.addOption(uninstallOption); + + QCommandLineOption silentOption(QStringList() << "s" << "silent", QApplication::tr("Silent mode")); + parser.addOption(silentOption); + + QCommandLineOption versionOption(QStringList() << "v" << "version", QApplication::tr("Version")); + parser.addOption(versionOption); + + QCommandLineOption installOption(QStringList() << "i" << "install", QApplication::tr("Install itself")); + parser.addOption(installOption); + + // process the actual command line arguments given by the user + parser.process(app); + + // don't need to load config file for version + if (parser.isSet(versionOption)) + { + printf("Ryzom Installer %s (built on %s)\nCopyright (C) %s\n", RYZOM_VERSION, BUILD_DATE, COPYRIGHT); + + return 0; + } + // instanciate ConfigFile CConfigFile config; OperationStep step = config.load() ? config.getInstallNextStep():DisplayNoServerError; @@ -163,22 +191,6 @@ int main(int argc, char *argv[]) // use product name from ryzom_installer.ini if (!config.getProductName().isEmpty()) QApplication::setApplicationName(config.getProductName()); - // define commandline arguments - QCommandLineParser parser; - parser.setApplicationDescription(QApplication::tr("Instalation and launcher tool for Ryzom")); - parser.addHelpOption(); - parser.addVersionOption(); - - // root, username and password are optional because they can be saved in settings file - QCommandLineOption uninstallOption(QStringList() << "u" << "uninstall", QApplication::tr("Uninstall")); - parser.addOption(uninstallOption); - - QCommandLineOption silentOption(QStringList() << "s" << "silent", QApplication::tr("Silent mode")); - parser.addOption(silentOption); - - // process the actual command line arguments given by the user - parser.process(app); - if (parser.isSet(uninstallOption)) { SComponents components; diff --git a/code/ryzom/tools/client/ryzom_installer/src/profilesdialog.cpp b/code/ryzom/tools/client/ryzom_installer/src/profilesdialog.cpp index 8a5b84b0a..5bbeb86b2 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/profilesdialog.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/profilesdialog.cpp @@ -19,6 +19,7 @@ #include "profilesmodel.h" #include "serversmodel.h" #include "operationdialog.h" +#include "utils.h" #ifdef DEBUG_NEW #define new DEBUG_NEW @@ -222,27 +223,12 @@ void CProfilesDialog::updateExecutableVersion(int index) // file doesn't exist if (executable.isEmpty() || !QFile::exists(executable)) return; - // launch executable with --version argument - QProcess process; - process.setProcessChannelMode(QProcess::MergedChannels); - process.start(executable, QStringList() << "--version", QIODevice::ReadWrite); - - if (!process.waitForStarted()) return; - - QByteArray data; - - // read all output - while (process.waitForReadyRead()) data.append(process.readAll()); - // convert output to string - QString versionString = QString::fromUtf8(data); + QString versionString = getVersionFromExecutable(executable); - // parse version from output - QRegExp reg("([A-Za-z0-1_.]+) ((DEV|FV) ([0-9.]+))"); - - if (reg.indexIn(versionString) > -1) + if (!versionString.isEmpty()) { - executablePathLabel->setText(QString("%1 (%2)").arg(QFileInfo(executable).fileName()).arg(reg.cap(2))); + executablePathLabel->setText(QString("%1 (%2)").arg(QFileInfo(executable).fileName()).arg(versionString)); } } diff --git a/code/ryzom/tools/client/ryzom_installer/src/utils.cpp b/code/ryzom/tools/client/ryzom_installer/src/utils.cpp index e2b26a7bb..ac03abe90 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/utils.cpp +++ b/code/ryzom/tools/client/ryzom_installer/src/utils.cpp @@ -17,6 +17,10 @@ #include "stdpch.h" #include "utils.h" +#ifdef DEBUG_NEW + #define new DEBUG_NEW +#endif + QString qBytesToHumanReadable(qint64 bytes) { static std::vector units; @@ -244,6 +248,69 @@ bool resolveLink(const QWidget &window, const QString &pathLink, QString &pathOb #endif +QString getVersionFromExecutable(const QString &path) +{ + // launch executable with --version argument + QProcess process; + process.setProcessChannelMode(QProcess::MergedChannels); + process.start(path, QStringList() << "--version", QIODevice::ReadWrite); + + if (!process.waitForStarted()) return ""; + + QByteArray data; + + // read all output + while (process.waitForReadyRead(1000)) data.append(process.readAll()); + + if (!data.isEmpty()) + { + QString versionString = QString::fromUtf8(data); + + // parse version from output (client) + QRegExp reg("([A-Za-z0-1_.]+) ((DEV|FV) ([0-9.]+))"); + if (reg.indexIn(versionString) > -1) return reg.cap(2); + + // parse version from output (other tools) + reg.setPattern("([A-Za-z_ ]+) ([0-9.]+)"); + if (reg.indexIn(versionString) > -1) return reg.cap(2); + } + +#ifdef Q_OS_WIN + // try to parse version of executable in resources + DWORD verHandle = NULL; + uint size = 0; + VS_FIXEDFILEINFO *verInfo = NULL; + + // get size to be allocated + uint32_t verSize = GetFileVersionInfoSizeW(qToWide(path), &verHandle); + if (!verSize) return ""; + + // allocate buffer + QScopedArrayPointer verData(new char[verSize]); + + // get pointer on version structure + if (!GetFileVersionInfoW(qToWide(path), verHandle, verSize, &verData[0])) return ""; + + // get pointer on version + if (!VerQueryValueA(&verData[0], "\\", (void**)&verInfo, &size)) return ""; + + // check if version is right + if (size && verInfo && verInfo->dwSignature == 0xfeef04bd) + { + // Doesn't matter if you are on 32 bit or 64 bit, + // DWORD is always 32 bits, so first two revision numbers + // come from dwFileVersionMS, last two come from dwFileVersionLS + return QString("%1.%2.%3.%4") + .arg((verInfo->dwFileVersionMS >> 16) & 0xffff) + .arg((verInfo->dwFileVersionMS >> 0) & 0xffff) + .arg((verInfo->dwFileVersionLS >> 16) & 0xffff) + .arg((verInfo->dwFileVersionLS >> 0) & 0xffff); + } +#endif + + return ""; +} + CCOMHelper::CCOMHelper() { #ifdef Q_OS_WIN diff --git a/code/ryzom/tools/client/ryzom_installer/src/utils.h b/code/ryzom/tools/client/ryzom_installer/src/utils.h index c016ed8ba..1d6519a85 100644 --- a/code/ryzom/tools/client/ryzom_installer/src/utils.h +++ b/code/ryzom/tools/client/ryzom_installer/src/utils.h @@ -51,6 +51,8 @@ wchar_t* qToWide(const QString &str); bool createLink(const QString &link, const QString &name, const QString &executable, const QString &arguments, const QString &icon, const QString &workingDir); bool resolveLink(const QWidget &window, const QString &pathLink, QString &pathObj); +QString getVersionFromExecutable(const QString &path); + class CCOMHelper { bool m_mustUninit;