From 92eea633491ce8138c5caceb904ad26c1eb91044 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Fri, 7 Feb 2020 14:12:57 +0100 Subject: Obsolete command-string parsing QProcess::start/execute overloads The command string parsing covers only simple quoting patterns, while users tend to expect something that is in line with their shell. The overloads that take a QStringList are the recommended APIs to use anyway, so exposing the splitting method as a static function for which we document the exact behavior allows callers to post-process the QStringList, before calling the preferred overloads. [ChangeLog][QtCore][QProcess] Overloads of start/execute/startDatached that parse a single command string into program and arguments have been marked as deprecated. A static helper splitCommand has been added to construct a QStringList from a command string. Change-Id: Ie91fcfb5eae6a52e5065efc60d2d9e068d20869d Fixes: QTBUG-80640 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 33 +++++++++++++++++++++++---------- src/corelib/io/qprocess.h | 19 ++++++++++++++++++- 2 files changed, 41 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index aedcae2cdc..40ef911894 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -2246,8 +2246,16 @@ void QProcessPrivate::start(QIODevice::OpenMode mode) startProcess(); } +/*! + \since 5.15 + + Splits the string \a command into a list of tokens, and returns + the list. -static QStringList parseCombinedArgString(const QString &program) + Tokens with spaces can be surrounded by double quotes; three + consecutive double quotes represent the quote character itself. +*/ +QStringList QProcess::splitCommand(const QString &command) { QStringList args; QString tmp; @@ -2257,13 +2265,13 @@ static QStringList parseCombinedArgString(const QString &program) // handle quoting. tokens can be surrounded by double quotes // "hello world". three consecutive double quotes represent // the quote character itself. - for (int i = 0; i < program.size(); ++i) { - if (program.at(i) == QLatin1Char('"')) { + for (int i = 0; i < command.size(); ++i) { + if (command.at(i) == QLatin1Char('"')) { ++quoteCount; if (quoteCount == 3) { // third consecutive quote quoteCount = 0; - tmp += program.at(i); + tmp += command.at(i); } continue; } @@ -2272,13 +2280,13 @@ static QStringList parseCombinedArgString(const QString &program) inQuote = !inQuote; quoteCount = 0; } - if (!inQuote && program.at(i).isSpace()) { + if (!inQuote && command.at(i).isSpace()) { if (!tmp.isEmpty()) { args += tmp; tmp.clear(); } } else { - tmp += program.at(i); + tmp += command.at(i); } } if (!tmp.isEmpty()) @@ -2288,6 +2296,7 @@ static QStringList parseCombinedArgString(const QString &program) } /*! + \obsolete \overload Starts the command \a command in a new process. @@ -2324,11 +2333,13 @@ static QStringList parseCombinedArgString(const QString &program) list-based API. In these rare cases you need to use setProgram() and setNativeArguments() instead of this function. + \sa splitCommand() + */ #if !defined(QT_NO_PROCESS_COMBINED_ARGUMENT_START) void QProcess::start(const QString &command, OpenMode mode) { - QStringList args = parseCombinedArgString(command); + QStringList args = splitCommand(command); if (args.isEmpty()) { Q_D(QProcess); d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined")); @@ -2493,6 +2504,7 @@ int QProcess::execute(const QString &program, const QStringList &arguments) } /*! + \obsolete \overload Starts the program \a command in a new process, waits for it to finish, @@ -2503,7 +2515,7 @@ int QProcess::execute(const QString &program, const QStringList &arguments) After the \a command string has been split and unquoted, this function behaves like the overload which takes the arguments as a string list. - \sa start() + \sa start(), splitCommand() */ int QProcess::execute(const QString &command) { @@ -2559,6 +2571,7 @@ bool QProcess::startDetached(const QString &program, } /*! + \obsolete \overload startDetached() Starts the command \a command in a new process, and detaches from it. @@ -2569,11 +2582,11 @@ bool QProcess::startDetached(const QString &program, After the \a command string has been split and unquoted, this function behaves like the overload which takes the arguments as a string list. - \sa start(const QString &command, QIODevice::OpenMode mode) + \sa start(const QString &command, QIODevice::OpenMode mode), splitCommand() */ bool QProcess::startDetached(const QString &command) { - QStringList args = parseCombinedArgString(command); + QStringList args = splitCommand(command); if (args.isEmpty()) return false; diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index 585508adf1..504b4a8061 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -160,7 +160,13 @@ public: void start(const QString &program, const QStringList &arguments, OpenMode mode = ReadWrite); #if !defined(QT_NO_PROCESS_COMBINED_ARGUMENT_START) +#if QT_DEPRECATED_SINCE(5, 15) + QT_DEPRECATED_X( + "Use QProcess::start(const QString &program, const QStringList &arguments," + "OpenMode mode = ReadWrite) instead" + ) void start(const QString &command, OpenMode mode = ReadWrite); +#endif #endif void start(OpenMode mode = ReadWrite); bool startDetached(qint64 *pid = nullptr); @@ -250,8 +256,12 @@ public: bool atEnd() const override; // ### Qt6: remove trivial override static int execute(const QString &program, const QStringList &arguments); +#if QT_DEPRECATED_SINCE(5, 15) + QT_DEPRECATED_X( + "Use QProcess::execute(const QString &program, const QStringList &arguments) instead" + ) static int execute(const QString &command); - +#endif static bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory #if defined(Q_QDOC) @@ -261,12 +271,19 @@ public: #if !defined(Q_QDOC) static bool startDetached(const QString &program, const QStringList &arguments); // ### Qt6: merge overloads #endif +#if QT_DEPRECATED_SINCE(5, 15) + QT_DEPRECATED_X( + "Use QProcess::startDetached(const QString &program, const QStringList &arguments) instead" + ) static bool startDetached(const QString &command); +#endif static QStringList systemEnvironment(); static QString nullDevice(); + static QStringList splitCommand(const QString &command); + public Q_SLOTS: void terminate(); void kill(); -- cgit v1.2.3