2 Functions for escaping and unescaping strings
4 Copyright (C) 2009, 2011
5 The Free Software Foundation, Inc.
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/>.
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 ****************************************************************************/
48 strutils_escape (const char *src
, gsize src_len
, const char *escaped_chars
,
49 gboolean escape_non_printable
)
53 /* do NOT break allocation semantics */
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
])
72 g_string_append (ret
, "\\n");
75 g_string_append (ret
, "\\t");
78 g_string_append (ret
, "\\b");
81 g_string_append (ret
, "\\0");
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 /* --------------------------------------------------------------------------------------------- */
96 strutils_unescape (const char *src
, gsize src_len
, const char *unescaped_chars
,
97 gboolean unescape_non_printable
)
108 ret
= g_string_sized_new (16);
110 if (src_len
== (gsize
) (-1))
111 src_len
= strlen (src
);
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
]);
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
, '\\');
131 if (unescape_non_printable
)
133 switch (src
[curr_index
])
136 g_string_append_c (ret
, '\n');
139 g_string_append_c (ret
, '\t');
142 g_string_append_c (ret
, '\b');
145 g_string_append_c (ret
, '\0');
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 * @returns escaped string (which needs to be freed later) or NULL when NULL string is passed.
173 strutils_shell_escape (const char *src
)
175 return strutils_escape (src
, -1, ESCAPE_SHELL_CHARS
, FALSE
);
178 /* --------------------------------------------------------------------------------------------- */
181 strutils_glob_escape (const char *src
)
183 return strutils_escape (src
, -1, ESCAPE_GLOB_CHARS
, TRUE
);
186 /* --------------------------------------------------------------------------------------------- */
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 * @returns unescaped string (which needs to be freed)
206 strutils_shell_unescape (const char *text
)
208 return strutils_unescape (text
, -1, ESCAPE_SHELL_CHARS
, TRUE
);
211 /* --------------------------------------------------------------------------------------------- */
214 strutils_glob_unescape (const char *text
)
216 return strutils_unescape (text
, -1, ESCAPE_GLOB_CHARS
, TRUE
);
219 /* --------------------------------------------------------------------------------------------- */
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 * @returns TRUE if string contain escaped chars otherwise return FALSE
238 strutils_is_char_escaped (const char *start
, const char *current
)
242 if (start
== NULL
|| current
== NULL
|| current
<= start
)
246 while (current
>= start
&& *current
== '\\')
251 return (gboolean
) num_esc
% 2;
254 /* --------------------------------------------------------------------------------------------- */