KDECore
kshell_win.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "kshell.h"
00024 #include "kshell_p.h"
00025
00026 #include <kkernel_win.h>
00027
00028 #include <QString>
00029 #include <QStringList>
00030 #include <QtCore/QDir>
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 inline static bool isMetaChar(ushort c)
00059 {
00060 static const uchar iqm[] = {
00061 0x00, 0x00, 0x00, 0x00, 0x40, 0x03, 0x00, 0x50,
00062 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
00063 };
00064
00065 return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
00066 }
00067
00068 inline static bool isSpecialChar(ushort c)
00069 {
00070
00071
00072
00073
00074 static const uchar iqm[] = {
00075 0xff, 0xff, 0xff, 0xff, 0x41, 0x13, 0x00, 0x78,
00076 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10
00077 };
00078
00079 return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
00080 }
00081
00082 inline static bool isWhiteSpace(ushort c)
00083 {
00084 return c == ' ' || c == '\t';
00085 }
00086
00087 QStringList KShell::splitArgs(const QString &_args, Options flags, Errors *err)
00088 {
00089 QString args(_args);
00090 QStringList ret;
00091
00092 const QLatin1Char bs('\\'), dq('\"');
00093
00094 if (flags & AbortOnMeta) {
00095 args.remove(PERCENT_ESCAPE);
00096 if (args.indexOf('%') >= 0) {
00097 if (err)
00098 *err = FoundMeta;
00099 return QStringList();
00100 }
00101
00102 args = _args;
00103 args.replace(PERCENT_ESCAPE, "%");
00104
00105 if (!args.isEmpty() && args[0].unicode() == '@')
00106 args.remove(0, 1);
00107
00108 for (int p = 0; p < args.length(); p++) {
00109 ushort c = args[p].unicode();
00110 if (c == '^') {
00111 args.remove(p, 1);
00112 } else if (c == '"') {
00113 while (++p < args.length() && args[p].unicode() != '"')
00114 ;
00115 } else if (isMetaChar(c)) {
00116 if (err)
00117 *err = FoundMeta;
00118 return QStringList();
00119 }
00120 }
00121 }
00122
00123 if (err)
00124 *err = NoError;
00125
00126 int p = 0;
00127 const int length = args.length();
00128 forever {
00129 while (p < length && isWhiteSpace(args[p].unicode()))
00130 ++p;
00131 if (p == length)
00132 return ret;
00133
00134 QString arg;
00135 bool inquote = false;
00136 forever {
00137 bool copy = true;
00138 int bslashes = 0;
00139 while (p < length && args[p] == bs) {
00140 ++p;
00141 ++bslashes;
00142 }
00143 if (p < length && args[p] == dq) {
00144 if (bslashes % 2 == 0) {
00145
00146 if (inquote) {
00147 if (p + 1 < length && args[p + 1] == dq) {
00148
00149
00150 ++p;
00151 } else {
00152
00153 copy = false;
00154 inquote = !inquote;
00155 }
00156 } else {
00157
00158 copy = false;
00159 inquote = !inquote;
00160 }
00161 }
00162 bslashes /= 2;
00163 }
00164
00165 while (--bslashes >= 0)
00166 arg.append(bs);
00167
00168 if (p == length || (!inquote && isWhiteSpace(args[p].unicode()))) {
00169 ret.append(arg);
00170 if (inquote) {
00171 if (err)
00172 *err = BadQuoting;
00173 return QStringList();
00174 }
00175 break;
00176 }
00177
00178 if (copy)
00179 arg.append(args[p]);
00180 ++p;
00181 }
00182 }
00183
00184 }
00185
00186 QString KShell::quoteArgInternal(const QString &arg, bool _inquote)
00187 {
00188
00189
00190
00191 const QLatin1Char bs('\\'), dq('\"');
00192 QString ret;
00193 bool inquote = _inquote;
00194 int bslashes = 0;
00195 for (int p = 0; p < arg.length(); p++) {
00196 if (arg[p] == bs) {
00197 bslashes++;
00198 } else if (arg[p] == dq) {
00199 if (inquote) {
00200 ret.append(dq);
00201 inquote = false;
00202 }
00203 for (; bslashes; bslashes--)
00204 ret.append(QLatin1String("\\\\"));
00205 ret.append(QLatin1String("\\^\""));
00206 } else {
00207 if (!inquote) {
00208 ret.append(dq);
00209 inquote = true;
00210 }
00211 for (; bslashes; bslashes--)
00212 ret.append(bs);
00213 ret.append(arg[p]);
00214 }
00215 }
00216 ret.replace('%', PERCENT_ESCAPE);
00217 if (bslashes) {
00218
00219
00220 if (!inquote && !_inquote)
00221 ret.append(dq);
00222 for (; bslashes; bslashes--)
00223 ret.append(QLatin1String("\\\\"));
00224 ret.append(dq);
00225 if (inquote && _inquote)
00226 ret.append(dq);
00227 } else if (inquote != _inquote) {
00228 ret.append(dq);
00229 }
00230 return ret;
00231 }
00232
00233 QString KShell::quoteArg(const QString &arg)
00234 {
00235 if (arg.isEmpty())
00236 return QString::fromLatin1("\"\"");
00237
00238
00239
00240 if (arg.endsWith(QLatin1Char('\\')))
00241 return quoteArgInternal(arg, false);
00242
00243 for (int x = arg.length() - 1; x >= 0; --x)
00244 if (isSpecialChar(arg[x].unicode()))
00245 return quoteArgInternal(arg, false);
00246
00247
00248
00249 QString ret(arg);
00250 ret.replace(QRegExp(QLatin1String("(\\\\*)\"")), QLatin1String("\\1\\1\\^\""));
00251 ret.replace('%', PERCENT_ESCAPE);
00252 return ret;
00253 }
00254