Import ezmlm-idx 0.40
[ezmlm] / decodeQ.c
CommitLineData
f8beb284
MW
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
14static 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
27static void die_nomem(fatal)
28 char *fatal;
29{
30 strerr_die2x(111,fatal,ERR_NOMEM);
31}
32
33void decodeQ(cpfrom,n,outdata,fatal)
34char *cpfrom;
35unsigned int n;
36stralloc *outdata;
37char *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