/*
 * Copyright (c) 1998 Qualcomm Incorporated. All rights reserved.
 *
 * File        : callback.c
 * Project     : Delivery agent implementing "On Server Filtering".
 * Comments    : Definitions of callback functions declared in daa.h,
 *               daa_util.h, and daa_trace.h.
 *
 *
 * Revisions   :
 *  10/26/98   [mb]
 *         - Initial development release.  Many bugs.
 *  11/05/98   [mb]
 *         - Second development release.
 *         - Implemented tracef().
 *         - Fixed bug in DAA_get_next_rfc822_header().
 *
 */

#ifndef _CALLBACK_H
#define _CALLBACK_H

#include "config.h"

#include "daa.h"
#include "daa_trace.h"

#include <ctype.h>
#include <errno.h>
#include <malloc.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <syslog.h>
#include <unistd.h>

#ifdef __STDC__
#include <stdarg.h>
#else
#include <vararg.h>
#endif

/*****************************************************************************
 * Functions declared in daa.h
 ****************************************************************************/

/* Look in "search" for header "target".  Retrun 0 if no match, otherwise,
 * return a pointer to the header contents.
 */
static char *HeaderMatch(search, target)
     char *search;
     char *target;
{
  for (;*search&&*target&&toupper(*search)==toupper(*target);
       search++,target++);

  if (*target&&toupper(*search)!=toupper(*target))
    return 0;

  if (*search!=':')
    return 0;

  search++;

  for (;*search&&isspace((int)*search); search++);

  return search;
}

char *DAA_parse_next_rfc821_address(msg, s, loc, dom)
     Context *msg;
     char *s;
     char *loc;
     char *dom;
{
  /* TODO:
   * Not currently used by Sieve, so not implemented yet */
  return 0;
}

char *DAA_get_next_rfc822_header(msg, start, target)
     Context *msg;
     ll_Line **start;
     char *target;
{
  char *result = 0;

  for (;*start&&!(result=HeaderMatch((*start)->buffer, target));
       *start = (*start)->next);

  if (result)
    *start = (*start)->next;

  return result;
}

char *DAA_get_rfc822_header(msg, lines, target)
     Context *msg;
     ll_Lines *lines;
     char *target;
{
  ll_Line *start;
  char *result = 0;

  start = lines->first;

  for (;start&&!(result=HeaderMatch(start->buffer, target));
       start=start->next);

  return result;
}

/*****************************************************************************
 * Functions declared in daa_util.h
 ****************************************************************************/

extern FILE *fpMsg;                /* Tmp file where the msg is located */
extern unsigned int uiMsgLen;      /* for Content-length */
extern unsigned int uiTotalMsgLen;
extern unsigned int uiHeaderLen;
extern char localHost[];

int forward_msg(work, pszDest, ln, debug)
     Context *work;
     char *pszDest;
     int ln;
     int debug;
{
  int stat;
  pid_t pid, id;
  int filedes[2];
  FILE *mta, *in;
  
  pipe(filedes);
  
  switch (pid=fork()) {
  case 0: /* child */
    
    if (dup2(filedes[1], STDIN_FILENO)<0) {
      tracef(ln, 0, "dup2 error: %s", strerror(errno));
    }
    if (!(in = fdopen(STDIN_FILENO, "r"))) {
      tracef(ln, 0, "fdopen error");
    }
    
    execl(MAIL_COMMAND, "send-mail", "-t", "-i", "-oem", 0);
    _exit(1);
    
  case -1: /* fork error */
    
    if (debug) tracef(ln, 0, "Fork error invoking mail command");
    return 1;
    
  default:
      
    mta = fdopen(filedes[0], "w");
    
    /* output the message to the MTA */

    /* add out resent- headers */
    fprintf(mta, "Resent-to: %s\n", pszDest);
    fprintf(mta, "Resent-from: %s@%s\n", work->msg_recip.name.local,
	    work->msg_recip.name.domain);

    /* output the original message */
    {
      ll_Line *current;

      for (current = work->message.headers.first;
	   current; current = current->next) {
	fprintf(mta, "%s\n", current->buffer);
      }

      fprintf(mta, "\n");
      
      /*
	for (current = work->message.body.first;
	current; current = current->next) {
	fprintf(mta, "%s\n", current->buffer);
      */

      {
	char line[1024];
	fseek(fpMsg, uiHeaderLen, SEEK_SET);
	while (fgets(line, sizeof(line), fpMsg)) {
	  fputs(line, mta);
	}
      }

    }

    fclose(mta);
    close(filedes[0]);

    id = waitpid(pid, &stat, 0);
    if ((!WIFEXITED(stat))||(WEXITSTATUS(stat)!=0)) {
      tracef(ln, 0, "Error invoking mail command");
      return 1;
    }
    
  }

  return 0;
}

int reply_msg(work, pszText, flags, ln, debug)
     Context *work;
     char *pszText;
     int flags;
     int ln;
     int debug;
{

  char *to;
  char buf[1024];

  /* TODO: check flags.  Must be 0 */

  /* Figure out who to reply to */
  to = DAA_get_rfc822_header(work, &work->message.headers, "reply-to");
  if (!to) {
    to = DAA_get_rfc822_header(work, &work->message.headers, "from");
  }
  if (!to&&work->msg_orig.local&&work->msg_orig.domain) {
    if (strlen(work->msg_orig.local)+strlen(work->msg_orig.domain)+1<
	sizeof(buf)) {
      sprintf(buf, "%s@%s", work->msg_orig.local, work->msg_orig.domain);
      to = buf;
    }
  }
  if (!to) {
    if (debug) tracef(ln, 0, "Unable to determine reply e-mail address");
    return 1;
  }

  {
    int stat;
    pid_t pid, id;
    int filedes[2];
    FILE *mta, *in;
    
    pipe(filedes);
    
    switch (pid=fork()) {
    case 0: /* child */
      
      if (dup2(filedes[1], STDIN_FILENO)<0) {
	tracef(ln, 0, "dup2 error: %s", strerror(errno));
      }
      if (!(in = fdopen(STDIN_FILENO, "r"))) {
	tracef(ln, 0, "fdopen error");
      }
      
      execl(MAIL_COMMAND, "send-mail", "-t", "-i", "-oem", 0);
      _exit(1);
      
    case -1: /* fork error */
      
      if (debug) tracef(ln, 0, "Fork error invoking mail command");
      return 1;
      
    default:
      
      mta = fdopen(filedes[0], "w");
      
      {
	char *subj;

	subj = DAA_get_rfc822_header(work, &work->message.headers, "subject");

	/* output the message to the MTA */
	fprintf(mta, "Sender: postmaster@%s\n", localHost);
	fprintf(mta, "From: %s@%s\n", work->msg_recip.name.local,
		work->msg_recip.name.domain);
	if (subj) {
	  fprintf(mta, "Subject: Auto Reply to Your Message: %s\n", subj);
	}
	else {
	  fprintf(mta, "Subject: Auto Reply to Your Message ...");
	}
	fprintf(mta, "To: %s\n", to);
	fprintf(mta, "\n");
	fprintf(mta, "  -----  The following is an automated reponse ");
	fprintf(mta, "to your message\n");
	fprintf(mta, "  -----  generated on behalf of %s@%s\n",
		work->msg_recip.name.local, work->msg_recip.name.domain);
	fprintf(mta, "\n");
	fprintf(mta, "%s\n", pszText);
	fclose(mta);
	close(filedes[0]);
      }

      id = waitpid(pid, &stat, 0);
      if ((!WIFEXITED(stat))||(WEXITSTATUS(stat)!=0)) {
	tracef(ln, 0, "Error invoking mail command");
	return 1;
      }
      
    }
  }


  return 0;
}

int annotate_msg(work, str, ln, debug)
     Context *work;
     char *str;
     int ln;
     int debug;
{
  ll_Line *line;

  line = (ll_Line*)malloc(sizeof(ll_Line));
  line->next = 0;
  line->buffer = strdup(str);

  if (!work->message.headers.last) {
    line->prev = 0;
    work->message.headers.first = work->message.headers.last = line;
  }
  else {
    work->message.headers.last->next = line;
    line->prev = work->message.headers.last;
    work->message.headers.last = line;
  }
  
  return 0;
}

int set_msg_folder(work, pszDest, ln, debug)
     Context *work;
     char *pszDest;
     int ln;
     int debug;
{
  return 0;
}

char *get_msg_folder(work)
     Context *work;
{
  return 0;
}

void tracef(int ln, int fPre, char *strSZ, ...)
{
  va_list ap;
  char *str;

  if (fPre) {
    syslog(LOG_DEBUG, "Line %d: %s", ln, strSZ);

    /* fprintf(stderr, "Line %d: %s\n", ln, strSZ); */

  }
  else {
    str = (char*)malloc(strlen(strSZ)+20);
    if (!str)
      return;
    sprintf(str, "Line %d: %s", ln, strSZ);

    va_start(ap, strSZ);
    vsyslog(LOG_DEBUG, str, ap);
    
    /*
    vfprintf(stderr, str, ap);
    fprintf(stderr, "\n");
    */

    va_end(ap);

    free(str);
  }
}

#endif
