Import ezmlm-idx 0.40
[ezmlm] / decodeQ.c
diff --git a/decodeQ.c b/decodeQ.c
new file mode 100644 (file)
index 0000000..7e5d388
--- /dev/null
+++ b/decodeQ.c
@@ -0,0 +1,77 @@
+/*$Id: decodeQ.c,v 1.3 1998/10/29 21:48:24 lindberg Exp $*/
+/*$Name: ezmlm-idx-040 $*/
+
+#include "stralloc.h"
+#include "strerr.h"
+#include "errtxt.h"
+#include "mime.h"
+
+/* takes a string pointed to by cpfrom and adds the next 'n' bytes to        */
+/* outdata, replacing any Quoted-Printable codes with the real characters.   */
+/* NUL and LF in the input are allowed, but anything that decodes to these   */
+/* values is ignored. */
+
+static char char16table[128] = {
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+     0, 1, 2, 3,  4, 5, 6, 7,  8, 9,-1,-1, -1,-1,-1,-1,
+    -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+    -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+    -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
+};
+
+#define char16enc(c)  (((c) & 0x80) ? -1 : char16table[(c)])
+
+static void die_nomem(fatal)
+  char *fatal;
+{
+  strerr_die2x(111,fatal,ERR_NOMEM);
+}
+
+void decodeQ(cpfrom,n,outdata,fatal)
+char *cpfrom;
+unsigned int n;
+stralloc *outdata;
+char *fatal;
+/* does Q decoding of the string pointed to by cpfrom up to the character */
+/* before the one pointed to by cpnext, and appends the results to mimeline*/
+{
+  char *cp,*cpnext,*cpmore;
+  char holdch[2];
+  char ch1,ch2;                /* need to be signed */
+
+  cpmore = cpfrom;
+  cp = cpfrom;
+  cpnext = cp + n;
+  if (!stralloc_readyplus(outdata,n)) die_nomem(fatal);
+
+  while (cp < cpnext) {
+    if (*cp == '_') *cp = ' ';         /* '_' -> space */
+    else if (*cp == '=') {             /* "=F8" -> '\xF8' */
+                                       /* copy stuff before */
+      if (!stralloc_catb(outdata,cpmore,cp-cpmore)) die_nomem(fatal);
+      cpmore = cp;
+      ++cp;
+      if (*cp == '\n') {               /* skip soft line break */
+        ++cp;
+        cpmore = cp;
+        continue;
+      }
+      ch1 = char16enc(*cp);
+      if (++cp >= cpnext)
+        break;
+      ch2 = char16enc(*cp);
+      if (ch1 >= 0 && ch2 >= 0) {      /* ignore illegals */
+        holdch[0] = (ch1 << 4 | ch2) & 0xff;
+        if (!stralloc_catb(outdata,holdch,1)) die_nomem(fatal);
+        cpmore += 3;
+      }
+    }
+    ++cp;
+  }                                    /* copy stuff after */
+  if (!stralloc_catb(outdata,cpmore,cpnext-cpmore)) die_nomem(fatal);
+}      
+
+