mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-22 20:36:50 +03:00
Reworked functions strutils_shell_escape and strutils_shell_unescape
also added function: * strutils_glob_escape * strutils_glob_unescape * strutils_regex_escape * strutils_regex_unescape Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
parent
f018970577
commit
be27cd1a2e
240
src/strescape.c
240
src/strescape.c
@ -33,15 +33,9 @@
|
|||||||
|
|
||||||
/*** file scope macro definitions ****************************************************************/
|
/*** file scope macro definitions ****************************************************************/
|
||||||
|
|
||||||
#define shell_escape_toesc(x) \
|
#define ESCAPE_SHELL_CHARS " !#$%()&~{}[]`?|<>;*\\\""
|
||||||
(((x)==' ')||((x)=='!')||((x)=='#')||((x)=='$')||((x)=='%')|| \
|
#define ESCAPE_REGEX_CHARS "^!#$%()&~{}[]`?|<>;*.\\"
|
||||||
((x)=='(')||((x)==')')||((x)=='\'')||((x)=='&')||((x)=='~')|| \
|
#define ESCAPE_GLOB_CHARS "${}*."
|
||||||
((x)=='{')||((x)=='}')||((x)=='[')||((x)==']')||((x)=='`')|| \
|
|
||||||
((x)=='?')||((x)=='|')||((x)=='<')||((x)=='>')||((x)==';')|| \
|
|
||||||
((x)=='*')||((x)=='\\')||((x)=='"'))
|
|
||||||
|
|
||||||
#define shell_escape_nottoesc(x) \
|
|
||||||
(((x)!=0) && (!shell_escape_toesc((x))))
|
|
||||||
|
|
||||||
/*** file scope type declarations ****************************************************************/
|
/*** file scope type declarations ****************************************************************/
|
||||||
|
|
||||||
@ -51,6 +45,111 @@
|
|||||||
|
|
||||||
/*** public functions ****************************************************************************/
|
/*** public functions ****************************************************************************/
|
||||||
|
|
||||||
|
char *
|
||||||
|
strutils_escape (const char *src, int src_len, const char *escaped_chars,
|
||||||
|
gboolean escape_non_printable)
|
||||||
|
{
|
||||||
|
GString *ret;
|
||||||
|
gsize loop;
|
||||||
|
/* do NOT break allocation semantics */
|
||||||
|
if (src == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (*src == '\0')
|
||||||
|
return strdup ("");
|
||||||
|
|
||||||
|
ret = g_string_new ("");
|
||||||
|
|
||||||
|
if (src_len == -1)
|
||||||
|
src_len = strlen (src);
|
||||||
|
|
||||||
|
for (loop = 0; loop < src_len; loop++) {
|
||||||
|
|
||||||
|
if (escape_non_printable) {
|
||||||
|
switch (src[loop]) {
|
||||||
|
case '\n':
|
||||||
|
g_string_append (ret, "\\n");
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
g_string_append (ret, "\\t");
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case '\b':
|
||||||
|
g_string_append (ret, "\\b");
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case '\0':
|
||||||
|
g_string_append (ret, "\\0");
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strchr (escaped_chars, (int) src[loop]))
|
||||||
|
g_string_append_c (ret, '\\');
|
||||||
|
|
||||||
|
g_string_append_c (ret, src[loop]);
|
||||||
|
}
|
||||||
|
return g_string_free (ret, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
char *
|
||||||
|
strutils_unescape (const char *src, int src_len, const char *unescaped_chars,
|
||||||
|
gboolean unescape_non_printable)
|
||||||
|
{
|
||||||
|
GString *ret;
|
||||||
|
gsize loop;
|
||||||
|
|
||||||
|
if (src == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (*src == '\0')
|
||||||
|
return strdup ("");
|
||||||
|
|
||||||
|
ret = g_string_new ("");
|
||||||
|
|
||||||
|
if (src_len == -1)
|
||||||
|
src_len = strlen (src);
|
||||||
|
|
||||||
|
for (loop = 0; loop < src_len-1; loop++) {
|
||||||
|
if (src[loop] != '\\'){
|
||||||
|
g_string_append_c (ret, src[loop]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
loop++;
|
||||||
|
if (unescape_non_printable) {
|
||||||
|
switch (src[loop]) {
|
||||||
|
case 'n':
|
||||||
|
g_string_append_c (ret, '\n');
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
g_string_append_c (ret, '\t');
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
g_string_append_c (ret, '\b');
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
g_string_append (ret, '\0');
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (strchr (unescaped_chars, (int) src[loop]) == NULL)
|
||||||
|
g_string_append_c (ret, '\\');
|
||||||
|
|
||||||
|
g_string_append_c (ret, src[loop]);
|
||||||
|
}
|
||||||
|
g_string_append_c (ret, src[loop]);
|
||||||
|
|
||||||
|
return g_string_free (ret, FALSE);
|
||||||
|
}
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/** To be compatible with the general posix command lines we have to escape
|
/** To be compatible with the general posix command lines we have to escape
|
||||||
strings for the command line
|
strings for the command line
|
||||||
|
|
||||||
@ -64,38 +163,23 @@
|
|||||||
char *
|
char *
|
||||||
strutils_shell_escape (const char *src)
|
strutils_shell_escape (const char *src)
|
||||||
{
|
{
|
||||||
GString *str;
|
return strutils_escape (src, -1, ESCAPE_SHELL_CHARS, FALSE);
|
||||||
char *result = NULL;
|
}
|
||||||
|
|
||||||
/* do NOT break allocation semantics */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
if (!src)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (*src == '\0')
|
char *
|
||||||
return strdup ("");
|
strutils_glob_escape (const char *src)
|
||||||
|
{
|
||||||
|
return strutils_escape (src, -1, ESCAPE_GLOB_CHARS, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
str = g_string_new ("");
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* look for the first char to escape */
|
char *
|
||||||
while (1) {
|
strutils_regex_escape (const char *src)
|
||||||
char c;
|
{
|
||||||
/* copy over all chars not to escape */
|
return strutils_escape (src, -1, ESCAPE_REGEX_CHARS, TRUE);
|
||||||
while ((c = (*src)) && shell_escape_nottoesc (c)) {
|
|
||||||
g_string_append_c (str, c);
|
|
||||||
src++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at this point we either have an \0 or an char to escape */
|
|
||||||
if (!c) {
|
|
||||||
result = str->str;
|
|
||||||
g_string_free (str, FALSE);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_string_append_c (str, '\\');
|
|
||||||
g_string_append_c (str, c);
|
|
||||||
src++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
@ -112,78 +196,22 @@ strutils_shell_escape (const char *src)
|
|||||||
char *
|
char *
|
||||||
strutils_shell_unescape (const char *text)
|
strutils_shell_unescape (const char *text)
|
||||||
{
|
{
|
||||||
GString *str;
|
return strutils_unescape (text, -1, ESCAPE_SHELL_CHARS, TRUE);
|
||||||
char *result = NULL;
|
}
|
||||||
const char *readptr;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
if (!text)
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
return NULL;
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
strutils_glob_unescape (const char *text)
|
||||||
|
{
|
||||||
|
return strutils_unescape (text, -1, ESCAPE_GLOB_CHARS, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
/* look for the first \ - that's quick skipover if there's nothing to escape */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
readptr = text;
|
char *
|
||||||
while ((*readptr) && ((*readptr) != '\\'))
|
strutils_regex_unescape (const char *text)
|
||||||
readptr++;
|
{
|
||||||
if (!(*readptr)) {
|
return strutils_unescape (text, -1, ESCAPE_REGEX_CHARS, TRUE);
|
||||||
result = g_strdup (text);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
str = g_string_new_len (text, readptr - text);
|
|
||||||
|
|
||||||
/* if we're here, we're standing on the first '\' */
|
|
||||||
while ((c = *readptr)) {
|
|
||||||
if (c == '\\') {
|
|
||||||
readptr++;
|
|
||||||
switch ((c = *readptr)) {
|
|
||||||
case '\0': /* end of string! malformed escape string */
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
case 'n':
|
|
||||||
g_string_append_c (str, '\n');
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
g_string_append_c (str, '\r');
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
g_string_append_c (str, '\t');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ' ':
|
|
||||||
case '\\':
|
|
||||||
case '#':
|
|
||||||
case '$':
|
|
||||||
case '%':
|
|
||||||
case '(':
|
|
||||||
case ')':
|
|
||||||
case '[':
|
|
||||||
case ']':
|
|
||||||
case '{':
|
|
||||||
case '}':
|
|
||||||
case '<':
|
|
||||||
case '>':
|
|
||||||
case '!':
|
|
||||||
case '*':
|
|
||||||
case '?':
|
|
||||||
case '~':
|
|
||||||
case '`':
|
|
||||||
case '"':
|
|
||||||
case ';':
|
|
||||||
default:
|
|
||||||
g_string_append_c (str, c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else { /* got a normal character */
|
|
||||||
|
|
||||||
g_string_append_c (str, c);
|
|
||||||
}
|
|
||||||
readptr++;
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
|
|
||||||
result = str->str;
|
|
||||||
g_string_free (str, FALSE);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
@ -15,8 +15,18 @@
|
|||||||
|
|
||||||
/*** declarations of public functions ************************************************************/
|
/*** declarations of public functions ************************************************************/
|
||||||
|
|
||||||
gboolean strutils_is_char_escaped (const char *);
|
char *strutils_escape (const char *, int, const char *, gboolean);
|
||||||
|
char *strutils_unescape (const char *, int, const char *, gboolean);
|
||||||
|
|
||||||
char *strutils_shell_unescape (const char *);
|
char *strutils_shell_unescape (const char *);
|
||||||
char *strutils_shell_escape (const char *);
|
char *strutils_shell_escape (const char *);
|
||||||
|
|
||||||
|
char *strutils_glob_escape (const char *);
|
||||||
|
char *strutils_glob_escape (const char *);
|
||||||
|
|
||||||
|
char *strutils_regex_escape (const char *);
|
||||||
|
char *strutils_regex_escape (const char *);
|
||||||
|
|
||||||
|
gboolean strutils_is_char_escaped (const char *, const char *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user