/*
**
** Copyright (C) 1994 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@udac.uu.se
**                                        Torbjorn.Wictorin@udac.uu.se
**
**                                        UDAC	
**                                        P.O. Box 174
**                                        S-751 04 Uppsala
**                                        Sweden
**
*/


#include "emil.h"


char toqp[256] = {

1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 0, 1, 1, 0, 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, 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, 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
encode_quoted_printable(struct message *m)
{
  struct data *inbuf, *outbuf;
  static int linelen;
  char lastspace;
  char cbuf[5];
  char *inb;

  logger(LOG_DEBUG, "encode quoted-printabel");
  inbuf = m->td;
  /* Exit on empty input */
  if (!inbuf->size)
    return(NOK);

  linelen = 0;
  outbuf = (struct data *)Yalloc(sizeof(struct data));
  outbuf->encoding = EQP;
  outbuf->charset = m->td->charset;
  /* 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, pz);
	  outbuf ->lineend += 1;
	  linelen = 0;
	  lastspace = 0;
	}
      if (toqp[(unsigned char)*inb])
	{
	  sprintf(cbuf, "=%.2X", (unsigned char)*inb);
	  append_data(outbuf, cbuf, 3, pz);
	  linelen += 3;
	  lastspace = 0;
	}
      else
	{
	  if (*inb == '\n')
	    {
	      if (lastspace != 0)
		{
		  /* Quote space before end of line */
		  sprintf(cbuf, "=%.2X\n", (unsigned char)lastspace);
		  outbuf->end -= 1;
		  outbuf->bodyend -= 1;
		  append_data(outbuf, cbuf, 4, pz);
		  outbuf ->lineend += 1;
		}
	      else
		append_char(outbuf, *inb, pz);
	      linelen = 0;
	    }
	  else
	    {
	      append_char(outbuf, *inb, pz);
	      linelen++;
	    }

	  if (*inb == ' ' || *inb == '\t')
	    lastspace = *inb;
	  else
	    lastspace = 0;
	}
      inb++;
      inbuf->offset += 1;
    }
  safe_mchange(m, outbuf);
  return(OK);
}

int
decode_quoted_printable(struct message *m)
{
  struct data *inbuf, *outbuf;
  char *inb;
  char *endpointer;
  char t[3];
  char c;


  inbuf = m->td;
  logger(LOG_DEBUG, "decode quoted-printable");
#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "decode quoted-printable at offset: %lu\n",
	    inbuf->offset);
#endif
  /* 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));
      outbuf->encoding = E7BIT;
      outbuf->charset = m->td->charset;
    }
  bzero(t, 3);					

  /*
   * Process entire inbuf.
   */
  while (inbuf->offset < inbuf->bodyend)
    {
      switch (*inb)
	{
	case '\n':
	  if (process)
	    {
	      append_char(outbuf, *inb, pz);
	      outbuf->lineend += 1;
	    }
	  inb++;
	  inbuf->offset += 1;
	  break;
	case '=':
	  inb++;
	  inbuf->offset += 1;
	  if (*inb == '\n')
	    /* Soft line break */
	    {
	      inb++;
	      inbuf->offset += 1;
	    }
	  else
	    {
	      if (inbuf->offset + 2 >= inbuf->end)
		return(NOK);
	      strncpy(t, inb, 2);
	      if ((c = (char) strtol(t, &endpointer, 16)) == 0 && endpointer == t)
		{
		  /* Illegal encoding */
		  logger(LOG_WARNING, "WARNING: decode_quoted_printable: Illegal encoding");
		  return(NOK);
		}
	      else
		{
		  if (process)
		    append_char(outbuf, c, pz);
		  inb += 2;
		  inbuf->offset += 2;
		}
	    }
	  break;
	default:
	  if (process)
	    append_char(outbuf, *inb, pz);
	  inb++;
	  inbuf->offset += 1;
	  break;
	}
    }
  if (process)
    safe_mchange(m, outbuf);
  return(OK);
}

