summaryrefslogtreecommitdiffstats
path: root/common/miscellaneous.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2019-01-30 08:28:56 +0100
committerWerner Koch <wk@gnupg.org>2019-01-30 08:28:56 +0100
commit6ecedd0b25b6b1a33be63b99f2a8256370000521 (patch)
treed7f7363d870736f8c1a29b8e51ce8e68895a11b9 /common/miscellaneous.c
parentdoc: Fix typo (diff)
downloadgnupg2-6ecedd0b25b6b1a33be63b99f2a8256370000521.tar.xz
gnupg2-6ecedd0b25b6b1a33be63b99f2a8256370000521.zip
common: New function decode_c_string.
* common/miscellaneous.c (decode_c_string): New. -- This is basically a copy from the code we use in gpgme and gpa. Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'common/miscellaneous.c')
-rw-r--r--common/miscellaneous.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/common/miscellaneous.c b/common/miscellaneous.c
index 0b374e6c8..260552828 100644
--- a/common/miscellaneous.c
+++ b/common/miscellaneous.c
@@ -328,6 +328,82 @@ make_printable_string (const void *p, size_t n, int delim )
}
+/* Decode the C formatted string SRC and return the result in a newly
+ * allocated buffer. In error returns NULL and sets ERRNO. */
+char *
+decode_c_string (const char *src)
+{
+ char *buffer, *dst;
+ int val;
+
+ /* The converted string will never be larger than the original
+ string. */
+ buffer = dst = xtrymalloc (strlen (src) + 1);
+ if (!buffer)
+ return NULL;
+
+ while (*src)
+ {
+ if (*src != '\\')
+ {
+ *dst++ = *src++;
+ continue;
+ }
+
+#define DECODE_ONE(_m,_r) case _m: src += 2; *dst++ = _r; break;
+
+ switch (src[1])
+ {
+ DECODE_ONE ('n', '\n');
+ DECODE_ONE ('r', '\r');
+ DECODE_ONE ('f', '\f');
+ DECODE_ONE ('v', '\v');
+ DECODE_ONE ('b', '\b');
+ DECODE_ONE ('t', '\t');
+ DECODE_ONE ('\\', '\\');
+ DECODE_ONE ('\'', '\'');
+ DECODE_ONE ('\"', '\"');
+
+ case 'x':
+ val = hextobyte (src+2);
+ if (val == -1) /* Bad coding, keep as is. */
+ {
+ *dst++ = *src++;
+ *dst++ = *src++;
+ if (*src)
+ *dst++ = *src++;
+ if (*src)
+ *dst++ = *src++;
+ }
+ else if (!val)
+ {
+ /* A binary zero is not representable in a C string thus
+ * we keep the C-escaping. Note that this will also
+ * never be larger than the source string. */
+ *dst++ = '\\';
+ *dst++ = '0';
+ src += 4;
+ }
+ else
+ {
+ *(unsigned char *)dst++ = val;
+ src += 4;
+ }
+ break;
+
+ default: /* Bad coding; keep as is.. */
+ *dst++ = *src++;
+ *dst++ = *src++;
+ break;
+ }
+#undef DECODE_ONE
+ }
+ *dst++ = 0;
+
+ return buffer;
+}
+
+
/* Check whether (BUF,LEN) is valid header for an OpenPGP compressed
* packet. LEN should be at least 6. */
static int