blob: 6dd46127686d4c01ac55675139ff5fae7b8c6f16 [file]
#include "stralloc.h"
#include "strerr.h"
#include "messages.h"
#include "mime.h"
#include "die.h"
#include "idx.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 const 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[(int)(c)])
void decodeQ(const char *cpfrom,unsigned int n,stralloc *outdata)
/* 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 outdata */
{
const char *cp,*cpnext;
char ch1,ch2; /* need to be signed */
char ch;
cp = cpfrom;
cpnext = cp + n;
if (!stralloc_readyplus(outdata,n)) die_nomem();
while (cp < cpnext) {
ch = *cp++;
if (ch == '_') ch = ' '; /* '_' -> space */
if (ch == '=') { /* "=F8" -> '\xF8' */
if (*cp == '\n') { /* skip soft line break */
++cp;
continue;
}
ch1 = char16enc(*cp); ++cp;
if (cp >= cpnext)
break;
ch2 = char16enc(*cp); ++cp;
if (ch1 >= 0 && ch2 >= 0) { /* ignore illegals */
ch = (ch1 << 4 | ch2) & 0xff;
}
}
if (!stralloc_append(outdata,ch)) die_nomem();
}
}