/*
 * VERSION 1.0
 * UDP MAIL system (Author: Alvin@Sushi)
 * Requires INETD V0.60 or higher (INETD Author: Nostradamus@Zebedee)
 */
#pragma strict_types
#pragma no_clone
#pragma no_shadow
#pragma no_inherit
#pragma verbose_errors
#pragma combine_strings
//#pragma pedantic
//#pragma range_check
#pragma warn_deprecated

#include <udp.h>
#include <udp_mail.h>

#ifdef DEBUG
#undef DEBUG
#endif
#define DEBUG(x)

mapping spool_item;

static string *spool;

private int match_mud_name(string mudname, string match_str) {
    return mudname[0..sizeof(match_str)-1] == match_str;
}

static void save_spool_item()
{
  string name;
  int count;

  if(!spool_item || !mappingp(spool_item) || spool_item==([]))
    return;

  do {
    ++count;
    name=spool_item[UDPMS_DEST]+"-"+to_string(count);
  } while(spool && member(spool, name)!=-1);

  save_object(UDPM_SPOOL_DIR+name);

  if(!spool || !sizeof(spool))
    spool = ({ name });
  else
    spool += ({ name });
}

/* forward declaration */
void deliver_mail(string recipient,string mud,string from,
	string subj,string mail_body,int status_flag,string spool_name);

/* forward declaration */
static void start_retry_callout();

static void remove_from_spool(string spool_file)
{
  int idx;

  if(spool && (idx=member(spool,spool_file))!=-1)
    {
      spool -= ({ spool_file });
      if(!sizeof(spool))
        spool=0;
    }

  if(file_size("/"+UDPM_SPOOL_DIR+spool_file+".o")>0)
    if(!rm("/"+UDPM_SPOOL_DIR+spool_file+".o"))
      log_file(INETD_LOG_FILE,"UPD_MAIL: Can't delete spool file "+
		"/"+UDPM_SPOOL_DIR+spool_file+".o");
}

static void retry_send()
{
  int i;
  string msg;

  if(!spool || !sizeof(spool)) return;

  for(i=0;i<sizeof(spool);++i)
    {
      if(!restore_object(UDPM_SPOOL_DIR+spool[i]))
        {
          log_file(INETD_LOG_FILE,"UDP_MAIL: Falied to restore spool file "+
		UDPM_SPOOL_DIR+spool[i]);
          continue;
        }

      if(time() - spool_item[UDPMS_TIME] > UDPM_SEND_FAIL*60)
        {
          msg="Reason: Unable to connect to site \""+spool_item[UDPMS_DEST]+
		"\"\n\nINCLUDED MESSAGE FOLLOWS :-\n\n"+
		"To: "+spool_item[UDPMS_TO]+"\n"+
		"Subject: "+spool_item[UDPMS_SUBJECT]+"\n"+
		spool_item[UDPMS_BODY];

          LOCAL_MAILER->deliver_mail(
		spool_item[UDPMS_FROM],	/* TO */
		"Mailer@"+LOCAL_NAME,	/* FROM */
		"Bounced Mail",		/* SUBJECT */
		msg			/* MAIL BODY */
	  );
          remove_from_spool(spool[i]);
          return;
        }

      deliver_mail(
	spool_item[UDPMS_TO],
	spool_item[UDPMS_DEST],
	spool_item[UDPMS_FROM],
	spool_item[UDPMS_SUBJECT],
	spool_item[UDPMS_BODY],
	UDPM_STATUS_IN_SPOOL,
	spool[i]);
    }

  start_retry_callout();
}

static void start_retry_callout()
{
  if(find_call_out("retry_send")!= -1 ) return;

  call_out("retry_send",UDPM_RETRY_SEND*60);
}

static void failed_to_deliver(mapping data)
{
  string msg;
  object obj;

  if(!data[SYSTEM] || data[SYSTEM] != TIME_OUT)
    {
      msg="Reason: Error in connection to remote site \""+data[NAME]+"\"\n\n"+
	"INCLUDED MESSAGE FOLLOWS :-\n\n"+
	"To: "+data[RECIPIENT]+"\n"+
	"Subject: "+data[UDPM_SUBJECT]+"\n"+data[DATA];

      LOCAL_MAILER->deliver_mail(
		data[UDPM_WRITER],	/* TO */
		"Mailer@"+LOCAL_NAME,	/* FROM */
		"Bounced Mail",		/* SUBJECT */
		msg			/* MAIL BODY */
      );
      return;
    }

  /* OK transmission timed out.. place in mail spool */
  
  if((obj=find_player(data[UDPM_WRITER])))
    {
      tell_object(obj,"Mail delivery to "+data[RECIPIENT]+"@"+data[NAME]+
	" Timed Out. Placing mail in spool.\n");
    }

  spool_item=([
	UDPMS_TIME:	time(),
	UDPMS_TO:	data[RECIPIENT],
	UDPMS_DEST:	data[NAME],
	UDPMS_FROM:	data[UDPM_WRITER],
	UDPMS_SUBJECT:	data[UDPM_SUBJECT],
	UDPMS_BODY:	data[DATA]
  ]);

  save_spool_item();

  start_retry_callout();
}

static void get_pending_deliveries()
{
  string *entries;
  int i;

  entries=get_dir(UDPM_SPOOL_DIR+"*.o");
  if(!entries || !sizeof(entries)) return;

  spool=allocate(sizeof(entries));
  for(i=0;i<sizeof(entries);++i)
    spool[i]=entries[i][0..<3];

  start_retry_callout();
}

void create()
{
	seteuid(getuid(this_object()));
  get_pending_deliveries();
}

/*
 * Public routines
 */

int query_valid_mail_host(string hostname)
{
  string *match;

  match=filter(m_indices(({mapping})INETD->query("hosts")),
		#'match_mud_name,lower_case(hostname));

  return (sizeof(match)==1);
}

void deliver_mail(string recipient,string mud,string from,
	string subj,string mail_body,int status_flag,string spool_name)
{
  mapping data;

  // Geloggt wird, wenn ein aufrufendes Objekt nicht sicher ist.
  if (object_name(previous_object())[0..7]!="/secure/")
    write_file("/secure/ARCH/DELIVER_MAIL",
      sprintf("%s : Aufruf von /secure/udp_mail->deliver_mail()\n"
              "  Sender: %O Empfaenger: %O@%O\n  PO: %O TI: %O TP:%O\n\n",
              ctime(time()),from, recipient, mud,
              previous_object(), this_interactive(), this_player()));
  
  data=([
	REQUEST: "mail",
	RECIPIENT: recipient,
        SENDER: this_object(),
	UDPM_STATUS: status_flag,
	UDPM_WRITER: lower_case(from),
	UDPM_SUBJECT: subj,
        UDPM_SPOOL_NAME: spool_name,
	DATA: mail_body
  ]);

  INETD->_send_udp(mud,data,1);
}

void udp_reply(mapping data)
{
  object sender;

  DEBUG(sprintf("MAILER RECEIVED %O\n",data));
  if (!member(data,UDPM_STATUS))
  {
     DEBUG("BOUNCING\n");
     LOCAL_MAILER->deliver_mail(
        data[UDPM_WRITER],	/* TO */
	"INETD@"+data[NAME],	/* FROM */
	"Bounced Mail(No mail support yet?)",		/* SUBJECT */
	data[DATA]		/* MAIL BODY */
	);
        if(data[UDPM_SPOOL_NAME])
          remove_from_spool(data[UDPM_SPOOL_NAME]);
  } else
  switch(data[UDPM_STATUS])
    {
      case UDPM_STATUS_TIME_OUT:
        failed_to_deliver(data);
        break;

      case UDPM_STATUS_DELIVERED_OK:
        if((sender=find_player(data[UDPM_WRITER])))
          {
            tell_object(sender,"Mailer@"+data[NAME]+": "+
		"Mail to "+capitalize(data[DATA])+" delivered ok.\n");
          }
        if(data[UDPM_SPOOL_NAME])
          remove_from_spool(data[UDPM_SPOOL_NAME]);

        break;

      case UDPM_STATUS_UNKNOWN_PLAYER:
        LOCAL_MAILER->deliver_mail(
		data[UDPM_WRITER],	/* TO */
		"Mailer@"+data[NAME],	/* FROM */
		"Bounced Mail",		/* SUBJECT */
		data[DATA]		/* MAIL BODY */
	);
        if(data[UDPM_SPOOL_NAME])
          remove_from_spool(data[UDPM_SPOOL_NAME]);
        break;

	case UDPM_STATUS_IN_SPOOL:
          /* Do nothing */
          break;
    }
}
