chiark / gitweb /
Debianization and various other fixes.
[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