diff --git a/src/Makefile.am b/src/Makefile.am index 88faaf172..c7d2b8b37 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -67,7 +67,7 @@ SRCS = achown.c achown.h background.c background.h boxes.c boxes.h \ widget.h win.c win.h wtools.c wtools.h unixcompat.h \ x11conn.h x11conn.c ecs.h ecs.c \ strutil.h strutil.c strutilascii.c strutil8bit.c strutilutf8.c \ - search/search.h + search/search.h strescape.c strescape.h if CHARSET mc_SOURCES = $(SRCS) $(CHARSET_SRC) diff --git a/src/command.c b/src/command.c index a40a7069f..a92c5e571 100644 --- a/src/command.c +++ b/src/command.c @@ -44,6 +44,7 @@ #include "tree.h" /* for tree_chdir */ #include "color.h" /* DEFAULT_COLOR */ #include "execute.h" /* shell_execute */ +#include "../src/strescape.h" /* This holds the command line */ WInput *cmdline; diff --git a/src/complete.c b/src/complete.c index 1563fbee1..b4ee1291a 100644 --- a/src/complete.c +++ b/src/complete.c @@ -43,6 +43,7 @@ #include "wtools.h" #include "main.h" #include "util.h" +#include "../src/strescape.h" #include "key.h" /* XCTRL and ALT macros */ #include "strutil.h" diff --git a/src/file.c b/src/file.c index f32db9d12..467291af1 100644 --- a/src/file.c +++ b/src/file.c @@ -66,7 +66,7 @@ #include "widget.h" #include "wtools.h" #include "background.h" /* we_are_background */ -/* #include "util.h" */ +#include "../src/strescape.h" #include "strutil.h" #include "../src/search/search.h" diff --git a/src/strescape.c b/src/strescape.c new file mode 100644 index 000000000..e774f8e84 --- /dev/null +++ b/src/strescape.c @@ -0,0 +1,207 @@ +/* + Functions for escaping and unescaping strings + + Copyright (C) 2009 The Free Software Foundation, Inc. + + Written by: + Slava Zanko , 2009; + Patrick Winnertz , 2009 + + This file is part of the Midnight Commander. + + The Midnight Commander is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The Midnight Commander is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + */ + +#include +#include "../src/strescape.h" + + +/*** global variables ****************************************************************************/ + +/*** file scope macro definitions ****************************************************************/ + +#define shell_escape_toesc(x) \ + (((x)==' ')||((x)=='!')||((x)=='#')||((x)=='$')||((x)=='%')|| \ + ((x)=='(')||((x)==')')||((x)=='\'')||((x)=='&')||((x)=='~')|| \ + ((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 variables ************************************************************************/ + +/*** file scope functions ************************************************************************/ + +/*** public functions ****************************************************************************/ + +/** To be compatible with the general posix command lines we have to escape + strings for the command line + + \params in + string for escaping + + \returns + return escaped string (which needs to be freed later) + or NULL when NULL string is passed. + */ +char* +shell_escape(const char* src) +{ + GString *str; + char *result = NULL; + + /* do NOT break allocation semantics */ + if (!src) + return NULL; + + if (*src == '\0') + return strdup(""); + + str = g_string_new(""); + + /* look for the first char to escape */ + while (1) + { + char c; + /* copy over all chars not to escape */ + 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++; + } +} +/* --------------------------------------------------------------------------------------------- */ + +/** Unescape paths or other strings for e.g the internal cd + shell-unescape within a given buffer (writing to it!) + + \params src + string for unescaping + + \returns + return unescaped string (which needs to be freed) + */ +char* +shell_unescape(const char* text) +{ + GString *str; + char *result = NULL; + const char* readptr; + char c; + + if (!text) + return NULL; + + + /* look for the first \ - that's quick skipover if there's nothing to escape */ + readptr = text; + while ((*readptr) && ((*readptr)!='\\')) readptr++; + if (!(*readptr)) { + 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; +} +/* --------------------------------------------------------------------------------------------- */ + +/** Check if char in pointer contain escape'd chars + + \params in + string for checking + + \returns + return TRUE if string contain escaped chars + otherwise return FALSE + */ +gboolean +shell_is_char_escaped ( const char *in ) +{ + if (in == NULL || !*in || in[0] != '\\') + return FALSE; + if (shell_escape_toesc(in[1])) + return TRUE; + return FALSE; +} + + +/* --------------------------------------------------------------------------------------------- */ diff --git a/src/strescape.h b/src/strescape.h new file mode 100644 index 000000000..87fc1a919 --- /dev/null +++ b/src/strescape.h @@ -0,0 +1,22 @@ +#ifndef MC__STRUTILS_ESCAPE_H +#define MC__STRUTILS_ESCAPE_H + +#include + +#include "../src/global.h" /* */ + +/*** typedefs(not structures) and defined constants **********************************************/ + +/*** enums ***************************************************************************************/ + +/*** structures declarations (and typedefs of structures)*****************************************/ + +/*** global variables defined in .c file *********************************************************/ + +/*** declarations of public functions ************************************************************/ + +gboolean shell_is_char_escaped ( const char * ); +char *shell_unescape( const char * ); +char *shell_escape( const char * ); + +#endif diff --git a/src/util.c b/src/util.c index 48903b8d2..b14ea526b 100644 --- a/src/util.c +++ b/src/util.c @@ -1420,163 +1420,3 @@ Q_ (const char *s) return (sep != NULL) ? sep + 1 : result; } -#define shell_escape_toesc(x) \ - (((x)==' ')||((x)=='!')||((x)=='#')||((x)=='$')||((x)=='%')|| \ - ((x)=='(')||((x)==')')||((x)=='\'')||((x)=='&')||((x)=='~')|| \ - ((x)=='{')||((x)=='}')||((x)=='[')||((x)==']')||((x)=='`')|| \ - ((x)=='?')||((x)=='|')||((x)=='<')||((x)=='>')||((x)==';')|| \ - ((x)=='*')||((x)=='\\')||((x)=='"')) - -#define shell_escape_nottoesc(x) \ - (((x)!=0) && (!shell_escape_toesc((x)))) - -/** To be compatible with the general posix command lines we have to escape - strings for the command line - - \params in - string for escaping - - \returns - return escaped string (which needs to be freed later) - or NULL when NULL string is passed. - */ -char* -shell_escape(const char* src) -{ - GString *str; - char *result = NULL; - - /* do NOT break allocation semantics */ - if (!src) - return NULL; - - if (*src == '\0') - return strdup(""); - - str = g_string_new(""); - - /* look for the first char to escape */ - while (1) - { - char c; - /* copy over all chars not to escape */ - 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++; - } -} - -/** Unescape paths or other strings for e.g the internal cd - shell-unescape within a given buffer (writing to it!) - - \params src - string for unescaping - - \returns - return unescaped string (which needs to be freed) - */ -char* -shell_unescape(const char* text) -{ - GString *str; - char *result = NULL; - const char* readptr; - char c; - - if (!text) - return NULL; - - - /* look for the first \ - that's quick skipover if there's nothing to escape */ - readptr = text; - while ((*readptr) && ((*readptr)!='\\')) readptr++; - if (!(*readptr)) { - 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; -} - -/** Check if char in pointer contain escape'd chars - - \params in - string for checking - - \returns - return TRUE if string contain escaped chars - otherwise return FALSE - */ -gboolean -shell_is_char_escaped ( const char *in ) -{ - if (in == NULL || !*in || in[0] != '\\') - return FALSE; - if (shell_escape_toesc(in[1])) - return TRUE; - return FALSE; -} - diff --git a/src/util.h b/src/util.h index 18f24f059..67be72593 100644 --- a/src/util.h +++ b/src/util.h @@ -255,11 +255,6 @@ extern int ascii_alpha_to_cntrl (int ch); #undef Q_ const char *Q_ (const char *s); - -gboolean shell_is_char_escaped ( const char * ); -char *shell_unescape( const char * ); -char *shell_escape( const char * ); - #define str_dup_range(s_start, s_bound) (g_strndup(s_start, s_bound - s_start)) /* diff --git a/vfs/fish.c b/vfs/fish.c index 2181d6458..f2e5c39f9 100644 --- a/vfs/fish.c +++ b/vfs/fish.c @@ -51,6 +51,7 @@ #include "../src/wtools.h" /* message() */ #include "../src/main.h" /* print_vfs_message */ #include "../src/util.h" +#include "../src/strescape.h" #include "utilvfs.h" #include "xdirentry.h" #include "vfs.h"