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 /* --------------------------------------------------------------------------------------------- */
163 /** To be compatible with the general posix command lines we have to escape
164 strings for the command line
170 return escaped string (which needs to be freed later)
171 or NULL when NULL string is passed.
174 strutils_shell_escape (const char *src
)
176 return strutils_escape (src
, -1, ESCAPE_SHELL_CHARS
, FALSE
);
179 /* --------------------------------------------------------------------------------------------- */
182 strutils_glob_escape (const char *src
)
184 return strutils_escape (src
, -1, ESCAPE_GLOB_CHARS
, TRUE
);
187 /* --------------------------------------------------------------------------------------------- */
190 strutils_regex_escape (const char *src
)
192 return strutils_escape (src
, -1, ESCAPE_REGEX_CHARS
, TRUE
);
195 /* --------------------------------------------------------------------------------------------- */
197 /** Unescape paths or other strings for e.g the internal cd
198 shell-unescape within a given buffer (writing to it!)
201 string for unescaping
204 return unescaped string (which needs to be freed)
207 strutils_shell_unescape (const char *text
)
209 return strutils_unescape (text
, -1, ESCAPE_SHELL_CHARS
, TRUE
);
212 /* --------------------------------------------------------------------------------------------- */
215 strutils_glob_unescape (const char *text
)
217 return strutils_unescape (text
, -1, ESCAPE_GLOB_CHARS
, TRUE
);
220 /* --------------------------------------------------------------------------------------------- */
222 strutils_regex_unescape (const char *text
)
224 return strutils_unescape (text
, -1, ESCAPE_REGEX_CHARS
, TRUE
);
227 /* --------------------------------------------------------------------------------------------- */
229 /** Check if char in pointer contain escape'd chars
235 pointer to checked character
238 return TRUE if string contain escaped chars
239 otherwise return FALSE
242 strutils_is_char_escaped (const char *start
, const char *current
)
246 if (start
== NULL
|| current
== NULL
|| current
<= start
)
250 while (current
>= start
&& *current
== '\\')
255 return (gboolean
) num_esc
% 2;
258 /* --------------------------------------------------------------------------------------------- */