Filewatcher File Search
FTP Search
  
Directory 
  
Content Search 
   
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 5ustar00rootsystem000000 000000 emil-2.1.0-beta9/7bit.c100644 000000 000000 00000013144 06155035765 015012 0ustar00rootsystem000000 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.c100644 000000 000000 00000020372 06155035765 016442 0ustar00rootsystem000000 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.c100644 000000 000000 00000012221 06155035765 016101 0ustar00rootsystem000000 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.c100644 000000 000000 00000025526 06155035766 016460 0ustar00rootsystem000000 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.c100644 000000 000000 00000014474 06155035766 015241 0ustar00rootsystem000000 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.c100644 000000 000000 00000004547 06155035766 015441 0ustar00rootsystem000000 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.c100644 000000 000000 00000023033 06155035766 015421 0ustar00rootsystem000000 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.c100644 000000 000000 00000005557 06155035767 015431 0ustar00rootsystem000000 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.c100644 000000 000000 00000015110 06155035767 015622 0ustar00rootsystem000000 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.c100644 000000 000000 00000007050 06155035767 016111 0ustar00rootsystem000000 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.c100644 000000 000000 00000010413 06155035767 015267 0ustar00rootsystem000000 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.c100644 000000 000000 00000030713 06155035770 015432 0ustar00rootsystem000000 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.c100644 000000 000000 00000013665 06155035770 015405 0ustar00rootsystem000000 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.c100644 000000 000000 00000021274 06155035770 015374 0ustar00rootsystem000000 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.c100644 000000 000000 00000012504 06155035771 014731 0ustar00rootsystem000000 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.c100644 000000 000000 00000034165 06155035771 015441 0ustar00rootsystem000000 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.c100644 000000 000000 00000011153 06155035771 015057 0ustar00rootsystem000000 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.c100644 000000 000000 00000007765 06155035771 015435 0ustar00rootsystem000000 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.c100644 000000 000000 00000015124 06155035772 015763 0ustar00rootsystem000000 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.c100644 000000 000000 00000045076 06155035772 015100 0ustar00rootsystem000000 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.c100644 000000 000000 00000025154 06155035773 015574 0ustar00rootsystem000000 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.c100644 000000 000000 00000016400 06155035773 015071 0ustar00rootsystem000000 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.c100644 000000 000000 00000014377 06155035773 016137 0ustar00rootsystem000000 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.c100644 000000 000000 00000010477 06155035773 014572 0ustar00rootsystem000000 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.c100644 000000 000000 00000016677 06155035774 014772 0ustar00rootsystem000000 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 5ustar00martinstaff000000 000000 emil-2.1.0-beta9/doc/arrow_left3.gif100644 000145 000001 00000000356 06115041766 017560 0ustar00martinstaff000000 000000 GIF87a00,00̈́#
Zp3޺dX깖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.shtml100644 000000 000000 00000007665 06115536623 016734 0ustar00rootsystem000000 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&ouml;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.html100755 000000 000000 00000003427 06115314141 016231 0ustar00rootsystem000000 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.html100755 000000 000000 00000016356 06115315670 016237 0ustar00rootsystem000000 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.html100755 000000 000000 00000002325 06115314265 017105 0ustar00rootsystem000000 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.html100755 000000 000000 00000013777 06155035512 017446 0ustar00rootsystem000000 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 &lt;address&gt;		The address of the recipient.
<LI>	-s &lt;address&gt;		The address of the sender.
<LI>	-x &lt;hostname&gt;		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 &lt;group&gt;		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 &lt;appletype&gt;		The target applefile encoding style.
<LI>	-B &lt;encoding&gt;		The target binary encoding style.
<LI>	-C &lt;charset&gt;		The target charset.
<LI>	-F &lt;format&gt;		The target format.
<LI>	-H &lt;encoding&gt;		The target header encoding style.
<LI>	-S &lt;charset&gt;		The sender's charset.
<LI>	-T &lt;encoding&gt;		The target text encoding style.
</DIR>
<H4>Legal values</H4>
<UL>
<LI>&lt;appletype&gt;	One of:
<UL>
<LI>	(s)	AppleSingle
<LI>	(d)	AppleDouble
<LI>	(b)	BinHex
</UL>
<LI>&lt;format&gt;	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>&lt;encoding&gt;	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>&lt;charset&gt;	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 &lt;facility&gt;		The log facility of syslog logging.
<LI>	-h &lt;level&gt;		The log level of header logging.
<LI>	-l &lt;level&gt;		The log level of syslog logging.

</DIR>
<H4>Legal values</H4>
<UL>
<LI>&lt;facility&gt;	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>&lt;level&gt;		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 &lt;path&gt;		Path of charsets file.
<LI>	-e &lt;path&gt;		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 &lt;path&gt;		Path of input file.
<LI>	-m &lt;mailer&gt;	The program to which to pipe output (see the configuration file).
<LI>	-n			Pipe output to the builtin SMTP client.
<LI>	-o &lt;path&gt;		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.html100755 000000 000000 00000005067 06115314347 017061 0ustar00rootsystem000000 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.html100755 000000 000000 00000011350 06116610461 016546 0ustar00rootsystem000000 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.html100755 000000 000000 00000013454 06115316243 020277 0ustar00rootsystem000000 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.html100644 000000 000000 00000005215 06115316633 016557 0ustar00rootsystem000000 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.html100755 000000 000000 00000003747 06146112700 016354 0ustar00rootsystem000000 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.gif100644 000145 000001 00000000351 06115041774 017735 0ustar00martinstaff000000 000000 GIF87a00,00Ȅ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.gif100644 000145 000001 00000000353 06115042001 017225 0ustar00martinstaff000000 000000 GIF87a00,00ʄ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.gif100644 000145 000001 00000000763 06115050271 017142 0ustar00martinstaff000000 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(Nna<nL҃Ć.bH*-̨2f4w'N)MҠGu*29FN7>U5u iGXHc7[oa(vdRdgOU`dǐЋ&
kir.̹dw?(&mujO6ͷ	ٸ5{
Vܻy]:;</EM>
<HR>
<Aemil-2.1.0-beta9/doc/comparison.html100644 000000 000000 00000003607 06115315052 017573 0ustar00rootsystem000000 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.html100644 000000 000000 00000003565 06115315230 017473 0ustar00rootsystem000000 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.gif100644 000145 000001 00000002273 06115313246 016666 0ustar00martinstaff000000 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}^oF߀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,*pl;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.gif100644 000145 000001 00000002750 06115313262 016665 0ustar00martinstaff000000 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-
Results 1 - 1
Help - FTP Sites List - Software Dir.
Searching half a billion files worldwide
© 1997-2009 MARUHN Internet Solutions