summaryrefslogtreecommitdiffstats
path: root/kdecore/kmacroexpander.h
diff options
context:
space:
mode:
Diffstat (limited to 'kdecore/kmacroexpander.h')
-rw-r--r--kdecore/kmacroexpander.h380
1 files changed, 380 insertions, 0 deletions
diff --git a/kdecore/kmacroexpander.h b/kdecore/kmacroexpander.h
new file mode 100644
index 000000000..deb12e284
--- /dev/null
+++ b/kdecore/kmacroexpander.h
@@ -0,0 +1,380 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (c) 2002-2003 Oswald Buddenhagen <ossi@kde.org>
+ Copyright (c) 2003 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef _KMACROEXPANDER_H
+#define _KMACROEXPANDER_H
+
+#include <qstringlist.h>
+#include <qstring.h>
+#include <qmap.h>
+#include "kdelibs_export.h"
+
+/**
+ * Abstract base class for the worker classes behind the KMacroExpander namespace
+ * and the KCharMacroExpander and KWordMacroExpander classes.
+ *
+ * @since 3.1.3
+ * @author Oswald Buddenhagen <ossi@kde.org>
+ */
+class KDECORE_EXPORT KMacroExpanderBase {
+
+public:
+ /**
+ * Constructor.
+ * @param c escape char indicating start of macros, or QChar::null for none
+ */
+ KMacroExpanderBase( QChar c = '%' );
+
+ /**
+ * Destructor.
+ */
+ virtual ~KMacroExpanderBase();
+
+ /**
+ * Perform safe macro expansion (substitution) on a string.
+ *
+ * @param str the string in which macros are expanded in-place
+ */
+ void expandMacros( QString &str );
+
+ /*
+ * Perform safe macro expansion (substitution) on a string for use
+ * in shell commands.
+ *
+ * Explicitly supported shell constructs:
+ * \ '' "" $'' $"" {} () $(()) ${} $() ``
+ *
+ * Implicitly supported shell constructs:
+ * (())
+ *
+ * Unsupported shell constructs that will cause problems:
+ * @li Shortened "case $v in pat)" syntax. Use "case $v in (pat)" instead.
+ *
+ * The rest of the shell (incl. bash) syntax is simply ignored,
+ * as it is not expected to cause problems.
+ *
+ * Note that bash contains a bug which makes macro expansion within
+ * double quoted substitutions ("${VAR:-%macro}") inherently insecure.
+ *
+ * @param str the string in which macros are expanded in-place
+ * @param pos the position inside the string at which parsing/substitution
+ * should start, and upon exit where processing stopped
+ * @return false if the string could not be parsed and therefore no safe
+ * substitution was possible. Note that macros will have been processed
+ * up to the point where the error occurred. An unmatched closing paren
+ * or brace outside any shell construct is @em not an error (unlike in
+ * the function below), but still prematurely terminates processing.
+ */
+ bool expandMacrosShellQuote( QString &str, uint &pos );
+
+ /**
+ * Same as above, but always starts at position 0, and unmatched closing
+ * parens and braces are treated as errors.
+ */
+ bool expandMacrosShellQuote( QString &str );
+
+ /**
+ * Set the macro escape character.
+ * @param c escape char indicating start of macros, or QChar::null if none
+ */
+ void setEscapeChar( QChar c );
+
+ /**
+ * Obtain the macro escape character.
+ * @return escape char indicating start of macros, or QChar::null if none
+ */
+ QChar escapeChar() const;
+
+protected:
+ /**
+ * This function is called for every single char within the string if
+ * the escape char is QChar::null. It should determine whether the
+ * string starting at @p pos within @p str is a valid macro and return
+ * the substitution value for it if so.
+ * @param str the input string
+ * @param pos the offset within @p str
+ * @param ret return value: the string to substitute for the macro
+ * @return if greater than zero, the number of chars at @p pos in @p str
+ * to substitute with @p ret (i.e., a valid macro was found). if less
+ * than zero, subtract this value from @p pos (to skip a macro, i.e.,
+ * substitute it with itself). zero requests no special action.
+ */
+ virtual int expandPlainMacro( const QString &str, uint pos, QStringList &ret );
+
+ /**
+ * This function is called every time the escape char is found if it is
+ * not QChar::null. It should determine whether the
+ * string starting at @p pos witin @p str is a valid macro and return
+ * the substitution value for it if so.
+ * @param str the input string
+ * @param pos the offset within @p str. Note that this is the position of
+ * the occurrence of the escape char
+ * @param ret return value: the string to substitute for the macro
+ * @return if greater than zero, the number of chars at @p pos in @p str
+ * to substitute with @p ret (i.e., a valid macro was found). if less
+ * than zero, subtract this value from @p pos (to skip a macro, i.e.,
+ * substitute it with itself). zero requests no special action.
+ */
+ virtual int expandEscapedMacro( const QString &str, uint pos, QStringList &ret );
+
+private:
+ QChar escapechar;
+};
+
+/**
+ * Abstract base class for simple word macro substitutors. Use this instead of
+ * the functions in the KMacroExpander namespace if speculatively pre-filling
+ * the substitution map would be too expensive.
+ *
+ * A typical application:
+ *
+ * \code
+ * class MyClass {
+ * ...
+ * private:
+ * QString m_str;
+ * ...
+ * friend class MyExpander;
+ * };
+ *
+ * class MyExpander : public KWordMacroExpander {
+ * public:
+ * MyExpander( MyClass *_that ) : KWordMacroExpander(), that( _that ) {}
+ * protected:
+ * virtual bool expandMacro( const QString &str, QStringList &ret );
+ * private:
+ * MyClass *that;
+ * };
+ *
+ * bool MyExpander::expandMacro( const QString &str, QStringList &ret )
+ * {
+ * if (str == "macro") {
+ * ret += complexOperation( that->m_str );
+ * return true;
+ * }
+ * return false;
+ * }
+ *
+ * ... MyClass::...(...)
+ * {
+ * QString str;
+ * ...
+ * MyExpander mx( this );
+ * mx.expandMacrosShellQuote( str );
+ * ...
+ * }
+ * \endcode
+ *
+ * Alternatively MyClass could inherit from KWordMacroExpander directly.
+ *
+ * @since 3.3
+ * @author Oswald Buddenhagen <ossi@kde.org>
+ */
+class KDECORE_EXPORT KWordMacroExpander : public KMacroExpanderBase {
+
+public:
+ /**
+ * Constructor.
+ * @param c escape char indicating start of macros, or QChar::null for none
+ */
+ KWordMacroExpander( QChar c = '%' ) : KMacroExpanderBase( c ) {}
+
+protected:
+ virtual int expandPlainMacro( const QString &str, uint pos, QStringList &ret );
+ virtual int expandEscapedMacro( const QString &str, uint pos, QStringList &ret );
+
+ /**
+ * Return substitution list @p ret for string macro @p str.
+ * @param str the macro to expand
+ * @param ret return variable reference. It is guaranteed to be empty
+ * when expandMacro is entered.
+ * @return @c true iff @p chr was a recognized macro name
+ */
+ virtual bool expandMacro( const QString &str, QStringList &ret ) = 0;
+};
+
+/**
+ * Abstract base class for single char macro substitutors. Use this instead of
+ * the functions in the KMacroExpander namespace if speculatively pre-filling
+ * the substitution map would be too expensive.
+ *
+ * See KWordMacroExpander for a sample application.
+ *
+ * @since 3.3
+ * @author Oswald Buddenhagen <ossi@kde.org>
+ */
+class KDECORE_EXPORT KCharMacroExpander : public KMacroExpanderBase {
+
+public:
+ /**
+ * Constructor.
+ * @param c escape char indicating start of macros, or QChar::null for none
+ */
+ KCharMacroExpander( QChar c = '%' ) : KMacroExpanderBase( c ) {}
+
+protected:
+ virtual int expandPlainMacro( const QString &str, uint pos, QStringList &ret );
+ virtual int expandEscapedMacro( const QString &str, uint pos, QStringList &ret );
+
+ /**
+ * Return substitution list @p ret for single-character macro @p chr.
+ * @param chr the macro to expand
+ * @param ret return variable reference. It is guaranteed to be empty
+ * when expandMacro is entered.
+ * @return @c true iff @p chr was a recognized macro name
+ */
+ virtual bool expandMacro( QChar chr, QStringList &ret ) = 0;
+};
+
+/**
+ * A group of functions providing macro expansion (substitution) in strings,
+ * optionally with quoting appropriate for shell execution.
+ * @since 3.1.3
+ */
+namespace KMacroExpander {
+ /**
+ * Perform safe macro expansion (substitution) on a string.
+ * The escape char must be quoted with itself to obtain its literal
+ * representation in the resulting string.
+ *
+ * @param str The string to expand
+ * @param map map with substitutions
+ * @param c escape char indicating start of macro, or QChar::null if none
+ * @return the string with all valid macros expanded
+ *
+ * \code
+ * // Code example
+ * QMap<QChar,QString> map;
+ * map.insert('u', "/tmp/myfile.txt");
+ * map.insert('n', "My File");
+ * QString s = "%% Title: %u:%n";
+ * s = KMacroExpander::expandMacros(s, map);
+ * // s is now "% Title: /tmp/myfile.txt:My File";
+ * \endcode
+ */
+ KDECORE_EXPORT QString expandMacros( const QString &str, const QMap<QChar,QString> &map, QChar c = '%' );
+
+ /**
+ * Perform safe macro expansion (substitution) on a string for use
+ * in shell commands.
+ * The escape char must be quoted with itself to obtain its literal
+ * representation in the resulting string.
+ *
+ * @param str The string to expand
+ * @param map map with substitutions
+ * @param c escape char indicating start of macro, or QChar::null if none
+ * @return the string with all valid macros expanded, or a null string
+ * if a shell syntax error was detected in the command
+ *
+ * \code
+ * // Code example
+ * QMap<QChar,QString> map;
+ * map.insert('u', "/tmp/myfile.txt");
+ * map.insert('n', "My File");
+ * QString s = "kedit --caption %n %u";
+ * s = KMacroExpander::expandMacrosShellQuote(s, map);
+ * // s is now "kedit --caption 'My File' '/tmp/myfile.txt'";
+ * system(QFile::encodeName(s));
+ * \endcode
+ */
+ KDECORE_EXPORT QString expandMacrosShellQuote( const QString &str, const QMap<QChar,QString> &map, QChar c = '%' );
+
+ /**
+ * Perform safe macro expansion (substitution) on a string.
+ * The escape char must be quoted with itself to obtain its literal
+ * representation in the resulting string.
+ * Macro names can consist of chars in the range [A-Za-z0-9_];
+ * use braces to delimit macros from following words starting
+ * with these chars, or to use other chars for macro names.
+ *
+ * @param str The string to expand
+ * @param map map with substitutions
+ * @param c escape char indicating start of macro, or QChar::null if none
+ * @return the string with all valid macros expanded
+ *
+ * \code
+ * // Code example
+ * QMap<QString,QString> map;
+ * map.insert("url", "/tmp/myfile.txt");
+ * map.insert("name", "My File");
+ * QString s = "Title: %{url}-%name";
+ * s = KMacroExpander::expandMacros(s, map);
+ * // s is now "Title: /tmp/myfile.txt-My File";
+ * \endcode
+ */
+ KDECORE_EXPORT QString expandMacros( const QString &str, const QMap<QString,QString> &map, QChar c = '%' );
+
+ /**
+ * Perform safe macro expansion (substitution) on a string for use
+ * in shell commands.
+ * The escape char must be quoted with itself to obtain its literal
+ * representation in the resulting string.
+ * Macro names can consist of chars in the range [A-Za-z0-9_];
+ * use braces to delimit macros from following words starting
+ * with these chars, or to use other chars for macro names.
+ *
+ * @param str The string to expand
+ * @param map map with substitutions
+ * @param c escape char indicating start of macro, or QChar::null if none
+ * @return the string with all valid macros expanded, or a null string
+ * if a shell syntax error was detected in the command
+ *
+ * \code
+ * // Code example
+ * QMap<QString,QString> map;
+ * map.insert("url", "/tmp/myfile.txt");
+ * map.insert("name", "My File");
+ * QString s = "kedit --caption %name %{url}";
+ * s = KMacroExpander::expandMacrosShellQuote(s, map);
+ * // s is now "kedit --caption 'My File' '/tmp/myfile.txt'";
+ * system(QFile::encodeName(s));
+ * \endcode
+ */
+ KDECORE_EXPORT QString expandMacrosShellQuote( const QString &str, const QMap<QString,QString> &map, QChar c = '%' );
+
+ /**
+ * Same as above, except that the macros expand to string lists that
+ * are simply join(" ")ed together.
+ */
+ KDECORE_EXPORT QString expandMacros( const QString &str, const QMap<QChar,QStringList> &map, QChar c = '%' );
+ /**
+ * Same as above, except that the macros expand to string lists that
+ * are simply join(" ")ed together.
+ */
+ KDECORE_EXPORT QString expandMacros( const QString &str, const QMap<QString,QStringList> &map, QChar c = '%' );
+
+ /**
+ * Same as above, except that the macros expand to string lists.
+ * If the macro appears inside a quoted string, the list is simply
+ * join(" ")ed together; otherwise every element expands to a separate
+ * quoted string.
+ */
+ KDECORE_EXPORT QString expandMacrosShellQuote( const QString &str, const QMap<QChar,QStringList> &map, QChar c = '%' );
+ /**
+ * Same as above, except that the macros expand to string lists.
+ * If the macro appears inside a quoted string, the list is simply
+ * join(" ")ed together; otherwise every element expands to a separate
+ * quoted string.
+ */
+ KDECORE_EXPORT QString expandMacrosShellQuote( const QString &str, const QMap<QString,QStringList> &map, QChar c = '%' );
+}
+
+#endif /* _KMACROEXPANDER_H */