fix logic
[personal-kdelibs.git] / kdecore / util / kmacroexpander.h
blob3fd81d6cbdad267edc1b56b5db2f406329d79a3c
1 /*
2 This file is part of the KDE libraries
4 Copyright (c) 2002-2003 Oswald Buddenhagen <ossi@kde.org>
5 Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
22 #ifndef KMACROEXPANDER_H
23 #define KMACROEXPANDER_H
25 #include <kdecore_export.h>
26 #include <QtCore/QChar>
28 class QString;
29 class QStringList;
30 template <typename KT, typename VT> class QHash;
31 class KMacroExpanderBasePrivate;
33 /**
34 * \class KMacroExpanderBase kmacroexpander.h <KMacroExpanderBase>
36 * Abstract base class for the worker classes behind the KMacroExpander namespace
37 * and the KCharMacroExpander and KWordMacroExpander classes.
39 * @author Oswald Buddenhagen <ossi@kde.org>
41 class KDECORE_EXPORT KMacroExpanderBase {
43 public:
44 /**
45 * Constructor.
46 * @param c escape char indicating start of macros, or QChar::null for none
48 explicit KMacroExpanderBase( QChar c = QLatin1Char('%') );
50 /**
51 * Destructor.
53 virtual ~KMacroExpanderBase();
55 /**
56 * Perform safe macro expansion (substitution) on a string.
58 * @param str the string in which macros are expanded in-place
60 void expandMacros( QString &str );
62 // TODO: This documentation is relevant for end-users. Where to put it?
63 /**
64 * Perform safe macro expansion (substitution) on a string for use
65 * in shell commands.
67 * <h3>*NIX notes</h3>
69 * Explicitly supported shell constructs:
70 * \ '' "" $'' $"" {} () $(()) ${} $() ``
72 * Implicitly supported shell constructs:
73 * (())
75 * Unsupported shell constructs that will cause problems:
76 * Shortened &quot;<tt>case $v in pat)</tt>&quot; syntax. Use
77 * &quot;<tt>case $v in (pat)</tt>&quot; instead.
79 * The rest of the shell (incl. bash) syntax is simply ignored,
80 * as it is not expected to cause problems.
82 * Note that bash contains a bug which makes macro expansion within
83 * double quoted substitutions (<tt>"${VAR:-%macro}"</tt>) inherently
84 * insecure.
86 * For security reasons, @em never put expandos in command line arguments
87 * that are shell commands by themselves -
88 * &quot;<tt>sh -c 'foo \%f'</tt>&quot; is taboo.
89 * &quot;<tt>file=\%f sh -c 'foo "$file"'</tt>&quot; is OK.
91 * <h3>Windows notes</h3>
93 * All quoting syntax supported by KShell is supported here as well.
94 * Additionally, command grouping via parentheses is recognized - note
95 * however, that the parser is much stricter about unquoted parentheses
96 * than cmd itself.
97 * The rest of the cmd syntax is simply ignored, as it is not expected
98 * to cause problems - do not use commands that embed other commands,
99 * though - &quot;<tt>for /f ...</tt>&quot; is taboo.
101 * @param str the string in which macros are expanded in-place
102 * @param pos the position inside the string at which parsing/substitution
103 * should start, and upon exit where processing stopped
104 * @return false if the string could not be parsed and therefore no safe
105 * substitution was possible. Note that macros will have been processed
106 * up to the point where the error occurred. An unmatched closing paren
107 * or brace outside any shell construct is @em not an error (unlike in
108 * the function below), but still prematurely terminates processing.
110 bool expandMacrosShellQuote( QString &str, int &pos );
113 * Same as above, but always starts at position 0, and unmatched closing
114 * parens and braces are treated as errors.
116 bool expandMacrosShellQuote( QString &str );
119 * Set the macro escape character.
120 * @param c escape char indicating start of macros, or QChar::null if none
122 void setEscapeChar( QChar c );
125 * Obtain the macro escape character.
126 * @return escape char indicating start of macros, or QChar::null if none
128 QChar escapeChar() const;
130 protected:
132 * This function is called for every single char within the string if
133 * the escape char is QChar::null. It should determine whether the
134 * string starting at @p pos within @p str is a valid macro and return
135 * the substitution value for it if so.
136 * @param str the input string
137 * @param pos the offset within @p str
138 * @param ret return value: the string to substitute for the macro
139 * @return If greater than zero, the number of chars at @p pos in @p str
140 * to substitute with @p ret (i.e., a valid macro was found). If less
141 * than zero, subtract this value from @p pos (to skip a macro, i.e.,
142 * substitute it with itself). If zero, no macro starts at @p pos.
144 virtual int expandPlainMacro( const QString &str, int pos, QStringList &ret );
147 * This function is called every time the escape char is found if it is
148 * not QChar::null. It should determine whether the
149 * string starting at @p pos witin @p str is a valid macro and return
150 * the substitution value for it if so.
151 * @param str the input string
152 * @param pos the offset within @p str. Note that this is the position of
153 * the occurrence of the escape char
154 * @param ret return value: the string to substitute for the macro
155 * @return If greater than zero, the number of chars at @p pos in @p str
156 * to substitute with @p ret (i.e., a valid macro was found). If less
157 * than zero, subtract this value from @p pos (to skip a macro, i.e.,
158 * substitute it with itself). If zero, scanning continues as if no
159 * escape char was encountered at all.
161 virtual int expandEscapedMacro( const QString &str, int pos, QStringList &ret );
163 private:
164 KMacroExpanderBasePrivate * const d;
168 * \class KWordMacroExpander kmacroexpander.h <KMacroExpanderBase>
170 * Abstract base class for simple word macro substitutors. Use this instead of
171 * the functions in the KMacroExpander namespace if speculatively pre-filling
172 * the substitution map would be too expensive.
174 * A typical application:
176 * \code
177 * class MyClass {
178 * ...
179 * private:
180 * QString m_str;
181 * ...
182 * friend class MyExpander;
183 * };
185 * class MyExpander : public KWordMacroExpander {
186 * public:
187 * MyExpander( MyClass *_that ) : KWordMacroExpander(), that( _that ) {}
188 * protected:
189 * virtual bool expandMacro( const QString &str, QStringList &ret );
190 * private:
191 * MyClass *that;
192 * };
194 * bool MyExpander::expandMacro( const QString &str, QStringList &ret )
196 * if (str == "macro") {
197 * ret += complexOperation( that->m_str );
198 * return true;
200 * return false;
203 * ... MyClass::...(...)
205 * QString str;
206 * ...
207 * MyExpander mx( this );
208 * mx.expandMacrosShellQuote( str );
209 * ...
211 * \endcode
213 * Alternatively MyClass could inherit from KWordMacroExpander directly.
215 * @author Oswald Buddenhagen <ossi@kde.org>
217 class KDECORE_EXPORT KWordMacroExpander : public KMacroExpanderBase {
219 public:
221 * Constructor.
222 * @param c escape char indicating start of macros, or QChar::null for none
224 explicit KWordMacroExpander( QChar c = QLatin1Char('%') ) : KMacroExpanderBase( c ) {}
226 protected:
227 /** \internal Not to be called or reimplemented. */
228 virtual int expandPlainMacro( const QString &str, int pos, QStringList &ret );
229 /** \internal Not to be called or reimplemented. */
230 virtual int expandEscapedMacro( const QString &str, int pos, QStringList &ret );
233 * Return substitution list @p ret for string macro @p str.
234 * @param str the macro to expand
235 * @param ret return variable reference. It is guaranteed to be empty
236 * when expandMacro is entered.
237 * @return @c true iff @p chr was a recognized macro name
239 virtual bool expandMacro( const QString &str, QStringList &ret ) = 0;
243 * \class KCharMacroExpander kmacroexpander.h <KMacroExpanderBase>
245 * Abstract base class for single char macro substitutors. Use this instead of
246 * the functions in the KMacroExpander namespace if speculatively pre-filling
247 * the substitution map would be too expensive.
249 * See KWordMacroExpander for a sample application.
251 * @author Oswald Buddenhagen <ossi@kde.org>
253 class KDECORE_EXPORT KCharMacroExpander : public KMacroExpanderBase {
255 public:
257 * Constructor.
258 * @param c escape char indicating start of macros, or QChar::null for none
260 explicit KCharMacroExpander( QChar c = QLatin1Char('%') ) : KMacroExpanderBase( c ) {}
262 protected:
263 /** \internal Not to be called or reimplemented. */
264 virtual int expandPlainMacro( const QString &str, int pos, QStringList &ret );
265 /** \internal Not to be called or reimplemented. */
266 virtual int expandEscapedMacro( const QString &str, int pos, QStringList &ret );
269 * Return substitution list @p ret for single-character macro @p chr.
270 * @param chr the macro to expand
271 * @param ret return variable reference. It is guaranteed to be empty
272 * when expandMacro is entered.
273 * @return @c true iff @p chr was a recognized macro name
275 virtual bool expandMacro( QChar chr, QStringList &ret ) = 0;
279 * A group of functions providing macro expansion (substitution) in strings,
280 * optionally with quoting appropriate for shell execution.
282 namespace KMacroExpander {
284 * Perform safe macro expansion (substitution) on a string.
285 * The escape char must be quoted with itself to obtain its literal
286 * representation in the resulting string.
288 * @param str The string to expand
289 * @param map map with substitutions
290 * @param c escape char indicating start of macro, or QChar::null if none
291 * @return the string with all valid macros expanded
293 * \code
294 * // Code example
295 * QHash<QChar,QString> map;
296 * map.insert('u', "/tmp/myfile.txt");
297 * map.insert('n', "My File");
298 * QString s = "%% Title: %u:%n";
299 * s = KMacroExpander::expandMacros(s, map);
300 * // s is now "% Title: /tmp/myfile.txt:My File";
301 * \endcode
303 KDECORE_EXPORT QString expandMacros( const QString &str, const QHash<QChar,QString> &map, QChar c = '%' );
306 * Perform safe macro expansion (substitution) on a string for use
307 * in shell commands.
308 * The escape char must be quoted with itself to obtain its literal
309 * representation in the resulting string.
311 * @param str The string to expand
312 * @param map map with substitutions
313 * @param c escape char indicating start of macro, or QChar::null if none
314 * @return the string with all valid macros expanded, or a null string
315 * if a shell syntax error was detected in the command
317 * \code
318 * // Code example
319 * QHash<QChar,QString> map;
320 * map.insert('u', "/tmp/myfile.txt");
321 * map.insert('n', "My File");
322 * QString s = "kedit --caption %n %u";
323 * s = KMacroExpander::expandMacrosShellQuote(s, map);
324 * // s is now "kedit --caption 'My File' '/tmp/myfile.txt'";
325 * system(QFile::encodeName(s));
326 * \endcode
328 KDECORE_EXPORT QString expandMacrosShellQuote( const QString &str, const QHash<QChar,QString> &map,
329 QChar c = QLatin1Char('%') );
332 * Perform safe macro expansion (substitution) on a string.
333 * The escape char must be quoted with itself to obtain its literal
334 * representation in the resulting string.
335 * Macro names can consist of chars in the range [A-Za-z0-9_];
336 * use braces to delimit macros from following words starting
337 * with these chars, or to use other chars for macro names.
339 * @param str The string to expand
340 * @param map map with substitutions
341 * @param c escape char indicating start of macro, or QChar::null if none
342 * @return the string with all valid macros expanded
344 * \code
345 * // Code example
346 * QHash<QString,QString> map;
347 * map.insert("url", "/tmp/myfile.txt");
348 * map.insert("name", "My File");
349 * QString s = "Title: %{url}-%name";
350 * s = KMacroExpander::expandMacros(s, map);
351 * // s is now "Title: /tmp/myfile.txt-My File";
352 * \endcode
354 KDECORE_EXPORT QString expandMacros( const QString &str, const QHash<QString,QString> &map,
355 QChar c = QLatin1Char('%') );
358 * Perform safe macro expansion (substitution) on a string for use
359 * in shell commands. See KMacroExpanderBase::expandMacrosShellQuote()
360 * for the exact semantics.
361 * The escape char must be quoted with itself to obtain its literal
362 * representation in the resulting string.
363 * Macro names can consist of chars in the range [A-Za-z0-9_];
364 * use braces to delimit macros from following words starting
365 * with these chars, or to use other chars for macro names.
367 * @param str The string to expand
368 * @param map map with substitutions
369 * @param c escape char indicating start of macro, or QChar::null if none
370 * @return the string with all valid macros expanded, or a null string
371 * if a shell syntax error was detected in the command
373 * \code
374 * // Code example
375 * QHash<QString,QString> map;
376 * map.insert("url", "/tmp/myfile.txt");
377 * map.insert("name", "My File");
378 * QString s = "kedit --caption %name %{url}";
379 * s = KMacroExpander::expandMacrosShellQuote(s, map);
380 * // s is now "kedit --caption 'My File' '/tmp/myfile.txt'";
381 * system(QFile::encodeName(s));
382 * \endcode
384 KDECORE_EXPORT QString expandMacrosShellQuote( const QString &str, const QHash<QString,QString> &map,
385 QChar c = QLatin1Char('%') );
388 * Same as above, except that the macros expand to string lists that
389 * are simply join(" ")ed together.
391 KDECORE_EXPORT QString expandMacros( const QString &str, const QHash<QChar,QStringList> &map,
392 QChar c = QLatin1Char('%') );
393 KDECORE_EXPORT QString expandMacros( const QString &str, const QHash<QString,QStringList> &map,
394 QChar c = QLatin1Char('%') );
397 * Same as above, except that the macros expand to string lists.
398 * If the macro appears inside a quoted string, the list is simply
399 * join(" ")ed together; otherwise every element expands to a separate
400 * quoted string.
402 KDECORE_EXPORT QString expandMacrosShellQuote( const QString &str, const QHash<QChar,QStringList> &map,
403 QChar c = QLatin1Char('%') );
404 KDECORE_EXPORT QString expandMacrosShellQuote( const QString &str, const QHash<QString,QStringList> &map,
405 QChar c = QLatin1Char('%') );
408 #endif /* KMACROEXPANDER_H */