pkg://emil-2.1.0beta9-789.src.rpm:223473/emil-2.1.0-beta9.tar.gz
info downloads
emil-2.1.0-beta9/ 042755 000000 000000 00000000000 06155036014 013767 5 ustar 00root system 000000 000000 emil-2.1.0-beta9/7bit.c 100644 000000 000000 00000013144 06155035765 015012 0 ustar 00root system 000000 000000 /*
**
** 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"
static unsigned char to_se[256] = {
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,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x21, 0x24, 0x24, 0x24, 0x24, 0x7C, 0x25,
0x22, 0x43, 0x20, 0x3C, 0x2D, 0x2D, 0x52, 0x5E,
0x20, 0x2B, 0x32, 0x33, 0x27, 0x20, 0x20, 0x2A,
0x2C, 0x31, 0x20, 0x3E, 0x20, 0x20, 0x20, 0x3F,
0x41, 0x41, 0x41, 0x41, 0x5B, 0x5D, 0x5B, 0x43,
0x45, 0x40, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x5C, 0x78,
0x5C, 0x55, 0x55, 0x55, 0x5E, 0x59, 0x50, 0x42,
0x61, 0x61, 0x61, 0x61, 0x7B, 0x7D, 0x7B, 0x63,
0x65, 0x60, 0x65, 0x65, 0x69, 0x69, 0x69, 0x69,
0x64, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x7C, 0x20,
0x7C, 0x75, 0x75, 0x75, 0x7E, 0x79, 0x70, 0x79};
static unsigned char to_seu[256] = {
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,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x21, 0x24, 0x24, 0x24, 0x24, 0x7C, 0x25,
0x22, 0x43, 0x20, 0x3C, 0x2D, 0x2D, 0x52, 0x5E,
0x20, 0x2B, 0x32, 0x33, 0x27, 0x20, 0x20, 0x2A,
0x2C, 0x31, 0x20, 0x3E, 0x20, 0x20, 0x20, 0x3F,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43,
0x45, 0x40, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49,
0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x78,
0x4F, 0x55, 0x55, 0x55, 0x5E, 0x59, 0x50, 0x42,
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x63,
0x65, 0x60, 0x65, 0x65, 0x69, 0x69, 0x69, 0x69,
0x64, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x20,
0x6F, 0x75, 0x75, 0x75, 0x7E, 0x79, 0x70, 0x79};
int
to_7bit(struct message *m)
{
char *c;
long offset;
long end;
c = (char *)m->td->contents + m->td->offset;
end = get_length(m->td);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", to 7bit");
#endif
for (offset = 0; offset < end; offset++, c++)
*c = to_se[(unsigned char)*c];
return(OK);
}
int
to_stripped(struct message *m)
{
char *c;
long offset;
long end;
c = (char *)m->td->contents + m->td->offset;
end = get_length(m->td);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", to 7bit");
#endif
for (offset = 0; offset < end; offset++, c++)
*c = to_seu[(unsigned char)*c];
return(OK);
}
int
to_h7bit(struct hprs *m)
{
char *c;
long offset;
long end;
c = (char *)m->td->contents + m->td->offset;
end = get_length(m->td);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", to stripped");
#endif
for (offset = 0; offset < end; offset++, c++)
*c = to_se[(unsigned char)*c];
return(OK);
}
int
to_hstripped(struct hprs *m)
{
char *c;
long offset;
long end;
c = (char *)m->td->contents + m->td->offset;
end = get_length(m->td);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", to stripped");
#endif
for (offset = 0; offset < end; offset++, c++)
*c = to_seu[(unsigned char)*c];
return(OK);
}
2,
0x61, 0x61, 0x61, 0x61, 0x7B, 0x7D, 0x7B, 0x63,
0x65, 0x60, 0x65, 0x65, 0x69, 0x69, 0x69, 0x69,
0x64, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x7C, 0x20,
0x7C, 0x75, 0x75, 0x75, 0x7E, 0x79, 0x70, 0x79};
static unsigned char to_seu[256] = {
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, emil-2.1.0-beta9/appledouble.c 100644 000000 000000 00000020372 06155035765 016442 0 ustar 00root system 000000 000000 /*
**
** 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"
#include <assert.h>
int
get_appledouble_binary(struct message *m)
{
struct data *d;
unsigned long magic;
unsigned long version;
unsigned long filler;
unsigned short entries;
unsigned long doffset;
unsigned long dlength;
int i;
doffset = dlength = 0;
d = m->td;
d->offset = d->bodystart;
/* Check magic number */
if (getlong(&magic, d) == NOK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_appledouble_binary: magic number: short file.\n");
#endif
return(NOK);
}
if (magic != 0x00051607)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_appledouble_binary: Wrong magic number %lX.\n",
magic);
#endif
return(NOK);
}
/* Check version number */
if (getlong(&version, d) == NOK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_appledouble_binary: version number: short file.\n");
#endif
return(NOK);
}
if (version != 0x00020000)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_appledouble_binary: Wrong magic number.\n");
#endif
return(NOK);
}
/* Check filler */
for (i = 0; i < 4; i++)
{
if (getlong(&filler, d) == NOK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_appledouble_binary: filler: short file.\n");
#endif
return(NOK);
}
if (filler != 0x00000000)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_appledouble_binary: Wrong filler.\n");
#endif
return(NOK);
}
}
/* Get entries */
if (getshort(&entries, d) == NOK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_appledouble_binary: entries: short file.\n");
#endif
return(NOK);
}
/* Get entries */
for (i = 0; i < entries; i++)
{
unsigned long entry_id;
unsigned long offset;
unsigned long length;
/* Get entry ID */
if (getlong(&entry_id, d) == NOK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_appledouble_binary: entry ID: short file %lu.\n", d->offset);
#endif
return(NOK);
}
/* Get offset */
if (getlong(&offset, d) == NOK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_appledouble_binary: offset: short file %lu.\n", d->offset);
#endif
return(NOK);
}
/* Get length */
if (getlong(&length, d) == NOK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_appledouble_binary: length: short file %lu.\n", d->offset);
#endif
return(NOK);
}
switch(entry_id)
{
case 1:
/* Data fork */
break;
case 2:
/* Resource fork */
if (length)
{
if (check_length(d, offset + length) != OK)
{
#ifdef DEBUG
if (edebug)
{
fprintf(stderr, "* get_appledouble_binary: resource fork: short file %lu.\n", d->offset);
fprintf(stderr, "* get_appledouble_binary: suggested offset: %lu suggested length: %lu\n", offset, length);
fprintf(stderr, "* get_appledouble_binary: bodystart %lu end %lu\n", d->bodystart, d->bodyend);
}
#endif
return(NOK);
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* Marked up AppleDouble resource fork at offset %lu and size %lu. End is %lu.\n", offset, length, d->bodyend);
#endif
doffset = d->bodystart + offset;
dlength = length;
d->applefile = ADOUBLE;
}
break;
case 3:
/* Name */
if (check_length(d, offset + length) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_appledouble_binary: name: short file %lu.\n", d->offset);
#endif
return(NOK);
}
m->sd->name = (char *)get_string(d, offset, length);
break;
case 4:
/* Comment */
/* Ignore */
break;
case 5:
/* BW icon */
/* Ignore */
break;
case 6:
/* Color icon */
/* Ignore */
break;
case 8:
/* dates */
/* Ignore */
break;
case 9:
/* Finder info */
if (check_length(d, offset + length) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_appledouble_binary: finder info: short file %lu.\n", d->offset);
#endif
return(NOK);
}
m->sd->appletype = get_string(d, offset, 8);
break;
case 10:
/* Mac file info */
/* Ignore */
break;
case 11:
/* ProDOS file info */
/* Ignore */
break;
case 12:
/* MS-DOS file info */
/* Ignore */
break;
case 13:
/* AFP short name */
/* Ignore */
break;
case 14:
/* AFP file info */
/* Ignore */
break;
case 15:
/* AFP directory id */
/* Ignore */
break;
default:
/* Unknown entry ID */
return(NOK);
break;
}
}
d->bodystart = doffset;
d->bodyend = doffset + dlength;
return(OK);
}
int
put_appledouble(struct message *m)
{
struct data *target;
struct data *resource;
int i;
unsigned long offset, nlength, rlength, flength;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* put_appledouble().\n");
#endif
if ((resource = m->td->next) != NULL)
resource->offset = resource->bodystart;
else
{
m->sd->applefile = 0;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "FAILED.\n");
#endif
return(NOK);
}
target = (struct data *)Yalloc(sizeof(struct data));
target->encoding = EBINARY;
macify_filename(m);
/* Add magic number */
append_data(target, makelong((unsigned long)0x00051607, 4), 4, pz);
/* Add version */
append_data(target, makelong((unsigned long)0x00020000, 4), 4, pz);
/* Add filler */
for (i = 0; i < 4; i++)
append_data(target, makelong((unsigned long)0x00000000, 4), 4, pz);
/* Add entries */
append_data(target, makelong((unsigned long)0x0003, 2), 2, pz);
/* Add entries, Offset = 26 */
/* Name */
offset = 62;
append_data(target, makelong((unsigned long)0x00000003, 4), 4, pz);
append_data(target, makelong(offset, 4), 4, pz);
nlength = strlen(m->sd->name);
append_data(target, makelong(nlength, 4), 4, pz);
offset += nlength;
/* Finder info */
append_data(target, makelong((unsigned long)0x00000009, 4), 4, pz);
append_data(target, makelong(offset, 4), 4, pz);
flength = 32;
append_data(target, makelong(flength, 4), 4, pz);
offset += flength;
/* Resource fork */
append_data(target, makelong((unsigned long)0x00000002, 4), 4, pz);
append_data(target, makelong(offset, 4), 4, pz);
rlength = resource->bodyend - resource->bodystart;
append_data(target, makelong(rlength, 4), 4, pz);
/* Add name */
append_data(target, m->sd->name, nlength, pz);
#ifdef DEBUG
if (edebug)
fprintf(stderr, " Creating AppleDouble, name = %s, Type&Creator = %s, Resource fork = %lu\n", m->sd->name, m->sd->appletype, rlength);
#endif
/* Add finder info */
append_data(target, m->sd->appletype, 8, pz);
for (i = 0; i < 6; i++)
append_data(target, makelong((unsigned long)0x00000000, 4), 4, pz);
/* Add resource fork */
append_data(target, resource->contents + resource->bodystart, rlength, pz);
target->encoding = EBINARY;
target->next = m->td;
target->next->next = NULL;
m->td = target;
m->sd->next = (struct data *)Yalloc(sizeof(struct data ));
m->sd->type = NEWSTR("APPLEDOUBLE");
m->sd->applefile = AMDOUBLE;
return(OK);
}
Marked up AppleDouble resource fork at offset %lu and size %lu. End is %lu.\n", offset, length, d->bodyend);
#endif
doffset = d->bodystart + offset;
dlength = length;
d->applefile = ADOUBLE;
}
break;
case 3:
/* Name */
if (chemil-2.1.0-beta9/applefile.c 100644 000000 000000 00000012221 06155035765 016101 0 ustar 00root system 000000 000000 /*
**
** 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
fix_applefile(struct message *m)
{
struct message *mt;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* fix_applefile: ");
#endif
if (check_apple_target(m->sd) == OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "keeping.\n");
#endif
return(NOK);
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, "processing... ");
#endif
if (to_applefile(m) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "FAILED.\n");
#endif
m->sd->applefile = 0;
return(NOK);
}
switch(target->iapple)
{
case ABINHEX:
if (encode_binhex(m) != OK)
return(NOK);
break;
case ASINGLE:
if (put_applesingle(m) != OK)
return(NOK);
break;
case ADOUBLE:
if (put_appledouble(m) != OK)
return(NOK);
mt = (struct message *)Yalloc(sizeof(struct message));
mt->sd = m->sd;
mt->td = m->td;
mt->sdl = m->sdl;
mt->tdl = m->tdl;
mt->level = m->level + 1;
m->sd = (struct data *)Yalloc(sizeof(struct data));
m->sd->encoding = EMULTI;
m->td = m->sd;
m->child = mt;
mt->parent = m;
m->child = (struct message *)split_data_list(m->child);
m->child->sibling->sd->type = m->child->sd->type;
m->child->sibling->sd->name = m->child->sd->name;
m->child->sd->name = (char *)Yalloc(strlen(m->child->sd->name) + 2);
sprintf(m->child->sd->name, "%%%s", m->child->sibling->sd->name);
m->sd->type = NEWSTR("MULTIPART");
m->sd->applefile = AMDOUBLE;
m->child->sd->type = NEWSTR("APPLESINGLE");
break;
default:
#ifdef DEBUG
if (edebug)
fprintf(stderr, "FAILED.\n");
#endif
return(NOK);
break;
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, "SUCCEEDED.\n");
#endif
return(OK);
}
int
to_applefile(struct message *m)
{
struct data *d;
switch(m->sd->applefile)
{
case ABINHEX:
if (decode_binhex(m) == OK)
return(OK);
else
return(NOK);
break;
case AMDOUBLE:
if (decode_double(m->child) != OK)
return(NOK);
if (get_appledouble_binary(m->child) != OK)
return(NOK);
m->td = m->child->sibling->td;
m->td->next = m->child->td;
m->sd->applefile = AFILE;
m->sd->appletype = m->child->sd->appletype;
m->sd->name = m->child->sd->name;
m->td->next->applefile = ARESOURCE;
m->child = NULL;
return(OK);
break;
case ADOUBLE:
if (decode_double(m) != OK)
return(NOK);
if (get_appledouble_binary(m) != OK)
return(NOK);
d = m->td;
m->td = m->sibling->td;
m->td->next = d;
m->td->applefile = AFILE;
m->td->next->applefile = ARESOURCE;
m->sibling = m->sibling->sibling;
return(OK);
break;
case ASINGLE:
if (decode_enc(m) != OK)
return(NOK);
if (get_applesingle_binary(m) != OK)
return(NOK);
else
return(OK);
break;
case AFILE:
return(OK);
break;
case AMFILE:
m->td = m->child->sibling->td;
m->td->next = m->child->td;
m->td->applefile = AFILE;
m->td->next->applefile = ARESOURCE;
m->child = NULL;
return(OK);
break;
default:
#ifdef DEBUG
if (edebug)
fprintf(stderr, "UNKNOWN applefile type.\n");
#endif
return(NOK);
break;
}
return(NOK);
}
int
decode_double(struct message *m)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* decode_double\n");
#endif
if (m->sibling == NULL)
return(NOK);
if (decode_enc(m) != OK)
return(NOK);
if (decode_enc(m->sibling) != OK)
return(NOK);
return(OK);
}
int
decode_enc(struct message *m)
{
m->td->offset = m->td->bodystart;
switch(m->td->encoding)
{
case EUUENCODE:
return(decode_uuencode(m));
break;
case EBASE64:
return(decode_base64(m));
break;
case EBINHEX:
return(decode_binhex(m));
break;
case EQP:
return(decode_quoted_printable(m));
break;
default:
return(NOK);
}
}
ebug)
fprintf(stderr, "FAILED.\n");
#endif
m->sd->applefile = 0;
return(NOK);
}
switch(target->iapple)
{
case ABINHEX:
if (encode_binhex(m) != OK)
return(NOK);
break;
case ASINGLE:
if (put_applesingle(m) != OK)
return(NOK);
break;
case ADOUBLE:
if (put_appledouble(m) != OK)
return(NOK);
mt = emil-2.1.0-beta9/applesingle.c 100644 000000 000000 00000025526 06155035766 016460 0 ustar 00root system 000000 000000 /*
**
** 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"
#include <assert.h>
int
get_applesingle_binary(struct message *m)
{
struct data *d;
struct data *r = NULL;
unsigned long magic;
unsigned long version;
unsigned long filler;
unsigned short entries;
unsigned long doffset;
unsigned long dlength;
int i;
doffset = dlength = 0;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "get_applesingle_binary().\n");
#endif
if ((d = m->td) != NULL)
d->offset = d->bodystart;
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "get_applesingle_binary: empty input.\n");
#endif
return(NOK);
}
/* Check magic number */
if (getlong(&magic, d) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: magic number: short file.\n");
#endif
return(NOK);
}
if (magic != 0x00051600)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: Wrong magic number %lX.\n",
magic);
#endif
return(NOK);
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- get_applesingle_binary: got magic number\n");
#endif
/* Check version number */
if (getlong(&version, d) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: version number: short file.\n");
#endif
return(NOK);
}
if (version != 0x00020000)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: Wrong magic number.\n");
#endif
return(NOK);
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- get_applesingle_binary: got version number\n");
#endif
/* Check filler */
for (i = 0; i < 4; i++)
{
if (getlong(&filler, d) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: filler: short file.\n");
#endif
return(NOK);
}
if (filler != 0x00000000)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: Wrong filler.\n");
#endif
return(NOK);
}
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- get_applesingle_binary: got filler\n");
#endif
/* Get entries */
if (getshort(&entries, d) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: entries: short file.\n");
#endif
return(NOK);
}
if (entries < 1)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: emtpy entries, (failed)\n");
#endif
return(NOK);
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- get_applesingle_binary: got %u entries\n", entries);
#endif
/* Get entries */
for (i = 0; i < entries; i++)
{
unsigned long entry_id;
unsigned long offset;
unsigned long length;
/* Get entry ID */
if (getlong(&entry_id, d) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: entry ID: short file %lu.\n", d->offset);
#endif
return(NOK);
}
/* Get offset */
if (getlong(&offset, d) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: offset: short file %lu.\n", d->offset);
#endif
return(NOK);
}
/* Get length */
if (getlong(&length, d) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: length: short file %lu.\n", d->offset);
#endif
return(NOK);
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- get_applesingle_binary: got entry: id=%lu, offset=%lu, length=%lu\n", entry_id, offset, length);
#endif
switch(entry_id)
{
case 1:
/* Data fork */
doffset = d->bodystart + offset;
dlength = length;
if (check_length(d, doffset + dlength) != OK)
{
#ifdef DEBUG
if (edebug)
{
fprintf(stderr, "* get_applesingle_binary: data fork: short file %lu.\n", d->offset);
fprintf(stderr, "* get_applesingle_binary: suggested offset: %lu suggested length: %lu\n", offset, length);
fprintf(stderr, "* get_applesingle_binary: bodystart %lu end %lu\n", d->bodystart, d->bodyend);
}
#endif
return(NOK);
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* Marked up Applesingle data fork at offset %lu and size %lu. End is %lu.\n", offset, length, d->bodyend);
#endif
break;
case 2:
/* Resource fork */
if (length)
{
if (check_length(d, + offset + length) != OK)
{
#ifdef DEBUG
if (edebug)
{
fprintf(stderr, "* get_applesingle_binary: resource fork: short file %lu.\n", d->offset);
fprintf(stderr, "* get_applesingle_binary: suggested offset: %lu suggested length: %lu\n", offset, length);
fprintf(stderr, "* get_applesingle_binary: bodystart %lu end %lu\n", d->bodystart, d->bodyend);
}
#endif
return(NOK);
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* Marked up Applesingle resource fork at offset %lu and size %lu. End is %lu.\n", offset, length, d->bodyend);
#endif
r = (struct data *)Yalloc(sizeof(struct data));
/* Copied for now */
append_data(r, d->contents + d->bodystart + offset, length, pz);
r->applefile = ARESOURCE;
r->encoding = EBINARY;
d->applefile = AFILE;
}
break;
case 3:
/* Name */
if (check_length(d, offset + length) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: name: short file %lu.\n", d->offset);
#endif
return(NOK);
}
m->sd->name = (char *)Yalloc(length + 1);
bcopy(d->contents + d->bodystart + offset, m->sd->name, length);
break;
case 4:
/* Comment */
/* Ignore */
break;
case 5:
/* BW icon */
/* Ignore */
break;
case 6:
/* Color icon */
/* Ignore */
break;
case 8:
/* dates */
/* Ignore */
break;
case 9:
/* Finder info */
if (check_length(d, offset + length) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: finder info: short file %lu.\n", d->offset);
#endif
return(NOK);
}
if (m->sd->appletype == NULL)
m->sd->appletype = (char *)Yalloc(9);
bcopy(d->contents + d->bodystart + offset, m->sd->appletype, 8);
break;
case 10:
/* Mac file info */
/* Ignore */
break;
case 11:
/* ProDOS file info */
/* Ignore */
break;
case 12:
/* MS-DOS file info */
/* Ignore */
break;
case 13:
/* AFP short name */
/* Ignore */
break;
case 14:
/* AFP file info */
/* Ignore */
break;
case 15:
/* AFP directory id */
/* Ignore */
break;
default:
/* Unknown entry ID */
return(NOK);
break;
}
}
if (dlength != 0)
{
d->bodystart = doffset;
d->bodyend = doffset + dlength;
if ((d->type = (char *)confextr("APPLEFILE", d->appletype, NULL)) == NULL)
if ((d->type = (char *)confextr("APPLEFILE", "DEFAULT", NULL)) == NULL)
d->type = NEWSTR("APPLICATION");
}
else
{
free_data(d);
d = NULL;
}
m->td = d;
d->next = r;
return(OK);
}
int
put_applesingle(struct message *m)
{
struct data *target;
struct data *data;
struct data *resource;
int i;
unsigned long offset, dlength, nlength, rlength, flength;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* put_applesingle()...");
#endif
target = (struct data *)Yalloc(sizeof(struct data));
target->encoding = EBINARY;
macify_filename(m);
if ((data = m->td) != NULL)
data->offset = data->bodystart;
else
return(NOK);
target->type = data->type;
if ((resource = m->td->next) != NULL)
resource->offset = resource->bodystart;
/* Add magic number */
append_data(target, makelong(0x00051600, 4), 4, pz);
/* Add version */
append_data(target, makelong(0x00020000, 4), 4, pz);
/* Add filler */
for (i = 0; i < 4; i++)
append_data(target, makelong(0x00000000, 4), 4, pz);
/* Add entries */
append_data(target, makelong(0x0004, 2), 2, pz);
/* Add entries, Offset = 26 */
/* Name */
offset = 74;
append_data(target, makelong(0x00000003, 4), 4, pz);
append_data(target, makelong(offset, 4), 4, pz);
nlength = strlen(m->sd->name);
append_data(target, makelong(nlength, 4), 4, pz);
offset += nlength;
/* Finder info */
append_data(target, makelong(0x00000009, 4), 4, pz);
append_data(target, makelong(offset, 4), 4, pz);
flength = 32;
append_data(target, makelong(flength, 4), 4, pz);
offset += flength;
/* Data fork */
append_data(target, makelong(0x00000001, 4), 4, pz);
append_data(target, makelong(offset, 4), 4, pz);
dlength = data->bodyend - data->bodystart;
append_data(target, makelong(dlength, 4), 4, pz);
offset += dlength;
/* Resource fork */
append_data(target, makelong(0x00000002, 4), 4, pz);
append_data(target, makelong(offset, 4), 4, pz);
rlength = resource->bodyend - resource->bodystart;
append_data(target, makelong(rlength, 4), 4, pz);
/* Add name */
append_data(target, m->sd->name, nlength, pz);
/* Add finder info */
append_data(target, m->sd->appletype, 8, pz);
for (i = 0; i < 6; i++)
append_data(target, makelong(0x00000000, 4), 4, pz);
/* Add data fork */
append_data(target, data->contents + data->bodystart, dlength, pz);
/* Add resource fork */
append_data(target, resource->contents + resource->bodystart, rlength, pz);
m->td = target;
m->sd->applefile = ASINGLE;
m->sd->type = NEWSTR("APPLESINGLE");
m->td->encoding = EBINARY;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "OK.\n");
#endif
return(OK);
}
/*
* Check for AppleSingle/AppleDouble
*/
void
check_as_ad(struct message *m)
{
struct data *d;
char typer[5];
long ltyper;
d = m->td;
if (d->offset + 4 >= d->end)
return;
bzero(typer, 5);
bcopy(d->contents + d->offset, typer, 4);
ltyper = strtol(typer, NULL, 16);
if (0x0051607 == ltyper)
m->sd->applefile = ADOUBLE;
if (0x0051600 == ltyper)
m->sd->applefile = ASINGLE;
}
ngth) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* get_applesingle_binary: finder info: short file %lu.\n", d->offset);
#endif
return(NOK);
emil-2.1.0-beta9/base64.c 100644 000000 000000 00000014474 06155035766 015241 0 ustar 00root system 000000 000000 /*
**
** 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"
char tob64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int fromb64[] = {
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, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, 0x3e, FAIL, FAIL, FAIL, 0x3f,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
0x3c, 0x3d, FAIL, FAIL, FAIL, SKIP, 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, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, 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, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
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_base64(struct message *m)
{
struct data *inbuf, *outbuf;
int linelen;
int i, l, left;
unsigned long triple;
unsigned char *inb;
inbuf = m->td;
inbuf->offset = inbuf->bodystart;
logger(LOG_DEBUG, "encode base64");
/* Exit on empty input */
if (!inbuf->size)
return(NOK);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Encoding base64");
#endif
linelen = 1;
outbuf = (struct data *)Yalloc(sizeof(struct data ));
outbuf->encoding = EBASE64;
/* Initialize working pointers */
inb = (unsigned char *)inbuf->contents + inbuf->offset;
i = 0;
triple = 0;
left = inbuf->bodyend - inbuf->offset;
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", data length: %d\n", left);
#endif
/*
* Process entire inbuf.
*/
while (left != 0)
{
i++;
left--;
triple = (triple <<8) | *inb;
if (i == 3 || left == 0)
{
switch (i)
{
case 1:
triple = triple<<4;
break;
case 2:
triple = triple<<2;
break;
default:
break;
}
for (l = i; l >= 0; l--)
{
/* register */
int rr; rr = 0x3f & (triple>>(6*l)); assert (rr < 64);
append_char(outbuf, tob64[rr], pz);
if (linelen == 72)
{
append_char(outbuf, '\n', pz);
outbuf->lineend += 1;
linelen = 1;
}
else
{
linelen++;
}
}
if (left == 0)
switch(i)
{
case 2:
append_data(outbuf, "=\n", 2, pz);
break;
case 1:
append_data(outbuf, "==\n", 3, pz);
break;
default:
break;
}
triple = 0;
i = 0;
}
inb++;
inbuf->offset += 1;
}
safe_mchange(m, outbuf);
return(OK);
}
int
decode_base64(struct message *m)
{
struct data *inbuf, *outbuf;
char *inb;
int i;
int l;
int left;
unsigned long triple;
inbuf = m->td;
inbuf->offset = inbuf->bodystart;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Decoding base64 from offset %lu to bodyend %lu\n",
inbuf->offset, inbuf->bodyend);
#endif
logger(LOG_DEBUG, "decode base64");
/* Exit on empty input */
if (!inbuf->size)
return(NOK);
/* Initialize working pointers */
inb = inbuf->contents + inbuf->offset;
if (process)
{
outbuf = (struct data *)Yalloc(sizeof(struct data ));
}
l = 0;
triple = 0;
left = inbuf->bodyend - inbuf->offset;
/*
* Process entire inbuf.
*/
while (left != 0)
{
left--;
i = fromb64[(unsigned char)*inb];
switch(i)
{
case FAIL:
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", illegal char at %lu: %d (failed).\n",
inbuf->offset, *inb);
#endif
sprintf(ebuf, "decode_base64: Illegal character: %d", *inb);
logger(LOG_WARNING, ebuf);
return(NOK);
break;
case SKIP:
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)
for (l -= 2; l >= 0; l--)
{
append_char(outbuf,( 0xff & (triple>>(l*8))), pz);
}
triple = 0;
l = 0;
}
inb++;
inbuf->offset += 1;
}
if (process)
{
safe_mchange(m, outbuf);
if (match(m->sd->type, "TEXT"))
{
outbuf->encoding = E7BIT;
check_bits(m->td);
}
else
outbuf->encoding = EBINARY;
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", done.\n");
#endif
return(OK);
}
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL,emil-2.1.0-beta9/binary.c 100644 000000 000000 00000004547 06155035766 015441 0 ustar 00root system 000000 000000 /*
**
** 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"
void
check_bits(struct data *d)
{
int offset;
unsigned char *c;
#ifdef DEBUG
int deb = 1;
if (edebug)
fprintf(stderr, "check_bits: encoding is set to %d, start %lu end %lu\n", d->encoding, d->bodystart, d->bodyend);
#endif
if (d->encoding == 0)
d->encoding = E7BIT;
if (d->encoding == E7BIT)
{
for (offset = d->bodystart, c = d->contents + offset;
offset < d->bodyend;
offset++, c++)
{
if (*c == '\0')
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- checked 7bit, saw binary.\n");
#endif
d->encoding = EBINARY;
return;
}
if (*c & 0x80)
{
#ifdef DEBUG
if (edebug && deb)
{
fprintf(stderr, "- checked 7bit, saw 8bit.\n");
deb = 0;
}
#endif
d->encoding = E8BIT;
}
}
return;
}
if (d->encoding == E8BIT)
{
for (offset = d->bodystart, c = d->contents + offset;
offset < d->bodyend;
offset++, c++)
{
if (*c == '\0')
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- checked 8bit, saw binary.\n");
#endif
d->encoding = EBINARY;
return;
}
}
}
return;
}
a(outbuf, "==\n", 3, pz);
break;
default:
break;
}
triple = 0;
i = 0;
}
inb++;
inbuf->offset += 1;
}
safe_mchaemil-2.1.0-beta9/binhex.c 100644 000000 000000 00000023033 06155035766 015421 0 ustar 00root system 000000 000000 /*
**
** 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);
}
}
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 preamblemil-2.1.0-beta9/buffer.c 100644 000000 000000 00000005557 06155035767 015431 0 ustar 00root system 000000 000000 /*
**
** 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"
extern long memall;
void
safe_mchange(struct message *m, struct data *d)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* safe_mchange: ");
#endif
if (m == NULL || d == NULL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Null input, ignoring...\n");
#endif
return;
}
m->td->type = m->sd->type;
m->td->name = m->sd->name;
m->td->nameext = m->sd->nameext;
if (d->appletype != NULL)
bcopy(d->appletype, m->td->appletype, 9);
m->td->description = m->sd->description;
if (m->td == d)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Pointers identical, ignoring...\n");
#endif
return;
}
if (d->contents != NULL && (memcmp(m->td->contents + m->td->bodystart,
d->contents,
m->td->bodyend - m->td->bodystart) == 0))
{
if (d->charset != NULL)
m->td->charset = NEWSTR(d->charset);
m->td->encoding = d->encoding;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Data identical, ignoring...\n");
#endif
(void)free_data(d);
return;
}
if (m->td != m->sd)
{
(void)free_data(m->td);
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Data has been exchanged. Old size was %lu, new size is %lu\n",
m->td->bodyend - m->td->bodystart,
d->bodyend - d->bodystart);
#endif
m->td = d;
return;
}
void
free_data(struct data *d)
{
/* Get rid of contents, leave the rest */
if (d == NULL)
return;
#ifdef DEBUG
alloc_total -= d->size;
if (edebug)
{
fprintf(stderr, "* Freed %lu, new total %lu\n", d->size, alloc_total);
fflush(stderr);
}
#endif
if (d->contents != NULL)
free(d->contents);
memall -= d->size;
}
"* safe_mchange: ");
#endif
if (m == NULL || d == NULL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Null input, ignoring...\n");
#emil-2.1.0-beta9/convert.c 100644 000000 000000 00000015110 06155035767 015622 0 ustar 00root system 000000 000000 /*
**
** 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
convert_applefile(struct message *m)
{
if (fix_applefile(m) == OK)
return(OK);
else
if (m->child != NULL)
{
logger(LOG_DEBUG, "convert_applefile: Converting child");
(void) convert_applefile(m->child);
}
if (m->sibling != NULL)
{
logger(LOG_DEBUG, "convert_data: Converting sibling");
(void) convert_applefile(m->sibling);
}
return(OK);
}
int
convert_data(struct message *m)
{
int status;
if (target == NULL || source == NULL)
return(NOK);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* Converting bodypart %d at level: %d and type %s\n Starting at offset %lu, ending at %lu\n",
m->sd->count,
m->level,
m->sd->type==NULL?"<NULL>":m->sd->type,
m->sd->bodystart,
m->sd->bodyend);
#endif
if (m->sd->type == NULL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ no type (TEXT)\n");
#endif
m->sd->type = NEWSTR("TEXT");
}
/* Start at the beginning */
m->td->offset = m->td->bodystart;
/* Check for 8bit data */
if (m->td->encoding == E7BIT)
check_bits(m->td);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* Recoding data\n");
#endif
while ((status = recode_data(m)) == CONT)
m->td->offset = m->td->bodystart;
;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* Encode header\n");
#endif
encode_header(m);
/* Recursion over children and siblings */
if (m->child != NULL)
{
logger(LOG_DEBUG, "convert_data: Converting child");
(void) convert_data(m->child);
}
if (m->sibling != NULL)
{
logger(LOG_DEBUG, "convert_data: Converting sibling");
(void) convert_data(m->sibling);
}
return(OK);
}
int
recode_data(struct message *m)
{
int tari;
if (match(m->sd->type, "TEXT") && m->td->encoding != EBINARY)
tari = target->itext;
else
tari = target->ibin;
switch(m->td->encoding)
{
case E7BIT:
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- is 7bit\n");
#endif
if (m->td->charset == NULL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* no charset (US-ASCII)");
#endif
m->td->charset = source->charset == NULL ? NEWSTR("US-ASCII") :
source->charset;
}
if (tocharset(m) == OK)
check_bits(m->td);
if (m->td->encoding != E7BIT)
return(CONT);
/* Default */
return(DONE);
break;
case E8BIT:
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- is 8bit\n");
#endif
if (m->td->charset == NULL)
{
m->td->charset = source->charset == NULL ? NEWSTR("ISO-8859-1") :
source->charset;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* no charset (%s)\n", m->td->charset);
#endif
}
if (tocharset(m) == OK) /* Handle charset conversion first */
check_bits(m->td);
if (m->td->encoding != E8BIT)
return(CONT);
/* Convert to target encoding */
switch (tari)
{
case EQP:
encode_quoted_printable(m);
break;
case EBINHEX:
encode_binhex(m);
break;
case EUUENCODE:
encode_uuencode(m);
break;
case EBASE64:
encode_base64(m);
break;
default:
break;
}
return(DONE);
break;
case EQP:
/* Convert to target charset and possibly decode or encode
* to quoted-printable.
*/
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- is qp\n");
#endif
if (tari != EQP ||
((target->charset != NULL) &&
(cmatch(target->charset, m->sd->charset) == FALSE)))
{
if (decode_quoted_printable(m) == OK)
{
check_bits(m->td);
return(CONT);
}
return(FAIL);
}
else
return(DONE);
break;
case EBINARY:
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- is binary\n");
#endif
switch(tari)
{
case EBINHEX:
encode_binhex(m);
return(DONE);
break;
case EUUENCODE:
encode_uuencode(m);
return(DONE);
break;
case EBASE64:
encode_base64(m);
return(DONE);
break;
default:
/* Fail */
m->td = m->sd;
return(FAIL);
break;
}
break;
case EBINHEX:
/* Check if source and target binary format is equal
* Else convert here
*/
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- is BinHex\n");
#endif
if (m->sd->applefile != 0)
return(DONE);
if (tari != EBINHEX)
{
if (decode_binhex(m) == OK)
return(CONT);
return(FAIL);
}
else
return(DONE);
break;
case EUUENCODE:
/* Check if source and target binary format is equal
* Else convert here
*/
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- is UUencode\n");
#endif
if (tari != EUUENCODE)
{
if (decode_uuencode(m) == OK)
return(CONT);
else
return(FAIL);
}
else
return(DONE);
break;
case EBASE64:
/* Check if source and target binary format is equal
* Else convert here
*/
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- is base64\n");
#endif
if (tari != EBASE64)
{
if (decode_base64(m) == OK)
return(CONT);
return(FAIL);
}
else
return(DONE);
break;
case EMULTI:
#ifdef DEBUG
if (edebug)
fprintf(stderr, "- is multi\n");
#endif
/* This is not convertable */
return(DONE);
break;
default:
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* is unknown (skip or check)\n");
#endif
/* Ignore, possibly some error has occurred */
check_bits(m->td);
return(FAIL);
break;
}
return(FAIL);
}
ver children and siblings */
if (m->child != NULL)
{
logger(LOG_DEBUG, "convert_data: Converting child");
(void) convert_data(m->child);
}
if (m->sibling != NULL)
{
logger(LOG_DEBUG, "convert_data: Converting sibling");
(void) convert_data(m->sibling);
}
return(OK);
}
int
recode_data(struct message *m)
{
int tari;
if (match(m->sd->type, "TEXT") && m->td->encoding != EBINARY)
tari = emil-2.1.0-beta9/filenames.c 100644 000000 000000 00000007050 06155035767 016111 0 ustar 00root system 000000 000000 /*
**
** 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"
void
macify_filename(struct message *m)
{
char *name;
char *appletype;
if (m->sd->name == NULL)
m->sd->name = NEWSTR("noname");
fix_filename(m);
for (name = m->sd->name; *name != '\0'; name++)
{
switch (*name)
{
case ':':
*name = '-';
break;
default:
break;
}
if (*name & 0x80)
*name = '_';
}
if (m->sd->appletype == NULL)
{
m->sd->appletype = (char *)Yalloc(9);
if (m->sd->type == NULL)
strncpy(m->sd->appletype, "AURL ", 8);
else
{
if ((appletype = confextr("APPLEFILE", NULL, m->sd->type)) == NULL)
if ((appletype = confextr("APPLEFILE", NULL, "DEFAULT")) == NULL)
strncpy(m->sd->appletype, "AURL ", 8);
if (appletype != NULL)
strncpy(m->sd->appletype, appletype, 8);
}
}
}
void
dosify_filename(struct message *m)
{
char *name;
char *extension;
int i;
if (m->sd->name == NULL)
return;
fix_filename(m);
extension = (char *)getextension(m->sd->name);
for (name = m->sd->name, i = 0; *name != '\0'; name++, i++)
{
if ((name + 1 == extension) || i == 8)
break;
switch (*name)
{
case '\\':
*name = '-';
break;
case '.':
*name = '-';
default:
break;
}
if (*name & 0x80)
*name = '_';
}
}
void
unixify_filename(struct message *m)
{
char *name;
if (m->sd->name == NULL)
return;
fix_filename(m);
for (name = m->sd->name; *name != '\0'; name++)
{
switch (*name)
{
case '/':
*name = '-';
break;
default:
break;
}
if (*name & 0x80)
*name = '_';
}
}
char *
getextension(char *inb)
{
char *c;
c = NULL;
if (inb == NULL)
return(NULL);
for (; *inb != '\0'; inb++)
if (*inb == '.')
c = inb;
return(c);
}
void fix_filename(struct message *m)
{
char *extension, *name;
extension = getextension(m->sd->name);
if (m->sd->name == NULL)
m->sd->name = NEWSTR("noname");
if (m->sd->type != NULL)
if ((m->sd->nameext = confextr("UUENCODE", NULL, m->sd->type)) == NULL)
m->sd->nameext = confextr("UUENCODE", NULL, "DEFAULT");
if (m->sd->nameext == NULL)
return;
if (extension == NULL || cmatch(m->sd->nameext, extension) == FALSE)
{
name = (char *)Yalloc(strlen(m->sd->name) + strlen(m->sd->nameext) + 2);
sprintf(name, "%s%s", m->sd->name, m->sd->nameext);
}
return;
}
ITS
** P.O. Box 887
** S-751 08 Uppsala
** Sweden
**
*/
#include "emil.h"
void
macify_filename(struct message *m)
{
char *name;
char *appletype;
if (m->sd->name == NULL)
m->sd->name = NEWSTR("noname");
fix_filename(m);
for (name = m->sd->name; *name != '\0'; name++)
{
switch (*name)
{
case ':':
*name = '-';
emil-2.1.0-beta9/forks.c 100644 000000 000000 00000010413 06155035767 015267 0 ustar 00root system 000000 000000 /*
**
** 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"
#include <fcntl.h>
extern int pseudo_route;
static int fd[2];
void
do_fork()
{
/* int pgrp; */
char *precipient;
if (pipe(fd) != 0)
{
logger(LOG_ERR, "Unable to create pipe\n");
closelog();
fprintf(stderr, "Emil: Unable to create pipe\n");
exit(EX_OSERR);
}
if (fork() == 0)
{
/* Child */
int dev;
{
/* setpgrp(0, pgrp); */
if (close(0) == -1) {
logger(LOG_ERR, "close child failed \n");
fprintf(stderr, "Emil: Close child failed\n");
exit(EX_IOERR);
}
if (dup(fd[0]) == -1) {
logger(LOG_ERR, "dup 1 failed\n");
fprintf(stderr, "Emil: dup 1 failed\n");
exit(EX_OSERR);
}
if (close(fd[0]) == -1 || close(fd[1]) == -1) {
logger(LOG_ERR, "close 1 failed\n");
fprintf(stderr, "Emil: Close 1 failed\n");
exit(EX_IOERR);
}
if (close(1) == -1)
{
logger(LOG_ERR, "close 2 failed\n");
fprintf(stderr, "Emil: Close 2 failed\n");
exit(EX_IOERR);
}
if ((dev = open("/dev/null", O_WRONLY)) == -1)
{
logger(LOG_ERR, "open /dev/null failed\n");
fprintf(stderr, "Emil: Open /dev/null failed\n");
exit(EX_NOPERM);
}
if (dup(dev) == -1) {
logger(LOG_ERR, "dup 2 failed\n");
fprintf(stderr, "Emil: Dup 2 failed\n");
exit(EX_OSERR);
}
if (close(2) == -1)
{
logger(LOG_ERR, "close 3 failed\n");
fprintf(stderr, "Emil: Close 3 failed\n");
exit(EX_IOERR);
}
if (dup(dev) == -1) {
logger(LOG_ERR, "dup 3 failed\n");
fprintf(stderr, "Emil: Dup 3 failed\n");
exit(EX_OSERR);
}
if (close(dev) == -1)
{
logger(LOG_ERR, "close 3 failed\n");
fprintf(stderr, "Emil: Close 3 failed\n");
exit(EX_IOERR);
}
precipient = (char *)Yalloc(strlen(recipient) + 8);
if (pseudo_route == 1)
sprintf(precipient, "@EMIL:%s", recipient);
else
sprintf(precipient, "%s", recipient);
execv(mailer[0], &mailer[1]);
closelog();
fprintf(stderr, "Emil: Reached unreachable in forks.c\n");
exit(EX_UNAVAILABLE);
}
}
else
/* Parent */
{
if (close(fd[0]) == -1) {
logger(LOG_ERR, "close 4 failed\n");
closelog();
fprintf(stderr, "Emil: Close 4 failed\n");
exit(EX_IOERR);
}
if (close(1) == -1) {
logger(LOG_ERR, "close 5 failed\n");
closelog();
fprintf(stderr, "Emil: Close 5 failed\n");
exit(EX_IOERR);
}
if (dup(fd[1]) == -1)
{
logger(LOG_ERR, "dup 4 failed");
closelog();
fprintf(stderr, "Emil: Dup 4 failed\n");
exit(EX_OSERR);
}
}
}
int
end_fork()
{
/* Cleanup after fork */
int status;
if (close(1) == -1) {
logger(LOG_ERR, "close 6 failed\n");
closelog();
fprintf(stderr, "Emil: Close 6 failed\n");
exit(EX_IOERR);
}
if (close(fd[1]) == -1) {
logger(LOG_ERR, "close 7 failed\n");
closelog();
fprintf(stderr, "Emil: Close 7 failed\n");
exit(EX_IOERR);
}
closelog();
wait(&status);
if (status == -1)
exit(EX_SOFTWARE);
if ((status & 0377) != 0)
exit(EX_TEMPFAIL);
/* normal death -- return status */
status = (status >> 8) & 0377;
exit(status);
}
{
if ((name + 1 == extension) || i == 8)
break;
switch (*name)
{
case '\\':
*name = '-';
break;
case '.':
*name = '-';
default:
break;
}
if (*name & 0x80)
*name = '_';
}
}
void
unixify_filename(struemil-2.1.0-beta9/format.c 100644 000000 000000 00000030713 06155035770 015432 0 ustar 00root system 000000 000000 /*
**
** 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"
/*
*
*/
/*
* void
* encode_header()
*
*/
void
encode_header(struct message *m)
{
switch(target->iformat)
{
case MIME:
encode_mime(m);
break;
case MAILTOOL:
encode_mailtool(m);
break;
default:
encode_rfc822(m);
break;
}
}
/*
* void
* decode_header()
*
* Parses the header of current message.
*/
void
decode_header(struct message *m)
{
struct data *d;
d = m->sd;
if (m->h == NULL)
{
logger(LOG_DEBUG, "decode_header: empty header");
return;
}
/**
** m->level 0 specifics
**/
if (m->level == 0)
{
if (matchheader(m, "Content-Conversion", "Prohibited", 0))
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Content conversion prohibited.\n");
#endif
det_sket_sig = TRUE;
return;
}
}
if (decode_mime(m) != OK)
{
if (decode_mailtool(m) != OK)
{
decode_rfc822(m);
}
}
}
/*
* char *
* fixstring(STRING, BEFORE, AFTER, PROCESS)
*
* Process STRING according to PROCESS (UNQUOTE, UNSPACE) and return
* the merged BEFORE, STRING and AFTER.
*/
char *
fixstring(char *string, char *before, char *after, short process)
{
char *tmp1, *tmp2;
int slen, blen, alen;
if (string == NULL)
return(NULL);
if (*string != '\0' && (process & UNSPACE))
{
tmp1 = string;
while(*tmp1 == ' ' || *tmp1 == '\t')
tmp1++;
if (*tmp1 != '\0')
{
tmp2 = tmp1 + strlen(tmp1) - 1;
while (*tmp2 == ' ' || *tmp2 == '\t')
tmp2--;
tmp2++;
*tmp2 = '\0';
}
string = tmp1;
}
if (*string != '\0' && (process & UNQUOTE) )
{
tmp1 = string;
if (*tmp1 == '"')
{
tmp1++;
tmp2 = string + strlen(string) - 1;
if (*tmp2 == '"')
{
*tmp2 = '\0';
string = tmp1;
}
}
}
if (*string != '\0')
slen = strlen(string);
else
slen = 0;
if (before != NULL && *before != '\0')
blen = strlen(before);
else
blen = 0;
if (after != NULL && *after != '\0')
alen = strlen(after);
else
alen = 0;
tmp1 = (char *)Yalloc(blen + slen + alen + 1);
if (blen)
strcpy(tmp1, before);
if (slen)
strcat(tmp1, string);
if (alen)
strcat(tmp1, after);
return(tmp1);
}
/*
* bool
* matchheader(HFIELD, HVAL)
*
* If header HFIELD is available, matches HVAL against the value
* of the header. Returns TRUE on success and FALSE on failure.
*/
int
matchheader(struct message *m, char *hfield, char *hval, int format)
{
struct header *hdr;
if (hfield == NULL || hval == NULL)
return(FALSE);
for (hdr = m->h; hdr != NULL; hdr = hdr->next)
{
if (hdr->type != UNIXFROM && hdr->field->end != 0 &&
(cmatch(hdr->field->contents, hfield) == TRUE))
{
if (matchhvalue(hdr, hval))
/* if (hdr->value->end != 0 &&
(cmatch(hdr->value->contents, hval) == TRUE))
*/
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* matchhvalue success\n");
#endif
hdr->format = format;
return(TRUE);
}
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* matchhvalue failed\n");
#endif
return(FALSE);
}
}
}
return(FALSE);
}
int
matchhvalue(struct header *hdr, char *line)
{
static struct header *th = NULL;
if (th == NULL)
{
th = (struct header *)Yalloc(sizeof(struct header));
th->field = (struct data *)Yalloc(sizeof(struct data));
th->value = (struct data *)Yalloc(sizeof(struct data));
}
else
{
th->field->end = 0;
th->value->end = 0;
th->value->offset = 0;
th->hvalue = NULL;
}
append_data(th->field, hdr->field->contents, strlen(hdr->field->contents),
256);
append_data(th->value, line, strlen(line),
256);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* matchhvalue: %s: matching %s with %s\n",
hdr->field->contents,
hdr->value->contents,
line);
#endif
if (parse_rfc1522(th) != OK)
return(0);
if (parse_rfc1522(hdr) != OK)
return(0);
return(compare_header(hdr->hvalue, th->hvalue));
}
int
compare_header(struct hprs *dirty, struct hprs *clean)
{
if (clean == NULL && dirty == NULL)
return(0);
if (clean == NULL || clean->type != DELIMITER)
{
while(dirty != NULL && dirty->type == DELIMITER)
dirty = dirty->sibling;
if (dirty == NULL)
{
if (clean == NULL)
return(0);
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* compare_header: dirty unexpected end\n");
#endif
return(0);
}
}
}
while(dirty->type == COMMENT)
dirty = dirty->sibling;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* compare_header: trying match between %d and %d\n",
dirty->type, clean->type);
#endif
switch (clean->type)
{
case UNKNOWN:
if (dirty->type != UNKNOWN)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* compare_header: clean type is UNKNOWN\n");
#endif
return(0);
}
break;
case COMMENT:
break;
case HQSTRING:
if (dirty->type != HQSTRING)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* compare_header: expecting COMMENT got %d\n",
dirty->type);
#endif
return(0);
}
break;
case DLITERAL:
if (dirty->type != DLITERAL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* compare_header: expecting DLITERAL got %d\n",
dirty->type);
#endif
return(0);
}
break;
case RADDR:
if (dirty->type != RADDR)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* compare_header: expecting RADDR got %d\n",
dirty->type);
#endif
return(0);
}
break;
case RFC1522:
if (dirty->type != RFC1522)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* compare_header: expecting RFC1522 got %d\n",
dirty->type);
#endif
return(0);
}
break;
case ATOM:
if (dirty->type != ATOM)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* compare_header: expecting ATOM got %d\n",
dirty->type);
#endif
return(0);
}
/* MW 960517
if (dmatch(clean->sd, dirty->sd) == 0)
return(0);
*/
if (dmatch(clean->sd, dirty->sd) != 0)
return(1);
break;
case DELIMITER:
if (dirty->type != DELIMITER)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* compare_header: expecting DELIMITER got %d\n",
dirty->type);
#endif
return(0);
}
break;
case TEXT:
if (dirty->type != TEXT)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* compare_header: expecting TEXT got %d\n",
dirty->type);
#endif
return(0);
}
clean = clean->child;
dirty = dirty->child;
return(compare_header(dirty, clean));
break;
default:
break;
}
/* clean = clean->sibling; */
dirty = dirty->sibling;
return(compare_header(dirty, clean));
}
int
dmatch(struct data *a, struct data *b)
{
int alen, blen;
alen = a->bodyend - a->bodystart;
blen = b->bodyend - b->bodystart;
if (alen == 0 || alen != blen)
{
#ifdef DEBUG
if (edebug)
{
fprintf(stderr, "* dmatch: lengths differ: %d %d\n",
alen, blen);
fprintf(stderr, "* dmatch: tried to compare %s and %s\n",
a->contents, b->contents);
}
#endif
return(0);
}
if (strncasecmp(a->contents + a->bodystart, b->contents + b->bodystart, alen) != 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* dmatch: %s and %s does not match\n",
a->contents + a->bodystart, b->contents + b->bodystart);
#endif
return(0);
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* dmatch: %s and %s does match\n",
a->contents + a->bodystart, b->contents + b->bodystart);
#endif
return(1);
}
/*
* char *
* gethval(HFIELD)
*
* If header HFIELD is available, returns the corresponding value
* as a string. Returns NULL on failure.
*/
char *
gethval(struct message *m, char *hfield, int format)
{
struct header *hdr;
if (hfield == NULL)
return(NULL);
for (hdr = m->h; hdr != NULL; hdr = hdr->next)
{
if (hdr->type != UNIXFROM && hdr->field->end != 0 &&
cmatch(hdr->field->contents, hfield) == TRUE)
{
if (format)
hdr->format = format;
return(hdr->value->contents);
}
}
return(NULL);
}
/*
* int
* string2dec(STRING)
*
* If STRING is not NULL and not of m->length zero and consists of 0-9,
* returns the translation to an integer. Returns 0 on failure.
*/
int
string2dec(char *string)
{
if (string == NULL)
return(0);
return((int)atol(string));
}
/*
* char *
* stringpart(STRING, DEL, PARTNO)
*
* Delimits STRING by DEL and returns part number PARTNO, where
* parts start with zero for the first part and so on. Returns
* NULL on failure.
*/
char *
stringpart(char *string, char *del, int partno)
{
char *str, *start;
int slen;
int i = 0;
if (string == NULL || del == NULL)
return(string);
slen = strlen(string);
str = (char *)NEWSTR(string);
start = str;
/* Loop on string */
while (1)
{
/* Delimit string */
while (*str != '\0' && index(del, *str) == NULL)
{
str++;
slen--;
}
*str = '\0';
if (i == partno)
return(start);
else
{
if (!slen)
break;
str++;
slen--;
start = str;
}
i++;
}
return(NULL);
}
/*
* bool
* matchpart(STRING1, STRING2, DEL, PARTNO)
*
* Delimits STRING2 by DEL and and matches part number PARTNO with
* STRING1. Returns TRUE on success and FALSE on failure.
*/
int
matchpart(char *string1, char *string2, char *del, int partno)
{
char *str, *start;
int i = 0;
if (string1 == NULL || string2 == NULL || del == NULL)
return(FALSE);
str = NEWSTR(string1);
start = str;
for (; str != '\0' && i <= partno; str++)
{
if (index(del, *str) != NULL)
{
*str = '\0';
if (i == partno && cmatch(start, string2) == TRUE)
{
return(TRUE);
}
else
{
str++;
start = str;
}
i++;
}
}
return(FALSE);
}
/*
* char *
* getpartrest(STRING, MATCH, DEL)
*
* Delimits STRING by DEL and tries MATCH on every part returns the
* unmatched part of the part matched.
*/
char *
getpartrest(char *string, char *matchstr, char *del)
{
char *str, *start;
int mlen, slen;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "\ngetpartrest: string: %s matchstr: %s, del: %s\n",
string, matchstr, del);
#endif
if (string == NULL || matchstr == NULL || del == NULL)
return(NULL);
if ((mlen = strlen(matchstr)) == 0 || (slen = strlen(string)) == 0)
return(NULL);
str = (char *)NEWSTR(string);
start = str;
while (1)
{
/* Delimit string */
if (!slen)
return(NULL);
while (*str != '\0' && *del != *str)
{
str++;
slen--;
if (!slen)
break;
}
*str = '\0';
while (isspace(*start))
start++;
if (strncasecmp(matchstr, start, mlen) == 0)
return(start + mlen);
else
{
if (!slen)
break;
str++;
slen--;
start = str;
}
}
return(NULL);
}
/*
* int
* match(string1, string2)
*
* Case sensitive match
*/
int
match(char *string1, char *string2)
{
if (string1 == NULL || string2 == NULL)
return(FALSE);
if (strcmp(string1, string2) == 0)
return(TRUE);
else
return(FALSE);
}
/*
* int
* cmatch(string1, string2)
*
* Case insensitive match
*/
int
cmatch(char *string1, char *string2)
{
if (string1 == NULL || string2 == NULL)
return(FALSE);
if (strcasecmp(string1, string2) == 0)
return(TRUE);
else
return(FALSE);
}
%s does not match\n",
a->contents + a->bodystart, bemil-2.1.0-beta9/hbase64.c 100644 000000 000000 00000013665 06155035770 015405 0 ustar 00root system 000000 000000 /*
**
** 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"
static char tob64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static int fromb64[] = {
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, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, 0x3e, FAIL, FAIL, FAIL, 0x3f,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
0x3c, 0x3d, FAIL, FAIL, FAIL, SKIP, 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, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, 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, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
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
h_to_base64(struct hprs *h)
{
struct data *inbuf, *outbuf;
int linelen;
int i, l, left;
unsigned long triple;
unsigned char *inb;
inbuf = h->td;
/* Exit on empty input */
if (!inbuf->size)
return(NOK);
linelen = 0;
outbuf = (struct data *)Yalloc(sizeof(struct data ));
outbuf->encoding = EBASE64;
outbuf->charset = h->td->charset;
if (outbuf->charset == NULL)
{
logger(LOG_DEBUG, "h_to_base64: No charset in header");
return(NOK);
}
append_data(outbuf, "=?", 2, HEAD_BUF);
append_data(outbuf, outbuf->charset, strlen(outbuf->charset), HEAD_BUF);
append_data(outbuf, "?B?", 3, HEAD_BUF);
/* Initialize working pointers */
inb = (unsigned char *)inbuf->contents + inbuf->offset;
i = 0;
triple = 0;
left = inbuf->bodyend - inbuf->offset;
/*
* Process entire inbuf.
*/
while (left > 0)
{
left--;
i++;
triple = (triple <<8) | *inb;
if (i == 3 || left == 0)
{
switch (i)
{
case 1:
triple = triple<<4;
break;
case 2:
triple = triple<<2;
break;
default:
break;
}
for (l = i; l >= 0; l--)
{
/* register */
int rr; rr = 0x3f & (triple>>(6*l)); assert (rr < 64);
append_char(outbuf, tob64[rr], HEAD_BUF);
if (linelen == 72)
{
append_char(outbuf, '\n', HEAD_BUF);
outbuf->lineend += 1;
linelen = 0;
}
else
{
linelen++;
}
}
if (left == 0)
switch(i)
{
case 2:
append_data(outbuf, "=", 1, HEAD_BUF);
break;
case 1:
append_data(outbuf, "==", 2, HEAD_BUF);
break;
default:
break;
}
triple = 0;
i = 0;
}
inb++;
inbuf->offset += 1;
}
append_data(outbuf, "?=", 2, HEAD_BUF);
h->type = RFC1522;
h->td = outbuf;
return(OK);
}
int
h_from_base64(struct hprs *h)
{
struct data *inbuf, *outbuf;
char *inb;
int i;
int l;
int left;
unsigned long triple;
inbuf = h->td;
/* Exit on empty input */
if (!inbuf->size)
return(NOK);
inbuf->offset = h->pstart;
/* Initialize working pointers */
inb = inbuf->contents + inbuf->offset;
outbuf = (struct data *)Yalloc(sizeof(struct data ));
outbuf->encoding = EBINARY;
l = 0;
triple = 0;
left = h->pend - inbuf->offset;
/*
* Process entire inbuf.
*/
while (left != 0)
{
left--;
i = fromb64[(unsigned char)*inb];
switch(i)
{
case FAIL:
sprintf(ebuf, "h_from_base64: Illegal character: %c", *inb);
logger(LOG_WARNING, ebuf);
return(NOK);
break;
case SKIP:
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;
}
for (l -= 2; l >= 0; l--)
{
append_char(outbuf,( 0xff & (triple>>(l*8))), HEAD_BUF);
}
triple = 0;
l = 0;
}
inb++;
inbuf->offset += 1;
}
h->td = outbuf;
h->type = ATOM;
return(OK);
}
FAIL,
FAIL, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
0x21, 0x22, 0x23, emil-2.1.0-beta9/header.c 100644 000000 000000 00000021274 06155035770 015374 0 ustar 00root system 000000 000000 /*
**
** 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"
#define HQUOTE -1
/* Function definitions */
void process_header_line(struct header *, char *);
void save_header(struct message *, struct data *, short, int);
void clear_end(struct data *);
void add_header_item();
void add_header_delimiter();
static void code_header(struct header *);
static void code_hvalue(struct hprs *, struct data *);
int isheader(char *);
/*
*
*/
int
load_header(struct message *m)
{
struct data *line_buf;
struct data *indata;
int linelen;
long startoffset;
long startline;
char *buf;
indata = m->sd;
line_buf = (struct data *)Yalloc(sizeof (struct data));
/*
* Make sure there is data to process, else exit.
*/
if (indata->end <= indata->offset)
return(OK);
startoffset = indata->offset;
startline = indata->loffset;
/*
* If current header is not empty, look for folded header lines.
*/
while (1)
{
buf = indata->contents + indata->offset;
if ((linelen = getline(indata)) == 0)
{
/* End of data, illegal header */
indata->offset = startoffset; /* Rewind */
indata->loffset = startline; /* Rewind */
m->h = NULL;
return(NOK);
}
#ifdef DEBUG
if (edebug)
{
fprintf(stderr, "Read: ");
fwrite(indata->contents + indata->offset, 1, linelen, stderr);
}
#endif
indata->loffset += 1;
if ((*buf == ' ' || *buf == '\t') && line_buf->end != 0)
{
/* Unfold header line and append to previos line */
/* clear_end(line_buf); */
append_data(line_buf, buf, linelen, HEAD_BUF);
}
else
/* Not folded yet */
{
if (line_buf->end != 0)
/* If no header line yet, append header line */
/* Already got header line */
{
if (strncasecmp(line_buf->contents, "from ", 5) == 0 ||
strncasecmp(line_buf->contents,">from ", 6) == 0)
{
/* Process folded UNIX from line */
save_header(m, line_buf, (short) UNIXFROM, RFC822);
line_buf->end = 0;
*(line_buf->contents) = '\0';
}
else
{
if (isheader(line_buf->contents))
{
save_header(m, line_buf, (short) EMHEADER, m->sd->format);
line_buf->end = 0;
*(line_buf->contents) = '\0';
}
else
{
/* Syntax error or end of header */
indata->offset = startoffset; /* Rewind */
sprintf(ebuf, "load_header: illegal end of header: %s", line_buf->contents);
logger(LOG_ERR, ebuf);
m->h = NULL;
return(NOK);
}
}
}
}
if((linelen == 1 && *buf == '\n') || (linelen == 2 && *buf == '\r'))
{
/* End of header */
indata->offset++;
return(OK);
}
if (line_buf->end == 0)
{
append_data(line_buf, buf, linelen, HEAD_BUF);
}
indata->offset += linelen;
}
/* Not reached */
}
/*
*
*/
void
clear_end(struct data *d)
{
if (*(d->contents + d->end - 1) == '\n')
{
if (*(d->contents + d->end - 2) == '\r')
{
*(d->contents + d->end - 2) = '\0';
d->end -= 2;
}
else
{
*(d->contents + d->end - 1) = '\0';
d->end -= 1;
}
}
}
/*
* save_header()
*
* Save the header field and header value in a list of header structures.
*
*/
void
save_header(struct message *mess, struct data *line, short type, int format)
{
struct header *hdr, *thdr;
char *value;
hdr = (struct header *)Yalloc(sizeof(struct header));
hdr->type = type;
hdr->format = format;
clear_end(line);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Save header: %s\n", line->contents);
#endif
hdr->field = (struct data *)Yalloc(sizeof(struct data ));
if (type == UNIXFROM)
append_data(hdr->field, line->contents, line->end, HEAD_BUF);
else
{
hdr->value = (struct data *)Yalloc(sizeof(struct data ));
value = index(line->contents, ':'); assert(value);
*value = '\0';
value++;
while(isspace(*value))
value++;
append_data(hdr->field, line->contents, strlen(line->contents), HEAD_BUF);
append_data(hdr->value, value, strlen(value), HEAD_BUF);
}
if (mess->h == NULL)
mess->h = hdr;
else
{
for (thdr = mess->h; thdr->next != NULL; thdr = thdr->next)
;
thdr->next = hdr;
}
code_header(hdr);
}
void
add_header(struct message *mess, char *field, char *value, int format)
{
struct header *hdr, *thdr;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Add header: %s: %s\n", field, value);
#endif
if (mess->h != NULL)
for (thdr = mess->h; thdr != NULL; thdr = thdr->next)
{
if (thdr->field->end != 0 &&
cmatch(thdr->field->contents, field) == TRUE)
{
thdr->value->offset = 0;
thdr->value->end = 0;
thdr->value->bodyend = 0;
append_data(thdr->value, value, strlen(value), HEAD_BUF);
append_char(thdr->value, '\0', HEAD_BUF); /* NULL terminate */
thdr->format = format;
thdr->hvalue = NULL;
return;
}
hdr = thdr;
}
thdr = hdr;
hdr = (struct header *)Yalloc(sizeof(struct header));
hdr->type = EMHEADER;
hdr->format = format;
hdr->field = (struct data *)Yalloc(sizeof(struct data ));
hdr->value = (struct data *)Yalloc(sizeof(struct data ));
append_data(hdr->field, field, strlen(field), HEAD_BUF);
if (value != NULL)
append_data(hdr->value, value, strlen(value), HEAD_BUF);
if (mess->h == NULL)
mess->h = hdr;
else
thdr->next = hdr;
}
void
rm_header(struct message *mess, char *field)
{
struct header *hdr, *thdr;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Remove header: %s: **\n", field);
#endif
if (mess->h != NULL)
for (thdr = mess->h; thdr != NULL; thdr = thdr->next)
{
if (thdr->field->end != 0 &&
cmatch(thdr->field->contents, field) == TRUE)
{
if (thdr != NULL && thdr == mess->h)
mess->h = thdr->next;
else
hdr->next = thdr->next;
break;
}
hdr = thdr;
}
}
int
isheader(char *string)
{
char *t, *p;
if ((t = index(string, ':')) == NULL || t == string)
return(0);
if ((p = index(string, ' ')) != NULL && p < t)
return(0);
return(1);
}
static void code_header(struct header *th)
{
struct data *outbuf;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ code_header.\n");
#endif
parse_rfc1522(th);
if (th->hvalue != NULL)
{
outbuf = (struct data *)Yalloc(sizeof(struct data));
(void)code_hvalue(th->hvalue, outbuf);
th->value = outbuf;
}
}
static void code_hvalue(struct hprs *h, struct data *outbuf)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ code_hvalue.\n");
#endif
switch (h->type)
{
case ATOM:
case DELIMITER:
case RFC1522:
append_data(outbuf, h->td->contents + h->td->bodystart,
h->td->bodyend - h->td->bodystart, HEAD_BUF);
break;
case DLITERAL:
append_char(outbuf, '[', HEAD_BUF);
break;
case COMMENT:
append_char(outbuf, '(', HEAD_BUF);
break;
case HQSTRING:
append_char(outbuf, '"', HEAD_BUF);
break;
case RADDR:
append_char(outbuf, '<', HEAD_BUF);
break;
default:
break;
}
if (h->child != NULL)
code_hvalue(h->child, outbuf);
switch(h->type)
{
case DLITERAL:
append_char(outbuf, ']', HEAD_BUF);
break;
case COMMENT:
append_char(outbuf, ')', HEAD_BUF);
break;
case HQSTRING:
append_char(outbuf, '"', HEAD_BUF);
break;
case RADDR:
append_char(outbuf, '>', HEAD_BUF);
break;
default:
break;
}
if (h->sibling != NULL)
code_hvalue(h->sibling, outbuf);
}
char *
clear_end_space(char *c)
{
char *d;
d = c + strlen(c) -1;
while (isspace(*d))
{
*d = '\0';
d--;
}
return(c);
}
if (type == UNIXFROM)
append_data(hdr->field, line->contents, line->end, HEAD_BUF);
else
{
hdr->value = (struct data *)Yalloc(sizeof(struct data ));
value = index(line->contents, ':'); assert(value);
*value = '\0';
value++;
while(isspace(*value))
value++;
append_data(hdr->femil-2.1.0-beta9/hqp.c 100644 000000 000000 00000012504 06155035771 014731 0 ustar 00root system 000000 000000 /*
**
** 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"
static char toqp[256] = {
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 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
};
int
h_to_quoted_printable(struct hprs *h)
{
struct data *inbuf, *outbuf;
static int linelen;
char lastspace;
char cbuf[5];
char *inb;
inbuf = h->td;
/* Exit on empty input */
if (!inbuf->size)
return(NOK);
linelen = 0;
outbuf = (struct data *)Yalloc(sizeof(struct data));
outbuf->encoding = EQP;
outbuf->charset = h->td->charset;
if (outbuf->charset == NULL)
{
sprintf(ebuf, "h_to_quoted_printable: No charset in header");
logger(LOG_DEBUG, ebuf);
return(NOK);
}
append_data(outbuf, "=?", 2, HEAD_BUF);
append_data(outbuf, outbuf->charset, strlen(outbuf->charset), HEAD_BUF);
append_data(outbuf, "?Q?", 3, HEAD_BUF);
/* Initialize working pointers */
inb = inbuf->contents + inbuf->offset;
lastspace = 0;
/*
* Process entire inbuf.
*/
while (inbuf->offset < inbuf->bodyend)
{
if (linelen > 71 && *inb != '\n')
{
append_data(outbuf, "=\n", 2, HEAD_BUF);
outbuf ->lineend += 1;
linelen = 0;
}
if (toqp[(unsigned char)*inb])
{
sprintf(cbuf, "=%.2X", (unsigned char)*inb);
append_data(outbuf, cbuf, 3, HEAD_BUF);
linelen += 3;
}
else
{
if (*inb == '\n')
{
if (lastspace != 0)
{
/* Quote space before end of line */
sprintf(cbuf, "=%.2X\n", (unsigned char)lastspace);
append_data(outbuf, cbuf, 4, HEAD_BUF);
outbuf ->lineend += 1;
}
linelen = 0;
}
else
{
if (*inb == ' ')
append_char(outbuf, '_', HEAD_BUF);
else
append_char(outbuf, *inb, HEAD_BUF);
linelen++;
}
if (*inb == ' ' || *inb == '\t')
lastspace = *inb;
else
lastspace = 0;
}
inb++;
inbuf->offset += 1;
}
append_data(outbuf, "?=", 2, HEAD_BUF);
h->td = outbuf;
h->type = RFC1522;
return(OK);
}
int
h_from_quoted_printable(struct hprs *h)
{
struct data *inbuf, *outbuf;
char *inb;
char *q;
char t[3];
char c;
int l, b;
inbuf = h->td;
/* Exit on empty input */
if (!inbuf->size)
return(NOK);
inbuf->offset = h->pstart;
/* Initialize working pointers */
inb = inbuf->contents + inbuf->offset;
outbuf = (struct data *)Yalloc(sizeof(struct data));
outbuf->encoding = E7BIT;
outbuf->charset = h->td->charset;
t[2] = '\0';
/*
* Process entire inbuf.
*/
while (inbuf->offset < h->pend)
{
if ((q = index(inb, '=')) != NULL &&
(l = q - inb) > -1 &&
(inbuf->offset + l < h->pend))
{
/* Special case of _ character */
for (b = 0; b < l; b++)
if (*(inb + b) == '_')
*(inb + b) = ' ';
append_data(outbuf, inb, l, HEAD_BUF);
inb += l + 1;
inbuf->offset += l + 1;
if (*inb == '\n')
/* Soft line break */
{
inb++;
inbuf->offset += 1;
}
else
{
strncpy(t, inb, 2);
if ((c = (char) strtol(t, (char **)NULL, 16)) == 0)
{
/* Illegal encoding */
return(NOK);
}
else
{
append_char(outbuf, c, HEAD_BUF);
inb += 2;
inbuf->offset += 2;
}
}
}
else
{
/* This is the last bit */
l = h->pend - inbuf->offset;
/* Special case of _ character */
for (b = 0; b < l; b++)
if (*(inb + b) == '_')
*(inb + b) = ' ';
append_data(outbuf, inb, l, HEAD_BUF);
inb += l;
inbuf->offset += l;
}
}
h->td = outbuf;
h->type = ATOM;
return(OK);
}
, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0emil-2.1.0-beta9/hqxbin.c 100644 000000 000000 00000034165 06155035771 015441 0 ustar 00root system 000000 000000 /*
**
** 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"
#include <assert.h>
/*
** Calculates the CRC of a BinHex file
**
*/
unsigned long
calc_crc(unsigned long crc,unsigned int c)
{
register int i;
register unsigned long tmk;
tmk = crc;
for (i = 0; i < 8; i++)
{
c <<= 1;
if ((tmk <<= 1) & 0x10000)
tmk = (tmk & 0xffff) ^ 0x1021;
tmk ^= (c >> 8);
c &= 0xff;
}
assert(tmk <= 65535); /* ELSE TRUNC / TW */
return((unsigned short)tmk);
}
/*
**
** Extract and check the CRC of a BinHex file.
**
*/
int
get_binhex_crc(struct data *d, unsigned long checksum)
{
int partlen;
/* CRC for the CRC */
checksum = calc_crc(checksum, (unsigned char)'\0');
checksum = calc_crc(checksum, (unsigned char)'\0');
if (d->offset + 2 > d->end)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* ERROR get_binhex_crc: Premature end of data in BinHexed file %lu", d->offset);
#endif
logger(LOG_WARNING, "get_binhex_crc: Premature end of data in BinHexed file");
return(NOK);
}
for (partlen = 1; partlen >= 0; partlen--, d->offset += 1)
{
if (((0xFF & *(d->contents + d->offset)) ^ (0xFF & (checksum >> (8*partlen))))
!= 0)
return(NOK);
}
return(OK);
}
/*
**
** Extract header from a BinHex file
**
*/
int
get_binhex_binary(struct message *m)
{
unsigned long checksum;
unsigned int filenamelen;
char flags[3];
struct data *d;
struct data *r = NULL;
unsigned long partlen;
unsigned long rlen;
char cdlen[5];
d = m->td;
checksum = 0;
d->offset = d->bodystart;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Extracting applefile");
#endif
if (d->contents == NULL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", no input (failed)\n");
#endif
logger(LOG_WARNING, "get_binhex_binary: getting namelen: called with empty data");
return(NOK);
}
/* Extract filenamelen */
filenamelen = *(d->contents + d->offset);
checksum = calc_crc(0, (unsigned char) *(d->contents + d->offset));
d->offset += 1;
/* Extract name from a BinHex file */
m->sd->name = (char *)Yalloc(filenamelen + 1);
if (d->offset + filenamelen > d->end)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", no name (failed)\n");
#endif
logger(LOG_WARNING, "get_binhex_binary: getting name: premature end of data");
return(NOK);
}
assert (filenamelen > 0);
bcopy(d->contents + d->offset, m->sd->name, (unsigned) filenamelen);
for (partlen = 0; partlen < filenamelen; partlen++, d->offset += 1)
checksum = calc_crc(checksum, *(d->contents + d->offset));
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", filename - %s, namelength %d", m->sd->name, filenamelen);
#endif
if (*(d->contents + d->offset) != '\0')
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", no null byte (failed)\n");
#endif
logger(LOG_WARNING, "get_binhex_binary: Mandantory null byte unavailable in binhex header");
if (m->td != m->sd)
free_data(m->td);
m->td = m->sd;
return(NOK);
}
/* Move past NULL */
checksum = calc_crc(checksum, (unsigned char)'\0');
d->offset += 1;
/* Extract type of a BinHex file */
if ((d->offset + 4) > d->end)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", no type (failed)\n");
#endif
logger(LOG_WARNING, "get_binhex_binary: Type unavailable in binhex header");
if (m->td != m->sd)
free_data(m->td);
m->td = m->sd;
return(NOK);
}
m->sd->appletype = (char *)Yalloc(9);
bcopy(d->contents + d->offset, m->sd->appletype, 4);
for (partlen = 0; partlen < 4; partlen++, d->offset += 1)
checksum = calc_crc(checksum, *(d->contents + d->offset));
/* Extract auth of a BinHex file */
if ((d->offset + 4) > d->end)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", no auth (failed)\n");
#endif
logger(LOG_WARNING, "get_binhex_binary: Auth unavailable in binhex header");
if (m->td != m->sd)
free_data(m->td);
m->td = m->sd;
return(NOK);
}
bcopy(d->contents + d->offset, m->sd->appletype + 4, 4);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", type&creator - %s", m->sd->appletype);
fflush(stderr);
#endif
for (partlen = 0; partlen < 4; partlen++, d->offset += 1)
checksum = calc_crc(checksum, *(d->contents + d->offset));
if ((m->sd->type = confextr("APPLEFILE", m->sd->appletype, NULL)) == NULL)
if ((m->sd->type = confextr("APPLEFILE", "DEFAULT", NULL)) == NULL)
m->sd->type = NEWSTR("APPLICATION");
/* Extract flags of a BinHex file. */
if ((d->offset + 2) > d->end)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", no flags (failed)\n");
#endif
logger(LOG_WARNING, "get_binhex_binary: Flags unavailable in binhex header");
if (m->td != m->sd)
free_data(m->td);
m->td = m->sd;
return(NOK);
}
/* These might just as well be junked */
bzero(flags, 3);
bcopy(d->contents + d->offset, flags, 2);
for (partlen = 0; partlen < 2; partlen++, d->offset += 1)
checksum = calc_crc(checksum, *(d->contents + d->offset));
/* Extract datafork length of a BinHex file. */
if ((d->offset + 4) > d->end)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", no data fork length (failed)\n");
#endif
logger(LOG_WARNING, "get_binhex_binary: Data length unavailable in binhex header");
if (m->td != m->sd)
free_data(m->td);
m->td = m->sd;
return(NOK);
}
bzero(cdlen, 5);
bcopy(d->contents + d->offset, cdlen, 4);
for (partlen = 0; partlen < 4; partlen++, d->offset += 1)
checksum = calc_crc(checksum, *(d->contents + d->offset));
d->length = getblong(cdlen);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", data fork length: %lu", d->length);
#endif
/* Extract resource fork length of a BinHex file. */
/* This really not interesting until we support resource forks */
if ((d->offset + 4) > d->end)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", no resource fork length (failed)\n");
#endif
logger(LOG_WARNING, "get_binhex_binary: Resource length unavailable in binhex header");
if (m->td != m->sd)
free_data(m->td);
m->td = m->sd;
return(NOK);
}
bzero(cdlen, 5);
bcopy(d->contents + d->offset, cdlen, 4);
for (partlen = 0; partlen < 4; partlen++, d->offset += 1)
checksum = calc_crc(checksum, *(d->contents + d->offset));
if ((rlen = getblong(cdlen)) != 0)
m->sd->applefile = ABINHEX;
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", resource fork length: %lu", rlen);
#endif
/* Check header CRC */
if (get_binhex_crc(d, checksum) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", header CRC error (failed)\n");
#endif
logger(LOG_WARNING, "get_binhex_binary: CRC Error in header");
if (m->td != m->sd)
free_data(m->td);
m->td = m->sd;
return(NOK);
}
/* Extract and output the datafork */
if (process)
{
d->bodystart = d->offset;
d->bodyend = d->offset + d->length;
}
if (d->offset + d->length > d->end)
{
#ifdef DEBUG
if (edebug && process)
{
fprintf(stderr, ", premature end of data in data fork (failed)\n");
fprintf(stderr, "suggested offset %lu suggested length %lu real length %lu\n",
d->offset, d->length, d->end);
}
#endif
if (process)
logger(LOG_WARNING, "get_binhex_binary: getting datafork: premature end of data");
if (m->td != m->sd)
free_data(m->td);
m->td = m->sd;
return(NOK);
}
checksum = 0;
for(partlen = 0; partlen < d->length; partlen++, d->offset += 1)
{
checksum = calc_crc(checksum, (unsigned char)*(d->contents + d->offset));
}
if (get_binhex_crc(d, checksum) != OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", data fork CRC error at offset %lu (failed)\n", d->offset);
#endif
logger(LOG_WARNING, "get_binhex_binary: CRC Error in data fork");
if (m->td != m->sd)
free_data(m->td);
m->td = m->sd;
return(NOK);
}
/* Extract and output the resource fork */
if (rlen != 0)
{
if (d->offset + rlen <= d->end)
{
if (process)
{
r = (struct data *)Yalloc(sizeof(struct data));
r->bodystart = d->offset;
r->bodyend = d->offset + rlen;
r->contents = d->contents;
r->appletype = d->appletype;
r->name = d->name;
r->type = d->type;
r->applefile = ARESOURCE;
d->applefile = AFILE;
}
}
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", premature end of data in resource fork (failed) %lu\n", r->offset);
#endif
logger(LOG_WARNING, "get_binhex_binary: getting resource fork: premature end of data");
if (m->td != m->sd)
free_data(m->td);
m->td = m->sd;
return(NOK);
}
}
checksum = 0;
for(partlen = 0; partlen < rlen; partlen++, d->offset += 1)
{
checksum = calc_crc(checksum, (unsigned char)*(d->contents + d->offset));
}
if (get_binhex_crc(d, checksum) == OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", done (OK).\n");
#endif
if (r != NULL)
{
d->next = r;
r->encoding = EBINARY;
}
d->encoding = EBINARY;
return(OK);
}
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", resource fork CRC error (failed)\n");
#endif
logger(LOG_WARNING, "get_binhex_binary: CRC Error in resource fork");
if (m->td != m->sd)
free_data(m->td);
m->td = m->sd;
return(NOK);
}
}
int
create_binhex_binary(struct message *m)
{
unsigned long filenamelen;
char four[5];
struct data *d, *r, *h;
unsigned long crc;
unsigned long dlen, rlen;
unsigned long partlen;
h = (struct data *) Yalloc(sizeof(struct data ));
if ((d = m->td) != NULL)
{
d->offset = d->bodystart;
}
if ((r = d->next) != NULL)
{
r->offset = r->bodystart;
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, " Creating binhex binary");
#endif
if (m->sd->name == NULL)
m->sd->name = NEWSTR("noname");
filenamelen = strlen(m->sd->name);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", filename: %s", m->sd->name);
#endif
/* Add filenamelen */
append_char(h, (char) (0xff & filenamelen), pz);
/* Add filename */
append_data(h, m->sd->name, filenamelen, pz);
/* Add mandantory NULL byte */
append_char(h, '\0', pz);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", type&creator: %s\n", m->sd->appletype);
#endif
/* Add type */
append_data(h, m->sd->appletype, 4, pz);
/* Add auth */
append_data(h, m->sd->appletype + 4, 4, pz);
/* Add flags */
append_data(h, "\0\0\0", 2, pz);
/* Add data fork length */
dlen = d->bodyend - d->bodystart;
bzero(four, 5);
for (partlen = 4; partlen > 0; partlen--)
{
four[4 - partlen] = (char) 0xff & (dlen >> ((partlen - 1) * 8));
}
append_data(h, four, 4, pz);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", data length: %lu", dlen);
#endif
/* Add resource fork length */
if (r != NULL)
{
rlen = r->bodyend - r->bodystart;
}
else
{
rlen = 0; /* Resource fork is empty */
}
bzero(four, 5);
for (partlen = 4; partlen > 0; partlen--)
{
four[4 - partlen] = (char) 0xff & (rlen >> ((partlen - 1) * 8));
}
append_data(h, four, 4, pz);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", resource length: %lu\n", rlen);
#endif
/* Generate header CRC */
crc = 0;
for (partlen = 0; partlen < h->bodyend; partlen++)
{
crc = calc_crc(crc, *(h->contents + partlen));
}
crc = calc_crc(crc, '\0');
crc = calc_crc(crc, '\0');
bzero(four, 5);
for (partlen = 2; partlen > 0; partlen--)
{
four[2 - partlen] = (char) 0xff & (crc >> ((partlen - 1) * 8));
}
append_data(h, four, 2, pz);
dlen = d->bodyend - d->bodystart;
partlen = h->bodyend;
/* Append data fork */
append_data(h, d->contents + d->bodystart, dlen, pz);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Append data fork: old end %lu, new end %lu, length %lu\n", partlen, h->bodyend, dlen);
#endif
/* Append data CRC */
crc = 0;
for (; partlen < h->bodyend; partlen++)
{
crc = calc_crc(crc, *(h->contents + partlen));
}
crc = calc_crc(crc, (unsigned char)'\0');
crc = calc_crc(crc, (unsigned char)'\0');
bzero(four, 5);
for (partlen = 2; partlen > 0; partlen--)
{
four[2 - partlen] = (char) 0xff & (crc >> ((partlen - 1) * 8));
}
append_data(h, four, 2, pz);
/* Append resource fork */
crc = 0;
partlen = h->bodyend;
if (r != NULL)
{
rlen = r->bodyend - r->bodystart;
append_data(h, r->contents + r->bodystart, rlen, pz);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Append resource fork: old end %lu, new end %lu, length %lu\n", partlen, h->bodyend, rlen);
#endif
/* Append resource CRC */
for (partlen = h->bodyend - rlen; partlen < h->bodyend; partlen++)
{
crc = calc_crc(crc, *(h->contents + partlen));
}
}
crc = calc_crc(crc, '\0');
crc = calc_crc(crc, '\0');
bzero(four, 5);
for (partlen = 2; partlen > 0; partlen--)
{
four[2 - partlen] = (char) 0xff & (crc >> ((partlen - 1) * 8));
}
append_data(h, four, 2, pz);
safe_mchange(m, h);
return(OK);
}
encoding = EBINARY;
return(OK);
}
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", resource fork CRC error (failed)\n");
#endif
logger(LOG_WARNING, "get_binhex_binary: CRC Error in resource fork");
if (m->td != m->sd)
free_data(m->td);
m->td = m->sd;
return(NOK);
}
}
int
create_binhex_binary(struct message *m)
{
unsigned long filenameleemil-2.1.0-beta9/load.c 100644 000000 000000 00000011153 06155035771 015057 0 ustar 00root system 000000 000000 /*
**
** 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 <signal.h>
#include <stdlib.h>
#include "emil.h"
#define MAXSZ 16*1024 /* Maximum amount to allocate */
#define MULTF 2 /* Increase factor */
#ifdef SIGDANGER
extern int psdanger(int);
#endif
long memall = 0;
extern int in_fd;
static void * Zalloc(void * old, off_t prevsize, off_t newsize)
{
/* Allocate memory */
void * Z;
memall = memall + newsize - prevsize;
#ifdef DEBUG
alloc_total += newsize - prevsize;
if (edebug)
{
fprintf(stderr, "* Allocated %lu, new total: %lu\n", newsize - prevsize, alloc_total);
fflush(stderr);
}
#endif
if (old == NULL)
{
assert (prevsize == 0);
Z = malloc((size_t)newsize);
}
else {
assert (prevsize != 0);
assert (prevsize < newsize);
Z = realloc(old,(size_t)newsize);
}
if (Z == NULL) {
logger(LOG_ERR,"load_data cannot allocate memory");
closelog();
fprintf(stderr, "Emil: load_data: cannot allocate memory (using %lu bytes)\n", memall);
fflush(stderr);
exit(EX_OSERR);
}
memset(((char *) Z) + prevsize, 0, newsize - prevsize);
return Z;
}
struct data *
load_data()
{
struct data *out;
long chunk;
#ifdef SIGDANGER
long border;
#endif
char * tmp;
int l;
int left;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* Load data\n");
#endif
/* Allocate an output struct */
out = (struct data *) Yalloc(sizeof(struct data));
/* And an initial output buffer */
chunk = pz;
left = chunk;
out->contents = (char *) Zalloc(NULL,0,chunk);
out->size = chunk;
/* Read all on standard input and reallocate buffer if required */
while ((l=read(in_fd, (out->contents + out->end), chunk - 1)) > 0) {
out->end += l;
left -= l;
if (left < chunk)
{
chunk *= MULTF;
if (chunk > MAXSZ) chunk = MAXSZ;
#ifdef SIGDANGER
border = (psdanger(SIGDANGER) * pz) / 2;
if (chunk > border) chunk = border;
#endif
#ifdef DEBUG
if (edebug)
fprintf(stderr, "read %d characters\n", l);
if (edebug)
fprintf(stderr,"load_data: realloc %lud to %lud\n",
out->size,chunk + out->size);
#endif
out->contents =
(char *)Zalloc(out->contents,out->size,out->size+chunk);
out->size += chunk;
left += chunk;
}
}
out->contents[out->end] = 0;
/* Count number of lines */
for ( tmp = out->contents, out->lend = 0;
(tmp= index(tmp,'\n')) != NULL;
tmp++) out->lend++;
return(out);
}
int
append_data(struct data *d, char *c, int len, int busize)
{
if (d->size == 0)
{
if ((d->contents = Zalloc(NULL, 0, busize)) == NULL)
return(NOK);
d->size = busize;
}
while ((len + d->end + 2) > d->size) /* TW 941220 */
{
if ((d->contents = Zalloc(d->contents,d->size,d->size+busize)) == NULL)
return(NOK);
d->size += busize;
}
/* bcopy(c, (d->contents + d->end), len); */
memcpy((d->contents + d->end), c, (off_t) len);
d->end += len;
d->bodyend += len;
*(d->contents + d->end) = '\0';
return(OK);
}
int
append_char(struct data *d, char c, int busize)
{
if (d->size == 0)
{
if ((d->contents = Zalloc(NULL, 0, busize)) == NULL)
return(NOK);
d->size = busize;
}
while ((3 + d->end) > d->size)
{
if ((d->contents = Zalloc(d->contents,d->size,d->size+busize)) == NULL)
return(NOK);
d->size += busize;
}
*(d->contents + d->end) = c;
d->end += 1;
d->bodyend += 1;
*(d->contents + d->end) = '\0';
return(OK);
}
;
#ifdef DEBUG
alloc_total += newsize - prevsize;
if (edebug)
{
fprintf(stderr, "* Allocated %lu, new total: %lu\n", newsize - prevsize, alloc_total);
fflush(stderr);
}
#endif
if (old == NULL)
{
assert (prevsize == 0);
Z = malloc((size_t)newsize);
}
else {
assert (prevsize != 0);
assert (prevsize < newsize);
Z = realloc(old,(size_t)newsize);
}
if (Z == NULLemil-2.1.0-beta9/logger.c 100644 000000 000000 00000007765 06155035771 015435 0 ustar 00root system 000000 000000 /*
**
** 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"
#ifndef HAVE_GETHOSTNAME
#include <sys/utsname.h>
#endif
#define LOG_MAX 50 /* Max number of logged lines */
struct log_s {
struct log_s * f; /* points to next in chain */
struct log_s * b; /* points to previous */
char * m; /* Message text */
int l;
};
static struct log_s * log_f = NULL, * log_b = NULL;
static int log_n = 0;
extern int syslog_logging; /* defined in main() */
extern int header_logging; /* defined in main() */
extern int syslog_facility;/* defined in main() */
extern FILE * out_fd;
void logger(int level, char * data)
{
/* One could argue that va_lst should have been used. */
/* But varargs seems to bee at bit unstable sometimes */
char * buf;
int dosys, doheader;
struct log_s * s;
int l;
switch (syslog_logging) {
case 0: dosys = 0; break;
case 1: dosys = (level <= LOG_ERR); break;
case 2: dosys = (level <= LOG_NOTICE);break;
case 3: dosys = (level <= LOG_INFO); break;
default : dosys = 1;
}
switch (header_logging) {
case 0: doheader = 0; break;
case 1: doheader = (level <= LOG_ERR); break;
case 2: doheader = (level <= LOG_NOTICE);break;
case 3: doheader = (level <= LOG_INFO); break;
default : doheader = 1;
}
if ((dosys==0) && (doheader==0))return;
if ((++log_n) >= LOG_MAX) return;
l = strlen(data);
if ((buf=malloc(l+1)) == NULL) {
syslog(LOG_ERR,"Cannot get memory");
return;
}
strcpy(buf,data);
if (dosys) {
if (log_n == 1) {
#ifdef ultrix
openlog("emil",0);
#else
openlog("emil",LOG_CONS,syslog_facility);
#endif
}
syslog(level, "%s", buf);
}
if (doheader) {
if ((s = malloc(sizeof(struct log_s)))==NULL) {
syslog(LOG_ERR,"Cannot get memory");
return;
}
if (log_f == NULL) {
/* first element */
log_f = s;
}
else {
s->b = log_b; /* add to end */
log_b->f= s;
}
log_b = s; /* last in chain */
s->f = NULL;
s->m = buf;
s->l = level;
}
}
void print_log()
{
/* Print headerlog on stdout */
struct log_s * s;
char * h;
char hn[255];
time_t t;
#ifndef HAVE_GETHOSTNAME
struct utsname uts;
#endif
if (log_f != NULL) {
#ifdef HAVE_GETHOSTNAME
if (gethostname(hn,sizeof(hn)-1) < 0)
strcpy(hn,"unknown");
#else
if (uname(&uts)==0) strcpy(hn,uts.nodename);
else strcpy(hn,"unknown");
#endif
time(&t);
fprintf(out_fd,"Emil-server: %s v.%s %s", hn,EMIL_VERSION,ctime(&t));
}
for (s = log_f; s != NULL; s = s->f) {
switch (s->l) {
case LOG_EMERG: h = "EMERGENCY"; break;
case LOG_ALERT: h = "ALERT"; break;
case LOG_CRIT: h = "CRITICAL"; break;
case LOG_ERR: h = "Error"; break;
case LOG_WARNING: h = "Warning"; break;
case LOG_NOTICE: h = "info"; break;
case LOG_INFO: h = "notice"; break;
case LOG_DEBUG: h = "debug"; break;
default: h = "x";
}
fprintf(out_fd,"Emil-%s-message: %s\n",h,s->m);
}
header_logging = 0;
}
struct */
emil-2.1.0-beta9/mailtool.c 100644 000000 000000 00000015124 06155035772 015763 0 ustar 00root system 000000 000000 /*
**
** 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"
void encode_mailtool(struct message *m)
{
char buf[HDRLEN];
if (m->sd->format == MAILTOOL &&
m->sd == m->td)
return;
if (m->level == 0)
{
rm_header(m, "X-Charset");
rm_header(m, "X-Char-Esc");
if (match(m->sd->type, "TEXT"))
{
add_header(m, "Content-Type", "text", MAILTOOL);
sprintf(buf, "%d", get_body_lines(m->td));
add_header(m, "X-lines", buf, MAILTOOL);
}
else
{
add_header(m, "Content-Type", "X-Sun-Attachment", MAILTOOL);
m->td->startbound = NEWSTR("----------");
}
}
else
{
unsigned char *dt = NULL;
if (m->td->encoding == EMULTI)
{
m->td->startbound = NEWSTR("----------");
return;
}
if ((dt = (char *)confextr("MAILTOOL", NULL, m->sd->type)) != NULL ||
(dt = (char *)confextr("MAILTOOL", NULL, "DEFAULT")) != NULL)
{
add_header(m, "X-Sun-Data-Type", dt, MAILTOOL);
}
else
{
add_header(m, "X-Sun-Data-Type", "default", MAILTOOL);
}
/*
if (match(m->sd->type, "TEXT"))
{
add_header(m, "X-Sun-Data-Type", "text", MAILTOOL);
}
else
if (match(m->sd->type, "APPLICATION"))
{
add_header(m, "X-Sun-Data-Type", "default-app", MAILTOOL);
}
else
if (match(m->sd->type, "GIF"))
{
add_header(m, "X-Sun-Data-Type", "gif-file", MAILTOOL);
}
else
if (match(m->sd->type, "ULAW"))
{
add_header(m, "X-Sun-Data-Type", "audio-file", MAILTOOL);
}
else
{
add_header(m, "X-Sun-Data-Type", "default", MAILTOOL);
}
*/
switch (m->td->encoding) {
case EUUENCODE:
add_header(m, "X-Sun-Encoding-Info", "uuencode", MAILTOOL);
break;
case EBINHEX:
add_header(m, "X-Sun-Encoding-Info", "binhex", MAILTOOL);
break;
case EBASE64:
add_header(m, "X-Sun-Encoding-Info", "base64", MAILTOOL);
break;
}
if (m->sd->description != NULL)
add_header(m, "X-Sun-Data-description", m->sd->description, MAILTOOL);
else
add_header(m, "X-Sun-Data-description", "default", MAILTOOL);
if (m->sd->name != NULL)
add_header(m, "X-Sun-Data-name", m->sd->name, MAILTOOL);
sprintf(buf, "%d", get_body_lines(m->td));
add_header(m, "X-Sun-Content-lines", buf, MAILTOOL);
}
}
int decode_mailtool(struct message *m)
{
if (m->level == 0)
{
if (matchheader(m, "Content-Type", "text", MAILTOOL))
{
if ((m->sd->charset = (char *)gethval(m, "X-Sun-charset", MAILTOOL)) == NULL)
return(NOK);
m->sd->format = MAILTOOL;
m->sd->type = NEWSTR("TEXT");
m->sd->encoding = E7BIT;
}
else
/* Look for SUN Mailtool */
if (matchheader(m, "Content-Type", "X-Sun-Attachment", MAILTOOL))
{
m->sd->format = MAILTOOL;
m->sd->type = NEWSTR("MULTIPART");
m->sd->check = EMULTI;
m->sd->encoding = EMULTI;
m->sd->startbound = NEWSTR("----------");
}
if (m->sd->format == MAILTOOL)
{
m->sd->length = string2dec(gethval(m, "Content-length", MAILTOOL));
m->sd->bodylines = string2dec(gethval(m, "X-lines", MAILTOOL));
return(OK);
}
else
return(NOK);
}
/**
** This is valid for SUN Mailtool message, except for root header
**/
if (m->sd->format == MAILTOOL && m->level != 0)
{
char *line = NULL;
m->sd->charset = (char *)gethval(m, "X-Sun-charset", MAILTOOL);
if ((line = (char *)gethval(m, "X-Sun-Data-Type", MAILTOOL)) == NULL)
{
m->sd->type = NEWSTR("TEXT");
m->sd->charset = NEWSTR("US-ASCII");
}
else
{
while (isspace(*line))
line++;
if ((m->sd->type = confextr("MAILTOOL", clear_end_space(line), NULL)) == NULL)
m->sd->type = NEWSTR("APPLICATION");
}
/*
if (matchheader(m, "X-Sun-Data-Type", "text", MAILTOOL))
{
m->sd->type = NEWSTR("TEXT");
m->sd->charset = "ISO-8859-1";
m->sd->encoding = E7BIT;
}
else
if (matchheader(m, "X-Sun-Data-Type", "default", MAILTOOL))
{
m->sd->type = NEWSTR("TEXT");
}
else
if (matchheader(m, "X-Sun-Data-Type", "default-app", MAILTOOL))
{
m->sd->type = NEWSTR("APPLICATION");
}
else
if (matchheader(m, "X-Sun-Data-Type", "gif-file", MAILTOOL))
{
m->sd->type = NEWSTR("GIF");
}
else
if (matchheader(m, "X-Sun-Data-Type", "audio-file", MAILTOOL))
{
m->sd->type = NEWSTR("ULAW");
}
else
m->sd->type = NEWSTR("APPLICATION");
*/
m->sd->encoding = E7BIT;
if (matchheader(m, "X-Sun-Encoding-Info", "uuencode", MAILTOOL))
{
m->sd->encoding = EUUENCODE;
}
else
if (matchheader(m, "X-Sun-Encoding-Info", "binhex", MAILTOOL))
{
m->sd->encoding = EBINHEX;
}
else
if (matchheader(m, "X-Sun-Encoding-Info", "base64", MAILTOOL))
{
m->sd->encoding = EBASE64;
}
if (matchheader(m, "X-Sun-Data-Type", "default", MAILTOOL) && m->sd->charset != NULL && m->sd->encoding == E7BIT)
{
m->sd->type = NEWSTR("TEXT");
}
m->sd->length = string2dec(gethval(m, "X-Sun-Content-length", MAILTOOL));
m->sd->bodylines = string2dec(gethval(m, "X-Sun-Content-lines", MAILTOOL));
m->sd->description = (char *)gethval(m, "X-Sun-Data-description", MAILTOOL);
m->sd->name = (char *)gethval(m, "X-Sun-Data-name", MAILTOOL);
}
else
return (NOK);
return (OK);
}
int
get_body_lines(struct data *d)
{
char *c;
int i, e, l;
l = 0;
i = d->bodystart;
e = d->bodyend;
c = d->contents + i;
for (; i < e; i++, c++)
if (*c == '\n')
l++;
return(l);
}
-Sun-Data-Type", "audio-file", MAILTOOL);
}
else
{
add_header(m, "X-Sun-Data-Type", "default", MAILTOOL);
}
*/
switch (m->td->encoding) {
case EUUENCODE:
add_header(m, "X-Sun-Encoding-Info", "uuencode", MAILTOOL);
break;
case EBINHEX:
add_header(m, "X-Sun-Encoding-Info", "binhex", MAILTOOL);
break;
case EBASE64:
add_header(m, "X-Sun-Encoding-Info", "base64", MAILTOOL);
break;
}emil-2.1.0-beta9/main.c 100644 000000 000000 00000045076 06155035772 015100 0 ustar 00root system 000000 000000 /*
**
** 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"
char *emilbase(char *);
short det_sket_sig = FALSE;
long alloc_total;
struct message *rootmess = NULL;
struct config_struct *source = NULL,
*target = NULL;
char **mailer = NULL;
char * recipient = NULL, /* Recipient */
* sender = NULL; /* Sender */
char * rmx = NULL; /* Recipient's mx */
int want_unix_from = 0;
#ifdef SMTP
int smtp_client = 0;
#endif
#ifdef sun
extern char * optarg;
#elif defined(ultrix) || defined(_AUX_SOURCE)
extern char * optarg;
#endif
#ifdef DEBUG
int edebug = FALSE;
#endif
void fix_config_struct(struct config_struct *);
int process;
char ebuf[1024];
#ifndef ultrix
int syslog_facility = LOG_FACILITY;
#endif
int header_logging = 0;
int syslog_logging = 0;
int spawn_mailer = 0;
int pseudo_route = 0;
int in_fd = 0;
FILE * out_fd = stdout;
FILE * char_fd = NULL;
FILE * conf_fd = NULL;
off_t pz;
char * hostname = NULL;
int main(int argc, char *argv[])
{
struct data *d;
int c;
int no_run = FALSE;
char *cmailer = NULL;
char *member = NULL;
#ifdef HAVE_GETPAGESIZE
pz = (off_t) getpagesize();
#elif defined(hpux) || defined(_AUX_SOURCE)
pz = 4096;
#else
pz = sysconf(_SC_PAGESIZE);
#endif
if (strcmp(emilbase(argv[0]), "sendmail") == 0)
{
for (c = 1; c < argc; c++)
{
if (strncmp(argv[c], "-f", 2) == 0)
{
if (strlen(argv[c]) > 2)
sender = NEWSTR(argv[c] + 2);
else
{
c++;
sender = NEWSTR(argv[c]);
}
}
else
{
recipient = NEWSTR(argv[c]);
}
}
rmx = NEWSTR("localhost");
cmailer = NEWSTR("sendmail");
if (sender == NULL || recipient == NULL)
{
fprintf(stderr, "USAGE: %s -f <sender> <recipient>\n", argv[0]);
exit(-1);
}
}
else
#ifdef ultrix
while((c=getopt(argc, argv, "s:r:x:i:m:o:e:c:A:B:H:F:C:G:S:T:l:h:fpgduvn")) >= 0) {
#else
while((c=getopt(argc, argv, "s:r:x:l:i:m:o:e:c:A:B:H:F:C:G:S:T:h:f:pgduvn")) >= 0) {
#endif
switch (c) {
case 's': /* Sender's name */
sender = optarg;
break;
case 'r': /* Recipient's name */
recipient = optarg;
break;
case 'x': /* Recipient's mail exchanger address */
rmx = optarg;
break;
case 'l': /* syslog level */
if (optarg == NULL) {
/* Just increment */
syslog_logging++;
break;
}
else
switch(*optarg) {
case '1': syslog_logging = 1; break;
case '2': syslog_logging = 2; break;
case '3': syslog_logging = 3; break;
case '4': syslog_logging = 4; break;
case '5': syslog_logging = 5; break;
default: syslog_logging++ ; break;
}
break;
case 'f':
#ifndef ultrix
if (optarg == NULL) {
/* Just increment */
syslog_logging++;
break;
}
*optarg = tolower(*optarg);
if (optarg) switch (*optarg) {
case 'm': syslog_facility = LOG_MAIL; break;
case 'd': syslog_facility = LOG_DAEMON; break;
case '0': syslog_facility = LOG_LOCAL0; break;
case '1': syslog_facility = LOG_LOCAL1; break;
case '2': syslog_facility = LOG_LOCAL2; break;
case '3': syslog_facility = LOG_LOCAL3; break;
case '4': syslog_facility = LOG_LOCAL4; break;
case '5': syslog_facility = LOG_LOCAL5; break;
case '6': syslog_facility = LOG_LOCAL6; break;
case '7': syslog_facility = LOG_LOCAL7; break;
default:
sprintf(ebuf,"Invalid parameter to -f: %s",optarg);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ebuf);
#endif
logger(LOG_WARNING,ebuf);
}
#endif
break;
case 'h': /* Log in header */
if (optarg == NULL) {
/* Just increment */
header_logging++;
break;
}
else
switch(*optarg) {
case '1': header_logging = 1; break;
case '2': header_logging = 2; break;
case '3': header_logging = 3; break;
case '4': header_logging = 4; break;
case '5': header_logging = 5; break;
default: header_logging++ ; break;
}
break;
case 'm':
cmailer = NEWSTR(optarg);
break;
#ifdef SMTP
case 'n': /* SMTP Client */
smtp_client = 1;
break;
#endif
case 'p': /* Add loop back pseudo route */
pseudo_route = 1;
break;
case 'g': /* Just return group */
no_run = TRUE;
break;
#ifdef DEBUG
case 'd': /* Switch on debugging on stderr */
fprintf(stderr, "*** Emil version %s ***\n", EMIL_VERSION);
fprintf(stderr, "Processing with debug switched on.\n");
fprintf(stderr, "(This might produce voluminous output.)\n\n");
edebug = TRUE;
break;
#endif
case 'i': /* Input file */
in_fd = open(optarg,O_RDONLY,0);
if (in_fd < 0) {
logger(LOG_ERR,"Cannot open input file");
fprintf(stderr, "Emil: Cannot open input file\n");
exit(EX_NOINPUT);
}
break;
case 'o': /* Output file */
out_fd = fopen(optarg,"w");
if (out_fd == NULL) {
logger(LOG_ERR,"Cannot open output file");
fprintf(stderr, "Emil: Cannot open output file\n");
exit(EX_CANTCREAT);
}
break;
case 'e': /* Main configuration file */
conf_fd = fopen(optarg,"r");
if (conf_fd == NULL) {
logger(LOG_ERR,"Cannot open emil.cf");
fprintf(stderr, "Emil: Cannot open emil.cf\n");
exit(EX_OSFILE);
}
break;
case 'c': /* charsets file */
char_fd = fopen(optarg,"r");
if (char_fd == NULL) {
logger(LOG_ERR,"Cannot open charsets file");
fprintf(stderr, "Emil: Cannot open charsets file\n");
exit(EX_OSFILE);
}
break;
case 'A': /* applefile encoding */
if (target == NULL)
target = (struct config_struct *)Yalloc(sizeof(struct config_struct));
target->appletype = NEWSTR(optarg);
break;
case 'B': /* binary encoding */
if (target == NULL)
target = (struct config_struct *)Yalloc(sizeof(struct config_struct));
target->bin = NEWSTR(optarg);
break;
case 'H': /* target header encoding */
if (target == NULL)
target = (struct config_struct *)Yalloc(sizeof(struct config_struct));
target->header = NEWSTR(optarg);
break;
case 'T': /* target text encoding */
if (target == NULL)
target = (struct config_struct *)Yalloc(sizeof(struct config_struct));
target->text = NEWSTR(optarg);
break;
case 'F': /* target format */
if (target == NULL)
target = (struct config_struct *)Yalloc(sizeof(struct config_struct));
target->format = NEWSTR(optarg);
break;
case 'C': /* recipient charset */
if (target == NULL)
target = (struct config_struct *)Yalloc(sizeof(struct config_struct));
target->charset = NEWSTR(optarg);
break;
case 'G': /* Target group */
member = NEWSTR(optarg);
break;
case 'S': /* source charsets */
if (source == NULL)
source = (struct config_struct *)Yalloc(sizeof(struct config_struct));
source->charset = NEWSTR(optarg);
break;
case 'u':
want_unix_from = 1;
break;
case 'v':
printf("emil version %s at your service\n", EMIL_VERSION);
fflush(stdout);
exit(EX_OK);
break;
default:
sprintf(ebuf,"Invalid flag: -%c",c);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ebuf);
#endif
logger(LOG_WARNING,ebuf);
}
}
if (sender == NULL && source == NULL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "*** No sender, No source: Check arguments.\n");
#endif
sender = NULL;
}
if (sender == NULL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Missing -s");
#endif
logger(LOG_DEBUG,"Missing -s");
sender = "unknown@unknown";
}
if (recipient == NULL && target == NULL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "*** No recipient, No target: Check arguments.\n");
#endif
recipient = NULL;
}
if (recipient == NULL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Missing -r");
#endif
logger(LOG_DEBUG,"Missing -r");
recipient = "unknown@unknown";
}
if (rmx == NULL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "*** No recipient host: don't worry.\n");
#endif
logger(LOG_DEBUG,"Missing -x");
rmx = "unknown";
}
if (cmailer != NULL)
{
mailer = get_mailer(cmailer);
if (mailer == NULL) {
sprintf(ebuf, "Invalid mailer specification %s", optarg);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ebuf);
#endif
logger(LOG_ERR, ebuf);
fprintf(stderr, "Emil: %s\n", ebuf);
exit(EX_USAGE);
}
spawn_mailer = 1;
}
#ifdef SMTP
if (smtp_client)
{
if (sender == NULL)
{
fprintf(stderr, "Emil: Need sender to use SMTP.\n");
exit(EX_USAGE);
}
if (recipient == NULL)
{
fprintf(stderr, "Emil: Need recipient to use SMTP.\n");
exit(EX_USAGE);
}
if (rmx == NULL)
{
fprintf(stderr, "Emil: Need relay to use SMTP.\n");
exit(EX_USAGE);
}
spawn_mailer = 0;
smtp_open(rmx);
}
#endif
sprintf(ebuf,"mail from %s to %s via %s",sender,recipient,rmx);
logger(LOG_DEBUG,ebuf);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Processing message from %s to %s via %s.\n",
sender, recipient, rmx);
#endif
if (target == NULL)
{
if (member == NULL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Using getoption(%s, %s, %s) to get target structure.\n", recipient, sender, rmx);
#endif
target = (struct config_struct *) getoption(recipient, sender, rmx);
}
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Using getmember(%s) to get target structure.\n", member);
#endif
target = (struct config_struct *) getmember(member);
}
}
if (no_run == TRUE)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "\nResolving target group.\n");
#endif
if (target == NULL || target->name == NULL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "*** ERROR, unable to resolve target group\n");
#endif
target = NULL;
}
else
fprintf(stdout, "%s\n", target->name);
fflush(stderr);
exit(EX_OK);
}
if (target == NULL)
target = (struct config_struct *)Yalloc(sizeof(struct config_struct));
fix_config_struct(target);
if (source == NULL)
source = (struct config_struct *) getoption(sender, recipient, rmx); /* rmx?? smx */
sprintf(ebuf,"sender group = %s, recipient group = %s",
source ? (source->name ? source->name : "unknown") : "Unknown",
target ? (target->name ? target->name : "unknown") : "Unknown"
);
#ifdef DEBUG
if (edebug)
fprintf(stderr, ebuf);
#endif
logger(LOG_DEBUG,ebuf);
if (source == NULL)
source = (struct config_struct *)Yalloc(sizeof(struct config_struct));
d = (struct data *)load_data();
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Data loaded\n");
fflush(stderr);
#endif
logger(LOG_DEBUG,"Data loaded");
rootmess = (struct message *)Yalloc(sizeof(struct message));
rootmess->sd = d;
rootmess->sdl = d;
rootmess->td = d;
process = 0;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "\n* Parsing message.\n");
#endif
if (target->iformat == TRANSPARENT || parse_message(rootmess) == NOK)
{
#ifdef DEBUG
if (edebug)
{
if (target->iformat == TRANSPARENT)
fprintf(stderr, "*** TRANSPARENT Delivery ***.\n");
else
fprintf(stderr, "*** Parse message failed.\n");
}
#endif
det_sket_sig = TRUE;
if (target->iformat != TRANSPARENT)
logger(LOG_WARNING,"Parsing failed");
d->offset = 0;
if (spawn_mailer) do_fork();
print_log();
out_message(rootmess);
if (spawn_mailer) end_fork();
closelog();
#ifdef SMTP
if (smtp_client)
smtp_close(rmx);
#endif
exit(EX_OK);
}
process = 1;
rootmess = fix_structure(rootmess);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "\n* Processing message.\n");
#endif
convert_applefile(rootmess);
if (convert_data(rootmess) == NOK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "*** Convert data failed.\n");
#endif
det_sket_sig = TRUE;
logger(LOG_WARNING, "Conversion failed");
d->offset = 0;
if (spawn_mailer) do_fork();
print_log();
out_message(rootmess);
if (spawn_mailer) end_fork();
closelog();
#ifdef SMTP
if (smtp_client)
smtp_close(rmx);
#endif
exit(EX_OK);
}
if (spawn_mailer) do_fork();
print_log();
#ifdef DEBUG
if (edebug)
fprintf(stderr, "\n* Output message.\n");
#endif
if (rootmess->sd->format == RFC822)
multipart_kludge(rootmess);
out_message(rootmess);
#ifdef SMTP
if (smtp_client)
smtp_close(rmx);
#endif
if (spawn_mailer) end_fork();
/* end_fork returns here if not spawning: */
closelog();
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Exit OK.\n");
#endif
return EX_OK;
}
void
fix_config_struct(struct config_struct *c)
{
if (c == NULL)
return;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Fix target structure, format - ");
#endif
if (c->format != NULL)
{
if (cmatch(c->format, "mime") == TRUE)
{
c->iformat = MIME;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "mime");
#endif
}
else
if (cmatch(c->format, "mailtool") == TRUE)
{
c->iformat = MAILTOOL;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "mailtool");
#endif
}
else
if (cmatch(c->format, "transparent") == TRUE)
{
c->iformat = TRANSPARENT;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "TRANSPARENT");
#endif
}
else
{
c->iformat = RFC822;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "other (rfc822)");
#endif
}
}
else
{
c->iformat = RFC822;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "unspecified (rfc822)");
#endif
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", binary - ");
#endif
if (c->bin != NULL)
{
if (strncasecmp(c->bin, "ba", 2) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "base64");
#endif
c->ibin = EBASE64;
}
else
{
if (strncasecmp(c->bin, "bi", 2) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "binhex");
#endif
c->ibin = EBINHEX;
}
else
{
if (strncasecmp(c->bin, "u", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "uuencode");
#endif
c->ibin = EUUENCODE;
}
else
{
if (strncasecmp(c->bin, "q", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "quoted-printable");
#endif
c->ibin = EQP;
}
else
{
if (strncasecmp(c->bin, "8", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "8bit");
#endif
c->ibin = E8BIT;
}
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "other (7bit)");
#endif
c->ibin = E7BIT;
}}}}}
}
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "unspecified (7bit)");
#endif
c->ibin = E7BIT;
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", text - ");
#endif
if (c->text != NULL)
{
if (strncasecmp(c->text, "ba", 2) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "base64");
#endif
c->itext = EBASE64;
}
else
{
if (strncasecmp(c->text, "bi", 2) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "binhex");
#endif
c->itext = EBINHEX;
}
else
{
if (strncasecmp(c->text, "u", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "uuencode");
#endif
c->itext = EUUENCODE;
}
else
{
if (strncasecmp(c->text, "q", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "quoted-printable");
#endif
c->itext = EQP;
}
else
{
if (strncasecmp(c->text, "8", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "8bit");
#endif
c->itext = E8BIT;
}
else
{
if (strncasecmp(c->text, "s", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "SE");
#endif
c->itext = ESE;
}
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "other (7bit)");
#endif
c->itext = E7BIT;
}}}}}}
}
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "unspecified (7bit)");
#endif
c->itext = E7BIT;
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", appletype - ");
#endif
if (c->appletype != NULL)
{
if (strncasecmp(c->appletype, "s", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "applesingle");
#endif
c->iapple = ASINGLE;
}
else
{
if (strncasecmp(c->appletype, "b", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "binhex");
#endif
c->iapple = ABINHEX;
}
else
{
if (strncasecmp(c->appletype, "d", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "appledouble");
#endif
c->iapple = ADOUBLE;
}
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "other (unknown)");
#endif
}}}
}
else
{
if (c->ibin == EBINHEX)
{
c->iapple = ABINHEX;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "unspecified (using BinHex)");
#endif
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, "unspecified (unknown)");
#endif
}
#ifdef DEBUG
if (edebug)
fprintf(stderr, ", header - ");
#endif
if (c->header != NULL)
{
if (strncasecmp(c->header, "ba", 2) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "base64.\n");
#endif
c->htext = EBASE64;
}
else
{
if (strncasecmp(c->header, "q", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "quoted-printable.\n");
#endif
c->htext = EQP;
}
else
{
if (strncasecmp(c->header, "8", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "8bit.\n");
#endif
c->htext = E8BIT;
}
else
{
if (strncasecmp(c->header, "s", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "SE.\n");
#endif
c->htext = ESE;
}
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "other (7bit).\n");
#endif
c->htext = E7BIT;
}}}}
}
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "unspecified (7bit).\n");
#endif
c->htext = E7BIT;
}
}
char *
emilbase(char *string)
{
char *c;
if ((c = rindex(string, '/')) != NULL)
c++;
else
c = string;
return(c);
}
DEBUG
if (edebug)
fprintf(stderr, "binhex");
#endif
c->ibin = EBINHEX;
}
else
{
if (strncasecmp(c->bin, "u", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "uuencode");
#endif
c->ibin = EUUENCODE;
}
else
{
if (strncasecmp(c->bin, "q", 1) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "quoted-printable");
#endif
c->ibin = EQP;
}
else
{
if (strncasecmp(c->bin, "8",emil-2.1.0-beta9/message.c 100644 000000 000000 00000025154 06155035773 015574 0 ustar 00root system 000000 000000 /*
**
** 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 do_sibling = FALSE;
/*
* int
* parse_message(inbuf, message)
*
* Parse message and divide into a hierarchical structure of message parts.
*
*/
int
parse_message(struct message *m)
{
struct data *inbuf;
/* Initialize inbuf */
inbuf = (struct data *)m->sd;
/* Exit on empty input */
if (inbuf->size == 0 || (inbuf->end <= inbuf->offset))
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "*** Empty input (failed).\n");
#endif
logger(LOG_ERR, "parse_message: Empty input");
return(NOK);
}
/* Check header if possible */
if (!m->headerdone && (m->sd->format != RFC822 || m->level == 0))
if (check_header(m) != OK)
return(NOK);
switch(m->sd->format)
{
case MIME:
return(parse_mime_message(m));
break;
case MAILTOOL:
return(parse_sun_message(m));
break;
case RFC822:
return(parse_rfc822_message(m));
break;
default:
break;
}
return(NOK);
}
int
move_past_boundary(struct message *m, char *boundary)
{
int linelen;
struct data *inbuf;
inbuf = (struct data *)m->sd;
/* Find start boundary */
while (is_bound(inbuf, boundary) != TRUE)
{
if ((linelen = getline(inbuf)) == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* move_past_boundary failed, EOF.\n");
#endif
return(NOK);
}
inbuf->offset += linelen;
if (inbuf->end <= inbuf->offset)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "move_past_boundary: cannot find boundary\n");
#endif
sprintf(ebuf, "move_past_boundary: cannot find boundary");
logger(LOG_DEBUG, ebuf);
return(NOK);
}
inbuf->loffset += 1;
}
/* Move past boundary */
inbuf->offset += getline(inbuf);
inbuf->loffset += 1;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Found boundary, moved to %lu\n", inbuf->offset);
#endif
return(OK);
}
int
check_header(struct message *m)
{
m->headerdone = 1;
if (load_header(m) == OK)
/* Offset is updated with size of header! */
{
/* Decode the loaded header */
decode_header(m);
/* Set body lines, if available
* (body length is not trusted)
*/
if (m->sd->bodylines != 0)
m->sd->lineend = m->sd->loffset + m->sd->bodylines;
}
else
{
/* Load header failed */
sprintf(ebuf, "check_header: load header failed: %lu", m->sd->loffset);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "%s\n", ebuf);
#endif
logger(LOG_DEBUG, ebuf);
return(NOK);
}
return(OK);
}
int
check_encoding(struct message *m)
{
struct data *inbuf;
int status;
inbuf = m->sd;
/* Check for encoding */
switch (inbuf->encoding)
{
case 0:
inbuf->encoding = E7BIT;
status = OK;
break;
case EBINHEX:
if (decode_binhex(m) == NOK)
{
sprintf(ebuf, "WARNING: parse_message: BinHex decode failed :%lu",
inbuf->loffset);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "%s\n", ebuf);
#endif
logger(LOG_WARNING, ebuf);
status = NOK;
}
else
status = OK;
break;
case EUUENCODE:
if (decode_uuencode(m) == NOK)
{
sprintf(ebuf, "WARNING: parse_message: UUencode decode failed :%lu",
inbuf->loffset);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "%s\n", ebuf);
#endif
logger(LOG_WARNING, ebuf);
status = NOK;
}
else
status = OK;
break;
case EBASE64:
if (decode_base64(m) == NOK)
{
sprintf(ebuf, "WARNING: parse_message: Base64 decode failed :%lu",
inbuf->loffset);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "%s\n", ebuf);
#endif
logger(LOG_WARNING, ebuf);
status = NOK;
}
else
status = OK;
if (inbuf->bodyend == 0)
inbuf->bodyend = inbuf->end;
break;
case EQP:
if (decode_quoted_printable(m) == NOK)
{
sprintf(ebuf, "WARNING: parse_message: Quoted-Printable decode failed :%lu",
inbuf->loffset);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "%s\n", ebuf);
#endif
logger(LOG_WARNING, ebuf);
status = NOK;
}
else
status = OK;
if (inbuf->bodyend == 0)
inbuf->bodyend = inbuf->end;
break;
default:
status = OK;
break;
}
return(status);
}
int
boundary_check(struct message *m)
{
struct message *parent;
int encoding;
int check;
encoding = m->sd->encoding;
check = m->sd->check;
parent = m->parent;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "checking part %d with check %d and encoding %d\nat offset %lu\n",
m->sd->count, check, encoding, m->sd->offset);
#endif
/* Check a multipart, look for start boundary */
if (parent != NULL && parent->sd->startbound != NULL &&
(strlen(parent->sd->startbound)) != 0)
{
if (is_bound(m->sd, parent->sd->startbound))
{
return(E7BIT); /* Just a precaution */
}
}
/* Check for uuencode */
if (check & EUUENCODE)
{
if (encoding & EUUENCODE)
return(0);
/* Check for binhex and uuencode */
if (strncmp((m->sd->contents + m->sd->offset), "begin ", 6) == 0)
{
return(EUUENCODE);
}
}
/* Check for BinHex */
if (check & EBINHEX)
{
if (encoding & EBINHEX)
return(0);
/* Check for BinHex */
if (strncasecmp((m->sd->contents + m->sd->offset), "(This file ", 11) == 0)
{
return(EBINHEX);
}
}
if (encoding == 0)
return(E7BIT);
return(0);
}
/*
*
*/
int
is_bound(struct data *d, char *boundary)
{
int blen;
if (boundary != NULL &&
(blen = strlen(boundary)) != 0)
{
/*
printf("is_bound: '%20.20s'\n '%20.20'\n",
d->contents+d->offset,
boundary);
*/
if (d->offset + blen < d->end &&
strncmp((d->contents + d->offset), boundary, blen) == 0)
{
return(TRUE);
}
}
return(FALSE);
}
/*
*
*/
struct message *
copy_mstruct(struct message *m, int force)
{
struct data *cbuf, *inbuf;
struct message *cm;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Copying structure\n");
#endif
inbuf = m->sd;
if (force < 2)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Creating new data structure\n");
#endif
/* Copy data structure */
cbuf = (struct data *) Yalloc(sizeof(struct data));
cbuf->contents = inbuf->contents; /* data */
cbuf->offset = inbuf->offset; /* and offset */
cbuf->check = inbuf->check;
cbuf->size = inbuf->size;
cbuf->count = inbuf->count + 1;
cbuf->loffset = inbuf->loffset;
cbuf->charset = inbuf->charset;
cbuf->format = inbuf->format;
}
else
cbuf = m->sd;
/* Copy message structure */
if (force < 1 && m->sd->format == RFC822)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Living with old message structure\n");
#endif
m->sd->next = cbuf;
m->sd = m->sd->next;
m->td = m->sd;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "Reached offset %lu\n", m->sd->offset);
#endif
return(m);
}
else
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Copying message structure\n");
#endif
cm = (struct message *) Yalloc(sizeof(struct message));
cm->sdl = cbuf;
cm->sd = cm->sdl;
cm->td = cbuf;
return(cm);
}
}
/*
* int
* getline(inbuf)
*
* Move pointer to next line of inbuf. Return line length.
*/
int
getline(struct data *inbuf)
{
unsigned char *tmp;
if (inbuf == NULL || inbuf->contents == NULL ||
inbuf->offset >= inbuf->end)
return(0);
tmp = index(inbuf->contents + inbuf->offset, '\n');
if (tmp == NULL || (tmp - inbuf->contents) >= inbuf->end)
return(inbuf->end - inbuf->offset);
else
return(tmp - inbuf->contents + 1 - inbuf->offset);
}
int
set_end_by_boundary(struct message *m, char *boundary)
{
int linelen, offset, loffset;
struct data *inbuf;
inbuf = (struct data *)m->sd;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* set_end_by_boundary\n");
#endif
offset = inbuf->offset;
loffset = inbuf->loffset;
while (is_bound(inbuf, boundary) != TRUE)
{
if ((linelen = getline(inbuf)) == 0)
{
if (m->parent)
inbuf->bodyend = m->parent->sd->bodyend;
else
inbuf->bodyend = inbuf->offset;
inbuf->lineend = inbuf->loffset;
inbuf->offset = offset;
inbuf->loffset = loffset;
sprintf(ebuf, "set_end_by_boundary: cannot find boundary, setting end to %lu\n", inbuf->bodyend);
logger(LOG_DEBUG, ebuf);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "set_end_by_boundary: cannot find boundary, setting end to %lu\n", inbuf->bodyend);
#endif
return(NOK);
}
inbuf->offset += linelen;
inbuf->loffset += 1;
}
/* Set bodyend to just before the end boundary */
inbuf->bodyend = inbuf->offset;
inbuf->lineend = inbuf->loffset;
if (m->sd->format == MIME)
inbuf->bodyend -= 1;
inbuf->offset = offset;
inbuf->loffset = loffset;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Found boundary, setting end at %lu.\n", inbuf->bodyend);
#endif
return(OK);
}
int
set_end_by_lines(struct message *m, int lines)
{
int linelen, offset, loffset, lineend;
struct data *inbuf;
inbuf = (struct data *)m->sd;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* set_end_by_lines\n");
#endif
offset = inbuf->offset;
loffset = inbuf->loffset;
lineend = loffset + lines;
while ((linelen = getline(inbuf)) != 0 && lineend > inbuf->loffset)
{
inbuf->offset += linelen;
inbuf->loffset += 1;
}
/* Set bodyend to just before the end boundary */
inbuf->bodyend = inbuf->offset;
inbuf->lineend = inbuf->loffset;
inbuf->offset = offset;
inbuf->loffset = loffset;
return(OK);
}
/*
printf("is_bound: '%20.20s'\n '%20.20'\n",
d->contents+d->offset,
boundary);
*/
if (d->offset + blen < d->end &&
strncmp((d->contents + d->offset), boundary, blen) == 0)
{
return(TRUE);
}
}
return(FALSE);
}
/*
*
*/
struct message *
copy_mstruct(struct message *m, int force)
{
struct data *cbuf, *inbuf;
struct message *cm;
#ifdef DEBUG
if (emil-2.1.0-beta9/mime.c 100644 000000 000000 00000016400 06155035773 015071 0 ustar 00root system 000000 000000 /*
**
** 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 <time.h>
#include "emil.h"
char *getmimebound();
void
encode_mime(struct message *m)
{
char buf[HDRLEN];
char *ct;
char *bb = NULL;
if (m->sd->format == MIME && m->sd == m->td)
return;
if (m->level == 0)
{
rm_header(m, "X-Charset");
rm_header(m, "X-Char-Esc");
add_header(m, "MIME-Version", "1.0", MIME);
}
if ((ct = (char *)confextr("MIME", NULL, m->sd->type)) != NULL ||
(ct = (char *)confextr("MIME", NULL, "DEFAULT")) != NULL)
{
if (match(m->sd->type, "TEXT"))
{
if (m->td->charset != NULL)
sprintf(buf, "%s; charset=\"%s\"", ct, m->td->charset);
else
sprintf(buf, "%s", ct);
}
else
if (match(m->sd->type, "MULTIPART"))
{
bb = (char *)getmimebound();
if (m->sd->applefile == AMDOUBLE)
sprintf(buf, "Multipart/AppleDouble; boundary=\"%s\"", bb);
else
sprintf(buf,"%s; boundary=\"%s\"", ct, bb);
m->td->startbound = (char *)Yalloc(MIMEBOUNDLEN + 5);
m->td->endbound = (char *)Yalloc(MIMEBOUNDLEN + 7);
sprintf(m->td->startbound, "--%s", bb);
sprintf(m->td->endbound, "--%s--", bb);
}
else
{
sprintf(buf, "%s", ct);
}
}
else
/* Generic default */
sprintf(buf, "Application/Octet-Stream");
if (m->td->encoding == EBINHEX)
sprintf(buf, "application/mac-binhex40");
if (m->sd->name != NULL)
{
sprintf(buf, "%s; name=\"%s\"", buf, m->sd->name);
}
add_header(m, "Content-Type", buf, MIME);
if (bb != NULL)
rm_header(m, "Content-Transfer-Encoding");
else
switch(m->td->encoding)
{
case EQP:
add_header(m, "Content-Transfer-Encoding", "Quoted-Printable", MIME);
break;
case EBASE64:
add_header(m, "Content-Transfer-Encoding", "Base64", MIME);
break;
case E8BIT:
add_header(m, "Content-Transfer-Encoding", "8bit", MIME);
break;
case EUUENCODE:
add_header(m, "Content-Transfer-Encoding", "X-UUENCODE", MIME);
break;
case E7BIT:
case EBINHEX:
add_header(m, "Content-Transfer-Encoding", "7bit", MIME);
break;
default:
break;
}
if (m->sd->description != NULL)
add_header(m, "Content-Description", m->sd->description, MIME);
else
{
if (m->sd->name != NULL)
add_header(m, "Content-Description", m->sd->name, MIME);
}
}
int
decode_mime(struct message *m)
{
if (m->level == 0)
{
if (matchheader(m, "MIME-Version", "1.0", MIME))
{
m->sd->format = MIME;
}
else
return(NOK);
}
if (m->sd->format == MIME)
{
char *line = NULL;
/* Process content-type header line */
if((line = (char *)gethval(m, "Content-Type", MIME)) == NULL)
{
/* Use default if missing */
m->sd->type = NEWSTR("TEXT");
m->sd->charset = NEWSTR("US-ASCII");
m->sd->encoding = E7BIT;
}
else
{
while (isspace(*line))
line++;
/* Set type */
if (strncasecmp(line, "multipart/signed", 16) == 0)
{
m->sd->type = NEWSTR("_SIGNED_");
target->format = NEWSTR("MIME");
target->iformat = MIME;
return(OK);
}
else
if ((m->sd->type = (char *)
confextr("MIME", (char *)clear_end_space(stringpart(line, ";", 0))
, NULL)) == NULL)
{
if (strncasecmp(line, "Multipart", 9) == 0)
m->sd->type = NEWSTR("MULTIPART");
else
if ((m->sd->type = (char *)
confextr("MIME", "DEFAULT", NULL))
== NULL)
m->sd->type = NEWSTR("APPLICATION");
}
/* Get parameters for a few important types */
if (match(m->sd->type, "TEXT"))
{
m->sd->encoding = E7BIT;
/* Get m->charset for text */
m->sd->charset = (char *)fixstring(getpartrest(line, "charset=", ";"), NULL, NULL,
(short) UNQUOTE);
}
else
if (match(m->sd->type, "MULTIPART"))
{
/* Get boundaries for multipart */
m->sd->startbound = (char *)fixstring(getpartrest(line, "boundary=", ";"),
"--", NULL, (short) UNQUOTE);
m->sd->endbound = (char *)fixstring(getpartrest(line, "boundary=", ";"),
"--", "--", (short) UNQUOTE);
m->sd->encoding = EMULTI;
m->sd->check = EMULTI;
if (strncasecmp(line + 10, "appledouble", 11) == 0)
m->sd->applefile = AMDOUBLE;
if (strncasecmp(line + 10, "header-set", 10) == 0)
m->sd->applefile = AMDOUBLE;
}
if (match(m->sd->type, "APPLESINGLE"))
m->sd->applefile = ASINGLE;
if (match(m->sd->type, "BINHEX"))
m->sd->applefile = ABINHEX;
m->sd->name = (char *)fixstring(getpartrest(line, "name=", ";"),
NULL, NULL, (short) UNQUOTE);
}
/* Process content-transfer-m->encoding header line */
if (m->sd->encoding != EMULTI)
{
if ((line =
(char *)gethval(m, "Content-Transfer-encoding", MIME)) == NULL)
{
/* Use default if missing */
if (m->sd->encoding == 0)
{
m->sd->encoding = E7BIT;
}
}
else
{
if (cmatch(line, "7bit"))
m->sd->encoding = E7BIT;
else
if (cmatch(line, "quoted-printable"))
{
m->sd->encoding = EQP;
}
else
if (cmatch(line, "base64"))
{
m->sd->encoding = EBASE64;
}
else
if (cmatch(line, "8bit"))
m->sd->encoding = E8BIT;
else
if (cmatch(line, "binary"))
m->sd->encoding = EBINARY;
else
if (cmatch(line, "x-uuencode"))
{
m->sd->encoding = EUUENCODE;
}
else
if (cmatch(line, "x-binhex"))
{
m->sd->encoding = EBINHEX;
}
}
}
if (cmatch(m->sd->type, "BINHEX"))
{
m->sd->encoding = EBINHEX;
}
m->sd->description = (char *)gethval(m, "Content-description", MIME);
line = (char *)gethval(m, "Content-Disposition", MIME);
}
else
return(NOK);
return OK;
}
char *
getmimebound()
{
char * bound;
static long t;
int i;
bound = Yalloc(MIMEBOUNDLEN + 1);
strcpy(bound, "===_Emil_v2_Boundary_===");
if (t==0) { time(&t); srand((unsigned int) t); }
for (i=24; i < MIMEBOUNDLEN - 2 ; i++)
bound[i]=
"ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz"[rand()%50];
return bound;
}
it", MIME);
break;
default:
break;
}
if (m->sd->description != NULL)
add_header(m, "Content-Description", m->sd->description, MIME);
else
{
if (m->sd->name != NULL)
add_header(m, "Content-Description", m->sd->name, MIemil-2.1.0-beta9/mimeparse.c 100644 000000 000000 00000014377 06155035773 016137 0 ustar 00root system 000000 000000 /*
**
** 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
* parse_message(inbuf, message)
*
* Parse message and divide into a hierarchical structure of message parts.
*
*/
int
parse_mime_message(struct message *m)
{
struct data *inbuf;
static int not_first = 0;
/* Initialize inbuf */
inbuf = (struct data *)m->sd;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Parsing (MIME) body part %d at level %d and offset %lu.\n",
inbuf->count,
m->level,
inbuf->offset);
#endif
/* Exit on empty input */
if (inbuf->size == 0 || (inbuf->end <= inbuf->offset))
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "*** Empty input (failed).\n");
#endif
logger(LOG_ERR, "parse_message: Empty input");
return(NOK);
}
if (not_first)
{
/* Check header if possible */
if (!m->headerdone && (m->sd->format != RFC822 || m->level == 0))
if (check_header(m) != OK)
return(NOK);
}
else
not_first = 1;
/* Body starts here */
inbuf->bodystart = inbuf->offset;
inbuf->linestart = inbuf->loffset;
/* If Multipart create a child and run parse_message
* on the child.
* If MIME Multipart define the end boundary as end of
* current data. If Mailtool Multipart define end according
* to the lines field. Else leave end undefined.
*/
if (inbuf->encoding == EMULTI)
{
int status;
if ((status = parse_mime_multi(m)) == OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Marked up (MIME) multipart %d at level %d starting at %lu and ending at %lu.\n",
inbuf->count,
m->level,
inbuf->bodystart,
inbuf->bodyend);
#endif
return(OK);
}
if (status == NOK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ MIME body part %d at level %d failed.\n",
inbuf->count,
m->level);
#endif
return(NOK);
}
}
else
{
if (m->sd->bodyend == 0)
m->sd->bodyend = m->sd->end;
}
if (check_encoding(m) != OK)
m->sd->encoding = E7BIT;
return(OK);
}
int
parse_mime_multi(struct message *m)
{
struct data *childbuf, *inbuf;
struct message *childm;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ parse_mime_multi\n");
#endif
inbuf = (struct data *)m->sd;
/* Find end of part if prematured by an end boundary (MIME) */
if (m->sd->endbound != NULL)
set_end_by_boundary(m, m->sd->endbound);
else
{
/* Body end is end of data */
inbuf->bodyend = inbuf->end;
inbuf->lineend = inbuf->lend;
}
/* Copy off a child */
childm = (struct message *)copy_mstruct(m, 0);
/* Set more child data */
childbuf = childm->sd;
childm->level = m->level + 1;
childm->parent = m;
childm->bigsib = childm; /* Loop back */
childbuf->end = (inbuf->bodyend != 0) ? inbuf->bodyend: inbuf->end;
childbuf->lend = (inbuf->lineend != 0) ? inbuf->lineend: inbuf->lend;
childbuf->offset = inbuf->bodystart;
if (parse_mime_siblings(childm) == OK)
{
m->child = childm;
#ifdef DEBUG
if (edebug)
fprintf(stderr, " *parse_mime_multi: success, multipart OK\n");
#endif
return(OK);
}
else
{
/* Erroneous multipart, set type to text instead and
* run test check below
*/
#ifdef DEBUG
if (edebug)
fprintf(stderr, " *parse_mime_multi: failed, set type to TEXT\n");
#endif
m->sd->encoding = E7BIT;
m->sd->type = NEWSTR("TEXT");
check_bits(m->sd);
return(FAIL);
}
}
int
parse_mime_siblings(struct message *m)
{
struct data *inbuf, *sibbuf;
struct message *sibm;
inbuf = m->sd;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ parse_mime_siblings\n");
#endif
/* Parse child */
/* If this is a body part in a multipart with startbound set
* find the start of this body part
*/
if (m->parent != NULL && m->parent->sd->startbound != NULL)
{
if (move_past_boundary(m, m->parent->sd->startbound) != OK)
return(NOK);
}
/* If multipart, find end of bodypart */
if (m->parent != NULL && m->parent->sd->startbound != NULL)
set_end_by_boundary(m, m->parent->sd->startbound);
parse_mime_message(m);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Marked up (MIME) body part %d at level %d starting at %lu and ending at %lu.\n",
inbuf->count,
m->level,
inbuf->bodystart,
inbuf->bodyend);
#endif
m->sd->offset = m->sd->bodyend;
if (getline(m->sd) == 0)
return(OK);
if (m->sd->offset < m->sd->end)
{
/* Allocate siblings data sructure */
sibm = (struct message *)copy_mstruct(m, 0);
sibbuf = sibm->sd;
sibbuf->end = inbuf->end;
sibbuf->lend = inbuf->lend;
sibbuf->offset = inbuf->bodyend;
sibm->bigsib = m->bigsib;
sibm->level = m->level;
sibm->parent = m->parent;
/* Run Sibling */
if (parse_mime_siblings(sibm) == OK)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "* sibling ended at offset %lu\n", sibbuf->offset);
#endif
m->sibling = sibm;
if (m->parent)
m->parent->children += 1;
return(OK);
}
else
return(NOK);
/* Successful return from current part */
return(OK);
}
return(OK);
}
ne, "base64"))
{
m->sd->encoding = EBASE64;
}
else
if (cmatch(line, "8bit"))
m->sd->encoding = E8BIT;
else
if (cmatch(line, "binary"))
m->sd->encoding = EBINARY;
else
if (cmatch(line, "x-uuenemil-2.1.0-beta9/ns.c 100644 000000 000000 00000010477 06155035773 014572 0 ustar 00root system 000000 000000 /*
**
** 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"
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#ifdef PACKETSZ
#define MAXPACKET PACKETSZ
#else
#define MAXPACKET 1024
#endif
#ifdef NAMED_BIND
#ifdef HAVE_RES_SEARCH
typedef union {
HEADER hdr;
u_char buf[MAXPACKET];
} querybuf;
struct mxlist *
get_mx(char *dname)
{
querybuf answer;
register HEADER *hp;
register u_char *cp;
register int n;
u_char *eom;
char *bp;
char hostbuf[BUFSIZ + 1];
int type, class, buflen, ancount, qdcount;
int lpreference, preference;
int anslen;
struct mxlist *list, *tlist, *wlist;
type = T_MX;
list = NULL;
if ((_res.options & RES_INIT) == 0 && res_init() == -1)
{
fprintf(stderr, "Emil SMTP: res_init(): Check /etc/resolv.conf");
return(NULL);
}
if ((anslen = res_search(dname, C_IN, type, answer.buf, sizeof(answer))) < 0) {
switch (errno) {
case TRY_AGAIN:
exit(EX_TEMPFAIL);
break;
default:
/* MX lookup failed */
return(NULL);
break;
}
}
eom = answer.buf + anslen;
lpreference = -1; /* Set lowest preference unset */
/*
* find satisfactory answer
*/
hp = &answer.hdr;
ancount = ntohs(hp->ancount);
qdcount = ntohs(hp->qdcount);
bp = hostbuf;
buflen = sizeof(hostbuf);
cp = answer.buf + sizeof(HEADER);
/*
* Skipping over question entries
*/
if (qdcount) {
cp += dn_skipname(cp, eom) + QFIXEDSZ;
while ( --qdcount > 0)
cp += dn_skipname(cp, eom) + QFIXEDSZ;
}
/*
* Extracting hostnames from answer entries
*/
while (--ancount >= 0 && cp < eom) {
if ((n = dn_expand((char *)answer.buf, eom, cp, bp, buflen)) < 0) {
break;
}
cp += n;
type = _getshort(cp);
if (type == T_MX) {
cp += sizeof(u_short);
class = _getshort(cp);
cp += sizeof(u_short) + sizeof(u_long);
cp += sizeof(u_short);
/* MX RDATA */
preference = _getshort(cp);
cp += sizeof(u_short);
if ((n = dn_expand((char *)answer.buf, eom, cp, bp, buflen)) < 0) {
break;
}
tlist = (struct mxlist *)Yalloc(sizeof(struct mxlist));
tlist->host = NEWSTR(bp);
tlist->preference = preference;
if (list == NULL || preference < lpreference)
{
lpreference = preference;
tlist->next = list;
list = tlist;
}
else
{
/* Sort by preference */
for (wlist = list; wlist->next != NULL; wlist = wlist->next)
if (wlist->next->preference > preference)
break;
tlist->next = wlist->next;
wlist->next = tlist;
}
cp += n;
}
}
if (list == NULL)
return(NULL);
#ifdef DEBUG
if (edebug)
for (wlist = list; wlist != NULL; wlist = wlist->next)
fprintf(stderr, "Emil MX: %s preference %d\n", wlist->host, wlist->preference);
#endif
/* Removing localhost and lower preferences */
if (cmatch(list->host, SMTPHOSTNAME))
list = NULL;
else
for (wlist = list; wlist->next != NULL; wlist = wlist->next)
if (cmatch(wlist->next->host, SMTPHOSTNAME))
{
wlist->next = NULL;
break;
}
return(list);
}
#endif
#endif
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**
** Martin.Wendel@its.uu.se
** Torbjorn.Wictorin@its.uu.se
**
**emil-2.1.0-beta9/out.c 100644 000000 000000 00000016677 06155035774 014772 0 ustar 00root system 000000 000000 /*
**
** 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"
extern FILE *out_fd;
extern int smtp_client;
static void print_rheader(struct header *, int); /* forward */
static void print_hvalue(struct hprs *);
static void print_hbody(struct data *);
char *eol = NULL;
void out_message(struct message *m)
{
if (m == NULL)
return;
if (eol == NULL)
{
if (smtp_client)
eol = NEWSTR("\r\n");
else
eol = NEWSTR("\n");
}
if (det_sket_sig == TRUE)
{
m->sd->offset = 0;
m->sd->bodystart = 0;
m->sd->bodyend = m->sd->end;
print_body(m->sd, m->parent);
return;
}
if (m->parent != NULL && target->iformat != RFC822)
if (m->parent->td->startbound != NULL)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Start boundary %s\n", m->parent->td->startbound);
#endif
if (target->iformat == MIME)
fprintf(out_fd, "%s%s%s", eol, m->parent->td->startbound, eol);
else
if (m->td->encoding != EMULTI)
fprintf(out_fd, "%s%s", m->parent->td->startbound, eol);
}
/* encode_header(m); */
if (target->iformat != RFC822 || m->level == 0)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Printing header.\n");
#endif
print_rheader(m->h, target->iformat);
fprintf(out_fd, "%s", eol); /* End of header */
}
if (m->td->bodyend)
m->td->end = m->td->bodyend;
m->td->offset = m->td->bodystart;
if (m->td->encoding != EMULTI)
print_body(m->td, m->parent);
if (m->child != NULL)
out_message(m->child);
if (m->td->endbound != NULL && target->iformat == MIME)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ End boundary %s\n", m->td->endbound);
#endif
fprintf(out_fd, "%s%s%s", eol, m->td->endbound, eol);
}
if (m->sibling != NULL)
out_message(m->sibling);
fflush(out_fd);
}
void print_body(struct data *d, struct message *parent)
{
struct data *line;
long count;
int len;
int doeol = 0;
int checkeol = 0;
if (d == NULL)
{
#ifdef DEBUG
fprintf(stderr, "* print_body: Called with NULL input, ignoring...\n");
#endif
return;
}
if ((target->iformat != MIME) || (parent == NULL))
checkeol = 1;
line = (struct data *)Yalloc(sizeof(struct data));
if (det_sket_sig == TRUE)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "*** Printing transparent.\n");
#endif
count = 0;
}
else
{
count = 1;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Print body.\n");
#endif
}
d->offset = d->bodystart;
while ((len = getline(d)) != 0)
{
line->end = 0;
append_data(line, (d->contents + d->offset), len, MED_BUF);
if (checkeol)
{
if (index(line->contents, '\n') == NULL)
{
doeol = 1;
#ifdef DEBUG
if (edebug)
fprintf(stderr, "No EOL at line starting on d->offset = %d\n",
d->offset);
#endif
}
}
else
doeol = 0;
if (strcmp(line->contents, ".\n") == 0 ||
strcmp(line->contents, ".\r\n") == 0)
fprintf(out_fd, ".");
if (count)
{
if (strncmp(line->contents, "From ", 5) == 0)
fprintf(out_fd, ">");
print_line(line->contents);
}
else
{
if (want_unix_from == 0)
{
#ifdef OLD_UNIX_FROM
if (strncmp(line->contents, "From ", 5) == 0)
{
d->offset += len;
count++;
continue;
}
else
#endif /* OLD_UNIX_FROM */
print_line(line->contents);
}
else
{
if (strncmp(line->contents, "From ", 5) == 0)
print_line(line->contents);
else
{
fprintf(out_fd, "From %s%s", sender, eol);
print_line(line->contents);
}
}
}
d->offset += len;
count++;
fflush(out_fd);
}
if (doeol)
fprintf(out_fd, "%s", eol);
fflush(out_fd);
}
static void print_rheader(struct header *h, int format)
{
struct header *th;
static int hcount = 0;
for (th = h; th != NULL; th = th->next)
{
#ifdef OLD_UNIX_FROM
if (th->type == UNIXFROM && want_unix_from == 0)
continue;
#endif /* OLD_UNIX_FROM */
if (hcount == 0 && want_unix_from && th->type != UNIXFROM
&& sender != NULL)
fprintf(out_fd, "From %s%s", sender, eol);
hcount++;
if (th->field != NULL && th->field->end != 0 &&
(th->format == RFC822 || th->format == format))
{
parse_rfc1522(th);
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Print header (%s).\n",
th->field->contents);
#endif
/*
if (*th->field->contents == '>')
fprintf(out_fd, "%s", th->field->contents + 1);
else
*/
fprintf(out_fd, "%s", th->field->contents);
if (th->type != UNIXFROM)
{
fprintf(out_fd, ": ");
if (th->hvalue != NULL)
(void)print_hvalue(th->hvalue);
else
if (th->value != NULL && th->value->end != 0)
print_line(th->value->contents);
}
fprintf(out_fd, "%s", eol);
}
}
}
static void print_hvalue(struct hprs *h)
{
#ifdef DEBUG
if (edebug)
fprintf(stderr, "+ Printing hvalue structure.\n");
#endif
switch (h->type)
{
case ATOM:
case DELIMITER:
case RFC1522:
h->td->offset = h->td->bodystart;
print_hbody(h->td);
break;
case DLITERAL:
fprintf(out_fd, "[");
break;
case COMMENT:
fprintf(out_fd, "(");
break;
case HQSTRING:
fprintf(out_fd, "\"");
break;
case RADDR:
fprintf(out_fd, "<");
break;
default:
break;
}
if (h->child != NULL)
print_hvalue(h->child);
switch(h->type)
{
case DLITERAL:
fprintf(out_fd, "]");
break;
case COMMENT:
fprintf(out_fd, ")");
break;
case HQSTRING:
fprintf(out_fd, "\"");
break;
case RADDR:
fprintf(out_fd, ">");
break;
default:
break;
}
if (h->sibling != NULL)
print_hvalue(h->sibling);
}
static void print_hbody(struct data *d)
{
struct data * line;
line = (struct data *)Yalloc(sizeof(struct data));
append_data(line, (d->contents + d->offset), d->bodyend - d->offset, MED_BUF);
print_line(line->contents);
}
int
print_line(char *s)
{
char *e, *c;
int len;
if (s == NULL)
return(OK);
len = strlen(s);
while ((c = index(s, '\n')) != NULL)
{
e = c + 1;
while (*c == '\n' || *c == '\r')
{
*c = '\0';
c--;
}
fprintf(out_fd, "%s%s", s, eol);
s = e;
}
if (*s != '\0')
fprintf(out_fd, "%s", s);
return(OK);
}
intf(stderr, "*** Printing transparent.\n");
#endif
count =emil-2.1.0-beta9/doc/ 042755 000145 000001 00000000000 06155036020 014632 5 ustar 00martin staff 000000 000000 emil-2.1.0-beta9/doc/arrow_left3.gif 100644 000145 000001 00000000356 06115041766 017560 0 ustar 00martin staff 000000 000000 GIF87a0 0 , 0 0 ̈́#
Zp3dX깖bn*}ky&Hx#$:L0X <E궻Ս>W5Xq蘠h%99Py 1eȳEک9::j*)*zCZ(KRjfˢGLyۊ)%l=
},<Q ;ybK1kd9U
lastupdate = 801996431
flags =
anders:
password = W95Vbp56hZa1Y
lastupdate = 799583538
flags =
thomas:
password = 7hJQqj/nPs2ig
lastupdate = 803291233
flags =
kalle:
password = Gp7QToVu.SUbQ
lastupdate = 803291802
flags =
bug:
password = BYdeiq.emil-2.1.0-beta9/doc/index.shtml 100644 000000 000000 00000007665 06115536623 016734 0 ustar 00root system 000000 000000 <TITLE>Emil's Workshop version 2.1</TITLE>
<H1>Emil's Workshop</H1>
<P>(Emil is copyright SUNET and is made available under the<EM> GNU General Public License</EM>.)<BR><BR>
<EM>This page is written by Martin Wendel, ITS, Uppsala university:
Martin.Wendel@its.uu.se.
</EM>
<BR>
<HR>
<H3>General Info</H3>
<P>Emil v2 is a filter for converting Internet Messages.
It supports three basic formats: MIME, SUN Mailtool and
plain old style RFC822. It can be used with sendmail, as
a loopback mailer, or as a prefilter or backend program
with a mail client program, or as a plain filter.
<P>Emil v2 is a complete rewrite of Emil-v1. New features
are support for RFC1522 headers and a more robust basic
structure.
<P>The purpose of Emil v2 is to facilitate the official
migration to MIME for Internet Mail on SUNET (the Swedish
University Network), on hosts or sites unable to support
MIME. The migration was due on 1 Jan 1995. Information
about this is made available by SUNET at
<a href=http://www.nada.kth.se/sunet-mime/index-en.html>
http://www.nada.kth.se:/sunet-mime/index-en.html.</A>
<H3>What is Emil?</H3>
<P>Simply put, Emil is a message format converter for Internet
Messages. This is a general description:
<DL>
<LI> Emil is able to convert the format, headers and structure,
between messages of type MIME, Sun Mailtool and old style
RFC822.
<LI> Emil is able to convert the encoding of binary data
between the types Base64, BinHex and Uuencode.
<LI> Emil is able to convert the encoding of text to and from
the MIME encoding Quoted-Printable.
<LI> Emil is able to convert character set of text between the
character sets made available by Keld J. Simonsens strncnv
package. The strncnv package handles a large number of
character sets, as specified by RFC1345.
<LI> Emil also includes two special conversions for text:
<DL>
<LI>SE conversion, which is a one-way
conversion of 8bit text to the swedish national
variant of ISO-646.
<LI>7bit conversion, which is a one-way
conversion of 8bit text to characters in US-ASCII
of the closest resemblance.
</DL>
<LI> Emil is able to convert to and from RFC1522 format headers.
<LI> Conversion can be configured by a configuration file,
emil.cf, using sender, recipient and recipient host as input
parameters or by command line arguments.
</DL>
<H3>Why Use Emil?</H3>
<BR>
<DL>
<LI>In the SUNET case, usage is obvious. A national network
decides to migrate to MIME formatted mail. Emil is used
by the hosts or sites unable to support MIME. The effect
is outgoing MIME messages and incoming non-MIME messages.
<LI> Another example is non-MIME sites receiving occasional
MIME messages. Emil can be configured to convert these
incoming MIME messages to old style RFC822 and convert
the Base64 encodings to uuencode or BinHex.
<LI>Emil can be used as a tool. A user unable to decode MIME
messages can convert those messages using Emil.
<LI>et cetera.
</DL>
<BR>
<H3>Where can I find Emil?</H3>
<P> Emil is available by anonymous ftp from a large number of
sites. The latest version can always be found at Emil's home site
ftp://ftp.uu.se/pub/unix/networking/mail/emil/.
<a href="ftp://ftp.uu.se/pub/unix/networking/mail/emil">Click here</A>
to download now.
<H3>More info about Emil?</H3>
I've assembled a small tutorial that will give you a guided tour
on the design of Emil and how to use it.
<a href="main.html">Click here</a> to start now.
<BR>
<H3>The Authors</H3>
<P>Emil v2 is constructed by Martin Wendel and Torbjörn Wictorin
both working at Uppsala university in Sweden.
<hr size="4" noshade>
<ADDRESS>
<table WIDTH="95%">
<td>
March 1996<p>
<B>ITS Uppsala university</B><BR>
Box 887<BR>
751 08 Uppsala<BR>
SWEDEN<P>
</td>
<td ALIGN="right" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">Martin Wendel</a>
</td>
<td ALIGN="left" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">
<IMG border="0" SRC="binpobox.gif" ALT="E-Mail: "></a>
</td>
</table>
</ADDRESS>
</body>
</html>
emil-2.1.0-beta9/doc/why.html 100755 000000 000000 00000003427 06115314141 016231 0 ustar 00root system 000000 000000 <HEAD>
<TITLE>EMIL version 2 TUTORIAL</TITLE>
</HEAD>
<BODY>
<H1>TUTORIAL FOR EMIL VERSION 2.1
</H1>
<EM>Written by Martin Wendel, ITS, Uppsala university.
Martin.Wendel@its.uu.se
</EM>
<HR>
<A HREF=way.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A><A HREF=intro.html><IMG ALIGN=MIDDLE SRC=arrow_left3.gif></A>
<H2>WHY USE MESSAGE CONVERSION?
</H2>
<P>
The major motive for using message conversion is the need to convert
character set of a message text. The reason for this is that character
sets in internet messages (at least outside of the English speaking
countries) is a mess. <EM>When the common characters in US-ASCII does not
fully support the national alphabet, character set really matter when
you receive a message text.</EM>
<P>
The second motive is encoding. The problem is similar to that of
character sets. You normally do not support more than one or a few
encoding standards on your local mail agent. <EM>Therefore it is a big gain
in usability if you can convert messages to use the encodings your mail
agent supports.</EM>
<P>
The third motive is message format. The most commonly used formats for
Internet messages in Sweden is plain old style rfc822, Sun Mailtool, and
MIME. Neither of those formats is suited to interprate any of the other
ones.
<hr size="4" noshade>
<ADDRESS>
<table WIDTH="95%">
<td>
March 1996<p>
<B>ITS Uppsala university</B><BR>
Box 887<BR>
751 08 Uppsala<BR>
SWEDEN<P>
</td>
<td ALIGN="right" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">Martin Wendel</a>
</td>
<td ALIGN="left" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">
<IMG border="0" SRC="binpobox.gif" ALT="E-Mail: "></a>
</td>
</table>
</ADDRESS>
</body>
</html>
line arguments.
</DL>
<H3>Why Use Emil?</H3>
<BR>
<DL>
<LI>In the SUNET case, usage is obvious. A national network
decides to migrate to MIME formatted mail. Emil is used
by the hosts or sites unable to support MIME. The effect
iemil-2.1.0-beta9/doc/way.html 100755 000000 000000 00000016356 06115315670 016237 0 ustar 00root system 000000 000000 <HEAD>
<TITLE>EMIL version 2 TUTORIAL</TITLE>
</HEAD>
<BODY>
<H1>TUTORIAL FOR EMIL VERSION 2.1
</H1>
<EM>Written by Martin Wendel, ITS, Uppsala university.
Martin.Wendel@its.uu.se
</EM>
<HR>
<A HREF=comparison.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A><A HREF=why.html><IMG ALIGN=MIDDLE SRC=arrow_left3.gif></A>
<H2>HOW EMIL V2 DOES MESSAGE CONVERSION.
</H2>
<P>
To be able to understand message conversion it is important to understand
the components of a message and the types of these components. Basically
a message consists of a header and a body. The format of the header is
thoroughly defined in rfc822 and rfc1522. Basically it consists of lines
of text divided into two parts; the field and the value, separated by
a colon ':'. Apart from a few details the header is very straight forward.
The body, on the other hand, is somewhat more tricky to understand.
<P>
The body of a message consists of text or/and encoded data, where data
may refer to text as well. Emil recognizes the encodings BinHex, Base64,
Quoted-Printable and UUencode. Text is the parts of the message that is
not recognized as being an encoded enclosure. Text is a raw format whereas
encoded data follows the syntax of the encoding. <EM>This means that incorrect
or incomplete encodings are not recognized and are thus treated as raw text
(as a safety measure).</EM>
<P>
Emil works in a two pass manner. After loading the message, it first
interprets the header and body of the message before applying any
conversions. First the format is recognized. This is done by interprating
the header of the message. Then the data of the message is structured into
a hierarchical message structure.
<P>
UUencoded and BinHexed enclosures are recognized by their preamble and a
syntax check is made on them to make pretty sure they are valid. When emil
receives a MIME or Mailtool message, encoded enclosures are defined in the
header. Emil recognizes these definitions and trusts them to be valid, no
further processing is done initially. The rest of the body parts and the
erroneous BinHex and UUencode parts are treated as text. The text is checked
for 7bit or 8bit encoding.
<P>
Emil now has a hierarchical representation of the message and each part
is type marked by it's encoding. It may be that the trusted encodings of a MIME
or Mailtool message are erroneous as well. However, the definitions in the
header is a strong evidence that they must be correct. In the case of error,
in spite of all that,
the message part is left untouched, but not treated as text.
<P>
<EM>Conversion is applied as specified by the target format.</EM> Emil has a
clear view of the incoming message and can work pretty straight forward
parsing the hierarchical structure. Each object in the structure contains
headers, data, and pointers to other objects. When applying conversion, first
the data of each object is converted to what's specified in the target format,
then the headers of each object is taken care of based on the resulting type
and encoding of the data of the objects.
<P>
<B>An example:</B> The target format specifies Sun Mailtool, UUencoded attachments
and ISO-646-SE text. A MIME message containing a Quoted-Printable encoded
text/plain using ISO-8859-1 and a Base64 encoded Image/GIF will be converted
as follows (this is a fairly long and detailed description):
<OL>
<LI>The entire message is loaded into memory.
<LI>The header of the message is examined and loaded into a structure.
<DIR>
<LI>This yields format MIME and type Multipart/Mixed. The boundary
is saved.
</DIR>
<LI>The start of the body of the message is marked up at the end of
the header.
<LI>Find the end boundary, the end of the message is marked just
before the end boundary. The root object in the message structure
is completed.
<LI>Start off a child object.
<LI>We've got boundaries, go find the first boundary.
<LI>Examine the header of the first body part.
<DIR>
<LI> This yields type=Text/plain, charset=ISO-8859-1 and
encoding=Quoted-Printable.
</DIR>
<LI>Find the second boundary, terminating the first body part and
initiating the second. The first child object is completed.
<LI>Start off a sister object to the previous child object.
<LI>Examine the header of the second body part.
<DIR>
<LI> This yields type=Image/GIF, encoding=Base64.
</DIR>
<LI>There are no more boundaries (the end boundary was detected
in [3] and end of data as seen by the second bodypart is marked
just before the end boundary), terminating the second bodypart.
<LI>End of data is reached, message parsing is completed. We've got
a hierarchical message structure describing the incoming message.
<LI>Apply conversion.
<LI>Parse the message structure, converting the data.
<LI>First object (root object) is multipart, no data to be converted.
<LI>Second object (first child) is a text with charset=ISO-8859-1
and encoding quoted-printable.
<LI>Target format does not want quoted-printable and does not want
charset=ISO-8859-1. Thus, decode quoted-printable.
<DIR>
<LI> This yields an 8bit text with charset=ISO-8859-1.
</DIR>
<LI>Target format does not want charset=ISO-8859-1. Convert charset
to ISO-646-SE.
<DIR>
<LI> This yields a 7bit text with charset=ISO-646-SE.
</DIR>
<LI>Target format wants charset=ISO-646-SE, conversion on this data
is completed.
<LI>Third object (second child) is a GIF encoded in Base64.
<LI>Target format does not want Base64, decode Base64.
<DIR>
<LI> This yields a GIF with encoding=binary.
</DIR>
<LI>Target format does not want binary, encode UUencode.
<DIR>
<LI> This yields a GIF with encoding=UUencode.
</DIR>
<LI>Target format wants UUencode, conversion on this data is completed.
<LI>All data is now converted according to the target format. Start
converting headers.
<LI>All the MIME-specific headers in the root header are marked as such
in the first parse of the header. This includes
MIME-Version and Content-Type. These will not be part of the output.
<LI>The root object is a multipart, add header Content-Type
X-Sun-Encoding. Also add the Mailtool boundary to the boundary
string.
<LI>The second bodypart is a text. Add the Mailtool headers. Also
add header Content-Lines: number of lines.
<LI>The second bodypart is a GIF. Add the Mailtool headers. Also add
header Content-Lines: number of lines.
<LI>The message conversion is completed. Output the message.
<LI>Print the root header.
<LI>Print the Mailtool boundary.
<LI>Print the header of the first child.
<LI>Print the body of the first child.
<LI>Print the Mailtool boundary.
<LI>Print the header of the second child.
<LI>Print the body of the second child.
</OL>
<HR>
<A HREF=comparison.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A><A HREF=why.html><IMG ALIGN=MIDDLE SRC=arrow_left3.gif></A>
<hr size="4" noshade>
<ADDRESS>
<table WIDTH="95%">
<td>
March 1996<p>
<B>ITS Uppsala university</B><BR>
Box 887<BR>
751 08 Uppsala<BR>
SWEDEN<P>
</td>
<td ALIGN="right" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">Martin Wendel</a>
</td>
<td ALIGN="left" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">
<IMG border="0" SRC="binpobox.gif" ALT="E-Mail: "></a>
</td>
</table>
</ADDRESS>
</body>
</html>
e encoded
text/plain using ISO-8859-1 and a Base64 encoded Image/GIF will be converted
as follows (this is a fairly long and detailed description):
<OL>
<LI>The entire message is loaded into memory.
<LI>The header of the message is examined and loaded into a structure.
emil-2.1.0-beta9/doc/control.html 100755 000000 000000 00000002325 06115314265 017105 0 ustar 00root system 000000 000000 <HEAD>
<TITLE>EMIL version 2 TUTORIAL</TITLE>
</HEAD>
<BODY>
<H1>TUTORIAL FOR EMIL VERSION 2.1
</H1>
<EM>Written by Martin Wendel, ITS, Uppsala university.
Martin.Wendel@its.uu.se
</EM>
<HR>
<A HREF=arguments.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A><A HREF=using.html><IMG ALIGN=MIDDLE SRC=arrow_left3.gif></A>
<H2>CONTROLLING CONVERSION.
</H2>
<P>
There are two ways of controlling conversion using Emil. Either you
use command line arguments or you use the configuration file. <EM>When
using the configuration file you need to specify the mail address
of the sender and recipient and the name of the recipient host.</EM> These
are supplied by sendmail if you are using emil with sendmail.
<hr size="4" noshade>
<ADDRESS>
<table WIDTH="95%">
<td>
March 1996<p>
<B>ITS Uppsala university</B><BR>
Box 887<BR>
751 08 Uppsala<BR>
SWEDEN<P>
</td>
<td ALIGN="right" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">Martin Wendel</a>
</td>
<td ALIGN="left" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">
<IMG border="0" SRC="binpobox.gif" ALT="E-Mail: "></a>
</td>
</table>
</ADDRESS>
</body>
</html>
ESS>
</body>
</html>
e encoded
text/plain using ISO-8859-1 and a Base64 encoded Image/GIF will be converted
as follows (this is a fairly long and detailed description):
<OL>
<LI>The entire message is loaded into memory.
<LI>The header of the message is examined and loaded into a structure.
emil-2.1.0-beta9/doc/arguments.html 100755 000000 000000 00000013777 06155035512 017446 0 ustar 00root system 000000 000000 <HEAD>
<TITLE>EMIL version 2 TUTORIAL</TITLE>
</HEAD>
<BODY>
<H1>TUTORIAL FOR EMIL VERSION 2.1
</H1>
<EM>Written by Martin Wendel, ITS, Uppsala university.
Martin.Wendel@its.uu.se
</EM>
<HR>
<A HREF=configuration.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A><A HREF=control.html><IMG ALIGN=MIDDLE SRC=arrow_left3.gif></A>
<H2>COMMAND LINE ARGUMENTS
</H2>
<H3>Address specification arguments:
</H3>
<DIR>
<LI> -r <address> The address of the recipient.
<LI> -s <address> The address of the sender.
<LI> -x <hostname> The name of the recipient host.
</DIR>
<P>
The address specifications are used when you want to redirect output
to a program such as /bin/mail or sendmail. The usage of these addresses
is as arguments to the execv of the program. They are also used to
lookup sender and recipient information such as format and encoding etc.
Emil does not rewrite addresses, so beware the address format you use.
<H3> Target Group specification
</H3>
<DIR>
<LI> -G <group> The target conversion group.
</DIR>
<p>
The target group specification is used when you want Emil to act according
to a conversion profile specified in emil.cf. The conversion profile should be
specified in emil.cf using the group command (see the documentation of
emil.cf).
<H3> Format, Encodings and Charsets
</H3>
<DIR>
<LI> -A <appletype> The target applefile encoding style.
<LI> -B <encoding> The target binary encoding style.
<LI> -C <charset> The target charset.
<LI> -F <format> The target format.
<LI> -H <encoding> The target header encoding style.
<LI> -S <charset> The sender's charset.
<LI> -T <encoding> The target text encoding style.
</DIR>
<H4>Legal values</H4>
<UL>
<LI><appletype> One of:
<UL>
<LI> (s) AppleSingle
<LI> (d) AppleDouble
<LI> (b) BinHex
</UL>
<LI><format> One of:
<UL>
<LI> (MIME) MIME - MIME message format.
<LI> (MAILTOOL) Mailtool - SUN Mailtool message format.
<LI> (RFC822) RFC822 - Plain old style RFC822 message format.
<LI> (TRANSPARENT) Pass through the message as it is, without conversion.
</UL>
<LI><encoding> Choose between:
<UL>
<LI> (7) 7bit - 7bit encoding (if text or header, converts to US-ASCII).
<LI> (8) 8bit - 8bit encoding.
<LI> (s) se - convert to national variant of ASCII (for type text and header only).
<LI> (bi) binhex - BinHex encoding.
<LI> (u) uuencode - UUencode encoding.
<LI> (ba) base64 - Base64 encoding.
<LI> (q) quoted-printable - Quoted-Printable.
</UL>
<LI><charset> Any charset name as defined in rfc1345.
</UL>
<P>
It is possible to explicitly specify the format, encoding or charset of the
target message on the command line. If done, the lookup for this
information in the configuration file is disabled. Therefore, make sure
to <EM>apply a complete specification of the format and encoding features</EM> using
these arguments, if one of them is omitted the value of that feature will
be set to the default value.
<P><EM>The specification of the sender's charset will not override the charset
specification of a MIME or Mailtool message.</EM> Therefore this is really only
used when converting an old style RFC822 message.
<H3> Logging and Debug
</H3>
<DIR>
<LI> -d Debug output on stderr.
<LI> -f <facility> The log facility of syslog logging.
<LI> -h <level> The log level of header logging.
<LI> -l <level> The log level of syslog logging.
</DIR>
<H4>Legal values</H4>
<UL>
<LI><facility> Choose between:
<UL>
<LI> m - LOG_MAIL
<LI> d - LOG_DAEMON
<LI> 0 - LOG_LOCAL0
<LI> 1 - LOG_LOCAL1
<LI> 2 - LOG_LOCAL2
<LI> 3 - LOG_LOCAL3
<LI> 4 - LOG_LOCAL4
<LI> 5 - LOG_LOCAL5
<LI> 6 - LOG_LOCAL6
<LI> 7 - LOG_LOCAL7
</UL>
<LI><level> Choose between:
<UL>
<LI> 1 - LOG_ERR
<LI> 2 - LOG_NOTICE
<LI> 3 - LOG_INFO
<LI> 4 - LOG_DEBUG
</UL>
</UL>
<P>Logging and debug is controlled using the above command line arguments.
<H4> Configuration files
</H4>
<DIR>
<LI> -c <path> Path of charsets file.
<LI> -e <path> Path of configuration file.
</DIR>
<P>It is possible to explicitly specify the path of the configuration
or charsets files. If not specified, the default paths will be used.
<H4> I/O Specifications
</H4>
<DIR>
<LI> -i <path> Path of input file.
<LI> -m <mailer> The program to which to pipe output (see the configuration file).
<LI> -n Pipe output to the builtin SMTP client.
<LI> -o <path> Path to output file.
<LI> -p Add pseudo route to recipient address.
<LI> -u Wants UNIX style from line.
</DIR>
<P>Input/Output is controlled by command line arguments and this applies for
the SMTP client and the redirect of output to arbitrary programs aswell. When
using the builtin SMTP client, an SMTP connection to the <EM>recipient host</EM> (as
specified by the command line arguments) will be opened. In the SMTP
conversation, the specified <EM>sender</EM> and <EM>recipient</EM> addresses will be used.
<B>Therefore, make sure (when using this) that you have specified all three of
these arguments.</B>
<H4> Miscellaneous
</H4>
<DIR>
<LI> -g Return group match.
<LI> -v Print out version.
</DIR>
<P>It is possible the get information from Emil using the above flags.
These arguments disables all other activities and should be used
for testing purposes only. Emil will print the desired information and then exit.
<HR>
<A HREF=configuration.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A><A HREF=control.html><IMG ALIGN=MIDDLE SRC=arrow_left3.gif></A>
<hr size="4" noshade>
<ADDRESS>
<table WIDTH="95%">
<td>
March 1996<p>
<B>ITS Uppsala university</B><BR>
Box 887<BR>
751 08 Uppsala<BR>
SWEDEN<P>
</td>
<td ALIGN="right" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">Martin Wendel</a>
</td>
<td ALIGN="left" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">
<IMG border="0" SRC="binpobox.gif" ALT="E-Mail: "></a>
</td>
</table>
</ADDRESS>
</body>
</html>
emil-2.1.0-beta9/doc/details.html 100755 000000 000000 00000005067 06115314347 017061 0 ustar 00root system 000000 000000 <HEAD>
<TITLE>EMIL version 2 TUTORIAL</TITLE>
</HEAD>
<BODY>
<H1>TUTORIAL FOR EMIL VERSION 2.1
</H1>
<EM>Written by Martin Wendel, ITS, Uppsala university.
Martin.Wendel@its.uu.se
</EM>
<HR>
<A HREF=design-top.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A><A HREF=configuration.html><IMG ALIGN=MIDDLE SRC=arrow_left3.gif></A>
<H2>EMIL DETAILS</H2>
<P>
Emil has no mechanisms for handling spooling and message delivery errors.
Instead it relies on what is supplied by other programs, for example
sendmail, when it comes to handling these matters.
Normally Emil is setup as such that an originating process calls Emil and
sends a message to the stdin of Emil. After processing the message, Emil
sends the output either to another process, called by Emil, or to a file or
an SMTP stream. If sent to another process, and provided that the
conversion is otherwise successful, the return code of that process will be
returned by Emil to the originating process. If sent to a file or an SMTP
stream, the return code sent to the originating process will be that of the
conversion and output process made by Emil. In either case, the
originiating process will not get a return code from Emil until all further
processing and delivery, under control by Emil, is completed. This is to
make sure that the originating process will never receive a "delivery
successful" return code unless indicated successful by the subsequent
process or by Emil.
<P>
Emil is designed to be transparent when it comes to delivery failures. A
side effect of this is that a spooled copy of a message (for example by
sendmail) will not be unlinked until either control is successfully handed
over to another process (for example sendmail) or the message is safely
delivered to a file or SMTP stream. This is how Emil can keep the working
copy of a message in volatile memory without risking loss of messages.
There is a negative bieffect of this as well; if you manage to construct a
loop of sendmail-emil-sendmail-emil-sendmail your spool area will fill up
almost instantly nomatter how small message you sent.
<hr size="4" noshade>
<ADDRESS>
<table WIDTH="95%">
<td>
March 1996<p>
<B>ITS Uppsala university</B><BR>
Box 887<BR>
751 08 Uppsala<BR>
SWEDEN<P>
</td>
<td ALIGN="right" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">Martin Wendel</a>
</td>
<td ALIGN="left" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">
<IMG border="0" SRC="binpobox.gif" ALT="E-Mail: "></a>
</td>
</table>
</ADDRESS>
</body>
</html>
le or an SMTP
stream, the return code sent to the originating process will be that of the
conversion and output process made by Emil. In either case, the
originiating process will not get a return code from Emil until all further
processing and delivery, under control by Emil, is completed. This is to
make sure that the originating process will never receive a "delivery
successful" return code unless indicated successful by the subsequent
process or by emil-2.1.0-beta9/doc/using.html 100755 000000 000000 00000011350 06116610461 016546 0 ustar 00root system 000000 000000 <HEAD>
<TITLE>EMIL version 2 TUTORIAL</TITLE>
</HEAD>
<BODY>
<H1>TUTORIAL FOR EMIL VERSION 2.1
</H1>
<EM>Written by Martin Wendel, ITS, Uppsala university.
Martin.Wendel@its.uu.se
</EM>
<HR>
<A HREF=control.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A><A HREF=comparison.html><IMG ALIGN=MIDDLE SRC=arrow_left3.gif></A>
<H2>USING EMIL</H2>
<P>
There are several ways of using Emil. You may choose to use Emil as an
independant program or you may choose to integrate Emil into your message
delivery system. Using the capabilities specified below there is no
restriction on how you can use Emil.
<P>
Emil can take its input in two ways: You can pipe a message to the stdin of
Emil or you can place the message in a file and tell Emil to use that file
for input.
<P>
Emil can produce its output in three ways: To a file, to the stdout or to
an SMTP stream (Emil includes an SMTP client and can send the message to a
remote host using SMTP).
<P>
Emil can also fork off another program and send the output to the stdin of
that process.
<P>
If you intend to use Emil as an indepentant program feel free to experiment
on how you can use Emil. If, on the other hand you want to integrate Emil
into your message delivery systems there are a few things that need
considering. There are three main approaches: Input filtering, output
filtering and intermediate filtering.
<H3>Input filtering</H3>
<P>
This is applying Emil before the MTA receives the message and making Emil
call the MTA after conversion is completed. The one big disadvantage of
this method is that there is no way to apply Emil on a network input. This
is because Emil has no network daemon facilities. It is however possible to
use Emil as an input filter to sendmail on locally sent messages. This can
be done by installing Emil on the path of the sendmail program and move
sendmail to another place (sendmail must of course still be up and running
as a daemon). Emil can then be made to call sendmail and send the converted
messages to the stdin of sendmail. This is the general, and ugly, method of
using Emil as an input filter. Another way is restrict usage to specific
programs that need to have their messages converted. This, of course, means
changing the programs to call Emil instead of sendmail. This can be fairly
useful, for instance in a news-to-mail program that gateways a news group
to a mailling list. (The opposite is also possible, using Emil in a
mail-to-news program.)
<H3>Output filtering</H3>
<P>
This is letting the MTA apply Emil on it's output and is perhaps the most
useful method of using Emil. The most powerful way to implement output
filtering in sendmail is to change the mailer definitions in sendmail.cf.
Emil includes an SMTP client and can be made to fork off other programs and
redirect its output to them. Therefore it is possible to replace sendmail's
TCP mailer and the external mailers like the local mailer, uucp mailer etc
with mailers calling Emil. This is a total solution excluding only those
internal mailers that are not SMTP based. It is also possible to implement
conversion in a more restricted way using output filtering
<H3>Intermediate filtering</H3>
<P>
The only way to implement intermediate filtering using sendmail is to
combine output and input filtering in a loop back fasion letting Emil
receive the message from sendmail and redirect it back to sendmail again.
This is the method suggested in previous versions of Emil 2. The main
advantage is that this method is more general than any of the others. The
main disadvantages are that it is difficult to make the changes to
sendmail.cf correctly and that all message actually will be processed by
sendmail twice, spooled twice et cetera.
<p>If, on the other hand, you set up Emil to swap sender and recipient
address before calling sendmail, you have constructed a mail conversion
robot that will convert messages sent to it and return the result back
to the sender. This can be a solution for sites that wants ocasional
conversion; instead of teaching users how to use Emil you set up a server
that handles the configuration syntax.
<HR>
<A HREF=control.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A><A HREF=comparison.html><IMG ALIGN=MIDDLE SRC=arrow_left3.gif></A>
<hr size="4" noshade>
<ADDRESS>
<table WIDTH="95%">
<td>
March 1996<p>
<B>ITS Uppsala university</B><BR>
Box 887<BR>
751 08 Uppsala<BR>
SWEDEN<P>
</td>
<td ALIGN="right" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">Martin Wendel</a>
</td>
<td ALIGN="left" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">
<IMG border="0" SRC="binpobox.gif" ALT="E-Mail: "></a>
</td>
</table>
</ADDRESS>
</body>
</html>
on the command line. If done, the lookup for this
information in the configuration file is disabled. Therefore, make sure
to <EM>apply a complete specification of the format and encoding features</EM> using
these arguments, if one of them is omitted the value of that feature wiemil-2.1.0-beta9/doc/configuration.html 100755 000000 000000 00000013454 06115316243 020277 0 ustar 00root system 000000 000000 <HEAD>
<TITLE>EMIL version 2 TUTORIAL</TITLE>
</HEAD>
<BODY>
<H1>TUTORIAL FOR EMIL VERSION 2.1
</H1>
<EM>Written by Martin Wendel, ITS, Uppsala university.
Martin.Wendel@its.uu.se
</EM>
<HR>
<A HREF=details.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A><A HREF=arguments.html><IMG ALIGN=MIDDLE SRC=arrow_left3.gif></A>
<H2>THE CONFIGURATION FILE EMIL.CF</H2>
<P>
Emil uses a configuration file for multiple purposes. One purpose
is to retreive the conversion profile for the specified message
addresses. Another purpose is to retreive information about file
type marking among other things.
<P>
The configuration file consists of four parts or functions:
<OL>
<LI>group - Specifies a conversion profile.
<LI>mailer - Defines a mailer (program) with arguments.
<LI>match - Specifies file type information.
<LI>member - Binds addresses to a conversion profile.
</OL>
<H3>group</H3>
<P>
The group command is used to define a conversion profile, a named
method for conversion. The conversion profile contains a specification
of what format, charset and encodings to be used and when Emil has
selected a conversion profile, the information within that will be
used when undertaking conversion.
<P>
The syntax of the group command is the <B>group</B> keyword followed by
a name, a colon and a comma separeted list of options, as follows:
<blockquote>
<B> group</B> <I>Group_name</I> <B>: </B>[<B>charset=</B><I>CHARSET</I>] [<B>format=</B><I>FORMAT</I>]
[<B>bin=</B><I>ENCODING</I>] [<B>textenc=</B><I>ENCODING</I>] [<B>henc=</B><I>ENCODING</I>]<B> ;</B>
<UL>
<LI>
<I>Group_name</I> - The name of the group.
<LI>
<I>CHARSET</I> - The charset to use for text, according to RFC1345.
<LI>
<I>FORMAT</I> - The message format, pick one of MIME, MAILTOOL, RFC822 or
TRANSPARENT.
<LI>
<B>bin</B> - The encoding to use for binary attachments. Choose one of
BAse64, BInHex or Uuencode.
<LI>
<B>textenc</B> - Specifies the encoding to be used for text.
Pick one of BAse64, BInhex, Uuencode, Quoted-printable, 8bit
or 7bit. 7bit is default. When 7bit is chosen the text is
first converted to ISO-8859-1 and then the 8bit characters
are replaced by the appropriate characters as specified by
some national variants of ISO-646. This special conversion
is suited to work in Sweden but works probably also for other
european languages.
<LI>
<B>henc</B> - Specifies the encoding to be used for header lines.
Pick one of BAse64, Quoted-printable, 8bit or 7bit.
7bit is default. If BAse64 or Quoted-Printable is selected
headers are converted according to RFC1522 (MIME-II).
If 7bit is selected headers are first converted to ISO-8859-1
and then 8bit characters are converted to the US-ASCII
characters of closest resemblance.
</UL>
<BR>
<H3>mailer</H3>
<P>
The mailer command is used to define a mailer, or program, to be
used as an execv vector that will be forked off and will receive the
output of the conversion. The mailer name is referred when using the
"-m" command line flag and will thus result in the execv specified
by the mailer definition will be executed in a child and the output
of the conversion will be sent to the stdin of the child.
<P>
The syntax of the mailer command is as follows:
<P>
<blockquote>
<B>mailer</B> <I>Mailer_name</I><B> :</B> <I>PATH</I><B>, </B><I>PROGRAM</I><B>, </B><I>ARGUMENTS</I><B>,</B> ... <B>;
</B>
</blockquote>
<UL>
<LI>
<I>Mailer_name</I> - Name of the mailer.
<LI>
<I>Path</I> - Path of the program.
<LI>
<I>Program</I> - Name of the program.
<LI>
<I>Arguments</I> - A list of each command line argument to use when invoking the program.
To be suitable for mail programs you can specify variables representing
sender and recipient. These are specified by $s and $r respectively.
</UL>
<BR>
<H3>match</H3>
<P>
The match command is used to define file type information such as
X-Sun-Data-Type of Sun Mailtool messages, Content-Type of MIME messages,
file name extensions for UUencoded
files and Type&Creator for Applefiles. What kind of type information
is specified by the <I>CONTEXT</I>
<P>
The syntax of the match command is as follows:
<P>
<blockquote>
<B> match</B> <I>CONTEXT</I> <I>Match_String</I> <I>OUT</I><B> ;
</B>
</blockquote>
<UL>
<LI>
<I>CONTEXT</I> - One of MAILTOOL, MIME, BINHEX or UUENCODE.
<LI>
<I>Match_String</I> - A quoted string that corresponds to the
<I>Context</I>
of the field. For MIME
<I>Match_String</I> -
defines the content-type to be used. For UUENCODE
<I>Match_String</I>
defines the file name extension to be used.
For BINHEX
<I> Match_String</I>
defines the merged two 4byte strings Type and Auth info.
<LI>
<I>OUT</I> - The generic type of the field
</UL>
<H3>member</H3>
<P>
The member command is used to bind the address information, given as
command line arguments to Emil, to a
conversion profile. Address information is given as the triple of
<I>Recipient</I>, <I>Sender</I>, and <I>Recipient_host</I>. Several
triples may be bound to one conversion profile, in wich case the
triples are specified as a comma separated list.
<P>
The syntax of the member command is as follows:
<P>
<blockquote>
<B>member</B> <I>Group_name</I> <B>: </B><I>Recipient Sender Recipient_host</I><B>, </B>...<B> ;
</B>
</blockquote>
<BR>
<HR>
<A HREF=details.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A><A HREF=arguments.html><IMG ALIGN=MIDDLE SRC=arrow_left3.gif></A>
<hr size="4" noshade>
<ADDRESS>
<table WIDTH="95%">
<td>
March 1996<p>
<B>ITS Uppsala university</B><BR>
Box 887<BR>
751 08 Uppsala<BR>
SWEDEN<P>
</td>
<td ALIGN="right" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">Martin Wendel</a>
</td>
<td ALIGN="left" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">
<IMG border="0" SRC="binpobox.gif" ALT="E-Mail: "></a>
</td>
</table>
</ADDRESS>
</body>
</html>
ne of MIME, MAILTOOL, RFC822 or
TRANSPARENT.
<LI>
<B>bin</B> - The encoding to use for binary attachments. Choose one of
BAse64, BInHex or Uuencode.
<LI>
<B>textenc</B> - Specifies the encoding to be used for texemil-2.1.0-beta9/doc/intro.html 100644 000000 000000 00000005215 06115316633 016557 0 ustar 00root system 000000 000000 <HEAD>
<TITLE>EMIL version 2 TUTORIAL</TITLE>
</HEAD>
<BODY>
<H1>TUTORIAL FOR EMIL VERSION 2.1
</H1>
<EM>Written by Martin Wendel, ITS, Uppsala university.
Martin.Wendel@its.uu.se
</EM>
<HR>
<A HREF=why.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A>
<BODY>
<H2>INTRODUCTION</H2>
<P>Message transport is one of the major uses of the Internet today. Although the
mechanisms of transport itself may vary, the format of what is being transported
varies even more. Emil is a tool that gives the opportunity to bridge these format
variations. Emil does not deal with how messages are sent, therefore the transport
mechanisms are left out in favour of the message format in the rest of this
document.
<P>RFC822 is a common base that defines the format of an Internet Message.
Unfortunately this does not mean that all Mail User Agents (MUA's) conforming to
RFC822 will interoperate satisfactory. Messages may very well be incompatible
while still conforming to RFC822 <A HREF="rfc822.html">[RFC822]</A>. RFC822 is just a common base and does not address
compatibility of the data being sent, MIME
<A HREF="rfc1521.html">[RFC1521]</A>and
<A HREF="rfc1522.html">[RFC1522]</A> is an effort to do just that.
While RFC822 defines the format of the message itself, MIME
defines the format of the contents of the message (Internet messages not conforming
with MIME typically has a fairly unstructured content). Until MIME is widely
used these incompatibilities will remain. The intermediate cure for this is the tool Emil.
<P>Emil acts as a filter tool and transforms messages between message formats. It can act as
a manual filter or it can be used by a Mail Transfer Agent (MTA) like sendmail. It is often
argued that MTA's should only alter messages when they act as gateways between
heterogeneous networks. I argue that a MTA may very well transform a message
when passing it between heterogeneous logical communities (or networks) of MUA's.
These two arguments are really analogous.
<P>Using Emil, heterogeneous MUA networks can act as homogenous. This works both
ways; A single user can make the rest of the world act homogenous looking from his/her MUA.
<hr size="4" noshade>
<ADDRESS>
<table WIDTH="95%">
<td>
March 1996<p>
<B>ITS Uppsala university</B><BR>
Box 887<BR>
751 08 Uppsala<BR>
SWEDEN<P>
</td>
<td ALIGN="right" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">Martin Wendel</a>
</td>
<td ALIGN="left" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">
<IMG border="0" SRC="binpobox.gif" ALT="E-Mail: "></a>
</td>
</table>
</ADDRESS>
</body>
</html>
oes not deal with how messages are sent, therefore the transport
mechanisms are left out in favour of the message format in the rest of this
document.
<P>RFC822 is a common base that defines the format of an Internet Message.
Unfortunately this does not mean that all Mail User Agents (MUA's) conforming to
RFC822 will interoperate satisfactory. Messages may very welemil-2.1.0-beta9/doc/main.html 100755 000000 000000 00000003747 06146112700 016354 0 ustar 00root system 000000 000000 <HEAD>
<TITLE>EMIL version 2 TUTORIAL</TITLE>
</HEAD>
<BODY>
<H1>TUTORIAL FOR EMIL VERSION 2.1
</H1>
<EM>Written by Martin Wendel, ITS, Uppsala university.
Martin.Wendel@its.uu.se
</EM>
<HR>
<P>
<EM>Note: Emil converts internet messages that conforms with rfc822.
Therefore the use of the term "message" below refers to an rfc822
conforming message. Emil is developed for swedish conditions, but
will most likely be useful outside of Sweden as well.
</EM>
<HR>
<A HREF=intro.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A>
<UL>
<LI>
<A HREF="intro.html">Introduction</A>
<LI>
<A HREF="why.html">Why use message conversion?</A>
<LI>
<A HREF="way.html">How Emil v2 does message conversion</A>
<LI>
<A HREF="comparison.html">Comparison with Emil v1</A>
<LI>
<A HREF="using.html">Using Emil</A>
<UL>
<LI>
<A HREF="control.html">Controlling conversion</A>
<LI>
<A HREF="arguments.html">Command line arguments</A>
<LI>
<A HREF="configuration.html">The configuration file emil.cf</A>
<LI>
<A HREF="details.html">Emil details</A>
</UL>
<LI>
<A HREF="design-top.html">Emil design</A>
<UL>
<LI>
<A HREF="problem-statement.html">Problem statement</A>
<LI>
<A HREF="analysis.html">Analysis</A>
<LI>
<A HREF="design-spec.html">Design</A>
</UL>
<LI>
<A HREF="setting.html">Setting up conversion</A>
<UL>
<LI>
<A HREF="input.html">Input conversion</A>
<LI>
<A HREF="output.html">Output conversion</A>
<LI>
<A HREF="emil.cf.html">Configuration of emil.cf</A>
</UL>
</UL>
<BR>
<BR>
<HR>
Back to <A HREF="index.shtml">Emil's Workshop</A>
<BR>
<BR>
<BR>
<BR>
<hr size="4" noshade>
<ADDRESS>
<table WIDTH="95%">
<td>
March 1996<p>
<B>ITS Uppsala university</B><BR>
Box 887<BR>
751 08 Uppsala<BR>
SWEDEN<P>
</td>
<td ALIGN="right" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">Martin Wendel</a>
</td>
<td ALIGN="left" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">
<IMG border="0" SRC="binpobox.gif" ALT="E-Mail: "></a>
</td>
</table>
</ADDRESS>
</body>
</html>
mmunities (or networks) oemil-2.1.0-beta9/doc/arrow_right3.gif 100644 000145 000001 00000000351 06115041774 017735 0 ustar 00martin staff 000000 000000 GIF87a0 0 , 0 0 Ȅmᢜ|VOH~fIZɮ϶,舃ua~a;20'+9^ꢉXXZN1Ԟh$8v(h%9gyy)9 Z$UxZ$yHE6ZIYxˈ*)\%;E||FlĜ[[
N3yW ;<HR>
<P>
<EM>Note: Emil converts internet messages that conforms with rfc822.
Therefore the use of the term "message" below refers to an rfc822
conforming message. Emil is developed for swedish conditions, but
will most likely be useful outside of Sweden as well.
</EM>
<HR>
<Aemil-2.1.0-beta9/doc/arrow_up2.gif 100644 000145 000001 00000000353 06115042001 017225 0 ustar 00martin staff 000000 000000 GIF87a0 0 , 0 0 ʄmᢜ|VOH~fIZɮ~cи
2"Px(bXDz4ʔPNHx|crPmOʹ-xf
v%V(wȰf&VyE@E'rJ&R7 j"jY+ڗ
(KH|[Մ,=.4^J*X ;R>
<P>
<EM>Note: Emil converts internet messages that conforms with rfc822.
Therefore the use of the term "message" below refers to an rfc822
conforming message. Emil is developed for swedish conditions, but
will most likely be useful outside of Sweden as well.
</EM>
<HR>
<Aemil-2.1.0-beta9/doc/binpobox.gif 100644 000145 000001 00000000763 06115050271 017142 0 ustar 00martin staff 000000 000000 GIF87a@ @ ??? , @ @ 0I8ͻ`(`hdp,:f<oތ]!
4*eD35]"oB:
{<Zڶ\{kj/f)&Qn$9}=ZaJcz"bj|p`_v{10Ē!b;gɭˢŁv4 ﹺp3 Bmq:8x9(Nn a<nL҃Ć.bH*-̨2f4w'N)M ҠGu*29FN7>U5u iGXHc7[oa(vdRdgOU `dǐЋ&
kir.̹dw?(&mujO6ͷ ٸ5{
Vܻy]: ;</EM>
<HR>
<Aemil-2.1.0-beta9/doc/comparison.html 100644 000000 000000 00000003607 06115315052 017573 0 ustar 00root system 000000 000000 <HEAD>
<TITLE>EMIL version 2 TUTORIAL</TITLE>
</HEAD>
<BODY>
<H1>TUTORIAL FOR EMIL VERSION 2.1
</H1>
<EM>Written by Martin Wendel, ITS, Uppsala university.
Martin.Wendel@its.uu.se
</EM>
<HR>
<A HREF=using.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A><A HREF=way.html><IMG ALIGN=MIDDLE SRC=arrow_left3.gif></A>
<BODY>
<H2>COMPARISON WITH EMIL VERSION 1</H2>
<P>Emil version 1 has been in use for about a year at UDAC as well as at other sites around
the world. While initially aimed at handling character set translation and the Quoted-Printable
encoding of MIME in the Nordic countries, the scope of Emil broadened to encompass translation
of the encodings Base64, BinHex and uuencode as well. This together with the ability to transform
headers in messages made Emil version 1 a tool for converting between message formats.
Emil version 1 was based on interpreting a message as a sequential structure; this made it
awkward to handle hierarchical and nested messages. The configuration language used was
not so well suited to handle conflicting message formats.
<P>Emil version 2 is an attempt to fix some of the flaws in version 1, for example allowing
hierarchical structures and a direct interpretation of the format grammar, and being even
more general does not restrict usage to message conversion. Now the primary aims are encoding,
decoding translation and interpretation.
<hr size="4" noshade>
<ADDRESS>
<table WIDTH="95%">
<td>
March 1996<p>
<B>ITS Uppsala university</B><BR>
Box 887<BR>
751 08 Uppsala<BR>
SWEDEN<P>
</td>
<td ALIGN="right" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">Martin Wendel</a>
</td>
<td ALIGN="left" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">
<IMG border="0" SRC="binpobox.gif" ALT="E-Mail: "></a>
</td>
</table>
</ADDRESS>
</body>
</html>
converting between message formats.
Emil version 1 was based on interpreting a message as a sequential structure; this memil-2.1.0-beta9/doc/design-top.html 100644 000000 000000 00000003565 06115315230 017473 0 ustar 00root system 000000 000000 <HEAD>
<TITLE>EMIL version 2 TUTORIAL</TITLE>
</HEAD>
<BODY>
<H1>TUTORIAL FOR EMIL VERSION 2.1
</H1>
<EM>Written by Martin Wendel, ITS, Uppsala university.
Martin.Wendel@its.uu.se
</EM>
<HR>
<A HREF=problem-statement.html><IMG ALIGN=MIDDLE SRC=arrow_right3.gif></A><A HREF=main.html><IMG ALIGN=MIDDLE SRC=arrow_up2.gif></A><A HREF=details.html><IMG ALIGN=MIDDLE SRC=arrow_left3.gif></A>
<H2>THE DESIGN OF EMIL</H2>
<H3>About These Documents</H2>
<EM>This document intends to explain how Emil version 2 is constructed. It describes all the
phases in the work, starting with the problem statement, through analysis, design and finally
implementation.
</EM>
<H2>Notational Conventions</H2>
<P>
Primarily in the analysis OMT notation is used to define the functional model and the object
structures of the intermediate states.
In the functional model an ellipse is a process, an arrow is a data flow and a data store is
represented by two thick lines, one above and one under, surrounding the data store name.
In an object structure a square or rectangle is a class, a class is a prototype data structure
which when instantiated becomes an object. Lines between classes represents relations.
A single line represents a unary relation between instanses of the classes. A filled circle
represents relation with zero or many instanses, while an open circle represents a zero or
one relation. A +1 represent a one or many relation.
<hr size="4" noshade>
<ADDRESS>
<table WIDTH="95%">
<td>
March 1996<p>
<B>ITS Uppsala university</B><BR>
Box 887<BR>
751 08 Uppsala<BR>
SWEDEN<P>
</td>
<td ALIGN="right" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">Martin Wendel</a>
</td>
<td ALIGN="left" VALIGN="middle">
<a href="mailto:Martin.Wendel@its.uu.se">
<IMG border="0" SRC="binpobox.gif" ALT="E-Mail: "></a>
</td>
</table>
</ADDRESS>
</body>
</html>
its.uu.se">
<IMG border="0" SRC="binpobox.gif" ALT="E-Mail: "></a>
</td>
</table>
</ADDRESS>
</body>
</html>
mmunities (or networks) oemil-2.1.0-beta9/doc/figure1.gif 100644 000145 000001 00000002273 06115313246 016666 0 ustar 00martin staff 000000 000000 GIF87a , ڋH扦ʶL
ĢL*̦3JԪj ¢10;59b3zq?(XDXtx( CxY)ȩY)3zgJڲJuK4+{KVPl`-]`|l<m
pM^
=nNLl==^._n?.`<}
R/aPąMCG"-50Dn$`P/
M1$\^Ko| Rf^@~q
TSa`Ɣcͱsy,˲᭪½`WRTyR£ 0J+c'ǐ|e^:{:fvAdg\nEujinʈ۫7p!eΎn7_NiʡCL4ȹޞqན?><ڵϫgǧw}^o F߀fL&hɂ_\N6D87`HVa) xH ("08+8臍#2@͐DbGf"5IF2VY`Y\
(&^9Thw昰)t* lnJxi苈&ڟTF*)dsVh~G 餗jjzª
aV%+*'ӗuh+k҈6&#Z[Yb;zK,Oj1ϒh$f粱U]yU;|5/>uZ+K|ll?&lsX]C-|1^4n
M55z`ll^f\`LPE^TIbY|>?=n[YUm<7[qMc/1ͻm58;5gGOvhֽ^wW<=xK5>iR*5s3t'Δ+']7i]0lۻF{2h4W1ܭU3_ܼˁ
~˻9fH[Ƴh}Ol.Cѳ7ݾkR p,*pl ;en classes represents relations.
A single line represents a unary relation between instanses of the classes. A filled circle
represents relation with zero or many instanses, while an open circle represents a zero or
one relation. A +1 represent a one or many relation.
<hr size="4" noshade>
<ADDRESS>
<table WIDTH="95%">
emil-2.1.0-beta9/doc/figure2.gif 100644 000145 000001 00000002750 06115313262 016665 0 ustar 00martin staff 000000 000000 GIF87a , ڋH扦ʶL
ĢL*̦JԪj ¢10;9b/ 88ThȄh8Siii ع9'
)uBZrzj"jA;k;⋂{K:,wH-Em<|e}[m;
mP.^N>M!^n/<yU}5(a h&MYX$(N`J~+iTkd_|gˇ
sB@r&-93dg%*ϵ9J2EjSmPo<իůa$[ش42bj-n̥+.z[y8zkXhČ<jȔ|Y̜j9bЙ&=h3ȪWCز=Ӯ}aݔ(ᯉ7n
h3'9ҝP;ړp|≐/}o=|Kʯ>~N')C-$
6*3%V\ERa" }"P-fFa4zэ䨣X@"Ő82dd%iLAXRN|1:h%_]I|\FYa7&:_(Zw&YKybo)iz|DJA!ħemI6X
Ԣ&5Jȡhmԓf>!er9X}<WQG6*B))+O:5ZeT #lV>V,WwaS**JN^Ǿ:۳),j)9Zxo+¸owpp {
e%OLY,a-