Import ezmlm-idx 0.40
[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