Merge branch '1858_segfault_in_search'
[midnight-commander.git] / src / strescape.c
blobbd4c0e6575eed524cbfe805eb4e082d8fc75233b
1 /*
2 Functions for escaping and unescaping strings
4 Copyright (C) 2009 The Free Software Foundation, Inc.
6 Written by:
7 Slava Zanko <slavazanko@gmail.com>, 2009;
8 Patrick Winnertz <winnie@debian.org>, 2009
10 This file is part of the Midnight Commander.
12 The Midnight Commander is free software; you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
17 The Midnight Commander is distributed in the hope that it will be
18 useful, but WITHOUT ANY WARRANTY; without even the implied warranty
19 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 MA 02110-1301, USA.
28 #include <config.h>
29 #include "../src/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) {
69 switch (src[curr_index]) {
70 case '\n':
71 g_string_append (ret, "\\n");
72 continue;
73 break;
74 case '\t':
75 g_string_append (ret, "\\t");
76 continue;
77 break;
78 case '\b':
79 g_string_append (ret, "\\b");
80 continue;
81 break;
82 case '\0':
83 g_string_append (ret, "\\0");
84 continue;
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_new ("");
113 if (src_len == (gsize)-1)
114 src_len = strlen (src);
116 for (curr_index = 0; curr_index < src_len-1; curr_index++) {
117 if (src[curr_index] != '\\'){
118 g_string_append_c (ret, src[curr_index]);
119 continue;
121 curr_index++;
122 if (unescape_non_printable) {
123 switch (src[curr_index]) {
124 case 'n':
125 g_string_append_c (ret, '\n');
126 continue;
127 break;
128 case 't':
129 g_string_append_c (ret, '\t');
130 continue;
131 break;
132 case 'b':
133 g_string_append_c (ret, '\b');
134 continue;
135 break;
136 case '0':
137 g_string_append (ret, '\0');
138 continue;
139 break;
142 if (strchr (unescaped_chars, (int) src[curr_index]) == NULL)
143 g_string_append_c (ret, '\\');
145 g_string_append_c (ret, src[curr_index]);
147 g_string_append_c (ret, src[curr_index]);
149 return g_string_free (ret, FALSE);
151 /* --------------------------------------------------------------------------------------------- */
153 /** To be compatible with the general posix command lines we have to escape
154 strings for the command line
156 \params in
157 string for escaping
159 \returns
160 return escaped string (which needs to be freed later)
161 or NULL when NULL string is passed.
163 char *
164 strutils_shell_escape (const char *src)
166 return strutils_escape (src, -1, ESCAPE_SHELL_CHARS, FALSE);
169 /* --------------------------------------------------------------------------------------------- */
171 char *
172 strutils_glob_escape (const char *src)
174 return strutils_escape (src, -1, ESCAPE_GLOB_CHARS, TRUE);
177 /* --------------------------------------------------------------------------------------------- */
179 char *
180 strutils_regex_escape (const char *src)
182 return strutils_escape (src, -1, ESCAPE_REGEX_CHARS, TRUE);
185 /* --------------------------------------------------------------------------------------------- */
187 /** Unescape paths or other strings for e.g the internal cd
188 shell-unescape within a given buffer (writing to it!)
190 \params src
191 string for unescaping
193 \returns
194 return unescaped string (which needs to be freed)
196 char *
197 strutils_shell_unescape (const char *text)
199 return strutils_unescape (text, -1, ESCAPE_SHELL_CHARS, TRUE);
202 /* --------------------------------------------------------------------------------------------- */
204 char *
205 strutils_glob_unescape (const char *text)
207 return strutils_unescape (text, -1, ESCAPE_GLOB_CHARS, TRUE);
210 /* --------------------------------------------------------------------------------------------- */
211 char *
212 strutils_regex_unescape (const char *text)
214 return strutils_unescape (text, -1, ESCAPE_REGEX_CHARS, TRUE);
217 /* --------------------------------------------------------------------------------------------- */
219 /** Check if char in pointer contain escape'd chars
221 \params in
222 string for checking
224 \returns
225 return TRUE if string contain escaped chars
226 otherwise return FALSE
228 gboolean
229 strutils_is_char_escaped (const char *start, const char *current)
231 int num_esc = 0;
233 if (start == NULL || current == NULL || current <= start)
234 return FALSE;
236 current--;
237 while (current >= start && *current == '\\') {
238 num_esc++;
239 current--;
241 return (gboolean) num_esc % 2;
245 /* --------------------------------------------------------------------------------------------- */