Update ebuild.syntax to include new EAPI 6 keywords
[midnight-commander.git] / lib / strutil / strescape.c
blob29d09130aed885543016ef81dfc74487c28019eb
1 /*
2 Functions for escaping and unescaping strings
4 Copyright (C) 2009-2016
5 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/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 ****************************************************************************/
48 char *
49 strutils_escape (const char *src, gsize src_len, const char *escaped_chars,
50 gboolean escape_non_printable)
52 GString *ret;
53 gsize curr_index;
54 /* do NOT break allocation semantics */
55 if (src == NULL)
56 return NULL;
58 if (*src == '\0')
59 return strdup ("");
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])
72 case '\n':
73 g_string_append (ret, "\\n");
74 continue;
75 case '\t':
76 g_string_append (ret, "\\t");
77 continue;
78 case '\b':
79 g_string_append (ret, "\\b");
80 continue;
81 case '\0':
82 g_string_append (ret, "\\0");
83 continue;
84 default:
85 break;
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 /* --------------------------------------------------------------------------------------------- */
98 char *
99 strutils_unescape (const char *src, gsize src_len, const char *unescaped_chars,
100 gboolean unescape_non_printable)
102 GString *ret;
103 gsize curr_index;
105 if (src == NULL)
106 return NULL;
108 if (*src == '\0')
109 return strdup ("");
111 ret = g_string_sized_new (16);
113 if (src_len == (gsize) (-1))
114 src_len = strlen (src);
115 src_len--;
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]);
122 continue;
125 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, '\\');
132 else
134 if (unescape_non_printable)
136 switch (src[curr_index])
138 case 'n':
139 g_string_append_c (ret, '\n');
140 continue;
141 case 't':
142 g_string_append_c (ret, '\t');
143 continue;
144 case 'b':
145 g_string_append_c (ret, '\b');
146 continue;
147 case '0':
148 g_string_append_c (ret, '\0');
149 continue;
150 default:
151 break;
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.
177 char *
178 strutils_shell_escape (const char *src)
180 return strutils_escape (src, -1, ESCAPE_SHELL_CHARS, FALSE);
183 /* --------------------------------------------------------------------------------------------- */
185 char *
186 strutils_glob_escape (const char *src)
188 return strutils_escape (src, -1, ESCAPE_GLOB_CHARS, TRUE);
191 /* --------------------------------------------------------------------------------------------- */
193 char *
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)
210 char *
211 strutils_shell_unescape (const char *text)
213 return strutils_unescape (text, -1, ESCAPE_SHELL_CHARS, TRUE);
216 /* --------------------------------------------------------------------------------------------- */
218 char *
219 strutils_glob_unescape (const char *text)
221 return strutils_unescape (text, -1, ESCAPE_GLOB_CHARS, TRUE);
224 /* --------------------------------------------------------------------------------------------- */
225 char *
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
242 gboolean
243 strutils_is_char_escaped (const char *start, const char *current)
245 int num_esc = 0;
247 if (start == NULL || current == NULL || current <= start)
248 return FALSE;
250 current--;
251 while (current >= start && *current == '\\')
253 num_esc++;
254 current--;
256 return (gboolean) num_esc % 2;
259 /* --------------------------------------------------------------------------------------------- */