summaryrefslogtreecommitdiffstats
path: root/src/util/unescape.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/unescape.c')
-rw-r--r--src/util/unescape.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/src/util/unescape.c b/src/util/unescape.c
new file mode 100644
index 0000000..4eacbba
--- /dev/null
+++ b/src/util/unescape.c
@@ -0,0 +1,208 @@
+/*++
+/* NAME
+/* unescape 3
+/* SUMMARY
+/* translate C-like escape sequences
+/* SYNOPSIS
+/* #include <stringops.h>
+/*
+/* VSTRING *unescape(result, input)
+/* VSTRING *result;
+/* const char *input;
+/*
+/* VSTRING *escape(result, input, len)
+/* VSTRING *result;
+/* const char *input;
+/* ssize_t len;
+/* DESCRIPTION
+/* unescape() translates C-like escape sequences in the null-terminated
+/* string \fIinput\fR and places the result in \fIresult\fR. The result
+/* is null-terminated, and is the function result value.
+/*
+/* escape() does the reverse transformation.
+/*
+/* Escape sequences and their translations:
+/* .IP \ea
+/* Bell character.
+/* .IP \eb
+/* Backspace character.
+/* .IP \ef
+/* formfeed character.
+/* .IP \en
+/* newline character
+/* .IP \er
+/* Carriage-return character.
+/* .IP \et
+/* Horizontal tab character.
+/* .IP \ev
+/* Vertical tab character.
+/* .IP \e\e
+/* Backslash character.
+/* .IP \e\fInum\fR
+/* 8-bit character whose ASCII value is the 1..3 digit
+/* octal number \fInum\fR.
+/* .IP \e\fIother\fR
+/* The backslash character is discarded.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <ctype.h>
+
+/* Utility library. */
+
+#include <vstring.h>
+#include <stringops.h>
+
+/* unescape - process escape sequences */
+
+VSTRING *unescape(VSTRING *result, const char *data)
+{
+ int ch;
+ int oval;
+ int i;
+
+#define UCHAR(cp) ((unsigned char *) (cp))
+#define ISOCTAL(ch) (ISDIGIT(ch) && (ch) != '8' && (ch) != '9')
+
+ VSTRING_RESET(result);
+
+ while ((ch = *UCHAR(data++)) != 0) {
+ if (ch == '\\') {
+ if ((ch = *UCHAR(data++)) == 0)
+ break;
+ switch (ch) {
+ case 'a': /* \a -> audible bell */
+ ch = '\a';
+ break;
+ case 'b': /* \b -> backspace */
+ ch = '\b';
+ break;
+ case 'f': /* \f -> formfeed */
+ ch = '\f';
+ break;
+ case 'n': /* \n -> newline */
+ ch = '\n';
+ break;
+ case 'r': /* \r -> carriagereturn */
+ ch = '\r';
+ break;
+ case 't': /* \t -> horizontal tab */
+ ch = '\t';
+ break;
+ case 'v': /* \v -> vertical tab */
+ ch = '\v';
+ break;
+ case '0': /* \nnn -> ASCII value */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ for (oval = ch - '0', i = 0;
+ i < 2 && (ch = *UCHAR(data)) != 0 && ISOCTAL(ch);
+ i++, data++) {
+ oval = (oval << 3) | (ch - '0');
+ }
+ ch = oval;
+ break;
+ default: /* \any -> any */
+ break;
+ }
+ }
+ VSTRING_ADDCH(result, ch);
+ }
+ VSTRING_TERMINATE(result);
+ return (result);
+}
+
+/* escape - reverse transformation */
+
+VSTRING *escape(VSTRING *result, const char *data, ssize_t len)
+{
+ int ch;
+
+ VSTRING_RESET(result);
+ while (len-- > 0) {
+ ch = *UCHAR(data++);
+ if (ISASCII(ch)) {
+ if (ISPRINT(ch)) {
+ if (ch == '\\')
+ VSTRING_ADDCH(result, ch);
+ VSTRING_ADDCH(result, ch);
+ continue;
+ } else if (ch == '\a') { /* \a -> audible bell */
+ vstring_strcat(result, "\\a");
+ continue;
+ } else if (ch == '\b') { /* \b -> backspace */
+ vstring_strcat(result, "\\b");
+ continue;
+ } else if (ch == '\f') { /* \f -> formfeed */
+ vstring_strcat(result, "\\f");
+ continue;
+ } else if (ch == '\n') { /* \n -> newline */
+ vstring_strcat(result, "\\n");
+ continue;
+ } else if (ch == '\r') { /* \r -> carriagereturn */
+ vstring_strcat(result, "\\r");
+ continue;
+ } else if (ch == '\t') { /* \t -> horizontal tab */
+ vstring_strcat(result, "\\t");
+ continue;
+ } else if (ch == '\v') { /* \v -> vertical tab */
+ vstring_strcat(result, "\\v");
+ continue;
+ }
+ }
+ vstring_sprintf_append(result, "\\%03o", ch);
+ }
+ VSTRING_TERMINATE(result);
+ return (result);
+}
+
+#ifdef TEST
+
+#include <stdlib.h>
+#include <string.h>
+#include <msg.h>
+#include <vstring_vstream.h>
+
+int main(int argc, char **argv)
+{
+ VSTRING *in = vstring_alloc(10);
+ VSTRING *out = vstring_alloc(10);
+ int un_escape = 1;
+
+ if (argc > 2 || (argc > 1 && (un_escape = strcmp(argv[1], "-e"))) != 0)
+ msg_fatal("usage: %s [-e (escape)]", argv[0]);
+
+ if (un_escape) {
+ while (vstring_fgets_nonl(in, VSTREAM_IN)) {
+ unescape(out, vstring_str(in));
+ vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out));
+ VSTREAM_PUTC('\n', VSTREAM_OUT);
+ }
+ } else {
+ while (vstring_fgets_nonl(in, VSTREAM_IN)) {
+ escape(out, vstring_str(in), VSTRING_LEN(in));
+ vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out));
+ VSTREAM_PUTC('\n', VSTREAM_OUT);
+ }
+ }
+ vstream_fflush(VSTREAM_OUT);
+ exit(0);
+}
+
+#endif