Import ezmlm-idx 0.40
[ezmlm] / decodeHDR.c
diff --git a/decodeHDR.c b/decodeHDR.c
new file mode 100644 (file)
index 0000000..4693d3d
--- /dev/null
@@ -0,0 +1,92 @@
+/*$Id: decodeHDR.c,v 1.2 1998/02/28 19:03:02 lindberg Exp $*/
+/*$Name: ezmlm-idx-040 $*/
+
+#include "stralloc.h"
+#include "strerr.h"
+#include "error.h"
+#include "case.h"
+#include "byte.h"
+#include "uint32.h"
+#include "mime.h"
+#include "errtxt.h"
+
+static void die_nomem(fatal)
+  char *fatal;
+{
+  strerr_die2x(111,fatal,ERR_NOMEM);
+}
+
+void decodeHDR(indata,n,outdata,charset,fatal)
+char *indata;
+unsigned int n;
+stralloc *outdata;
+char *charset;
+char *fatal;
+
+/* decodes indata depending on charset. May put '\n' and '\0' into out */
+/* data and can take them as indata. */
+{
+  unsigned int pos;
+  char *cp,*cpnext,*cpstart,*cpenc,*cptxt,*cpend,*cpafter;
+
+  cpnext = indata;
+  cpafter = cpnext + n;
+  cpstart = cpnext;
+  if (!stralloc_copys(outdata,"")) die_nomem(fatal);
+  if (!stralloc_ready(outdata,n)) die_nomem(fatal);
+  for (;;) {
+    cpstart = cpstart + byte_chr(cpstart,cpafter-cpstart,'=');
+    if (cpstart == cpafter)
+      break;
+    ++cpstart;
+    if (*cpstart != '?')
+      continue;
+    ++cpstart;
+    cpenc = cpstart + byte_chr(cpstart,cpafter-cpstart,'?');
+    if (cpenc == cpafter)
+      continue;
+    cpenc++;
+    cptxt = cpenc + byte_chr(cpenc,cpafter-cpenc,'?');
+    if (cptxt == cpafter)
+      continue;
+    cptxt++;
+    cpend = cptxt + byte_chr(cptxt,cpafter-cptxt,'?');
+    if (cpend == cpafter || *(cpend + 1) != '=')
+      continue;
+       /* We'll decode anything. On lists with many charsets, this may */
+       /* result in unreadable subjects, but that's the case even if   */
+       /* no decoding is done. This way, the subject will be optimal   */
+       /* for threading, but charset info is lost. We aim to correctly */
+       /* decode us-ascii and all iso-8859/2022 charsets. Exacly how   */
+       /* these will be displayed depends on dir/charset.              */
+    cp = cpnext;
+                       /* scrap lwsp between coded strings */
+    while (*cp == ' ' || *cp == '\t')
+      cp++;
+    if (cp != cpstart - 2)
+      if (!stralloc_catb(outdata,cpnext, cpstart - cpnext - 2))
+               die_nomem(fatal);
+   cpnext = cp + 1;
+   cpstart = cpnext;
+          switch (*cpenc) {
+            case 'b':
+            case 'B':
+              pos = outdata->len;
+              decodeB(cptxt,cpend-cptxt,outdata,2,fatal);
+              cpnext = cpend + 2;
+              cpstart = cpnext;
+              break;
+            case 'q':
+            case 'Q':
+              decodeQ(cptxt,cpend-cptxt,outdata,fatal);
+              cpnext = cpend + 2;
+              cpstart = cpnext;
+              break;
+            default:           /* shouldn't happen, but let's be reasonable */
+              cpstart = cpend + 2;
+              break;
+          }
+  }
+  if (!stralloc_catb(outdata,cpnext,indata-cpnext+n)) die_nomem(fatal);
+}
+