/*
 * Intermud mail server, used by Huthar's mailer daemon
 * Original author: Huthar
 * Rewritten to conform to new socket efun specs,  Blackthorn (10/31/92)
 * Modified by Truilkan for use in Basis mudlib (11/01/92)
 * Modified by Pinkfish for use in the Discworld mudlib (5 jan 92)
 * (Stupid american date formats).
 */

#include <config.h>
#include "mailer.h"
#include "/adm/net/nameserver.h"
#define SAVE "/data/mail/"

#define TP(XXXX) tell_object(find_player("inspiral"), XXXX);
 
#define log(x) log_file("MS", x)
#define MS_SAVE "mail-queue"
#define FLUSH_TIME 86400
#define AGE_TIME 604800
#define EOF "%EOF%"
#define EOT "%EOT%"
 
static mapping sockets;
static string receiver, from, to, subject, message,cc;
static int date;
static string mud;
 
void process_message(int fd);
void flush_mail_queue();
void age_queue();
void bad_port(string mud, string from, string message);
 
void create() {
	seteuid(ROOT_UID);
  sockets = ([ ]);
} /* create() */

/*
 * This adds on the lmud and lname bit if it is not in name@address
 * format.
 */
string convert_name(string lname, string lmud) {
  string tmp, tmpaddr;
 
  if (sscanf(lname, "%s@%s", tmp, tmpaddr) != 2) {
    tmp = lname;
    tmpaddr = lmud;
  }

/*
 * this doe not handle aliases for the same mud at the moment.  I
 * will add in some new code here real soon now.  Maybe...
 */ 
  if (tmpaddr != "tabor") return tmp + "@" + tmpaddr;
  return tmp;
} /* convert_name() */

void dest_me() {
  destruct(this_object()); 
} /* dest_me() */
 
void close_callback(int id) {
  process_message(id);
  map_delete(sockets, id);
  return;
} /* close_callback() */
 
void connected(int id) {
  sockets[id] = ([ "msg" : "" ]);
  TP("Connected : "+id+"\n")
} /* connected() */

/*
 * They used to split it up on \n's I think.  How sad...
 */ 
void read_callback(int id, string data) {
  string str, rest;

  TP("Got : "+data+" from "+id+"\n")
  if (sscanf(data, "%s\nEOT\n%s", str, rest) == 2) {
    sockets[id]["msg"] += str;
    process_message(id);
    sockets[id]["msg"] = rest;
    return;
  }
  sockets[id]["msg"] += data;
} /* read_callback() */
 
void process_message(int id) {
  mixed tmp, tmp2;
  string *totmp, *cctmp;
  int i, j, res;

  TP("Processing message\n")
  sscanf(sockets[id]["msg"], "%s\n%s", mud, tmp);
  sockets[id]["msg"] = tmp;
 
  tmp = explode(sockets[id]["msg"], EOF);
  tmp = tmp[0..sizeof(tmp)-2];
  tmp2 = allocate(sizeof(tmp));
 
  for (i = 0; i < sizeof(tmp); i++) {
    tmp2[i] = explode(tmp[i], "\n");
  }
  for (i = 0; i < sizeof(tmp2); i++) {
    receiver = convert_name(tmp2[i][0], "tabor");
    TP("Mail for "+receiver+" ("+NAME_D+")\n")
    totmp = explode(tmp2[i][1], " ");
    for (j = 0; j < sizeof(totmp); j++)
      totmp[j] = convert_name(totmp[j], mud);
    cctmp = explode(tmp2[i][2], " ");
    if (cctmp[0])
      for (j = 0; j < sizeof(cctmp); j++)
        cctmp[j] = convert_name(cctmp[j], mud);
    else
      cctmp = ({ });
    from = convert_name(tmp2[i][3], mud);
    subject = tmp2[i][4];
    sscanf(tmp2[i][5], "%d", date);
    message = implode(tmp2[i][6..sizeof(tmp2[i]) - 1], "\n");
    TP("Me me!"+socket_address(id))
    NAME_D->lookup_mud(mud, "got_address", ({ socket_address(id),
                                              receiver, totmp, cctmp,
                                              from, subject, date,
                                              message }));
/*
 * Ok...  IN here we need to do a call out to check the validity
 * of the mud this is comming from.
 *
 */
  }
} /* process_message() */

void mail_postmaster(string from, string subject, mixed *args) {
  TP("Mailing postmaster\n")
  MAILER->do_mail_message("postmaster", from, subject,
                       0, ">From: "+args[4]+"\nTo: "+
                       implode(args[2], ", ")+"\nCc: "+
                       implode(args[3], ", ")+"\nSubject: "+
                       args[5]+"\nDate: "+ctime(args[6])+
                       "\n"+args[7], 1);
} /* mail_postmaster() */

void got_address(string host, string addr, mixed *args) {
  object ob;
  string *to, name, name2;
  int port;

  if (!addr) {
/* Unknown mud just tried to mail us... */
/*
 * Now, what exactly should I do about it?  Mail it to the postmaster?
 * Yeah, sounds good to me...
 */
    mail_postmaster(args[4], "From unknown mud", args);
/* Don't bother returning it to them. */
    return ;
  }
  sscanf(addr, "%s %d", name, port);
  sscanf(args[0], "%s %d", name2, port);
  if (!name || !name2) {
    mail_postmaster(args[4], "Strange error", args);
    return ;
  }
  if (name != name2) {
    mail_postmaster(args[4], "Forged mail", args);
    return ;
  }
/* Ok, its right.  Now deliver it... */
  MAILER->do_mail_message(implode(args[2], ","), args[4], args[5],
                       implode(args[3], ","), args[7], 0, args[1]);
} /* got_address() */