/* * quoted-printable [-e|-E|-d] * * -e specifies encoding, -d decoding. -E specifies encoding like -e, * but it encodes more characters, including several that may be * problematic if the message passes through an EBCDIC machine, and * minus signs at the beginnings of lines. Note that when encoding, * if the input is lacking a final trailing newline, the output will * end with a quoted-printable soft line break with nothing following * it, so as to ensure that the output always ends with a newline. */ #include #include #include extern const char *__progname; static char xdig[] = "0123456789ABCDEF"; static char paranoid_danger[] = "\t!\"#$@[\\]^`{|}~"; static void encode(int paranoid) { int c; int olen; int lbeg; int ws; olen = 0; lbeg = 1; ws = 0; while (1) { c = getchar(); if (c == EOF) break; if (olen > 70) { printf("=\n"); olen = 0; lbeg = 1; ws = 0; } if (c == '\n') { if (ws) printf("=\n"); putchar('\n'); olen = 0; lbeg = 1; ws = 0; } else if ((c == ' ') || (c == '\t')) { putchar(c); olen ++; lbeg = 0; ws = 1; } else if ( (c < 32) || (c > 126) || (c == '=') || ( paranoid && ( (lbeg && (c == '-')) || index(paranoid_danger,c) ) ) ) { if (c & ~0xff) { fprintf(stderr,"%s: out-of-range input character 0x%x dropped\n",__progname,c); } else { putchar('='); putchar(xdig[(c>>4)&15]); putchar(xdig[c&15]); olen += 3; lbeg = 0; ws = 0; } } else { putchar(c); olen ++; lbeg = 0; ws = 0; } } if (olen > 0) printf("=\n"); } static void decode(void) { int ilen; char *xp; int xbuf; enum { EQS_NONE = 1, EQS_EQUAL, EQS_MIDHEX } eqstate; int c; unsigned char *spcbuf; int spchave; int spclen; int spcptr; spcbuf = malloc(1); spchave = 0; spclen = 0; spcptr = 0; ilen = 0; eqstate = EQS_NONE; while (1) { if (spcptr > 0) { c = spcbuf[spcptr++]; if (spcptr >= spclen) { spcptr = 0; spclen = 0; } } else { c = getchar(); if (c == EOF) break; switch (c) { case ' ': case '\t': while (spclen >= spchave) spcbuf = realloc(spcbuf,(spchave+=8)+1); spcbuf[spclen++] = c; continue; break; case '\n': spclen = 0; break; } if (spclen > 0) { spcbuf[spclen++] = c; spcptr = 1; c = spcbuf[0]; } } if (c == '\n') { ilen = 0; } else { if (ilen++ == 76) { fprintf(stderr,"%s: warning: input line exceeds standard maximum length\n",__progname); } } switch (eqstate) { case EQS_NONE: if (c == '=') { eqstate = EQS_EQUAL; } else { putchar(c); } break; case EQS_EQUAL: if (c == '\n') { eqstate = EQS_NONE; } else { xp = index(xdig,c); if (xp) { eqstate = EQS_MIDHEX; xbuf = (xp-xdig) << 4; } else { fprintf(stderr,"%s: invalid character 0x%x after =\n",__progname,(unsigned int)c); eqstate = EQS_NONE; } } break; case EQS_MIDHEX: eqstate = EQS_NONE; xp = index(xdig,c); if (xp) { putchar(xbuf|(xp-xdig)); } else { fprintf(stderr,"%s: invalid second character 0x%x in hex = encoding\n",__progname,(unsigned int)c); } break; } } free(spcbuf); } int main(int, char **); int main(int ac, char **av) { if (0) { usage:; fprintf(stderr,"Usage: %s [-e|-E|-d]\n",__progname); exit(1); } if (ac != 2) goto usage; if (!strcmp(av[1],"-e")) encode(0); else if (!strcmp(av[1],"-E")) encode(1); else if (!strcmp(av[1],"-d")) decode(); else goto usage; exit(0); }