escape.c revision 4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering This file is part of systemd.
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering Copyright 2010 Lennart Poettering
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering systemd is free software; you can redistribute it and/or modify it
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering under the terms of the GNU Lesser General Public License as published by
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering (at your option) any later version.
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering systemd is distributed in the hope that it will be useful, but
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering Lesser General Public License for more details.
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering You should have received a copy of the GNU Lesser General Public License
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* For special chars we prefer octal over
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * hexadecimal encoding, simply because glib's
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * g_strescape() does the same */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = octchar((unsigned char) c >> 6);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(buf++) = octchar((unsigned char) c >> 3);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringchar *cescape(const char *s) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering const char *f;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Does C style string escaping. May be reversed with
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * cunescape(). */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering for (f = s, t = r; *f; f++)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringint cunescape_one(const char *p, size_t length, char *ret, uint32_t *ret_unicode) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Unescapes C style. Returns the unescaped character in ret,
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * unless we encountered a \u sequence in which case the full
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * unicode character is returned in ret_unicode, instead. */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering switch (p[0]) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* This is an extension of the XDG syntax files */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* hexadecimal encoding */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Don't allow NUL bytes */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (a == 0 && b == 0)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* C++11 style 16bit unicode */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering for (i = 0; i < 4; i++) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3];
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Don't allow 0 chars */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* C++11 style 32bit unicode */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering for (i = 0; i < 8; i++) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering c = ((uint32_t) a[0] << 28U) | ((uint32_t) a[1] << 24U) | ((uint32_t) a[2] << 20U) | ((uint32_t) a[3] << 16U) |
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] << 8U) | ((uint32_t) a[6] << 4U) | (uint32_t) a[7];
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Don't allow 0 chars */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Don't allow invalid code points */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* octal encoding */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* don't allow NUL bytes */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (a == 0 && b == 0 && c == 0)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Don't allow bytes above 255 */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering m = ((uint32_t) a << 6U) | ((uint32_t) b << 3U) | (uint32_t) c;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringint cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering const char *f;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Undoes C style string escaping, and optionally prefixes it. */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering for (f = s, t = r + pl; f < s + length; f++) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (*f != '\\') {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* A literal literal, copy verbatim */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* A trailing backslash, copy verbatim */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering k = cunescape_one(f + 1, remaining - 1, &c, &u);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Invalid escape code, let's take it literal then */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Non-Unicode? Let's encode this directly */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Unicode? Then let's encode this in UTF-8 */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringint cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return cunescape_length_with_prefix(s, length, NULL, flags, ret);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringint cunescape(const char *s, UnescapeFlags flags, char **ret) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering return cunescape_length(s, strlen(s), flags, ret);
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringchar *xescape(const char *s, const char *bad) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering const char *f;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Escapes all chars in bad, in addition to \ and all special
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * chars, in \xFF style escaping. May be reversed with
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * cunescape(). */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering for (f = s, t = r; *f; f++) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringstatic char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering for (; *s; s++) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering *(t++) = '\\';
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringchar *shell_escape(const char *s, const char *bad) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poetteringchar *shell_maybe_quote(const char *s) {
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering const char *p;
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering /* Encloses a string in double quotes if necessary to make it
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering * OK as shell string. */
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering for (p = s; *p; p++)
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering if (*p <= ' ' ||
4f5dd3943bef8a04be7e3b838b822bb9a7ad6cb3Lennart Poettering t = mempcpy(t, s, p - s);