/* ** ** 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" int fromuu[] = { 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, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 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, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, }; int encode_uuencode(struct message *m) { struct data *inbuf, *outbuf; int datalen; int i, l; int left; unsigned long triple; unsigned char *inb; char outb[256]; inbuf = m->td; inbuf->offset = inbuf->bodystart; #ifdef DEBUG if (edebug) fprintf(stderr, "* Encoding UUencode.\n"); #endif logger(LOG_DEBUG, "encode uuencode"); /* Exit on empty input */ if (!inbuf->size) { #ifdef DEBUG if (edebug) fprintf(stderr, "*** Empty input (failed).\n"); #endif return(NOK); } /* Is this first line? */ if (inbuf->offset == 0) datalen = 0; outbuf = (struct data *)Yalloc(sizeof(struct data )); outbuf->encoding = EUUENCODE; /* Initialize working pointers */ inb = inbuf->contents + inbuf->offset; triple = 0; /* Start with uuencode preamble */ fix_filename(m); snprintf(outb, sizeof(outb), "begin 644 %s\n", m->sd->name); append_data(outbuf, outb, strlen(outb), pz); outbuf->lineend += 1; i = 0; left = inbuf->bodyend - inbuf->offset; datalen = (45 < left) ? 45 : left; append_char(outbuf, datalen + ' ', pz); /* * Process entire inbuf. */ while (left != 0) { left--; datalen--; i++; triple = (triple<<8) | *inb; if (i == 3 || datalen == 0) { switch (i) { case 1: triple = triple<<4; break; case 2: triple = triple <<2; break; default: break; } for (l = i; l >= 0; l--) { char tmpi; tmpi = 0x3f & (triple>>(6*l)); append_char(outbuf, (tmpi != 0) ? (tmpi + ' '): '`', pz); } if (datalen == 0) { datalen = (45 < left) ? 45 : left; if (datalen == 0) { switch (i) { case 1: append_data(outbuf, "JJ\n \nend\n", 9, pz); outbuf->lineend += 3; left = 0; break; case 2: append_data(outbuf, "J\n \nend\n", 8, pz); outbuf->lineend += 3; left = 0; break; default: append_data(outbuf, "\n \nend\n", 7, pz); outbuf->lineend += 3; left = 0; break; } } else { append_char(outbuf, '\n', pz); append_char(outbuf, datalen + ' ', pz); outbuf->lineend += 1; } } triple = 0; i = 0; } inb++; inbuf->offset += 1; } safe_mchange(m, outbuf); return(OK); } /* * decode_uuencode() * * Decode an uuencoded encoding */ int decode_uuencode(struct message *m) { struct data *inbuf, *outbuf; char *inb; unsigned int i; int ii; int l; int dl = 0; int datalen; char filename[512]; unsigned long triple; inbuf = m->td; inbuf->offset = inbuf->bodystart; triple = 0; #ifdef DEBUG if (edebug) fprintf(stderr, "* Decoding UUencode.\n"); #endif logger(LOG_DEBUG, "decode uuencode"); /* Exit on empty input */ if (!inbuf->size) { #ifdef DEBUG if (edebug) fprintf(stderr, "*** Empty input (failed).\n"); #endif return(NOK); } outbuf = (struct data *)Yalloc(sizeof(struct data )); outbuf->encoding = EBINARY; inb = inbuf->contents + inbuf->offset; while (isspace(*inb)) { inb++; inbuf->offset += 1; } if ((i = sscanf(inb, "begin%*1[ ]%*3[0-7]%*1[ ]%511s", filename)) != 1) { #ifdef DEBUG if (edebug) fprintf(stderr, "*** Illegal start string at offset %lu (failed).\n",inbuf->offset); #endif sprintf(ebuf, "decode_uuencode: Illegal start string: %d", i); logger(LOG_WARNING, ebuf); return(NOK); } m->sd->name = NEWSTR(filename); /* Set type */ if (m->sd->type == NULL || strcmp(m->sd->type, "APPLICATION") == 0) if ((m->sd->nameext = getextension(filename)) != NULL) if ((m->sd->type = confextr("UUENCODE", m->sd->nameext, NULL)) == NULL) m->sd->type = confextr("UUENCODE", "DEFAULT", NULL); if (m->sd->type == NULL) m->sd->type = NEWSTR("APPLICATION"); inb += 10 + strlen(filename); inbuf->offset += 10 + strlen(filename); inbuf->loffset += 1; l = 0; datalen = 0; /* * Process entire inbuf. */ while (inbuf->offset < inbuf->end) { if (datalen == 0) { while (*inb != '\n') { /* Clean rest of the line */ inb++; inbuf->offset += 1; } /* Skip Line feed */ inb++; inbuf->offset += 1; inbuf->loffset += 1; /* Check for end */ if (strncmp(inb, "end", 3) == 0) { inbuf->offset += getline(inbuf); inbuf->loffset += 1; inbuf->bodyend = inbuf->offset; if (process) { safe_mchange(m, outbuf); if (match(m->sd->type, "TEXT")) { m->td->encoding = E7BIT; check_bits(m->td); } else m->td->encoding = EBINARY; } else if (dl == 6) { m->td = outbuf; check_as_ad(m); m->td = m->sd; } return(OK); } /* Get data length */ if ((datalen = fromuu[(unsigned char)*inb]) < 0) { #ifdef DEBUG if (edebug) fprintf(stderr, "*** Illegal datalen at %lu: %c.\n", inbuf->offset, *inb); #endif sprintf(ebuf, "decode_uuencode: Illegal datalen: %c at offset: %lu", *inb, inbuf->offset); logger(LOG_WARNING, ebuf); return(NOK); } inb++; inbuf->offset += 1; } else { if ((ii = fromuu[(unsigned char)*inb]) < 0) { #ifdef DEBUG if (edebug) fprintf(stderr, "*** Illegal character at %lu: %c.\n", inbuf->offset, *inb); #endif sprintf(ebuf, "decode_uuencode: Illegal character: %c", *inb); logger(LOG_WARNING, ebuf); return(NOK); } triple = triple<<6 | (0x3f & ii); l++; if (l == 4 || l > datalen) { switch(l) { case 2: triple = triple>>4; break; case 3: triple = triple>>2; break; default: break; } for (l -= 2; l >= 0 && datalen != 0; l--, datalen--) if (process || dl < 6) { append_char(outbuf,(char) (0xff & (triple>>(8*l))), pz); dl++; } triple = 0; l = 0; } inb++; inbuf->offset += 1; } } #ifdef DEBUG if (edebug) fprintf(stderr, "*** Premature end of data (failed).\n"); #endif logger(LOG_WARNING, "decode_uuencode: Premature end of data, uudecode failed"); return(NOK); }