2 Functions for escaping and unescaping strings
4 Copyright (C) 2009-2016
5 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/global.h"
30 #include "lib/strescape.h"
32 /*** global variables ****************************************************************************/
34 /*** file scope macro definitions ****************************************************************/
36 /*** file scope type declarations ****************************************************************/
38 /*** file scope variables ************************************************************************/
40 static const char ESCAPE_SHELL_CHARS
[] = " !#$%()&{}[]`?|<>;*\\\"'";
41 static const char ESCAPE_REGEX_CHARS
[] = "^!#$%()&{}[]`?|<>;*.\\";
42 static const char ESCAPE_GLOB_CHARS
[] = "$*\\?";
44 /*** file scope functions ************************************************************************/
46 /*** public functions ****************************************************************************/
49 strutils_escape (const char *src
, gsize src_len
, const char *escaped_chars
,
50 gboolean escape_non_printable
)
54 /* do NOT break allocation semantics */
61 ret
= g_string_new ("");
63 if (src_len
== (gsize
) (-1))
64 src_len
= strlen (src
);
66 for (curr_index
= 0; curr_index
< src_len
; curr_index
++)
68 if (escape_non_printable
)
70 switch (src
[curr_index
])
73 g_string_append (ret
, "\\n");
76 g_string_append (ret
, "\\t");
79 g_string_append (ret
, "\\b");
82 g_string_append (ret
, "\\0");
89 if (strchr (escaped_chars
, (int) src
[curr_index
]))
90 g_string_append_c (ret
, '\\');
92 g_string_append_c (ret
, src
[curr_index
]);
94 return g_string_free (ret
, FALSE
);
97 /* --------------------------------------------------------------------------------------------- */
99 strutils_unescape (const char *src
, gsize src_len
, const char *unescaped_chars
,
100 gboolean unescape_non_printable
)
111 ret
= g_string_sized_new (16);
113 if (src_len
== (gsize
) (-1))
114 src_len
= strlen (src
);
117 for (curr_index
= 0; curr_index
< src_len
; curr_index
++)
119 if (src
[curr_index
] != '\\')
121 g_string_append_c (ret
, src
[curr_index
]);
127 if (unescaped_chars
== ESCAPE_SHELL_CHARS
&& src
[curr_index
] == '$')
129 /* special case: \$ is used to disallow variable substitution */
130 g_string_append_c (ret
, '\\');
134 if (unescape_non_printable
)
136 switch (src
[curr_index
])
139 g_string_append_c (ret
, '\n');
142 g_string_append_c (ret
, '\t');
145 g_string_append_c (ret
, '\b');
148 g_string_append_c (ret
, '\0');
155 if (strchr (unescaped_chars
, (int) src
[curr_index
]) == NULL
)
156 g_string_append_c (ret
, '\\');
159 g_string_append_c (ret
, src
[curr_index
]);
161 g_string_append_c (ret
, src
[curr_index
]);
163 return g_string_free (ret
, FALSE
);
166 /* --------------------------------------------------------------------------------------------- */
169 * To be compatible with the general posix command lines we have to escape
170 * strings for the command line
172 * @param src string for escaping
174 * @return escaped string (which needs to be freed later) or NULL when NULL string is passed.
178 strutils_shell_escape (const char *src
)
180 return strutils_escape (src
, -1, ESCAPE_SHELL_CHARS
, FALSE
);
183 /* --------------------------------------------------------------------------------------------- */
186 strutils_glob_escape (const char *src
)
188 return strutils_escape (src
, -1, ESCAPE_GLOB_CHARS
, TRUE
);
191 /* --------------------------------------------------------------------------------------------- */
194 strutils_regex_escape (const char *src
)
196 return strutils_escape (src
, -1, ESCAPE_REGEX_CHARS
, TRUE
);
199 /* --------------------------------------------------------------------------------------------- */
202 * Unescape paths or other strings for e.g the internal cd
203 * shell-unescape within a given buffer (writing to it!)
205 * @param text string for unescaping
207 * @return unescaped string (which needs to be freed)
211 strutils_shell_unescape (const char *text
)
213 return strutils_unescape (text
, -1, ESCAPE_SHELL_CHARS
, TRUE
);
216 /* --------------------------------------------------------------------------------------------- */
219 strutils_glob_unescape (const char *text
)
221 return strutils_unescape (text
, -1, ESCAPE_GLOB_CHARS
, TRUE
);
224 /* --------------------------------------------------------------------------------------------- */
226 strutils_regex_unescape (const char *text
)
228 return strutils_unescape (text
, -1, ESCAPE_REGEX_CHARS
, TRUE
);
231 /* --------------------------------------------------------------------------------------------- */
234 * Check if char in pointer contain escape'd chars
236 * @param start string for checking
237 * @param current pointer to checked character
239 * @return TRUE if string contain escaped chars otherwise return FALSE
243 strutils_is_char_escaped (const char *start
, const char *current
)
247 if (start
== NULL
|| current
== NULL
|| current
<= start
)
251 while (current
>= start
&& *current
== '\\')
256 return (gboolean
) num_esc
% 2;
259 /* --------------------------------------------------------------------------------------------- */