File indexing completed on 2025-03-16 08:11:28
0001 /* 0002 SPDX-FileCopyrightText: 2007-2008 Robert Knight <robertknight@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 // Own 0008 #include "ShellCommand.h" 0009 0010 // KDE 0011 #include <KShell> 0012 0013 using Konsole::ShellCommand; 0014 0015 ShellCommand::ShellCommand(const QString &aCommand) 0016 : _arguments(KShell::splitArgs(aCommand)) 0017 { 0018 } 0019 0020 ShellCommand::ShellCommand(const QString &aCommand, const QStringList &aArguments) 0021 : _arguments(aArguments) 0022 { 0023 if (!_arguments.isEmpty()) { 0024 _arguments[0] = aCommand; 0025 } 0026 } 0027 0028 QString ShellCommand::fullCommand() const 0029 { 0030 QStringList quotedArgs(_arguments); 0031 for (int i = 0; i < quotedArgs.size(); i++) { 0032 QString arg = quotedArgs.at(i); 0033 bool hasSpace = false; 0034 for (int j = 0; j < arg.size(); j++) { 0035 if (arg[j].isSpace()) { 0036 hasSpace = true; 0037 } 0038 } 0039 if (hasSpace) { 0040 quotedArgs[i] = QLatin1Char('\"') + arg + QLatin1Char('\"'); 0041 } 0042 } 0043 return quotedArgs.join(QLatin1Char(' ')); 0044 } 0045 0046 QString ShellCommand::command() const 0047 { 0048 if (!_arguments.isEmpty()) { 0049 return _arguments[0]; 0050 } 0051 return QString(); 0052 } 0053 0054 QStringList ShellCommand::arguments() const 0055 { 0056 return _arguments; 0057 } 0058 0059 QStringList ShellCommand::expand(const QStringList &items) 0060 { 0061 QStringList result; 0062 result.reserve(items.size()); 0063 0064 for (const QString &item : items) { 0065 result << expand(item); 0066 } 0067 0068 return result; 0069 } 0070 0071 QString ShellCommand::expand(const QString &text) 0072 { 0073 QString result = text; 0074 expandEnv(result); 0075 return result; 0076 } 0077 0078 bool ShellCommand::isValidEnvCharacter(const QChar &ch) 0079 { 0080 const ushort code = ch.unicode(); 0081 return isValidLeadingEnvCharacter(ch) || ('0' <= code && code <= '9'); 0082 } 0083 0084 bool ShellCommand::isValidLeadingEnvCharacter(const QChar &ch) 0085 { 0086 const ushort code = ch.unicode(); 0087 return (code == '_') || ('A' <= code && code <= 'Z'); 0088 } 0089 0090 /* 0091 * expandEnv 0092 * 0093 * Expand environment variables in text. Escaped '$' characters are ignored. 0094 * Return true if any variables were expanded 0095 */ 0096 bool ShellCommand::expandEnv(QString &text) 0097 { 0098 const QLatin1Char dollarChar('$'); 0099 const QLatin1Char backslashChar('\\'); 0100 0101 int dollarPos = 0; 0102 bool expanded = false; 0103 0104 // find and expand all environment variables beginning with '$' 0105 while ((dollarPos = text.indexOf(dollarChar, dollarPos)) != -1) { 0106 // if '$' is the last character, there is no way of expanding 0107 if (dollarPos == text.length() - 1) { 0108 break; 0109 } 0110 0111 // skip escaped '$' 0112 if (dollarPos > 0 && text.at(dollarPos - 1) == backslashChar) { 0113 dollarPos++; 0114 continue; 0115 } 0116 0117 // if '$' is followed by an invalid leading character, skip this '$' 0118 if (!isValidLeadingEnvCharacter(text.at(dollarPos + 1))) { 0119 dollarPos++; 0120 continue; 0121 } 0122 0123 int endPos = dollarPos + 1; 0124 Q_ASSERT(endPos < text.length()); 0125 while (endPos < text.length() && isValidEnvCharacter(text.at(endPos))) { 0126 endPos++; 0127 } 0128 0129 const int len = endPos - dollarPos; 0130 const QString key = text.mid(dollarPos + 1, len - 1); 0131 const QString value = QString::fromLocal8Bit(qgetenv(key.toLocal8Bit().constData())); 0132 0133 if (!value.isEmpty()) { 0134 text.replace(dollarPos, len, value); 0135 expanded = true; 0136 dollarPos = dollarPos + value.length(); 0137 } else { 0138 dollarPos = endPos; 0139 } 0140 } 0141 0142 return expanded; 0143 }