diff options
author | Assam Boudjelthia <assam.boudjelthia@qt.io> | 2022-04-15 16:00:57 +0300 |
---|---|---|
committer | Assam Boudjelthia <assam.boudjelthia@qt.io> | 2022-04-21 11:52:52 +0300 |
commit | a9f18a6ec065b1538667e13f4d81db6cdee5b948 (patch) | |
tree | 4926cc0fd53fc1495687c74790e7e4271ab3a36d /src/tools | |
parent | 905bfb850389431f8928b89ce55dbabcab35b2d0 (diff) |
Android: de-duplicate shellquote helpers code in deploy and test tools
Move shellquote helper functions into a common place instead of having a
copy in each tool's code.
Change-Id: I9723c11f894a211864788a7635773610c0fde739
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/androiddeployqt/main.cpp | 74 | ||||
-rw-r--r-- | src/tools/androidtestrunner/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/tools/androidtestrunner/main.cpp | 73 | ||||
-rw-r--r-- | src/tools/shared/shellquote_shared.h | 107 |
4 files changed, 112 insertions, 144 deletions
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp index 94496fe61c..7f6a5d30f1 100644 --- a/src/tools/androiddeployqt/main.cpp +++ b/src/tools/androiddeployqt/main.cpp @@ -47,6 +47,7 @@ #include <QMap> #include <depfile_shared.h> +#include <shellquote_shared.h> #include <algorithm> @@ -249,77 +250,6 @@ static const QHash<QByteArray, QByteArray> elfArchitectures = { {"x86_64", "x86_64"} }; -// Copy-pasted from qmake/library/ioutil.cpp -inline static bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16]) -{ - for (int x = arg.length() - 1; x >= 0; --x) { - ushort c = arg.unicode()[x].unicode(); - if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)))) - return true; - } - return false; -} - -static QString shellQuoteUnix(const QString &arg) -{ - // Chars that should be quoted (TM). This includes: - static const uchar iqm[] = { - 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8, - 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78 - }; // 0-32 \'"$`<>|;&(){}*?#!~[] - - if (!arg.length()) - return "\"\""_L1; - - QString ret(arg); - if (hasSpecialChars(ret, iqm)) { - ret.replace(u'\'', "'\\''"_L1); - ret.prepend(u'\''); - ret.append(u'\''); - } - return ret; -} - -static QString shellQuoteWin(const QString &arg) -{ - // Chars that should be quoted (TM). This includes: - // - control chars & space - // - the shell meta chars "&()<>^| - // - the potential separators ,;= - static const uchar iqm[] = { - 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10 - }; - - if (!arg.length()) - return "\"\""_L1; - - QString ret(arg); - if (hasSpecialChars(ret, iqm)) { - // Quotes are escaped and their preceding backslashes are doubled. - // It's impossible to escape anything inside a quoted string on cmd - // level, so the outer quoting must be "suspended". - ret.replace(QRegularExpression("(\\\\*)\""_L1), "\"\\1\\1\\^\"\""_L1); - // The argument must not end with a \ since this would be interpreted - // as escaping the quote -- rather put the \ behind the quote: e.g. - // rather use "foo"\ than "foo\" - qsizetype i = ret.length(); - while (i > 0 && ret.at(i - 1) == u'\\') - --i; - ret.insert(i, u'"'); - ret.prepend(u'"'); - } - return ret; -} - -static QString shellQuote(const QString &arg) -{ - if (QDir::separator() == u'\\') - return shellQuoteWin(arg); - else - return shellQuoteUnix(arg); -} - QString architectureFromName(const QString &name) { QRegularExpression architecture(QStringLiteral("_(armeabi-v7a|arm64-v8a|x86|x86_64).so$")); @@ -362,8 +292,6 @@ static QString llvmReadobjPath(const Options &options) options.ndkHost)); } - - QString fileArchitecture(const Options &options, const QString &path) { auto arch = architectureFromName(path); diff --git a/src/tools/androidtestrunner/CMakeLists.txt b/src/tools/androidtestrunner/CMakeLists.txt index a078913fbf..e4cd663d3a 100644 --- a/src/tools/androidtestrunner/CMakeLists.txt +++ b/src/tools/androidtestrunner/CMakeLists.txt @@ -16,6 +16,8 @@ qt_internal_add_tool(${target_name} QT_NO_FOREACH PUBLIC_LIBRARIES Qt::Gui + INCLUDE_DIRECTORIES + ../shared ) qt_internal_return_unless_building_tools() set_target_properties(${target_name} PROPERTIES diff --git a/src/tools/androidtestrunner/main.cpp b/src/tools/androidtestrunner/main.cpp index efcc6ed7bc..3b9e53a5a5 100644 --- a/src/tools/androidtestrunner/main.cpp +++ b/src/tools/androidtestrunner/main.cpp @@ -39,6 +39,8 @@ #include <functional> #include <thread> +#include <shellquote_shared.h> + #ifdef Q_CC_MSVC #define popen _popen #define QT_POPEN_READ "rb" @@ -189,77 +191,6 @@ static bool execCommand(const QString &command, QByteArray *output = nullptr, bo return pclose(process) == 0; } -// Copy-pasted from qmake/library/ioutil.cpp -inline static bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16]) -{ - for (int x = arg.length() - 1; x >= 0; --x) { - ushort c = arg.unicode()[x].unicode(); - if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)))) - return true; - } - return false; -} - -static QString shellQuoteUnix(const QString &arg) -{ - // Chars that should be quoted (TM). This includes: - static const uchar iqm[] = { - 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8, - 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78 - }; // 0-32 \'"$`<>|;&(){}*?#!~[] - - if (!arg.length()) - return QStringLiteral("\"\""); - - QString ret(arg); - if (hasSpecialChars(ret, iqm)) { - ret.replace(u'\'', QStringLiteral("'\\''")); - ret.prepend(u'\''); - ret.append(u'\''); - } - return ret; -} - -static QString shellQuoteWin(const QString &arg) -{ - // Chars that should be quoted (TM). This includes: - // - control chars & space - // - the shell meta chars "&()<>^| - // - the potential separators ,;= - static const uchar iqm[] = { - 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78, - 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10 - }; - - if (!arg.length()) - return QStringLiteral("\"\""); - - QString ret(arg); - if (hasSpecialChars(ret, iqm)) { - // Quotes are escaped and their preceding backslashes are doubled. - // It's impossible to escape anything inside a quoted string on cmd - // level, so the outer quoting must be "suspended". - ret.replace(QRegularExpression(QStringLiteral("(\\\\*)\"")), QStringLiteral("\"\\1\\1\\^\"\"")); - // The argument must not end with a \ since this would be interpreted - // as escaping the quote -- rather put the \ behind the quote: e.g. - // rather use "foo"\ than "foo\" - qsizetype i = ret.length(); - while (i > 0 && ret.at(i - 1) == u'\\') - --i; - ret.insert(i, u'"'); - ret.prepend(u'"'); - } - return ret; -} - -static QString shellQuote(const QString &arg) -{ - if (QDir::separator() == u'\\') - return shellQuoteWin(arg); - else - return shellQuoteUnix(arg); -} - static bool parseOptions() { QStringList arguments = QCoreApplication::arguments(); diff --git a/src/tools/shared/shellquote_shared.h b/src/tools/shared/shellquote_shared.h new file mode 100644 index 0000000000..ff264008e5 --- /dev/null +++ b/src/tools/shared/shellquote_shared.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SHELLQUOTE_SHARED_H +#define SHELLQUOTE_SHARED_H + +#include <QDir> +#include <QRegularExpression> +#include <QString> + +// Copy-pasted from qmake/library/ioutil.cpp +inline static bool hasSpecialChars(const QString &arg, const uchar (&iqm)[16]) +{ + for (int x = arg.length() - 1; x >= 0; --x) { + ushort c = arg.unicode()[x].unicode(); + if ((c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)))) + return true; + } + return false; +} + +static QString shellQuoteUnix(const QString &arg) +{ + // Chars that should be quoted (TM). This includes: + static const uchar iqm[] = { + 0xff, 0xff, 0xff, 0xff, 0xdf, 0x07, 0x00, 0xd8, + 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x78 + }; // 0-32 \'"$`<>|;&(){}*?#!~[] + + if (!arg.length()) + return QLatin1String("\"\""); + + QString ret(arg); + if (hasSpecialChars(ret, iqm)) { + ret.replace(QLatin1Char('\''), QLatin1String("'\\''")); + ret.prepend(QLatin1Char('\'')); + ret.append(QLatin1Char('\'')); + } + return ret; +} + +static QString shellQuoteWin(const QString &arg) +{ + // Chars that should be quoted (TM). This includes: + // - control chars & space + // - the shell meta chars "&()<>^| + // - the potential separators ,;= + static const uchar iqm[] = { + 0xff, 0xff, 0xff, 0xff, 0x45, 0x13, 0x00, 0x78, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10 + }; + + if (!arg.length()) + return QLatin1String("\"\""); + + QString ret(arg); + if (hasSpecialChars(ret, iqm)) { + // Quotes are escaped and their preceding backslashes are doubled. + // It's impossible to escape anything inside a quoted string on cmd + // level, so the outer quoting must be "suspended". + ret.replace(QRegularExpression(QLatin1String("(\\\\*)\"")), QLatin1String("\"\\1\\1\\^\"\"")); + // The argument must not end with a \ since this would be interpreted + // as escaping the quote -- rather put the \ behind the quote: e.g. + // rather use "foo"\ than "foo\" + int i = ret.length(); + while (i > 0 && ret.at(i - 1) == QLatin1Char('\\')) + --i; + ret.insert(i, QLatin1Char('"')); + ret.prepend(QLatin1Char('"')); + } + return ret; +} + +static QString shellQuote(const QString &arg) +{ + if (QDir::separator() == QLatin1Char('\\')) + return shellQuoteWin(arg); + else + return shellQuoteUnix(arg); +} + +#endif // SHELLQUOTE_SHARED_H |