/* ** ** Copyright (C) 1993 Swedish University Network (SUNET) ** ** ** This program is developed by UDAC, Uppsala University by commission ** of the Swedish University Network (SUNET). ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITTNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ** ** ** Martin.Wendel@its.uu.se ** Torbjorn.Wictorin@its.uu.se ** ** ITS ** P.O. Box 887 ** S-751 08 Uppsala ** Sweden ** */ #include "emil.h" unsigned char thqx[] = "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"; int fhqx[] = { FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, SKIP, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, SKIP, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL, 0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL, 0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL, 0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL }; int encode_binhex(struct message *m) { struct data *inbuf, *outbuf; int linelen; int i, left; int run = 0; unsigned long triple; unsigned char *inb; inbuf = m->td; outbuf = (struct data *)Yalloc(sizeof(struct data )); #ifdef DEBUG if (edebug) fprintf(stderr, "Encoding BinHex\n"); #endif /* Exit on empty input */ if (!inbuf->size) { #ifdef DEBUG if (edebug) fprintf(stderr, ", no input (failed).\n"); #endif return(NOK); } macify_filename(m); /* Create binhex binary file */ if (create_binhex_binary(m) != OK) return(NOK); inbuf = m->td; run = 0; linelen = 0; outbuf->encoding = EBINHEX; /* Initialize working pointers */ inb = inbuf->contents + inbuf->offset; i = 0; triple = 0; /* * Add preamble */ append_data(outbuf, "(This file must be converted with BinHex 4.0)\n:", 47, pz); linelen = 1; outbuf->lineend += 1; /* * Process entire inbuf. */ left = inbuf->bodyend - inbuf->offset; while (left > 0 || i > 0) { if (left > 0) { triple = (triple <<8) | *inb; left--; i++; /* Handle special case of run length encoding */ if (*inb == 0x90) { if (i < 3) { /* #ifdef DEBUG if (edebug) fprintf(stderr, "* DOING A RUN 0 AT %d.\n", outbuf->bodyend); #endif */ triple = (triple <<8) ; i++; } else run = 1; } inb++; inbuf->offset += 1; } if (i == 3 || left == 0) { switch (i) { case 1: triple = triple<<4; break; case 2: triple = triple<<2; break; default : break; } for (; i >= 0; i--) { append_char(outbuf, thqx[0x3f & (triple>>(6*i))], pz); if (linelen == 64) { append_char(outbuf, '\n', pz); outbuf->lineend += 1; linelen = 0; } else { linelen++; } } triple = 0; i = 0; } if (run == 1 && i == 0) { /* fprintf(stderr, "* DOING A EXTRA RUN 0 AT %d.\n", outbuf->bodyend); */ triple = (triple <<8) ; i++; run = 0; } } if (linelen == 0) { outbuf->end -= 1; } append_data(outbuf, ":\n", 2, pz); outbuf->lineend += 1; safe_mchange(m, outbuf); #ifdef DEBUG if (edebug) fprintf(stderr, ", done.\n"); #endif return(OK); } int decode_binhex(struct message *m) { struct data *inbuf, *outbuf; char *inb; unsigned int i; int l; int dl = 0; int left; unsigned short run = 0; unsigned char crun, lrun = '\0'; unsigned long triple; inbuf = m->td; #ifdef DEBUG if (edebug) fprintf(stderr, "* Decode BinHex\n"); #endif inbuf->offset = inbuf->bodystart; logger(LOG_DEBUG, "decode binhex"); /* Exit on empty input */ if (!inbuf->size) return(NOK); /* Initialize working pointers */ inb = inbuf->contents + inbuf->offset; outbuf = (struct data *)Yalloc(sizeof(struct data)); outbuf->encoding = EBINARY; l = 0; /* Look for preamble */ while (isspace(*inb)) { inb++; inbuf->offset += 1; } if (strncmp(inb, "(This file must be converted with BinHex", 40) != 0) { logger(LOG_WARNING, "decode_binhex: BinHex preamble error"); #ifdef DEBUG if (edebug) fprintf(stderr, ", no preamble (failed).\n"); #endif return(NOK); } inb += 40; inbuf->offset += 40; while (*inb != '\n') { inb++; inbuf->offset += 1; } while (1) { int tmpi; tmpi = fhqx[(unsigned char)*inb]; if (tmpi != SKIP) break; inb++; inbuf->offset += 1; } if (*inb != ':') { logger(LOG_WARNING, "decode_binhex: BinHex: No starting colon"); #ifdef DEBUG if (edebug) fprintf(stderr, ", no starting colon (failed).\n"); #endif return(NOK); } inb++; inbuf->offset += 1; /* * Process entire inbuf. */ left = inbuf->end - inbuf->offset; triple = 0; while (left != 0) { left--; i = fhqx[(unsigned char)*inb]; switch(i) { case FAIL: #ifdef DEBUG if (edebug) fprintf(stderr, ", illegal character at %lu : %c (failed).\n", inbuf->offset, *inb); #endif sprintf(ebuf, "ERROR: BinHex: Illegal character: %c\n", *inb); logger(LOG_WARNING, ebuf); return(NOK); case SKIP: break; case DONE: inb++; inbuf->offset += 1; if (*inb != '\n' && *inb != '\r') return(NOK); left = 0; break; default: triple = triple<<6 | (0x3f & i); l++; break; } if (l == 4 || left == 0) { switch(l) { case 2: triple = triple>>4; break; case 3: triple = triple>>2; break; default: break; } if (process || dl < 300) for (l -= 2; l >= 0; l--) { /* Handle run length encoding */ crun = 0xff & (triple>>(l*8)); /* if (crun > 32 && crun < 128) fprintf(stderr, "PROCESSING: %c\n", crun); else fprintf(stderr, "PROCESSING: <%X>\n", crun); */ switch (run) { case 0: if (crun == 0x90) { /* fprintf(stderr, "DETECTED RUN at %d\n", inbuf->offset); */ run = 1; } else { /* if (crun > 31 && crun < 128) fprintf(stderr, "PRINTING: %c\n", crun); else fprintf(stderr, "PRINTING: <%X>\n", crun); */ append_char(outbuf, crun, pz); dl++; lrun = crun; } break; case 1: if (crun == 0) { /* fprintf(stderr, "RUNNING RUN 0 at %d\n", inbuf->offset); */ append_char(outbuf, 0x90, pz); dl++; lrun = 0x90; } else { run = crun; /* fprintf(stderr, "RUNNING RUN %d at %d\n", crun, inbuf->offset); */ while (run > 1) { /* if (crun > 31 && crun < 128) fprintf(stderr, "PRINTING: %c\n", lrun); else fprintf(stderr, "PRINTING: <%X>\n", lrun); */ append_char(outbuf, lrun, pz); dl++; run--; } } run = 0; break; default: /* This should neven occur */ #ifdef DEBUG if (edebug) fprintf(stderr, ", Confused state..."); #endif logger(LOG_DEBUG, "What?: decode_binhex: This should neven occur"); break; } } triple = 0; l = 0; } inb++; inbuf->offset += 1; } if (process) { safe_mchange(m, outbuf); if (get_binhex_binary(m) == OK) { #ifdef DEBUG if (edebug) fprintf(stderr, ", done.\n"); #endif if (match(m->sd->type, "TEXT")) { outbuf->encoding = E7BIT; check_bits(m->td); } else outbuf->encoding = EBINARY; return(OK); } else { m->td = m->sd; return(NOK); } } else { if (dl >= 300) { m->td = outbuf; get_binhex_binary(m); m->td = m->sd; } #ifdef DEBUG if (edebug) fprintf(stderr, ", done.\n"); #endif return(OK); } }