X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev_utils_string.c;h=e3dc137e63257be33471a2d1a8ede3523a281dd4;hp=36ef8bef7e8d156b5d8729c0ad952a951421bce0;hb=2e23125e112c0a56e1ccee193c2cfe0e26af1bad;hpb=1aa1e24848903d11780db1ade355be73ad61a937 diff --git a/udev_utils_string.c b/udev_utils_string.c index 36ef8bef7..e3dc137e6 100644 --- a/udev_utils_string.c +++ b/udev_utils_string.c @@ -1,6 +1,4 @@ /* - * udev_utils_string.c - string manipulation - * * Copyright (C) 2004-2005 Kay Sievers * * This program is free software; you can redistribute it and/or modify it @@ -14,7 +12,7 @@ * * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ @@ -32,59 +30,6 @@ #include "udev.h" -/* compare string with pattern (like fnmatch(), supports * ? [0-9] [!A-Z]) */ -int strcmp_pattern(const char *p, const char *s) -{ - if (s[0] == '\0') { - while (p[0] == '*') - p++; - return (p[0] != '\0'); - } - switch (p[0]) { - case '[': - { - int not = 0; - p++; - if (p[0] == '!') { - not = 1; - p++; - } - while ((p[0] != '\0') && (p[0] != ']')) { - int match = 0; - if (p[1] == '-') { - if ((s[0] >= p[0]) && (s[0] <= p[2])) - match = 1; - p += 3; - } else { - match = (p[0] == s[0]); - p++; - } - if (match ^ not) { - while ((p[0] != '\0') && (p[0] != ']')) - p++; - if (p[0] == ']') - return strcmp_pattern(p+1, s+1); - } - } - } - break; - case '*': - if (strcmp_pattern(p, s+1)) - return strcmp_pattern(p+1, s); - return 0; - case '\0': - if (s[0] == '\0') { - return 0; - } - break; - default: - if ((p[0] == s[0]) || (p[0] == '?')) - return strcmp_pattern(p+1, s+1); - break; - } - return 1; -} - int string_is_true(const char *str) { if (strcasecmp(str, "true") == 0) @@ -105,6 +50,49 @@ void remove_trailing_chars(char *path, char c) path[--len] = '\0'; } +size_t path_encode(char *s, size_t len) +{ + char t[(len * 3)+1]; + size_t i, j; + + t[0] = '\0'; + for (i = 0, j = 0; s[i] != '\0'; i++) { + if (s[i] == '/') { + memcpy(&t[j], "\\x2f", 4); + j += 4; + } else if (s[i] == '\\') { + memcpy(&t[j], "\\x5c", 4); + j += 4; + } else { + t[j] = s[i]; + j++; + } + } + t[j] = '\0'; + strncpy(s, t, len); + return j; +} + +size_t path_decode(char *s) +{ + size_t i, j; + + for (i = 0, j = 0; s[i] != '\0'; j++) { + if (memcmp(&s[i], "\\x2f", 4) == 0) { + s[j] = '/'; + i += 4; + }else if (memcmp(&s[i], "\\x5c", 4) == 0) { + s[j] = '\\'; + i += 4; + } else { + s[j] = s[i]; + i++; + } + } + s[j] = '\0'; + return j; +} + /* count of characters used to encode one unicode char */ static int utf8_encoded_expected_len(const char *str) { @@ -228,8 +216,8 @@ int utf8_encoded_valid_unichar(const char *str) return len; } -/* replace everything but whitelisted plain ascii and valid utf8 */ -int replace_untrusted_chars(char *str) +/* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */ +int replace_chars(char *str, const char *white) { size_t i = 0; int replaced = 0; @@ -237,22 +225,42 @@ int replace_untrusted_chars(char *str) while (str[i] != '\0') { int len; - /* valid printable ascii char */ + /* accept whitelist */ + if (white != NULL && strchr(white, str[i]) != NULL) { + i++; + continue; + } + + /* accept plain ascii char */ if ((str[i] >= '0' && str[i] <= '9') || (str[i] >= 'A' && str[i] <= 'Z') || - (str[i] >= 'a' && str[i] <= 'z') || - strchr(" #$%+-./:=?@_", str[i])) { + (str[i] >= 'a' && str[i] <= 'z')) { i++; continue; } - /* valid utf8 is accepted */ + + /* accept hex encoding */ + if (str[i] == '\\' && str[i+1] == 'x') { + i += 2; + continue; + } + + /* accept valid utf8 */ len = utf8_encoded_valid_unichar(&str[i]); if (len > 1) { i += len; continue; } - /* everything else is garbage */ + /* if space is allowed, replace whitespace with ordinary space */ + if (isspace(str[i]) && strchr(white, ' ') != NULL) { + str[i] = ' '; + i++; + replaced++; + continue; + } + + /* everything else is replaced with '_' */ str[i] = '_'; i++; replaced++;