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