chiark / gitweb /
Debianization and various other fixes.
[ezmlm] / decodeHDR.c
1 /*$Id: decodeHDR.c,v 1.2 1998/02/28 19:03:02 lindberg Exp $*/
2 /*$Name: ezmlm-idx-040 $*/
3
4 #include "stralloc.h"
5 #include "strerr.h"
6 #include "error.h"
7 #include "case.h"
8 #include "byte.h"
9 #include "uint32.h"
10 #include "mime.h"
11 #include "errtxt.h"
12
13 static void die_nomem(fatal)
14   char *fatal;
15 {
16   strerr_die2x(111,fatal,ERR_NOMEM);
17 }
18
19 void decodeHDR(indata,n,outdata,charset,fatal)
20 char *indata;
21 unsigned int n;
22 stralloc *outdata;
23 char *charset;
24 char *fatal;
25
26 /* decodes indata depending on charset. May put '\n' and '\0' into out */
27 /* data and can take them as indata. */
28 {
29   unsigned int pos;
30   char *cp,*cpnext,*cpstart,*cpenc,*cptxt,*cpend,*cpafter;
31
32   cpnext = indata;
33   cpafter = cpnext + n;
34   cpstart = cpnext;
35   if (!stralloc_copys(outdata,"")) die_nomem(fatal);
36   if (!stralloc_ready(outdata,n)) die_nomem(fatal);
37   for (;;) {
38     cpstart = cpstart + byte_chr(cpstart,cpafter-cpstart,'=');
39     if (cpstart == cpafter)
40       break;
41     ++cpstart;
42     if (*cpstart != '?')
43       continue;
44     ++cpstart;
45     cpenc = cpstart + byte_chr(cpstart,cpafter-cpstart,'?');
46     if (cpenc == cpafter)
47       continue;
48     cpenc++;
49     cptxt = cpenc + byte_chr(cpenc,cpafter-cpenc,'?');
50     if (cptxt == cpafter)
51       continue;
52     cptxt++;
53     cpend = cptxt + byte_chr(cptxt,cpafter-cptxt,'?');
54     if (cpend == cpafter || *(cpend + 1) != '=')
55       continue;
56         /* We'll decode anything. On lists with many charsets, this may */
57         /* result in unreadable subjects, but that's the case even if   */
58         /* no decoding is done. This way, the subject will be optimal   */
59         /* for threading, but charset info is lost. We aim to correctly */
60         /* decode us-ascii and all iso-8859/2022 charsets. Exacly how   */
61         /* these will be displayed depends on dir/charset.              */
62     cp = cpnext;
63                         /* scrap lwsp between coded strings */
64     while (*cp == ' ' || *cp == '\t')
65       cp++;
66     if (cp != cpstart - 2)
67       if (!stralloc_catb(outdata,cpnext, cpstart - cpnext - 2))
68                 die_nomem(fatal);
69    cpnext = cp + 1;
70    cpstart = cpnext;
71           switch (*cpenc) {
72             case 'b':
73             case 'B':
74               pos = outdata->len;
75               decodeB(cptxt,cpend-cptxt,outdata,2,fatal);
76               cpnext = cpend + 2;
77               cpstart = cpnext;
78               break;
79             case 'q':
80             case 'Q':
81               decodeQ(cptxt,cpend-cptxt,outdata,fatal);
82               cpnext = cpend + 2;
83               cpstart = cpnext;
84               break;
85             default:            /* shouldn't happen, but let's be reasonable */
86               cpstart = cpend + 2;
87               break;
88           }
89   }
90   if (!stralloc_catb(outdata,cpnext,indata-cpnext+n)) die_nomem(fatal);
91 }
92