Fix of DOXYGEN docs: @return instead of @returns
[midnight-commander.git] / lib / strutil / strescape.c
blobe647fd64faf5c4ea24e711bd58000911f743a119
1 /*
2 Functions for escaping and unescaping strings
4 Copyright (C) 2009, 2011
5 The Free Software Foundation, Inc.
7 Written by:
8 Slava Zanko <slavazanko@gmail.com>, 2009;
9 Patrick Winnertz <winnie@debian.org>, 2009
11 This file is part of the Midnight Commander.
13 The Midnight Commander is free software: you can redistribute it
14 and/or modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation, either version 3 of the License,
16 or (at your option) any later version.
18 The Midnight Commander is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include <config.h>
29 #include "lib/strescape.h"
31 /*** global variables ****************************************************************************/
33 /*** file scope macro definitions ****************************************************************/
35 /*** file scope type declarations ****************************************************************/
37 /*** file scope variables ************************************************************************/
39 static const char ESCAPE_SHELL_CHARS[] = " !#$%()&{}[]`?|<>;*\\\"'";
40 static const char ESCAPE_REGEX_CHARS[] = "^!#$%()&{}[]`?|<>;*.\\";
41 static const char ESCAPE_GLOB_CHARS[] = "$*\\?";
43 /*** file scope functions ************************************************************************/
45 /*** public functions ****************************************************************************/
47 char *
48 strutils_escape (const char *src, gsize src_len, const char *escaped_chars,
49 gboolean escape_non_printable)
51 GString *ret;
52 gsize curr_index;
53 /* do NOT break allocation semantics */
54 if (src == NULL)
55 return NULL;
57 if (*src == '\0')
58 return strdup ("");
60 ret = g_string_new ("");
62 if (src_len == (gsize) - 1)
63 src_len = strlen (src);
65 for (curr_index = 0; curr_index < src_len; curr_index++)
67 if (escape_non_printable)
69 switch (src[curr_index])
71 case '\n':
72 g_string_append (ret, "\\n");
73 continue;
74 case '\t':
75 g_string_append (ret, "\\t");
76 continue;
77 case '\b':
78 g_string_append (ret, "\\b");
79 continue;
80 case '\0':
81 g_string_append (ret, "\\0");
82 continue;
86 if (strchr (escaped_chars, (int) src[curr_index]))
87 g_string_append_c (ret, '\\');
89 g_string_append_c (ret, src[curr_index]);
91 return g_string_free (ret, FALSE);
94 /* --------------------------------------------------------------------------------------------- */
95 char *
96 strutils_unescape (const char *src, gsize src_len, const char *unescaped_chars,
97 gboolean unescape_non_printable)
99 GString *ret;
100 gsize curr_index;
102 if (src == NULL)
103 return NULL;
105 if (*src == '\0')
106 return strdup ("");
108 ret = g_string_sized_new (16);
110 if (src_len == (gsize) (-1))
111 src_len = strlen (src);
112 src_len--;
114 for (curr_index = 0; curr_index < src_len; curr_index++)
116 if (src[curr_index] != '\\')
118 g_string_append_c (ret, src[curr_index]);
119 continue;
122 curr_index++;
124 if (unescaped_chars == ESCAPE_SHELL_CHARS && src[curr_index] == '$')
126 /* special case: \$ is used to disallow variable substitution */
127 g_string_append_c (ret, '\\');
129 else
131 if (unescape_non_printable)
133 switch (src[curr_index])
135 case 'n':
136 g_string_append_c (ret, '\n');
137 continue;
138 case 't':
139 g_string_append_c (ret, '\t');
140 continue;
141 case 'b':
142 g_string_append_c (ret, '\b');
143 continue;
144 case '0':
145 g_string_append_c (ret, '\0');
146 continue;
150 if (strchr (unescaped_chars, (int) src[curr_index]) == NULL)
151 g_string_append_c (ret, '\\');
154 g_string_append_c (ret, src[curr_index]);
156 g_string_append_c (ret, src[curr_index]);
158 return g_string_free (ret, FALSE);
161 /* --------------------------------------------------------------------------------------------- */
164 * To be compatible with the general posix command lines we have to escape
165 * strings for the command line
167 * @param src string for escaping
169 * @return escaped string (which needs to be freed later) or NULL when NULL string is passed.
172 char *
173 strutils_shell_escape (const char *src)
175 return strutils_escape (src, -1, ESCAPE_SHELL_CHARS, FALSE);
178 /* --------------------------------------------------------------------------------------------- */
180 char *
181 strutils_glob_escape (const char *src)
183 return strutils_escape (src, -1, ESCAPE_GLOB_CHARS, TRUE);
186 /* --------------------------------------------------------------------------------------------- */
188 char *
189 strutils_regex_escape (const char *src)
191 return strutils_escape (src, -1, ESCAPE_REGEX_CHARS, TRUE);
194 /* --------------------------------------------------------------------------------------------- */
197 * Unescape paths or other strings for e.g the internal cd
198 * shell-unescape within a given buffer (writing to it!)
200 * @param text string for unescaping
202 * @return unescaped string (which needs to be freed)
205 char *
206 strutils_shell_unescape (const char *text)
208 return strutils_unescape (text, -1, ESCAPE_SHELL_CHARS, TRUE);
211 /* --------------------------------------------------------------------------------------------- */
213 char *
214 strutils_glob_unescape (const char *text)
216 return strutils_unescape (text, -1, ESCAPE_GLOB_CHARS, TRUE);
219 /* --------------------------------------------------------------------------------------------- */
220 char *
221 strutils_regex_unescape (const char *text)
223 return strutils_unescape (text, -1, ESCAPE_REGEX_CHARS, TRUE);
226 /* --------------------------------------------------------------------------------------------- */
229 * Check if char in pointer contain escape'd chars
231 * @param start string for checking
232 * @param current pointer to checked character
234 * @return TRUE if string contain escaped chars otherwise return FALSE
237 gboolean
238 strutils_is_char_escaped (const char *start, const char *current)
240 int num_esc = 0;
242 if (start == NULL || current == NULL || current <= start)
243 return FALSE;
245 current--;
246 while (current >= start && *current == '\\')
248 num_esc++;
249 current--;
251 return (gboolean) num_esc % 2;
254 /* --------------------------------------------------------------------------------------------- */