From d54f17db583fbd3b1031481efb084e9dd68f2983 Mon Sep 17 00:00:00 2001 From: Katja Marttila Date: Mon, 31 Jan 2022 11:58:09 +0200 Subject: Use of separators in Execute operation Execute -operation might be strict with the path separators. If wrong separators are used the Execute -operation might fail. Fixed so that Execute -operations paths are saved to dat file without converting to normalized separators. As the target dir is saved as @RELOCATABLE_PATH@ also for Execute -operation, check from the next available separator which separator should be used for operation. Task-number: QTIFW-2501 Change-Id: Ia9969bbe3177a6b2daab21c026df88d4e2ec2bb0 Reviewed-by: Arttu Tarkiainen --- src/libs/installer/fileutils.cpp | 16 ++++++++++++---- src/libs/installer/fileutils.h | 4 ++-- src/libs/kdtools/updateoperation.cpp | 35 +++++++++++++++++++++++++++++------ 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/libs/installer/fileutils.cpp b/src/libs/installer/fileutils.cpp index d534b3651..b46883c5a 100644 --- a/src/libs/installer/fileutils.cpp +++ b/src/libs/installer/fileutils.cpp @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -689,16 +689,24 @@ bool QInstaller::isInBundle(const QString &path, QString *bundlePath) /*! Replaces the path \a before with the path \a after at the beginning of \a path and returns the replaced path. If \a before cannot be found in \a path, the original value is returned. + If \a cleanPath is \c true, path is returned with directory separators normalized (that is, + platform-native separators converted to "/") and redundant ones removed, and "."s and ".."s + resolved (as far as possible). If \a cleanPath is \c false, path is returned as such. Default + value is \c true. */ -QString QInstaller::replacePath(const QString &path, const QString &before, const QString &after) +QString QInstaller::replacePath(const QString &path, const QString &before, const QString &after, bool cleanPath) { if (path.isEmpty() || before.isEmpty()) return path; QString pathToPatch = QDir::cleanPath(path); const QString pathToReplace = QDir::cleanPath(before); - if (pathToPatch.startsWith(pathToReplace)) - return QDir::cleanPath(after) + pathToPatch.mid(pathToReplace.size()); + if (pathToPatch.startsWith(pathToReplace)) { + if (cleanPath) + return QDir::cleanPath(after) + pathToPatch.mid(pathToReplace.size()); + else + return after + path.mid(before.size()); + } return path; } diff --git a/src/libs/installer/fileutils.h b/src/libs/installer/fileutils.h index ac3f95098..daaa3485b 100644 --- a/src/libs/installer/fileutils.h +++ b/src/libs/installer/fileutils.h @@ -1,6 +1,6 @@ /************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Installer Framework. @@ -93,7 +93,7 @@ private: quint64 INSTALLER_EXPORT fileSize(const QFileInfo &info); bool INSTALLER_EXPORT isInBundle(const QString &path, QString *bundlePath = 0); - QString replacePath(const QString &path, const QString &pathBefore, const QString &pathAfter); + QString replacePath(const QString &path, const QString &pathBefore, const QString &pathAfter, bool cleanPath = true); void replaceHighDpiImage(QString &imagePath); void INSTALLER_EXPORT trimmedCopyConfigData(const QString &source, const QString &target, const QStringList &elementsToRemoveTags); diff --git a/src/libs/kdtools/updateoperation.cpp b/src/libs/kdtools/updateoperation.cpp index 897fecf1b..c3961663a 100644 --- a/src/libs/kdtools/updateoperation.cpp +++ b/src/libs/kdtools/updateoperation.cpp @@ -475,8 +475,15 @@ QDomDocument UpdateOperation::toXml() const const QString target = m_core ? m_core->value(QInstaller::scTargetDir) : QString(); Q_FOREACH (const QString &s, arguments()) { QDomElement arg = doc.createElement(QLatin1String("argument")); - arg.appendChild(doc.createTextNode(QInstaller::replacePath(s, target, - QLatin1String(QInstaller::scRelocatable)))); + // Do not call cleanPath to Execute operations paths. The operation might require the + // exact separators that are set in the operation call. + if (name() == QLatin1String("Execute")) { + arg.appendChild(doc.createTextNode(QInstaller::replacePath(s, target, + QLatin1String(QInstaller::scRelocatable), false))); + } else { + arg.appendChild(doc.createTextNode(QInstaller::replacePath(s, target, + QLatin1String(QInstaller::scRelocatable)))); + } args.appendChild(arg); } root.appendChild(args); @@ -528,6 +535,7 @@ QDomDocument UpdateOperation::toXml() const bool UpdateOperation::fromXml(const QDomDocument &doc) { QString target = QCoreApplication::applicationDirPath(); + static const QLatin1String relocatable = QLatin1String(QInstaller::scRelocatable); // Does not change target on non macOS platforms. if (QInstaller::isInBundle(target, &target)) target = QDir::cleanPath(target + QLatin1String("/..")); @@ -539,8 +547,23 @@ bool UpdateOperation::fromXml(const QDomDocument &doc) for (QDomNode n = argsElem.firstChild(); ! n.isNull(); n = n.nextSibling()) { const QDomElement e = n.toElement(); if (!e.isNull() && e.tagName() == QLatin1String("argument")) { - args << QInstaller::replacePath(e.text(), QLatin1String(QInstaller::scRelocatable), - target); + // Sniff the Execute -operations file path separator. The operation might be + // strict with the used path separator + if (name() == QLatin1String("Execute")) { + if (e.text().startsWith(relocatable) && e.text().size() > relocatable.size()) { + const QChar separator = e.text().at(relocatable.size()); + if (separator == QLatin1Char('\\')) { + args << QInstaller::replacePath(e.text(), relocatable, + QDir::toNativeSeparators(target), false); + } + } else { + args << QInstaller::replacePath(e.text(), relocatable, + target); + } + } else { + args << QInstaller::replacePath(e.text(), relocatable, + target); + } } } setArguments(args); @@ -565,13 +588,13 @@ bool UpdateOperation::fromXml(const QDomDocument &doc) QStringList list = var.toStringList(); for (int i = 0; i < list.count(); ++i) { list[i] = QInstaller::replacePath(list.at(i), - QLatin1String(QInstaller::scRelocatable), target); + relocatable, target); } var = QVariant::fromValue(list); } } else if (t == QVariant::String) { const QString str = QInstaller::replacePath(value, - QLatin1String(QInstaller::scRelocatable), target); + relocatable, target); var = QVariant::fromValue(str); } -- cgit v1.2.3