Import ezmlm-idx 0.40
[ezmlm] / decodeQ.c
1 /*$Id: decodeQ.c,v 1.3 1998/10/29 21:48:24 lindberg Exp $*/
2 /*$Name: ezmlm-idx-040 $*/
3
4 #include "stralloc.h"
5 #include "strerr.h"
6 #include "errtxt.h"
7 #include "mime.h"
8
9 /* takes a string pointed to by cpfrom and adds the next 'n' bytes to */
10 /* outdata, replacing any Quoted-Printable codes with the real characters. */
11 /* NUL and LF in the input are allowed, but anything that decodes to these */
12 /* values is ignored. */
13
14 static char char16table[128] = {
15 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
16 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
17 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
18 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1,
19 -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
20 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
21 -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
22 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
23 };
24
25 #define char16enc(c) (((c) & 0x80) ? -1 : char16table[(c)])
26
27 static void die_nomem(fatal)
28 char *fatal;
29 {
30 strerr_die2x(111,fatal,ERR_NOMEM);
31 }
32
33 void decodeQ(cpfrom,n,outdata,fatal)
34 char *cpfrom;
35 unsigned int n;
36 stralloc *outdata;
37 char *fatal;
38 /* does Q decoding of the string pointed to by cpfrom up to the character */
39 /* before the one pointed to by cpnext, and appends the results to mimeline*/
40 {
41 char *cp,*cpnext,*cpmore;
42 char holdch[2];
43 char ch1,ch2; /* need to be signed */
44
45 cpmore = cpfrom;
46 cp = cpfrom;
47 cpnext = cp + n;
48 if (!stralloc_readyplus(outdata,n)) die_nomem(fatal);
49
50 while (cp < cpnext) {
51 if (*cp == '_') *cp = ' '; /* '_' -> space */
52 else if (*cp == '=') { /* "=F8" -> '\xF8' */
53 /* copy stuff before */
54 if (!stralloc_catb(outdata,cpmore,cp-cpmore)) die_nomem(fatal);
55 cpmore = cp;
56 ++cp;
57 if (*cp == '\n') { /* skip soft line break */
58 ++cp;
59 cpmore = cp;
60 continue;
61 }
62 ch1 = char16enc(*cp);
63 if (++cp >= cpnext)
64 break;
65 ch2 = char16enc(*cp);
66 if (ch1 >= 0 && ch2 >= 0) { /* ignore illegals */
67 holdch[0] = (ch1 << 4 | ch2) & 0xff;
68 if (!stralloc_catb(outdata,holdch,1)) die_nomem(fatal);
69 cpmore += 3;
70 }
71 }
72 ++cp;
73 } /* copy stuff after */
74 if (!stralloc_catb(outdata,cpmore,cpnext-cpmore)) die_nomem(fatal);
75 }
76
77