root/lib/strutil/strescape.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. strutils_escape
  2. strutils_unescape
  3. strutils_shell_escape
  4. strutils_glob_escape
  5. strutils_regex_escape
  6. strutils_shell_unescape
  7. strutils_glob_unescape
  8. strutils_regex_unescape
  9. strutils_is_char_escaped

   1 /*
   2    Functions for escaping and unescaping strings
   3 
   4    Copyright (C) 2009-2019
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Slava Zanko <slavazanko@gmail.com>, 2009;
   9    Patrick Winnertz <winnie@debian.org>, 2009
  10 
  11    This file is part of the Midnight Commander.
  12 
  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.
  17 
  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.
  22 
  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/>.
  25  */
  26 
  27 #include <config.h>
  28 
  29 #include "lib/global.h"
  30 #include "lib/strescape.h"
  31 
  32 /*** global variables ****************************************************************************/
  33 
  34 /*** file scope macro definitions ****************************************************************/
  35 
  36 /*** file scope type declarations ****************************************************************/
  37 
  38 /*** file scope variables ************************************************************************/
  39 
  40 static const char ESCAPE_SHELL_CHARS[] = " !#$%()&{}[]`?|<>;*\\\"'";
  41 static const char ESCAPE_REGEX_CHARS[] = "^!#$%()&{}[]`?|<>;*.\\";
  42 static const char ESCAPE_GLOB_CHARS[] = "$*\\?";
  43 
  44 /*** file scope functions ************************************************************************/
  45 
  46 /*** public functions ****************************************************************************/
  47 
  48 char *
  49 strutils_escape (const char *src, gsize src_len, const char *escaped_chars,
     /* [previous][next][first][last][top][bottom][index][help]  */
  50                  gboolean escape_non_printable)
  51 {
  52     GString *ret;
  53     gsize curr_index;
  54     /* do NOT break allocation semantics */
  55     if (src == NULL)
  56         return NULL;
  57 
  58     if (*src == '\0')
  59         return strdup ("");
  60 
  61     ret = g_string_new ("");
  62 
  63     if (src_len == (gsize) (-1))
  64         src_len = strlen (src);
  65 
  66     for (curr_index = 0; curr_index < src_len; curr_index++)
  67     {
  68         if (escape_non_printable)
  69         {
  70             switch (src[curr_index])
  71             {
  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;
  86             }
  87         }
  88 
  89         if (strchr (escaped_chars, (int) src[curr_index]))
  90             g_string_append_c (ret, '\\');
  91 
  92         g_string_append_c (ret, src[curr_index]);
  93     }
  94     return g_string_free (ret, FALSE);
  95 }
  96 
  97 /* --------------------------------------------------------------------------------------------- */
  98 char *
  99 strutils_unescape (const char *src, gsize src_len, const char *unescaped_chars,
     /* [previous][next][first][last][top][bottom][index][help]  */
 100                    gboolean unescape_non_printable)
 101 {
 102     GString *ret;
 103     gsize curr_index;
 104 
 105     if (src == NULL)
 106         return NULL;
 107 
 108     if (*src == '\0')
 109         return strdup ("");
 110 
 111     ret = g_string_sized_new (16);
 112 
 113     if (src_len == (gsize) (-1))
 114         src_len = strlen (src);
 115     src_len--;
 116 
 117     for (curr_index = 0; curr_index < src_len; curr_index++)
 118     {
 119         if (src[curr_index] != '\\')
 120         {
 121             g_string_append_c (ret, src[curr_index]);
 122             continue;
 123         }
 124 
 125         curr_index++;
 126 
 127         if (unescaped_chars == ESCAPE_SHELL_CHARS && src[curr_index] == '$')
 128         {
 129             /* special case: \$ is used to disallow variable substitution */
 130             g_string_append_c (ret, '\\');
 131         }
 132         else
 133         {
 134             if (unescape_non_printable)
 135             {
 136                 switch (src[curr_index])
 137                 {
 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;
 152                 }
 153             }
 154 
 155             if (strchr (unescaped_chars, (int) src[curr_index]) == NULL)
 156                 g_string_append_c (ret, '\\');
 157         }
 158 
 159         g_string_append_c (ret, src[curr_index]);
 160     }
 161     g_string_append_c (ret, src[curr_index]);
 162 
 163     return g_string_free (ret, FALSE);
 164 }
 165 
 166 /* --------------------------------------------------------------------------------------------- */
 167 
 168 /**
 169  * To be compatible with the general posix command lines we have to escape
 170  * strings for the command line
 171  *
 172  * @param src string for escaping
 173  *
 174  * @return escaped string (which needs to be freed later) or NULL when NULL string is passed.
 175  */
 176 
 177 char *
 178 strutils_shell_escape (const char *src)
     /* [previous][next][first][last][top][bottom][index][help]  */
 179 {
 180     return strutils_escape (src, -1, ESCAPE_SHELL_CHARS, FALSE);
 181 }
 182 
 183 /* --------------------------------------------------------------------------------------------- */
 184 
 185 char *
 186 strutils_glob_escape (const char *src)
     /* [previous][next][first][last][top][bottom][index][help]  */
 187 {
 188     return strutils_escape (src, -1, ESCAPE_GLOB_CHARS, TRUE);
 189 }
 190 
 191 /* --------------------------------------------------------------------------------------------- */
 192 
 193 char *
 194 strutils_regex_escape (const char *src)
     /* [previous][next][first][last][top][bottom][index][help]  */
 195 {
 196     return strutils_escape (src, -1, ESCAPE_REGEX_CHARS, TRUE);
 197 }
 198 
 199 /* --------------------------------------------------------------------------------------------- */
 200 
 201 /**
 202  * Unescape paths or other strings for e.g the internal cd
 203  * shell-unescape within a given buffer (writing to it!)
 204  *
 205  * @param text string for unescaping
 206  *
 207  * @return unescaped string (which needs to be freed)
 208  */
 209 
 210 char *
 211 strutils_shell_unescape (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 212 {
 213     return strutils_unescape (text, -1, ESCAPE_SHELL_CHARS, TRUE);
 214 }
 215 
 216 /* --------------------------------------------------------------------------------------------- */
 217 
 218 char *
 219 strutils_glob_unescape (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 220 {
 221     return strutils_unescape (text, -1, ESCAPE_GLOB_CHARS, TRUE);
 222 }
 223 
 224 /* --------------------------------------------------------------------------------------------- */
 225 char *
 226 strutils_regex_unescape (const char *text)
     /* [previous][next][first][last][top][bottom][index][help]  */
 227 {
 228     return strutils_unescape (text, -1, ESCAPE_REGEX_CHARS, TRUE);
 229 }
 230 
 231 /* --------------------------------------------------------------------------------------------- */
 232 
 233 /**
 234  * Check if char in pointer contain escape'd chars
 235  *
 236  * @param start string for checking
 237  * @param current pointer to checked character
 238  *
 239  * @return TRUE if string contain escaped chars otherwise return FALSE
 240  */
 241 
 242 gboolean
 243 strutils_is_char_escaped (const char *start, const char *current)
     /* [previous][next][first][last][top][bottom][index][help]  */
 244 {
 245     int num_esc = 0;
 246 
 247     if (start == NULL || current == NULL || current <= start)
 248         return FALSE;
 249 
 250     current--;
 251     while (current >= start && *current == '\\')
 252     {
 253         num_esc++;
 254         current--;
 255     }
 256     return (gboolean) num_esc % 2;
 257 }
 258 
 259 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */