/*
** 
** 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)
	    snprintf(buf, sizeof(buf), "%s; charset=\"%s\"", ct, m->td->charset);
	  else
	    snprintf(buf, sizeof(buf), "%s", ct);
	}
      else
	if (match(m->sd->type, "MULTIPART"))
	  {
	    bb = (char *)getmimebound();
	    if (m->sd->applefile == AMDOUBLE)
	      snprintf(buf, sizeof(buf), "Multipart/AppleDouble; boundary=\"%s\"", bb);
	    else
	      snprintf(buf, sizeof(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
	  {
	    snprintf(buf, sizeof(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)
    {
      char *buf2;
      buf2 = strdup(buf);
      snprintf(buf, sizeof(buf), "%s; name=\"%s\"", buf2, m->sd->name);
      free(buf2);
    }
  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;
}


syntax highlighted by Code2HTML, v. 0.9.1