/* Routines to handle messages.
   Copyright (C) 1993 Free Software Foundation, Inc.
   Contributed by Tim Wicinski (wicinski@polyp.barn.com).

This file is part of GNU GNATS.

GNU GNATS 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, or (at your option)
any later version.

GNU GNATS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS 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 GNU GNATS; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */

#include "config.h"

#include <stdio.h>
#include <sys/types.h>

#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
#endif

#include "globals.h"
#include "headers.h"
#include "gnats.h"

typedef struct
{
  /* what you check against */
  char *name;
  /* the stored value that is extracted */
  char *value;
} Header;

Header header[NUM_HEADER_ITEMS];

/* Look to see if STRING is a mail header we know about.  */
static short 
lookup_header (string)
     char *string;
{
  Header_Name i;

  for (i = (Header_Name) 0; i < NUM_HEADER_ITEMS; i++)
    if ((header[i].name != NULL && string != NULL)
	&& (strncasecmp (header[i].name, string, strlen (string)) == 0))
      return i;

  return -1;
}

/* If there's more than one instance of a given header, keep
   the first one and ignore any future ones.  There's one
   exception to this rule: the `Received:' header.  We are likely
   to get many of them, so just drop them down into the "value"
   of the first received header. */
static void
set_continued_header (i, buf)
     Header_Name i;
     char *buf;
{
  char *b;

  if (header[i].value != NULL)
    {
      if (keep_rec && i == RECEIVED)
	{
	  b = (char *) xmalloc (strlen (header[i].value) + 10
				+ strlen (buf) + 1);
	  if (*buf == ' ')
	    sprintf (b, "%sReceived:%s", header[i].value, buf);
	  else
	    sprintf (b, "%sReceived: %s", header[i].value, buf);
	  free (header[i].value);
	  free (buf);
	  header[i].value = b;
	}
    }
  else
    header[i].value = buf;
}

void
read_header (fp)
     FILE *fp;
{
  Header_Name i;
  bool processing = FALSE;
  bool headers_found = FALSE;
  char *l;
  char line[STR_MAX];
  char token[STR_MAX];
  char *b, *buf;
  int buf_len, buf_max;
  int c, len;

  init_header ();

#define PEEK(FP) (c = getc (FP), ungetc (c, FP))
  
  while (PEEK (fp) != EOF)
    {
      if ((c == '\t' || c == ' ') && processing)
	{
	  /* RFC-822 multi-line header.  */
	  read_string (line, fp);
	  APPEND_STRING (line, buf, b, buf_len, buf_max, len, 0);
	}
      else
	{
	  if (processing)
	    {
	      *b = '\0';
	      set_continued_header (i, buf);
	      buf = NULL;
	      processing = FALSE;
	    }

	  /* If there's a blank line or a PR field, get out quickly.
	     (sometimes buggy sendmails (SunOS 4.1.3) will mix in PR
	     fields with mail headers).  */
	  if (c == '\n' || c == '>')
	    break;

	  read_string (line, fp);
	  
	  l = get_token (line, token);
	  i = lookup_header (token);
	  if (i == -1)
	    continue;

	  headers_found = TRUE;
	  processing = TRUE;

	  buf_len = strlen (l);
	  buf_max = buf_len + BUFSIZ + 1;
	  buf = (char *) xmalloc (buf_max);
	  memcpy (buf, l, buf_len);
	  b = buf + buf_len;
	}
    }

  /* If no headers found, then back up and send it thru read_pr.  */
  if (!headers_found)
    rewind (fp);
}

void 
write_header (fp, string)
     FILE *fp;
     Header_Name string;
{
  Header_Name i;

  if (string != NUM_HEADER_ITEMS)
    fprintf (fp, "%s %s", header[string].name, header[string].value);
  else
    for (i = (Header_Name) 0; i < NUM_HEADER_ITEMS; i++)
      if (header[i].value != NULL)
	{
	  if (*header[i].value)
	    {
	      if (*header[i].value != ' ')
		fprintf (fp, "%s %s", header[i].name, header[i].value);
	      else
		fprintf (fp, "%s%s", header[i].name, header[i].value);
	    }
	  else
	    fprintf (fp, "%s\n", header[i].name);
	}
}

void
init_header ()
{
  Header_Name i;

  for (i = SM_FROM; i < NUM_HEADER_ITEMS; i++)
    xfree (header[i].value);
  
  memset (&header[0], 0, sizeof (Header) * NUM_HEADER_ITEMS);

  header[SM_FROM].name = "From";
  header[RETURN_PATH].name = "Return-Path:";
  header[RECEIVED].name = "Received:";
  header[MSG_ID].name = "Message-Id:";
  header[DATE].name = "Date:";
  header[FROM].name = "From:";
  header[SENDER].name = "Sender:";
  header[REPLY_TO].name = "Reply-To:";
  header[TO].name = "To:";
  header[APPAR_TO].name = "Apparently-To:";
  header[CC].name = "Cc:";
  header[IN_REP_TO].name = "In-Reply-To:";
  header[SUBJECT].name = "Subject:";
  header[REFERENCES].name = "References:";
  header[COMMENTS].name = "Comments:";
  header[KEYWORDS].name = "Keywords:";
  header[X_SEND_PR].name = "X-Send-Pr-Version:";
}

char *
header_name (name)
     Header_Name name;
{
  if (name < 0 || name >= (int) NUM_HEADER_ITEMS)
    return NULL;
  else
    return header[name].name;
}

char *
header_value (name)
     Header_Name name;
{
  if (name < 0 || name >= (int) NUM_HEADER_ITEMS)
    return NULL;

  if (header[name].value == NULL)
    header[name].value = strdup ("");

  return header[name].value;
}

void 
set_header (name, string)
     Header_Name name;
     char *string;
{

  if (name < 0 || name >= NUM_HEADER_ITEMS || !string)
    return;

  xfree (header[name].value);
  header[name].value = (char *) strdup (string);
}
