/* A simple post office. Now somewhat more secure. All references to mailboxes are owned by the owner of the postoffice, and are NOT world readable. Similarly, all elements of a mail message are not world readable. The postmaster, and wizards, can still read your mail. No one else can, unless they are smarter than I am. Everyone has a mailbox object, whose object number lives in the player object's .mbx element. A mailbox has the following elements: .new -- list of unread mail messages .old -- list of old mail messages .ts -- timestamp. Last time mail was read. .nam -- name of the player who owns this box .curr -- contains the object number of the message being sent .to -- used to track who the currently being sent message is going to A mail message has the following elements: .snd -- object number of the sender .txt -- The text of the message .subj -- subject of the message .ts -- when the message was sent */ #define OFFICE #440 /* PARR: Does a lot of stuff when the player arrives in the post office. It checks for unread mail, and attempts to register the player. This runs with the #actor's perms, NOTHING else in this system does. This is important. */ func OFFICE.parr { /* Is this person registered? */ if(#actor.mbx == NULL){ /* Nope, register them. */ #actor.mbx = OFFICE.newbox(#actor); /* Make this tough to get at */ chmod(&#actor.mbx,"O:r:I:r"); chown(&#actor.mbx,objectowner(OFFICE)); echo("You now have a mailbox, and can be sent mail.\n"); } else { /* Check for unread mail */ OFFICE.cntnew(#actor); } } /* CNTNEW: Lists a count of the outstanding mail messages. */ func OFFICE.cntnew { $count = listcount($1.mbx.new); echo("You have "); if($count > 1) echo($count," unread mail messages.\n"); else if ($count == 1) echo("one unread mail message.\n"); else echo("no unread mail.\n"); } chmod(&OFFICE.cntnew,"O:rw,I:r,W:rs"); /* DIRECTORY: Gives a directory of all registered mailbox owners. */ func OFFICE.directory { if($# == 0){ $count = listcount(OFFICE.bxlist); if($count == 0){ echo("There are no registered mailboxes.\n"); return; } echo("Registered mailboxes:\n"); if($count == 1){ $box = listelem(OFFICE.bxlist,1); echo($box.nam); return; } foreach $box in (OFFICE.bxlist){ if($count == 1) echo("and ",$box.nam,".\n"); else echo($box.nam,", "); $count = $count - 1; } } else { $box = match($1,OFFICE.bxlist,"nam"); if($box == NULL){ echo("Could not find any mailbox for ",$1,". Sorry.\n"); return; } echo($box.nam," has "); $cnt = listcount($box.new); if($cnt == 0 || $cnt == NULL){ echo("no unread mail.\n"); } else { if ($cnt == 1){ echo("one unread mail message.\n"); } else { echo(listcount($box.new), " unread mail messages.\n"); } $last = listelem($box.new,listcount($box.new)); echo("-- Mail last received ",$last.ts,".\n"); } echo("-- Last read mail ",$box.ts,"\n"); } } chmod(&OFFICE.directory,"O:rw,I:r,W:rs"); /* READ: Implements the reading of mail. Surprise surprise. */ func OFFICE.read { $box = #actor.mbx; if($box == NULL){ echo("you have no mailbox!! See the postmaster.\n"); return; } if($# == 0){ /* Update the timestamp in this case ONLY. */ #actor.mbx.ts = strtime(); /* try to read the next new message */ $msg = listelem($box.new,1); if($msg == NULL){ echo("You have no new messages.\n"); return; } $box.new = listdrop($box.new,$msg); $box.old = listappend($box.old,$msg); } else if ($1 == "msg"){ $msg = #actor.mbx.curr; if($msg == NULL){ echo("You have no message in progress to read back.\n"); return; } $msg.snd = #actor; $msg.ts = strtime(); } else { $num = atoi($1); if($num == NULL){ echo("Please specify a numeric parameter.\n"); return; } $msg = listelem($box.old,$num); if($msg == NULL){ echo("No such message.\n"); return; } } /* OK, now print out what ever is in $msg */ echo("From: ",$msg.snd.nam,"\n"); echo("Subject: ",$msg.subj,"\n"); echo("Date: ",$msg.ts,"\n\n"); echo($msg.txt,"\n"); } chmod(&OFFICE.read,"O:rw,I:r,W:rs"); /* SEND: Implements sending of mail. Whee! */ func OFFICE.send { if(#actor.mbx.curr == NULL){ echo("No mail to send..Use to, subject, and text commands\n"); return; } if(#actor.mbx.to == NULL){ echo("No recipient specified. Use to command\n"); return; } $msg = #actor.mbx.curr; if($msg.subj == NULL || $msg.txt == NULL){ echo("Incomplete message. Please specify both subject and text.\n"); return; } $msg.ts = strtime(); $msg.snd = #actor; /* Make the message secure */ chmod(&$msg.txt,"O:rw,I:rw"); chmod(&$msg.snd,"O:rw,I:rw"); chmod(&$msg.subj,"O:rw,I:rw"); chmod(&$msg.ts,"O:rw,I:rw"); #actor.mbx.to.new = listappend(#actor.mbx.to.new,$msg); #actor.mbx.curr = NULL; echo("Sent to ",#actor.mbx.to.who.nam,"\n"); } chmod(&OFFICE.send,"O:rw,I:r,W:rs"); /* TO: sets the .to element of the actor's mailbox to the specified recipient's mailbox. If possible. */ func OFFICE.to { if(#actor.mbx.curr == NULL){ #actor.mbx.curr = OFFICE.newobject(); } $mbx = match($1,OFFICE.bxlist,"nam"); if($mbx == NULL){ echo("No mailbox found for player ",$1,"\n"); } else { echo("Mail recipient designated as ",$mbx.nam,"\n"); #actor.mbx.to = $mbx; } } chmod(&OFFICE.to,"O:rw,I:r,W:rs"); /* SUBJECT: Sets the subject string of the currently being worked on message */ func OFFICE.subject { if(#actor.mbx.curr == NULL){ #actor.mbx.curr = OFFICE.newobject(); } #actor.mbx.curr.subj = $1; echo("Set subject to ",$1,"\n"); } chmod(&OFFICE.subject,"O:rw,I:r,W:rs"); /* TEXT: Sets up the text part of the message currently being worked on. */ func OFFICE.text { if(#actor.mbx.curr == NULL){ #actor.mbx.curr = OFFICE.newobject(); } #actor.mbx.curr.txt = $1; echo("Set message text to:\n",$1,"\n"); } chmod(&OFFICE.text,"O:rw,I:r,W:rs"); /* LIST: Lists mail messages out. */ func OFFICE.list { if($1 == "old"){ if(!(listcount(#actor.mbx.old) >= 1)){ echo("You have no old mail messages.\n"); return; } $list = #actor.mbx.old; echo("Old messages:\n"); } else { if(!(listcount(#actor.mbx.new) >= 1)){ echo("You have no new mail messages.\n"); return; } $list = #actor.mbx.new; echo("New messages:\n"); } $n = 1; foreach $msg in ($list){ echo($n," From: ",$msg.snd.nam," Date: ",$msg.ts, " Subj: ",$msg.subj,"\n"); $n = $n + 1; } } chmod(&OFFICE.list,"O:rw,I:r,W:rs"); /* DELETE: Allows the user to delete mail messages. */ func OFFICE.delete { $num = atoi($1); if($num == NULL){ echo("Please use a numeric parameter.\n"); return; } $msg = listelem(#actor.mbx.old,$num); if($msg == NULL){ echo("No such message.\n"); return; } #actor.mbx.old = listdrop(#actor.mbx.old,$msg); echo("Deleted message number ",$num,"\n"); $msg.ts = NULL; $msg.txt = NULL; $msg.snd = NULL; $msg.subj = NULL; OFFICE.free = listadd(OFFICE.free,$msg); } chmod(&OFFICE.delete,"O:rw,I:r,W:rs"); /* HELP: Real simple help system. */ func OFFICE.help { echo("Commands are: directory -- prints out a list of all registered mailboxes directory -- gives more detailed information on the specified person list -- lists all new mail messages list old -- lists all old mail messages read -- reads the next new mail message read -- reads the nth old message read msg -- reads back the message you are currently sending to -- specifies who you wish to send mail to. subject -- specifies the subject line of the message. text -- specifies the text of the message you wish to send. send -- sends a mail message you have set up delete -- deletes the nth old mail message.\n"); } /* NEWBOX: Makes a new MailBox, and returns it. */ func OFFICE.newbox { $box = OFFICE.newobject(); $box.who = #actor; $box.nam = &#actor.nam; /* Beats name changers. Heh. */ $box.ts = strtime(); /* Store them all in a big list for now */ OFFICE.bxlist = listadd(OFFICE.bxlist,$box); chmod(&OFFICE.bxlist,"O:rw,I:r"); return($box); } /* NEWOBJECT: This either makes a new object, or gets one off the list of recycled ones. It returns an empty object, in either case. */ func OFFICE.newobject { if(OFFICE.free == NULL){ $it = objectnew(); } else { $it = listelem(OFFICE.free,1); OFFICE.free = listdrop(OFFICE.free,$it); } return($it); } chmod(&OFFICE.newobject,"O:rw,I:r,W:rs");