inherit "std/object";
#include "mail.h"
static int just_mail;
int New;
mixed mail;
static int *deleted, cur;
static string subject, cc, send_to, body, from;
static string do_this_last;
/*
* functions should be called on this I suppose, although I suppose
* every one should get their own one... hmmm.
*/
int *expand_range(string str);
int mail_message(string str, string bo);
int reply_message(string str, string sub, string cc);
set_do_this_last(bing) { do_this_last = bing; }
query_do_this_last() { return do_this_last; }
/*
* Ok format...
* mail ({ ({ from, to, subject, ccers, body }) });
*/
void setup() {
mail = ({ });
set_short("Mailer object");
set_long("The wonderous and zoopy mailer object. Beware errant Ducks!\n");
/* Cannot be dropped, should self destruct. */
reset_drop();
seteuid("mailer");
New = -1;
} /* setup() */
void show_headers(string str) {
int i, cols;
string s;
cols = (int)this_player()->query_cols();
if (str) {
restore_object("/save/post/"+str);
from = str;
if (New == -1)
cur = 0;
else
cur = New;
}
if (!mail)
mail = ({ });
if (!sizeof(mail))
write("No messages.\n");
if (!deleted)
deleted = allocate(sizeof(mail));
for (i=0;i<sizeof(mail);i++) {
s = "";
if (i==cur)
s += ">";
else
s += " ";
if (deleted[i])
s += "D ";
else if (i>=New && New != -1)
s += "N ";
else
s += " ";
s += (i+1)+": "+mail[i][M_FROM]+" Sub: ";
printf("%s%-=*s\n", s, cols-strlen(s),mail[i][M_SUB]);
}
} /* show_headers() */
void status_line() {
if (just_mail)
return ;
if (!sizeof(mail))
write("[None] ");
else
write("[1-"+sizeof(mail)+"]("+(cur+1)+") ");
write("Mail (+ - R r m q x d h f s ?) : ");
} /* status_line() */
/* this will be called when asked to read mail, what else? */
int read_mail(string str, string sub) {
if (str) {
restore_object("/save/post/"+this_player()->query_name());
from = (string)this_player()->query_name();
just_mail = 1;
if (!sub)
mail_message(str, 0);
else
reply_message(str, sub, "");
return 1;
}
/* ok this will also load the stuff... jolly good. */
show_headers((string)this_player()->query_name());
MAIL_TRACK->add_mailer(this_object(), from);
status_line();
input_to("read_loop");
return 1;
} /* read_mail() */
int load_me(string str) {
int i;
if (sscanf(file_name(previous_object()),MAILER+"#%d",i)!=1) {
write("Bad boy\n");
return 0;
}
seteuid("mailer");
restore_object("/save/post/"+str);
if (!mail)
mail = ({ });
from = str;
return 1;
} /* load_me() */
void save_me() {
if (from)
save_object("/save/post/"+from);
} /* save_me() */
string new_mail(string str) {
mixed s;
New = -1;
restore_object("/save/post/"+str);
if (New != -1) {
/* Can I just say puke here please? All that to find new messages! */
if (!(s=(object)this_player()->query_guild_ob()) ||
!(s=(object)s->query_start_pos()) ||
!(s=(string)s->query_new_messages()))
return "\nYou have NEW messages. "+
"Go to the Post Office to read them.\n"+
"The path is: south, west, west, west, north from Lady Luck Tavern.\n";
return s;
}
/* Just wanna check whether all this shit is necessary Ducky */
return "";
} /* new_mail() */
string finger_mail(string str) {
string ret;
New = -1;
mail = ({ });
restore_object("/save/post/"+str);
if (!mail || !sizeof(mail))
return "No mail.\n";
ret = ""+sizeof(mail)+" mail messages";
if (New != -1) {
ret += ", "+(sizeof(mail)-New)+" of them unread.\n";
} else {
ret += ".\n";
}
return ret;
} /* finger_mail() */
void get_message(string from, string to, string subject, string cc, string body) {
mail += ({ ({ time(), from, to, subject, cc, body }) });
if (New == -1)
New = sizeof(mail)-1;
if (deleted)
deleted += ({ 0 });
save_me();
} /* get_message() */
void send_message() {
int i;
object new_mailer, bing, ob;
string *goto;
goto = explode(send_to, ",");
if (MAIL_TRACK->query_list(send_to))
goto = (mixed)MAIL_TRACK->query_numbers(send_to);
else
goto = explode(send_to, ",");
printf("%O\n", cc);
if (!goto) goto = ({ });
if (cc && cc != "" && cc != ",")
goto += explode(replace(lower_case(cc), " ", ","), ",");
for (i=0;i<sizeof(goto);i++) {
goto[i] = (string)this_player()->expand_nickname(goto[i]);
/* ok expand mailing lists... */
if (MAIL_TRACK->query_list(goto[i])) {
goto += (mixed)MAIL_TRACK->query_numbers(goto[i]);
goto = delete(goto,i,1);
}
}
new_mailer = clone_object(MAILER);
for (i=0;i<sizeof(goto);i++) {
if(goto[i])
write("Sending to : "+goto[i]+"\n");
if ((bing=(mixed)MAIL_TRACK->find_mailer(goto[i]))) {
bing->get_message(from, send_to, subject, cc, body);
if (environment(this_player()))
if (!environment(this_player())->send_message(goto[i])) {
write("A small fairie with a post office hat flies up and takes "+
"your mail.\n");
say("A small fairie with a post office hat flies up and takes "+
this_player()->query_name()+"'s mail.\n");
if ((ob = find_player(goto[i]))) {
tell_object(ob, "A small fairie flies up and tells you, "+
"you have some mail from "+this_player()->query_name()+
"! (bing)\n");
tell_room(environment(ob), "A small fairie flies up to "+goto[i]+
" and whispers something to "+
ob->query_objective()+".\n", ({ ob }) );
}
}
} else
if ("secure/login"->test_user(goto[i])) {
new_mailer->load_me(goto[i]);
new_mailer->get_message(from, send_to, subject, cc, body);
if (environment(this_player()))
environment(this_player())->send_message(goto[i]);
}
}
new_mailer->dest_me();
} /* send_message() */
string message_string(int i) {
return "Sent at "+ctime(mail[i-1][M_TIME])+
"\nMessage #"+i+(deleted[i-1] ? (" (deleted)\n") : "\n")+
"From : "+mail[i-1][M_FROM]+"\nTo : "+mail[i-1][M_TO]+
"\nSubject : "+mail[i-1][M_SUB]+"\nCc : "+
mail[i-1][M_CC]+"\n"+mail[i-1][M_BODY];
} /* message_string() */
void read_message(int i) {
write("\n\n");
this_player()->set_finish_func("finish_message");
this_player()->more_string(message_string(i));
} /* read_message() */
void finish_message() {
status_line();
input_to("read_loop");
} /* finish_message() */
void delete_things() {
int i;
while (i<sizeof(mail)) {
if (deleted[i]) {
mail = delete(mail,i,1);
deleted = delete(deleted,i,1);
} else
i++;
}
} /* delete_things() */
int mail_message(string to, string bo) {
int i;
string *bing;
send_to = (string)this_player()->expand_nickname(send_to);
send_to = replace(to, " ", ",");
bing = explode(send_to, ",") - ({ "" });
for (i=0;i<sizeof(bing);i++) {
if (!"secure/login"->test_user(bing[i]) &&
!MAIL_TRACK->query_list(bing[i])) {
write(bing[i]+" does not exist, try try again\n");
bing = delete(bing, i, 1);
i--;
}
}
if (!sizeof(bing)) {
write("A recipient for the mail might help.\n");
status_line();
input_to("read_loop");
return 1;
}
send_to = implode(bing, ",");
write("Subject : ");
input_to("get_subject");
subject = 0;
send_to = to;
cc = "";
if (!bo)
body = "";
else
body = bo;
} /* mail_message() */
int reply_message(string to, string sub, string rcc) {
string s1;
send_to = to;
subject = sub;
if (sscanf(sub,"Re: %s",s1)==1)
subject = "Re(many): "+s1;
else if (sscanf(sub,"Re(many): %s",s1)!=1)
subject = "Re: "+sub;
cc = rcc;
body = "";
write("Press return for a subject of \""+subject+"\"\nSubject : ");
input_to("get_subject");
return 1;
} /* reply_message() */
int get_subject(string str) {
if (!str)
str = "";
if (str == "" && !subject) {
write("Aborted.\n");
status_line();
input_to("read_loop");
return 1;
}
if (str != "")
subject = str;
write("Enter your Cc's now. Terminate with a blank line.\nCc: ");
input_to("get_cc");
return 1;
} /* get_subject() */
int finish_body(string str) {
if (!str || str == "") {
write("Aborted.\n");
if (just_mail)
return 1;
status_line();
input_to("read_loop");
return 1;
}
body = str + (string)this_player()->append_signature();
write("Ok.\n");
send_message();
write("Sent.\n");
if (just_mail)
return 1;
status_line();
input_to("read_loop");
return 1;
} /* finish_body() */
int do_forward(string to, string sub, string bo) {
send_to = to;
subject = sub;
body = bo;
cc = 0;
send_message();
status_line();
input_to("read_loop");
return 1;
} /* do_forward() */
int get_cc(string str) {
string *bits;
int i;
if (str == "" || !str || str == "**") {
this_player()->do_edit(0, "finish_body");
return 1;
}
str = replace(str, " ", ",");
/*
str = implode(explode(str, " "), ",");
*/
bits = explode(str, ",") - ({ "" });
for (i=0;i<sizeof(bits);i++)
if (!"/secure/login"->test_user(bits[i])) {
write("Sorry "+bits[i]+" does not exist.\n");
bits = delete(bits, i--, 1);
}
cc += ","+implode(bits,",");
write("Cc: ");
input_to("get_cc");
return 1;
} /* get_cc() */
int read_loop(string str) {
int num, i, *ms;
string comm, s1, s2;
if (just_mail)
return 1;
if (!cur)
cur = 1;
/*
* ok this should (theoreticaly) do some clever things and get the message
* number being reffered to out of the junk. But then again, maybe not.
*/
if (str == "-")
num = -1;
else if (sscanf(str, "%d%s",num,str)!=2) {
comm = "";
if (sscanf(str, "%s %d %s", s1, num, s2) == 3)
str = s1 + " " + s2;
}
if (sscanf(str, "%s %s", comm, str) != 2) {
comm = str;
str = "";
}
comm = extract(comm,0,0);
switch (comm) {
case "" : if (num > 0 && num <= sizeof(mail)) {
read_message(num);
cur = num;
return 1;
} else if (num==0) {
if (++cur > sizeof(mail)) {
write("Run out of messages\n");
cur = sizeof(mail);
} else {
read_message(cur);
return 1;
}
} else {
write("Sorry message number must be in the range "+1+
" to "+sizeof(mail)+"\n");
}
break;
case "+" : if (num == 0)
cur++;
else
cur += num;
if (cur > sizeof(mail) || cur < 1) {
write("Gone too far.\n");
if (num > 0)
cur = sizeof(mail);
else
cur = 1;
} else
read_message(cur);
break;
case "-" : if (num == 0)
cur--;
else
cur -= num;
if (cur > sizeof(mail) || cur < 1) {
write("Gone too far.\n");
if (num>0)
cur = 1;
else
cur = sizeof(mail);
}
break;
case "x" : write ("Dont let them massages pile up.\n");
New = -1;
save_me();
if (do_this_last)
call_other(do_this_last[0], do_this_last[1], do_this_last[2]);
else
dest_me();
return 1;
case "q" : delete_things();
New = -1;
save_me();
write("Ok.\n");
if (do_this_last)
call_other(do_this_last[0], do_this_last[1], do_this_last[2]);
else
dest_me();
return 1;
case "d" : ms = expand_range(str);
for (i=0;i<sizeof(ms);i++) {
deleted[ms[i]-1] = !deleted[ms[i]-1];
if (deleted[ms[i]-1])
write("Deleted message "+ms[i]+".\n");
else
write("Undeleted message "+ms[i]+".\n");
}
break;
case "m" : mail_message(str,""); /* no cc at this point ;) */
return 0;
break;
case "r" : if (num)
if (num > sizeof(mail) || num < 1)
write("Number out of bounds (6!!!!)\n");
else {
reply_message(mail[num-1][M_FROM], mail[num-1][M_SUB],
mail[num-1][M_CC]+","+
implode(explode(mail[num-1][M_CC]+
mail[num-1][M_TO], ",") -
({ from }), ","));
return 0;
} else {
/* ok so handle the fact that we may be a CC and send to the person who
* it was addressed to as well. */
reply_message(mail[cur-1][M_FROM], mail[cur-1][M_SUB],
implode(explode(mail[cur-1][M_CC]+
mail[cur-1][M_TO], ",") -
({ from }), ","));
return 0;
}
break;
case "h" : show_headers(0);
break;
case "?" : cat("/doc/helpdir/mail");
break;
case "R" : if (num)
if (num > sizeof(mail) || num < 1)
write("Number out of bounds.\n");
else /* dont remember CC's */ {
reply_message(mail[num-1][M_FROM], mail[num-1][M_SUB], "");
return 0;
} else {
reply_message(mail[cur-1][M_FROM], mail[cur-1][M_SUB], "");
return 0;
}
break;
case "s" : /* save to a file... only for the lonely, I mean wizs */
if (!this_player()->query_creator()) {
write("Only creators can save files, sorry.\n");
break;
}
if (!num)
num = cur;
if (num < 1 || num > sizeof(mail)) {
write("Message out of bounds.\n");
break;
}
str = (string)this_player()->get_path(str);
if (!"/secure/master"->valid_write(str, geteuid(this_player()),
"write_file")) {
write("You cannot write to that file.\n");
break;
}
if ((i=file_size(str)) > 0)
write("Appending.\n");
else if (i == -2) {
write("Directory\n");
break;
}
seteuid(geteuid(this_player()));
if (!write_file(str, message_string(num)))
write("Write file failed.\n");
else
write("Saved message "+num+" to "+str+".\n");
seteuid("mailer");
break;
case "f" : /* forward a message... */
if (!num)
num = cur;
if (num < 1 || num > sizeof(mail)) {
write("Message out of bounds.\n");
break;
}
do_forward(str, "Fwd: "+mail[num-1][M_SUB],
">"+replace(message_string(num), "\n", "\n>"));
/*
mail_message(str, ">"+implode(explode(
message_string(num), "\n"), "\n>"));
*/
return 0;
}
status_line();
input_to("read_loop");
} /* read_loop() */
void dest_me() {
MAIL_TRACK->delete_mailer(this_object());
::dest_me();
} /* dest_me() */
int *expand_range(string str) {
int *ms, i, num, start, end;
string s1,s2;
if (str == "" || !str)
str = ""+cur;
if (!sizeof(mail))
return ({ });
str = implode(explode(str, " "),"");
ms = ({ });
if (sscanf(str, "%sall%s", s1,s2)==2) {
for (i=1;i<sizeof(mail)+1;i++)
ms += ({ i });
return ms;
}
while (sscanf(str, "%d%s",start,str) == 2) {
if (start < 1)
start = 1;
if (start > sizeof(mail))
start = sizeof(mail);
if (str && str != "" && str[0] == '-') {
sscanf(str, "-%d%s", end, str);
if (end >= start) {
if (end > sizeof(mail))
end = sizeof(mail);
for (i=start;i<=end;i++)
if (member_array(i, ms) == -1)
ms += ({ i });
}
} else
if (member_array(start, ms) == -1)
ms += ({ start });
sscanf(str,",%s",str);
}
return ms;
} /* expand_range() */