/*
**
** 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);
}
}
syntax highlighted by Code2HTML, v. 0.9.1