lima-1.0b5/
lima-1.0b5/driver/
lima-1.0b5/driver/ChangeLog.old/
lima-1.0b5/driver/Win32/
lima-1.0b5/driver/compat/
lima-1.0b5/driver/include/
lima-1.0b5/driver/testsuite/
lima-1.0b5/driver/testsuite/clone/
lima-1.0b5/driver/testsuite/command/
lima-1.0b5/driver/testsuite/data/
lima-1.0b5/driver/testsuite/etc/
lima-1.0b5/driver/testsuite/include/
lima-1.0b5/driver/testsuite/inherit/
lima-1.0b5/driver/testsuite/inherit/master/
lima-1.0b5/driver/testsuite/log/
lima-1.0b5/driver/testsuite/single/
lima-1.0b5/driver/testsuite/single/tests/compiler/
lima-1.0b5/driver/testsuite/single/tests/efuns/
lima-1.0b5/driver/testsuite/single/tests/operators/
lima-1.0b5/driver/testsuite/u/
lima-1.0b5/driver/tmp/
lima-1.0b5/etc/
lima-1.0b5/lib/WWW/help/
lima-1.0b5/lib/cmds/
lima-1.0b5/lib/cmds/create/
lima-1.0b5/lib/cmds/player/attic/
lima-1.0b5/lib/contrib/bboard/
lima-1.0b5/lib/contrib/boards/
lima-1.0b5/lib/contrib/marriage/
lima-1.0b5/lib/contrib/roommaker/
lima-1.0b5/lib/contrib/transient_effect/
lima-1.0b5/lib/daemons/channel/
lima-1.0b5/lib/daemons/imud/
lima-1.0b5/lib/data/
lima-1.0b5/lib/data/config/
lima-1.0b5/lib/data/links/
lima-1.0b5/lib/data/news/
lima-1.0b5/lib/data/players/
lima-1.0b5/lib/data/secure/
lima-1.0b5/lib/domains/
lima-1.0b5/lib/domains/std/2.4.5/maze1/
lima-1.0b5/lib/domains/std/2.4.5/npc/
lima-1.0b5/lib/domains/std/2.4.5/post_dir/
lima-1.0b5/lib/domains/std/2.4.5/sub/
lima-1.0b5/lib/domains/std/camera/
lima-1.0b5/lib/domains/std/config/
lima-1.0b5/lib/domains/std/cult/
lima-1.0b5/lib/domains/std/effects/
lima-1.0b5/lib/domains/std/misc/
lima-1.0b5/lib/domains/std/monsters/
lima-1.0b5/lib/domains/std/recorder/
lima-1.0b5/lib/domains/std/rooms/
lima-1.0b5/lib/domains/std/rooms/beach/
lima-1.0b5/lib/domains/std/rooms/labyrinth/
lima-1.0b5/lib/domains/std/school/
lima-1.0b5/lib/domains/std/school/O/
lima-1.0b5/lib/domains/std/spells/
lima-1.0b5/lib/domains/std/spells/stock-mage/
lima-1.0b5/lib/domains/std/spells/stock-priest/
lima-1.0b5/lib/help/
lima-1.0b5/lib/help/admin/
lima-1.0b5/lib/help/hints/General_Questions/
lima-1.0b5/lib/help/hints/Pirate_Quest/
lima-1.0b5/lib/help/player/
lima-1.0b5/lib/help/player/bin/
lima-1.0b5/lib/help/player/quests/
lima-1.0b5/lib/help/wizard/
lima-1.0b5/lib/help/wizard/coding/guilds/
lima-1.0b5/lib/help/wizard/coding/rooms/
lima-1.0b5/lib/help/wizard/lib/daemons/
lima-1.0b5/lib/help/wizard/lib/lfun/
lima-1.0b5/lib/help/wizard/lib/std/
lima-1.0b5/lib/help/wizard/mudos_doc/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/interactive/
lima-1.0b5/lib/help/wizard/mudos_doc/applies/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/concepts/
lima-1.0b5/lib/help/wizard/mudos_doc/driver/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/arrays/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/buffers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/compile/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/filesystem/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/floats/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/functions/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/general/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mappings/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/mixed/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/numbers/
lima-1.0b5/lib/help/wizard/mudos_doc/efuns/parsing/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/constructs/
lima-1.0b5/lib/help/wizard/mudos_doc/lpc/types/
lima-1.0b5/lib/include/driver/
lima-1.0b5/lib/log/
lima-1.0b5/lib/obj/admtool/
lima-1.0b5/lib/obj/admtool/internal/
lima-1.0b5/lib/obj/admtool/mudinfo/
lima-1.0b5/lib/obj/admtool/secure/
lima-1.0b5/lib/obj/secure/
lima-1.0b5/lib/obj/secure/cmd/
lima-1.0b5/lib/obj/secure/mailers/
lima-1.0b5/lib/obj/secure/shell/
lima-1.0b5/lib/obj/secure/shell/classes/
lima-1.0b5/lib/obj/tasktool/
lima-1.0b5/lib/obj/tasktool/internal/
lima-1.0b5/lib/open/
lima-1.0b5/lib/secure/
lima-1.0b5/lib/secure/cgi/
lima-1.0b5/lib/secure/modules/
lima-1.0b5/lib/secure/simul_efun/
lima-1.0b5/lib/std/adversary/
lima-1.0b5/lib/std/adversary/advancement/
lima-1.0b5/lib/std/adversary/armor/
lima-1.0b5/lib/std/adversary/blows/
lima-1.0b5/lib/std/adversary/death/
lima-1.0b5/lib/std/adversary/formula/
lima-1.0b5/lib/std/adversary/health/
lima-1.0b5/lib/std/adversary/pulse/
lima-1.0b5/lib/std/adversary/wield/
lima-1.0b5/lib/std/classes/event_info/
lima-1.0b5/lib/std/container/
lima-1.0b5/lib/std/living/
lima-1.0b5/lib/std/modules/contrib/
lima-1.0b5/lib/std/patterns/
lima-1.0b5/lib/std/race/
lima-1.0b5/lib/std/race/restricted/
lima-1.0b5/lib/std/room/
lima-1.0b5/lib/tmp/
lima-1.0b5/lib/trans/
lima-1.0b5/lib/trans/admincmds/
lima-1.0b5/lib/trans/obj/
lima-1.0b5/lib/wiz/
/* Do not remove the headers from this file! see /USAGE for more info. */

/*
** mailer.c
**
** Base class for a mailer object.  Provides basic support for all mailers.
**
** Created 31-OCT-94, Deathblade.
**
** Changed send_news_reply() to Support Boards as well as newsreader
**  Vette  April 15, 1997
*/

#include <security.h>
#include <daemons.h>
#include <playerflags.h>
#include <mudlib.h>
#include <classes.h>
#include <edit.h>

inherit M_ACCESS;
inherit M_INPUT;

inherit CLASS_MAILMSG;

//### make it private so it can't be changed?
nosave object	mailbox_ob;


/*
** tmp_fname()
**
** Return a temporary filename for editing mail messages
*/
protected nomask string tmp_fname()
{
    return "/tmp/tmail." + this_user()->query_userid();
}

/*
** get_message_key()
**
** Get a message key from a user's message number.
** 0 is returned if the user number is out of bounds.
*/
protected nomask int get_message_key(int user_num)
{
    int * mail_keys;

    if ( !user_num )
	user_num = mailbox_ob->query_message_index();
    else 
	user_num--;

    mail_keys = mailbox_ob->query_message_keys();
    if ( user_num < 0 || user_num >= sizeof(mail_keys) )
    {
	write("Message number out of bounds.\n");
	return 0;
    }

    return mail_keys[user_num];
}

/*
** format_name_list()
**
** Format a list of names (as in To: or CC:).  Returns an array of lines.
*/
protected nomask string * format_name_list(string prompt, string * names)
{
    if ( !names || !sizeof(names) )
	return ({ });

    return explode(prompt + implode(map_array(names, (: capitalize :)),
	  ", "),
      "\n");
}

/*
** build_message()
**
** Build an array of strings containing a mail message.
*/
protected nomask string * build_message(int mail_key, int supress_header)
{
    string *	output;
    class mail_msg msg;

    msg = mailbox_ob->get_one_message(mail_key);
    if ( !msg )
	return ({ "*** LOST THE MESSAGE! ***" });

    output = ({});
    if ( !supress_header )
    {
	output += format_name_list("To     : ", msg->to_list);
	output += format_name_list("Cc     : ", msg->cc_list);
	output += ({ "From   : " + capitalize(msg->sender) });
	output += ({ "Date   : " + ctime(msg->date) });
	output += explode("Subject: " + msg->subject,"\n");
    output += ({ repeat_string("-", 39) });
    }

    output += msg->body;
    output += ({ "" });

    return output;
}

/*
** write_dead_letter()
**
** Write the array of lines to the wizard's dead.letter.  Does nothing
** if the player is not a wizard or no home dir exists.
*/
protected nomask void write_dead_letter(string * buf)
{
    if ( wizardp(this_user()) && 
      file_size("/wiz/"+this_user()->query_userid()) == -2 )
    {
	write("Appending to ~/dead.letter\n");
	write_file(sprintf("/wiz/%s/dead.letter",
	    this_user()->query_userid()),
	  implode(buf,"\n")+"\n");
    }
}

/*
** build_body_inclusion()
**
** Build an array of lines for the body of a message to be included into
** another message (prefixed with "> ")
*/
protected nomask string * build_body_inclusion(string * body)
{
    return map_array(body, (: "> " + $1 :));
}

/*
** send_mail_message()
**
** Send a mail message to the given people.
*/
private nomask void send_mail_message(string subject,
  string *buf,
  mixed to_list,
  mixed cc_list,
  int use_dead_letter)
{
    string * name_list;

    if ( stringp(to_list) )
	to_list = map(explode(to_list, ","), (:trim_spaces:));
    else if ( !arrayp(to_list) )
	to_list = ({ });

    if ( stringp(cc_list) )
	cc_list = map(explode(cc_list, ","), (:trim_spaces:));
    else if ( !arrayp(cc_list) )
	cc_list = ({ });

    name_list = MAIL_D->send_mail(this_user()->query_userid(),
      subject,
      buf,
      to_list,
      cc_list);
    if ( !sizeof(name_list) )
    {
	write("No valid destination.\n");
	if ( use_dead_letter )
	    write_dead_letter(buf);
	return;
    }

    write(implode(format_name_list("Mail sent to: ", name_list), "\n") + "\n");
}


/*------------------------------------------------------------------------
**
** COMMANDS
**
** These are some basic implementations of mail commands.  Mailer
** subclasses may use them if they fit within the schema/style of
** the mailer interface.  If not, then subclasses are, of course,
** free to implement new commands.
**
** Note that the commands must have their arguments validated on
** entry -- usage information cannot be printed from these commands.
*/

protected nomask void cmd_read(int user_num,
  string outputfile,
  int supress_header)
{
    int		timestamp;
    string *	output;

    if ( !user_num )
	user_num = mailbox_ob->query_message_index() + 1;

    timestamp = get_message_key(user_num);
    if ( !timestamp ) return;

    output = build_message(timestamp, supress_header);

    if ( outputfile )
    {
	if ( strsrch(outputfile,"/") == -1 )
	    outputfile = wiz_dir(this_user()) + "/Mail/" + outputfile;

	if ( !write_file(outputfile, implode(output,"\n")) )
	    write("Failed.\n");
	else
	    printf("Saved message to %s.\n",outputfile);
	return;
    }

    mailbox_ob->set_message_index(user_num - 1);
    mailbox_ob->set_message_read(timestamp);

    more(output);
}


protected nomask void cmd_headers(string rangestr)
{
    int   i;
    string* output;
    int * mail_keys;
    mapping nums;
    int key;

    output = ({});

    if ( rangestr )
	rangestr = expand_range(rangestr);

    mail_keys = mailbox_ob->query_message_keys();
    if ( !sizeof(mail_keys) )
	return write("No mail.\n");

    nums = ([ ]);
    for ( i = sizeof(mail_keys); i--; )
	nums[mail_keys[i]] = i + 1;

    if ( rangestr )
    {
	for ( i = sizeof(mail_keys); i--; )
	    if ( !test_bit(rangestr, i+1) )
	    {
		nums[mail_keys[i]] = 0;
		mail_keys[i] = 0;
	    }

	mail_keys -= ({ 0 });
    }

    foreach ( key in mail_keys )
    {
	class mail_msg msg = mailbox_ob->get_one_message(key);

	if ( !msg )
	    output +=
	    ({ sprintf("  %-3d %-15s  %10s  %s",
		nums[key], "", "", "*** LOST MESSAGE ***")
	    });
	else
	    output +=
	    ({ sprintf("%c %-3d %-15s (%s) %s",
		mailbox_ob->query_message_read(key) ? 'N' : ' ',
		nums[key],
		capitalize(msg->sender),
		ctime(msg->date)[0..9],
		msg->subject)
	    });
    }

    more(output);
}



/* to_list is a string * or a string */
private nomask void mailer_get_cc_list(mixed to_list,
  string subject,
  string cc_list)
{
    string * buf;
    string file;

    file = tmp_fname();
    buf = explode(read_file(file), "\n");
    send_mail_message(subject, buf, to_list, cc_list, 1);

    rm(file);
}

private nomask void mailer_done_edit(string to_list,
  string subject,
  string fname)
{
    /*
    ** Just return if they cancelled the edit
    */
    if ( !fname )
	return;

    write("Cc: ");
    modal_simple((: mailer_get_cc_list, to_list, subject :));
}

private nomask void mailer_get_subject(string to_list, string arg)
{
    string subject = arg ? arg : "<none>";

    new(EDIT_OB, EDIT_FILE, tmp_fname(),
      (: mailer_done_edit, to_list, subject :));
}

protected nomask void cmd_mail(string to_list)
{
    //Until a new maskable editor is in place, don't allow a null
    // to line.
    if ( !stringp(to_list) )
    {
	write("No destination.\n");
	return;
    }

    write("Subject: ");
    modal_simple((: mailer_get_subject, to_list :));
}

protected nomask void cmd_reply(int user_num, int reply_all)
{
    int key;
    class mail_msg msg;
    mixed body;
    string * to_list;
    string subject;
    string file;

    key = get_message_key(user_num);
    if ( !key )
	return;

    msg = mailbox_ob->get_one_message(key);
    if ( !msg )
    {
	write("*** ERROR: the message was lost!\n");
	return;
    }

    body = build_body_inclusion(msg->body);
    body = implode(body, "\n");
    body = sprintf("On %s %s wrote:\n%s\n",
      ctime(msg->date),
      capitalize(msg->sender),
      body);

    subject = "Re: " + msg->subject;

    to_list = ({ msg->sender });
    if ( reply_all )
	to_list = clean_array(to_list + msg->to_list + msg->cc_list);

    file = tmp_fname();
    write_file(file, body);

    new(EDIT_OB, EDIT_FILE, tmp_fname(),
      (: mailer_done_edit, to_list, subject :));
}


protected nomask void cmd_delete(string arg)
{
    int *	mail_keys;
    int		i;
    string	whichones;

    mail_keys = mailbox_ob->query_message_keys();

    whichones = "";
    if( arg )
	whichones = expand_range( arg );
    else
	whichones = set_bit(whichones, mailbox_ob->query_message_index() + 1);

    for ( i = sizeof(mail_keys) + 1; --i; )
	if( test_bit(whichones,i) )
	{
	    mailbox_ob->delete_message(mail_keys[i-1]);
	    printf("Message %d deleted.\n",i);
	}
}


protected nomask void cmd_setcurrent(mixed arg)
{
    int count;

    if ( !(count = mailbox_ob->query_message_count()) )
	return printf("No messages.\n");

    if ( !arg )
	return (void)printf("Current message is: %d\n",
	  mailbox_ob->query_message_index() + 1);

    arg = to_int( arg );
    if ( arg <= 0 || arg > count )
    {
	printf("Message number out of range.\n");
	return;
    }
    mailbox_ob->set_message_index(arg - 1);

    printf("Current message now set to: %d\n",arg);
}


protected nomask void cmd_forward(int user_num, string newto)
{
    int			key;
    string *		body;
    class mail_msg	msg;

    key = get_message_key(user_num);
    if ( !key ) return;

    msg = mailbox_ob->get_one_message(key);
    if ( !msg )
    {
	write("*** ERROR: the message was lost!\n");
	return;
    }

    body = build_body_inclusion(msg->body);
    body = ({"Begin forwarded message:",
      sprintf("On %s %s wrote:",
	ctime(msg->date),
	capitalize(msg->sender))
    }) + body;

    send_mail_message("FWD: " + msg->subject,
      body,
      newto,
      ({ }),	/* cc_list */
      0);
}

void send_news_reply(string subject, string * text, string * to)
{
    if ( base_name(previous_object()) != NEWSREADER )
      error("security: attempted use by: " +
	    base_name(previous_object()) + "\n");

    send_mail_message(subject, text, to, 0, 0);
}


void create()
{
    set_privilege(1);

    mailbox_ob = MAILBOX_D->get_mailbox(this_user()->query_userid());
}

void remove()
{
    destruct();
}