summaryrefslogtreecommitdiff
path: root/src/basic/escape.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic/escape.c')
-rw-r--r--src/basic/escape.c502
1 files changed, 0 insertions, 502 deletions
diff --git a/src/basic/escape.c b/src/basic/escape.c
deleted file mode 100644
index 4a1ec4505e..0000000000
--- a/src/basic/escape.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2010 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "alloc-util.h"
-#include "escape.h"
-#include "hexdecoct.h"
-#include "macro.h"
-#include "utf8.h"
-
-size_t cescape_char(char c, char *buf) {
- char * buf_old = buf;
-
- switch (c) {
-
- case '\a':
- *(buf++) = '\\';
- *(buf++) = 'a';
- break;
- case '\b':
- *(buf++) = '\\';
- *(buf++) = 'b';
- break;
- case '\f':
- *(buf++) = '\\';
- *(buf++) = 'f';
- break;
- case '\n':
- *(buf++) = '\\';
- *(buf++) = 'n';
- break;
- case '\r':
- *(buf++) = '\\';
- *(buf++) = 'r';
- break;
- case '\t':
- *(buf++) = '\\';
- *(buf++) = 't';
- break;
- case '\v':
- *(buf++) = '\\';
- *(buf++) = 'v';
- break;
- case '\\':
- *(buf++) = '\\';
- *(buf++) = '\\';
- break;
- case '"':
- *(buf++) = '\\';
- *(buf++) = '"';
- break;
- case '\'':
- *(buf++) = '\\';
- *(buf++) = '\'';
- break;
-
- default:
- /* For special chars we prefer octal over
- * hexadecimal encoding, simply because glib's
- * g_strescape() does the same */
- if ((c < ' ') || (c >= 127)) {
- *(buf++) = '\\';
- *(buf++) = octchar((unsigned char) c >> 6);
- *(buf++) = octchar((unsigned char) c >> 3);
- *(buf++) = octchar((unsigned char) c);
- } else
- *(buf++) = c;
- break;
- }
-
- return buf - buf_old;
-}
-
-char *cescape_length(const char *s, size_t n) {
- const char *f;
- char *r, *t;
-
- assert(s || n == 0);
-
- /* Does C style string escaping. May be reversed with
- * cunescape(). */
-
- r = new(char, n*4 + 1);
- if (!r)
- return NULL;
-
- for (f = s, t = r; f < s + n; f++)
- t += cescape_char(*f, t);
-
- *t = 0;
-
- return r;
-}
-
-char *cescape(const char *s) {
- assert(s);
-
- return cescape_length(s, strlen(s));
-}
-
-int cunescape_one(const char *p, size_t length, char32_t *ret, bool *eight_bit) {
- int r = 1;
-
- assert(p);
- assert(*p);
- assert(ret);
-
- /* Unescapes C style. Returns the unescaped character in ret.
- * Sets *eight_bit to true if the escaped sequence either fits in
- * one byte in UTF-8 or is a non-unicode literal byte and should
- * instead be copied directly.
- */
-
- if (length != (size_t) -1 && length < 1)
- return -EINVAL;
-
- switch (p[0]) {
-
- case 'a':
- *ret = '\a';
- break;
- case 'b':
- *ret = '\b';
- break;
- case 'f':
- *ret = '\f';
- break;
- case 'n':
- *ret = '\n';
- break;
- case 'r':
- *ret = '\r';
- break;
- case 't':
- *ret = '\t';
- break;
- case 'v':
- *ret = '\v';
- break;
- case '\\':
- *ret = '\\';
- break;
- case '"':
- *ret = '"';
- break;
- case '\'':
- *ret = '\'';
- break;
-
- case 's':
- /* This is an extension of the XDG syntax files */
- *ret = ' ';
- break;
-
- case 'x': {
- /* hexadecimal encoding */
- int a, b;
-
- if (length != (size_t) -1 && length < 3)
- return -EINVAL;
-
- a = unhexchar(p[1]);
- if (a < 0)
- return -EINVAL;
-
- b = unhexchar(p[2]);
- if (b < 0)
- return -EINVAL;
-
- /* Don't allow NUL bytes */
- if (a == 0 && b == 0)
- return -EINVAL;
-
- *ret = (a << 4U) | b;
- *eight_bit = true;
- r = 3;
- break;
- }
-
- case 'u': {
- /* C++11 style 16bit unicode */
-
- int a[4];
- unsigned i;
- uint32_t c;
-
- if (length != (size_t) -1 && length < 5)
- return -EINVAL;
-
- for (i = 0; i < 4; i++) {
- a[i] = unhexchar(p[1 + i]);
- if (a[i] < 0)
- return a[i];
- }
-
- c = ((uint32_t) a[0] << 12U) | ((uint32_t) a[1] << 8U) | ((uint32_t) a[2] << 4U) | (uint32_t) a[3];
-
- /* Don't allow 0 chars */
- if (c == 0)
- return -EINVAL;
-
- *ret = c;
- r = 5;
- break;
- }
-
- case 'U': {
- /* C++11 style 32bit unicode */
-
- int a[8];
- unsigned i;
- char32_t c;
-
- if (length != (size_t) -1 && length < 9)
- return -EINVAL;
-
- for (i = 0; i < 8; i++) {
- a[i] = unhexchar(p[1 + i]);
- if (a[i] < 0)
- return a[i];
- }
-
- c = ((uint32_t) a[0] << 28U) | ((uint32_t) a[1] << 24U) | ((uint32_t) a[2] << 20U) | ((uint32_t) a[3] << 16U) |
- ((uint32_t) a[4] << 12U) | ((uint32_t) a[5] << 8U) | ((uint32_t) a[6] << 4U) | (uint32_t) a[7];
-
- /* Don't allow 0 chars */
- if (c == 0)
- return -EINVAL;
-
- /* Don't allow invalid code points */
- if (!unichar_is_valid(c))
- return -EINVAL;
-
- *ret = c;
- r = 9;
- break;
- }
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7': {
- /* octal encoding */
- int a, b, c;
- char32_t m;
-
- if (length != (size_t) -1 && length < 3)
- return -EINVAL;
-
- a = unoctchar(p[0]);
- if (a < 0)
- return -EINVAL;
-
- b = unoctchar(p[1]);
- if (b < 0)
- return -EINVAL;
-
- c = unoctchar(p[2]);
- if (c < 0)
- return -EINVAL;
-
- /* don't allow NUL bytes */
- if (a == 0 && b == 0 && c == 0)
- return -EINVAL;
-
- /* Don't allow bytes above 255 */
- m = ((uint32_t) a << 6U) | ((uint32_t) b << 3U) | (uint32_t) c;
- if (m > 255)
- return -EINVAL;
-
- *ret = m;
- *eight_bit = true;
- r = 3;
- break;
- }
-
- default:
- return -EINVAL;
- }
-
- return r;
-}
-
-int cunescape_length_with_prefix(const char *s, size_t length, const char *prefix, UnescapeFlags flags, char **ret) {
- char *r, *t;
- const char *f;
- size_t pl;
-
- assert(s);
- assert(ret);
-
- /* Undoes C style string escaping, and optionally prefixes it. */
-
- pl = prefix ? strlen(prefix) : 0;
-
- r = new(char, pl+length+1);
- if (!r)
- return -ENOMEM;
-
- if (prefix)
- memcpy(r, prefix, pl);
-
- for (f = s, t = r + pl; f < s + length; f++) {
- size_t remaining;
- bool eight_bit = false;
- char32_t u;
- int k;
-
- remaining = s + length - f;
- assert(remaining > 0);
-
- if (*f != '\\') {
- /* A literal, copy verbatim */
- *(t++) = *f;
- continue;
- }
-
- if (remaining == 1) {
- if (flags & UNESCAPE_RELAX) {
- /* A trailing backslash, copy verbatim */
- *(t++) = *f;
- continue;
- }
-
- free(r);
- return -EINVAL;
- }
-
- k = cunescape_one(f + 1, remaining - 1, &u, &eight_bit);
- if (k < 0) {
- if (flags & UNESCAPE_RELAX) {
- /* Invalid escape code, let's take it literal then */
- *(t++) = '\\';
- continue;
- }
-
- free(r);
- return k;
- }
-
- f += k;
- if (eight_bit)
- /* One byte? Set directly as specified */
- *(t++) = u;
- else
- /* Otherwise encode as multi-byte UTF-8 */
- t += utf8_encode_unichar(t, u);
- }
-
- *t = 0;
-
- *ret = r;
- return t - r;
-}
-
-int cunescape_length(const char *s, size_t length, UnescapeFlags flags, char **ret) {
- return cunescape_length_with_prefix(s, length, NULL, flags, ret);
-}
-
-int cunescape(const char *s, UnescapeFlags flags, char **ret) {
- return cunescape_length(s, strlen(s), flags, ret);
-}
-
-char *xescape(const char *s, const char *bad) {
- char *r, *t;
- const char *f;
-
- /* Escapes all chars in bad, in addition to \ and all special
- * chars, in \xFF style escaping. May be reversed with
- * cunescape(). */
-
- r = new(char, strlen(s) * 4 + 1);
- if (!r)
- return NULL;
-
- for (f = s, t = r; *f; f++) {
-
- if ((*f < ' ') || (*f >= 127) ||
- (*f == '\\') || strchr(bad, *f)) {
- *(t++) = '\\';
- *(t++) = 'x';
- *(t++) = hexchar(*f >> 4);
- *(t++) = hexchar(*f);
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- return r;
-}
-
-char *octescape(const char *s, size_t len) {
- char *r, *t;
- const char *f;
-
- /* Escapes all chars in bad, in addition to \ and " chars,
- * in \nnn style escaping. */
-
- r = new(char, len * 4 + 1);
- if (!r)
- return NULL;
-
- for (f = s, t = r; f < s + len; f++) {
-
- if (*f < ' ' || *f >= 127 || *f == '\\' || *f == '"') {
- *(t++) = '\\';
- *(t++) = '0' + (*f >> 6);
- *(t++) = '0' + ((*f >> 3) & 8);
- *(t++) = '0' + (*f & 8);
- } else
- *(t++) = *f;
- }
-
- *t = 0;
-
- return r;
-
-}
-
-static char *strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
- assert(bad);
-
- for (; *s; s++) {
- if (*s == '\\' || strchr(bad, *s))
- *(t++) = '\\';
-
- *(t++) = *s;
- }
-
- return t;
-}
-
-char *shell_escape(const char *s, const char *bad) {
- char *r, *t;
-
- r = new(char, strlen(s)*2+1);
- if (!r)
- return NULL;
-
- t = strcpy_backslash_escaped(r, s, bad);
- *t = 0;
-
- return r;
-}
-
-char *shell_maybe_quote(const char *s) {
- const char *p;
- char *r, *t;
-
- assert(s);
-
- /* Encloses a string in double quotes if necessary to make it
- * OK as shell string. */
-
- for (p = s; *p; p++)
- if (*p <= ' ' ||
- *p >= 127 ||
- strchr(SHELL_NEED_QUOTES, *p))
- break;
-
- if (!*p)
- return strdup(s);
-
- r = new(char, 1+strlen(s)*2+1+1);
- if (!r)
- return NULL;
-
- t = r;
- *(t++) = '"';
- t = mempcpy(t, s, p - s);
-
- t = strcpy_backslash_escaped(t, p, SHELL_NEED_ESCAPE);
-
- *(t++)= '"';
- *t = 0;
-
- return r;
-}