/*
** 
** 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);
}

