Mail Distribution Center #46

Parent #1Owner #36Flags readSource QuestCore.db

Aliases: Mail Distribution Center, Postmaster

52 verbs · 9 properties · 0 children

Verbs

VerbSpecFlagsDefinerLines
resolve_addrthis none thisrxd#4660
sends_tothis none thisrxd#4614
send_messagethis none thisrxd#4627
raw_sendthis none thisrxd#4661
mail_forward mail_notifythis none thisrxd#466
touchthis none thisrxd#4619
look_selfthis none thisrxd#464
acceptablethis none thisrxd#463
check_namesthis none thisrxd#4629
matchthis none thisrxd#4638
match_recipientthis none thisrxd#4616
match_failedthis none thisrxd#4618
make_messagethis none thisrxd#4641
namethis none thisrxd#469
name_listthis none thisrxd#461
parse_address_fieldthis none thisrxd#4611
display_seq_fullthis none thisrxd#4615
display_seq_headersthis none thisrxd#4621
rm_message_seqthis none thisrxd#4629
undo_rmmthis none thisrxd#4628
expunge_rmm list_rmmthis none thisrxd#4644
renumberthis none thisrxd#4645
msg_summary_linethis none thisrxd#4616
parse_message_seqthis none thisrxd#46165
_parse_from _parse_tothis none thisrxd#4624
_parse_datethis none thisrxd#4623
new_message_numthis none thisrxd#4612
length_all_msgsthis none thisrxd#462
length_date_lethis none thisrxd#4621
length_date_gtthis none thisrxd#4622
length_num_lethis none thisrxd#463
exists_num_eqthis none thisrxd#463
from_msg_seqthis none thisrxd#4623
%from_msg_seqthis none thisrxd#4625
to_msg_seqthis none thisrxd#4624
%to_msg_seqthis none thisrxd#4625
subject_msg_seqthis none thisrxd#4619
body_msg_seqthis none thisrxd#4624
messages_in_seqthis none thisrxd#469
__convert_newthis none thisrxd#4646
to_textthis none thisrxd#462
is_readable_by is_writable_by is_usable_bythis none thisrxd#469
reserved_patternthis none thisrxd#4610
is_recipientthis none thisrxd#461
keep_message_seqthis none thisrxd#4623
kept_msg_seq unkept_msg_seqthis none thisrxd#4612
msg_seq_to_msg_num_stringthis none thisrxd#463
msg_seq_to_msg_num_listthis none thisrxd#463
send_log_messagethis none thisrxd#4613
parse_misc_headersthis none thisrxd#4629
resend_messagethis none thisrxd#4619
init_for_corethis none thisrx#466

Properties

PropertyDefinerFlagsOwnerValue
options#46rc#36
list of 11{"include", "noinclude", "all", "sender", "nosubject", "expert", "enter", "sticky", "@mail", "manymsgs", "replyto"}
reserved_patterns#46r#36{}
player_expire_time#46rc#362592000
player_default_@mail#46rc#36"last:15"
max_mail_notify#46rc#3615
key#1c#36<clear>
aliases#1rc#36{"Mail Distribution Center", "Postmaster"}
description#1rc#36
list of 5{"This is the database of mailing-list/mail-folder objects.", "The basic procedure for creating a new list/folder is to create a child of $mail_recipient (Generic Mail Recipient) assign it a suitable name&aliases, set a suitable .mail_forward/.mail_notify (or create suitable :mail_forward() and :mail_notify() verbs) and then teleport it here.", "", "Avaliable aliases:", ""}
object_size#1r#36{54249, -1090650497}

Ancestry

Ancestors (nearest first): #1 Root Class

Children: none

Call graph

calls n46_0 #46:resolve_addr n46_0->n46_0 n52_5 #52:isa n46_0->n52_5 n6_18 #6:tell n46_0->n6_18 n20_6 #20:english_list n46_0->n20_6 n46_4 #46:mail_forward n46_0->n46_4 n55_19 #55:iassoc_suspended n46_0->n55_19 n52_2 #52:has_verb n46_4->n52_2 n46_1 #46:sends_to n46_1->n46_4 n46_1->n46_1 n56_8 #56:suspend_if_needed n46_1->n56_8 n46_2 #46:send_message n42_0 #42:controls n46_2->n42_0 n46_12 #46:make_message n46_2->n46_12 n46_3 #46:raw_send n46_2->n46_3 n46_14 #46:name_list n46_12->n46_14 n46_13 #46:name n46_12->n46_13 n20_71 #20:redirect_ansi n46_12->n20_71 n46_3->n46_0 n24_40 #24:random_wizard n46_3->n24_40 n46_5 #46:touch n46_3->n46_5 n6_10 #6:notify n46_3->n6_10 n55_18 #55:iassoc n46_3->n55_18 n52_3 #52:has_callable_verb n46_3->n52_3 n46_5->n46_4 n46_5->n56_8 n46_5->n46_5 n52_6 #52:ancestors n46_5->n52_6 n46_6 #46:look_self n6_79 #6:tell_lines n46_6->n6_79 n46_7 #46:acceptable n46_7->n52_5 n46_8 #46:check_names n46_7->n46_8 n46_8->n6_18 n46_42 #46:reserved_pattern n46_8->n46_42 n46_9 #46:match n46_8->n46_9 n46_9->n56_8 n46_9->n52_6 n46_9->n46_42 n20_16 #20:literal_object n46_9->n20_16 n46_10 #46:match_recipient n46_10->n46_9 n20_20 #20:match_player n46_10->n20_20 n46_11 #46:match_failed n46_11->n6_18 n46_11->n20_6 n37_2 #37:find_all n46_11->n37_2 n55_4 #55:map_arg n46_11->n55_4 n46_14->n20_6 n46_14->n55_4 n46_13->n52_3 n46_17 #46:display_seq_headers n46_17->n6_18 n46_17->n20_71 n33_18 #33:contract n46_17->n33_18 n33_2 #33:complement n46_17->n33_2 n6_13 #6:linelen n46_17->n6_13 n46_18 #46:rm_message_seq n46_18->n6_18 n46_18->n56_8 n46_18->n52_3 n46_18->n33_18 n56_7 #56:running_out_of_time n46_18->n56_7 n33_20 #33:intersection n46_18->n33_20 n33_4 #33:tostr n46_18->n33_4 n46_19 #46:undo_rmm n46_19->n52_3 n33_3 #33:union n46_19->n33_3 n33_17 #33:expand n46_19->n33_17 n46_20 #46:expunge_rmm n46_20->n6_18 n46_20->n20_71 n46_20->n33_18 n46_20->n33_2 n33_11 #33:last n46_20->n33_11 n46_21 #46:renumber n46_21->n6_18

Showing 48 of 91 verbs; 43 not shown.

Source

resolve_addr

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1"resolve(name,from,seen,prevrcpts,prevnotifs) => {rcpts,notifs} or E_INVARG";
2"resolve(list,from,seen,prevrcpts,prevnotifs) => {bogus,rcpts,notifs}";
3"Given either an address (i.e., objectid) or a list of such, traces down all .mail_forward lists and .mail_notify to determine where a message should actually go and who should be told about it.  Both forms take previous lists of recipients/notifications and add only those addresses that weren't there before.  `seen' is the stack of addresses we are currently resolving (for detecting loops).  The first form returns E_INVARG if `name' is invalid.  The second form returns all invalid addresses in the `bogus' list but still does the appropriate search on the remaining addresses.";
4{recip, from, ?seen = {}, ?prevrcpts = {}, ?prevnotifs = {}} = args;
5sofar = {prevrcpts, prevnotifs};
6if (typeof(recip) == LIST)
7bogus = {};
8for r in (recip)
9result = this:resolve_addr(r, from, seen, @sofar);
10if (result)
11sofar = result;
12else
13bogus = setadd(bogus, r);
14endif
15endfor
16return {bogus, @sofar};
17else
18fwd = include_recip = 0;
19if ((recip == $nothing) || (recip in seen))
20return sofar;
21elseif ((!valid(recip)) || ((!(is_player(recip) || $object_utils:isa(recip, $mail_recipient))) || (typeof(fwd = recip:mail_forward(from)) != LIST)))
22"recip is a non-player non-mailing-list/folder or forwarding is screwed.";
23if (typeof(fwd) == STR)
24player:tell(fwd);
25endif
26return E_INVARG;
27elseif (is_player(recip) && `recip:refuses_action(from, "mail") ! E_VERBNF')
28player:tell(recip:mail_refused_msg());
29return E_INVARG;
30elseif (fwd)
31if (r = recip in fwd)
32include_recip = 1;
33fwd = listdelete(fwd, r);
34endif
35result = this:resolve_addr(fwd, recip, setadd(seen, recip), @sofar);
36if (bogus = result[1])
37player:tell(recip.name, "(", recip, ")'s .mail_forward list includes the following bogus entr", (length(bogus) > 1) ? "ies:  " | "y:  ", $string_utils:english_list(bogus));
38endif
39sofar = result[2..3];
40else
41include_recip = 1;
42endif
43if ((ticks_left() < 1000) || (seconds_left() < 2))
44suspend(0);
45endif
46biffs = sofar[2];
47for n in (this:mail_notify(recip, from))
48if (valid(n))
49if (i = $list_utils:iassoc_suspended(n, biffs))
50biffs[i] = setadd(biffs[i], recip);
51else
52biffs = {{n, recip}, @biffs};
53endif
54endif
55if ((ticks_left() < 1000) || (seconds_left() < 2))
56suspend(0);
57endif
58endfor
59return {include_recip ? setadd(sofar[1], recip) | sofar[1], biffs};
60endif

sends_to

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1"sends_to(from,addr,rcpt[,seen]) ==> true iff mail sent to addr passes through rcpt.";
2{from, addr, rcpt, ?seen = {}} = args;
3if (addr == rcpt)
4return 1;
5elseif (!(addr in seen))
6seen = {@seen, addr};
7for a in ((typeof(fwd = this:mail_forward(addr, @from ? {} | {from})) == LIST) ? fwd | {})
8if (this:sends_to(addr, a, rcpt, seen))
9return 1;
10endif
11$command_utils:suspend_if_needed(0);
12endfor
13endif
14return 0;

send_message

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1"send_message(from,rcpt-list,hdrs,msg) -- formats and sends a mail message.  hders is either the text of the subject line, or a {subject,{reply-to,...}} list.";
2"Return E_PERM if from isn't owned by the caller.";
3"Return {0, @invalid_rcpts} if rcpt-list contains any invalid addresses.  No mail is sent in this case.";
4"Return {1, @actual_rcpts} if successful.";
5{from, to, orig_hdrs, msg} = args;
6"...";
7"... remove bogus Resent-To/Resent-By headers...";
8"...";
9if ((typeof(orig_hdrs) == LIST) && (length(orig_hdrs) > 2))
10hdrs = orig_hdrs[1..2];
11orig_hdrs[1..2] = {};
12strip = {"Resent-To", "Resent-By"};
13for h in (orig_hdrs)
14(h[1] in strip) || (hdrs = {@hdrs, h});
15endfor
16else
17hdrs = orig_hdrs;
18endif
19"...";
20"... send it...";
21"...";
22if ($perm_utils:controls(caller_perms(), from))
23text = $mail_agent:make_message(from, to, hdrs, msg);
24return this:raw_send(text, to, from);
25else
26return E_PERM;
27endif

raw_send

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

Source

1"Copied from Mail Distribution Center (#6418):raw_send by Nosredna (#2487) Mon Feb 24 10:46:26 1997 PST";
2"WIZARDLY";
3"raw_send(text,rcpts,sender) -- does the actual sending of a message.  Assumes that text has already been formatted correctly.  Decides who to send it to and who wants to be notified about it and does so.";
4"Return {E_PERM} if the caller is not entitled to use this verb.";
5"Return {0, @invalid_rcpts} if rcpts contains any invalid addresses.  No mail is sent in this case.";
6"Return {1, @actual_rcpts} if successful.";
7{text, rcpts, from} = args;
8if (typeof(rcpts) != LIST)
9rcpts = {rcpts};
10endif
11if (!(caller in {$mail_agent, $mail_editor}))
12return {E_PERM};
13elseif (bogus = (resolve = this:resolve_addr(rcpts, from))[1])
14return {0, bogus};
15else
16set_task_perms($wiz_utils:random_wizard());
17this:touch(rcpts);
18actual_rcpts = resolve[2];
19biffs = resolve[3];
20results = {};
21for recip in (actual_rcpts)
22if ((ticks_left() < 10000) || (seconds_left() < 2))
23player:notify(tostr("...", recip));
24suspend(1);
25endif
26if (typeof(e = recip:receive_message(text, from)) in {ERR, STR})
27"...receive_message bombed...";
28player:notify(tostr(recip, ":receive_message:  ", e));
29e = 0;
30elseif ((!is_player(recip)) || (!e))
31"...not a player or receive_message isn't giving out the message number";
32"...no need to force a notification...";
33elseif (i = $list_utils:iassoc(recip, biffs))
34"...player-recipient was already getting a notification...";
35"...make sure notification includes a mention of him/her/itself.";
36if (!(recip in listdelete(biffs[i], 1)))
37biffs[i][2..1] = {recip};
38endif
39else
40"...player-recipient wasn't originally being notified at all...";
41biffs = {{recip, recip}, @biffs};
42endif
43results = {@results, e};
44endfor
45"The following is because the scheduler can BITE ME. --Nosredna";
46fork (0)
47for b in (biffs)
48if ((ticks_left() < 10000) || (seconds_left() < 2))
49suspend(1);
50endif
51if ($object_utils:has_callable_verb(b[1], "notify_mail"))
52mnums = {};
53for r in (listdelete(b, 1))
54mnums = {@mnums, (rn = r in actual_rcpts) && results[rn]};
55endfor
56b[1]:notify_mail(from, listdelete(b, 1), mnums);
57endif
58endfor
59endfork
60return {1, @actual_rcpts};
61endif

mail_forward mail_notify

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1who = args[1];
2if ($object_utils:has_verb(who, verb))
3return who:(verb)(@listdelete(args, 1));
4else
5return {};
6endif

touch

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1"touch(name or list,seen) => does .last_used_time = time() if we haven't already touched this in the last hour";
2{recip, ?seen = {}} = args;
3if (typeof(recip) == LIST)
4for r in (recip)
5result = this:touch(r, seen);
6$command_utils:suspend_if_needed(0);
7endfor
8else
9if (((!valid(recip)) || (recip in seen)) || ((!is_player(recip)) && (!($mail_recipient in $object_utils:ancestors(recip)))))
10"recip is neither a player nor a mailing list/folder";
11else
12if (fwd = this:mail_forward(recip))
13this:touch(fwd, {@seen, recip});
14endif
15if (!is_player(recip))
16recip.last_used_time = time();
17endif
18endif
19endif

look_self

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

none

Source

1player:tell_lines(this.description);
2for c in (this.contents)
3c:look_self();
4endfor

acceptable

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

none

Source

1"Only allow mailing lists/folders in here and only if their names aren't already taken.";
2what = args[1];
3return ($object_utils:isa(what, $mail_recipient) && this:check_names(@what.aliases)) && (what:description() != parent(what):description());

check_names

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1"...make sure the list has at least one usable name.";
2"...make sure none of the aliases are already taken.";
3ok = 0;
4for a in (args)
5sub1 = strsub(a, "_", "-");
6sub2 = strsub(a, "-", "_");
7if (sub1 == sub2)
8check = 0;
9else
10check = 1;
11endif
12if (index(a, " "))
13elseif (rp = $mail_agent:reserved_pattern(a))
14player:tell("Mailing list name \"", a, "\" uses a reserved pattern: ", rp[1]);
15return 0;
16elseif (valid(p = $mail_agent:match(a, #-1)) && (a in p.aliases))
17player:tell("Mailing list name \"", a, "\" in use on ", p.name, "(", p, ")");
18return 0;
19elseif ((check && valid(p = $mail_agent:match(sub1, #-1))) && (sub1 in p.aliases))
20player:tell("Mailing list name \"", sub1, "\" in use on ", p.name, "(", p, ")");
21return 0;
22elseif ((check && valid(p = $mail_agent:match(sub2, #-1))) && (sub2 in p.aliases))
23player:tell("Mailing list name \"", sub2, "\" in use on ", p.name, "(", p, ")");
24return 0;
25else
26ok = 1;
27endif
28endfor
29return ok;

match

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1":match(string) => mailing list object in here that matches string.";
2":match(string,player) => similar but also matches against player's private mailing lists (as kept in .mail_lists).";
3if (!(string = args[1]))
4return $nothing;
5elseif (string[1] == "*")
6string = string[2..$];
7endif
8if (valid(o = $string_utils:literal_object(string)) && ($mail_recipient in $object_utils:ancestors(o)))
9return o;
10elseif (rp = this:reserved_pattern(string))
11return rp[2]:match_mail_recipient(string);
12else
13if (valid(who = {@args, player}[2]) && (typeof(use = `who.mail_lists ! E_PROPNF, E_PERM') == LIST))
14use = {@this.contents, @use};
15else
16use = this.contents;
17endif
18partial = 1;
19string = strsub(string, "_", "-");
20for l in (use)
21if (string in l.aliases)
22return l;
23endif
24if (partial != $ambiguous_match)
25for a in (l.aliases)
26if ((index(a, string) == 1) && (!index(a, " ")))
27if (partial)
28partial = l;
29elseif (partial != l)
30partial = $ambiguous_match;
31endif
32endif
33$command_utils:suspend_if_needed(2);
34endfor
35endif
36endfor
37return partial && $failed_match;
38endif

match_recipient

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1":match_recipient(string[,meobj]) => $player or $mail_recipient object that matches string.  Optional second argument (defaults to player) is returned in the case string==\"me\" and is also used to obtain a list of private $mail_recipients to match against.";
2{string, ?me = player} = args;
3if (valid(me) && ($failed_match != (o = me:my_match_recipient(string))))
4return o;
5elseif (!string)
6return $nothing;
7elseif ((string[1] == "*") && (string != "*"))
8return this:match(@args);
9elseif (string[1] == "`")
10args[1][1..1] = "";
11return $string_utils:match_player(@args);
12elseif (valid(o = $string_utils:match_player(@args)) || (o == $ambiguous_match))
13return o;
14else
15return this:match(@args);
16endif

match_failed

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1{match_result, string, ?cmd_id = ""} = args;
2cmd_id = cmd_id || "";
3if (match_result == $nothing)
4player:tell(cmd_id, "You must specify a valid mail recipient.");
5elseif (match_result == $failed_match)
6player:tell(cmd_id, "There is no mail recipient called \"", string, "\".");
7elseif (match_result == $ambiguous_match)
8if ((nostar = index(string, "*") != 1) && (lst = $player_db:find_all(string)))
9player:tell(cmd_id, "\"", string, "\" could refer to ", (length(lst) > 20) ? tostr("any of ", length(lst), " players") | $string_utils:english_list($list_utils:map_arg(2, $string_utils, "pronoun_sub", "%n (%#)", lst), "no one", " or "), ".");
10else
11player:tell(cmd_id, "I don't know which \"", nostar ? "*" | "", string, "\" you mean.");
12endif
13elseif (!valid(match_result))
14player:tell(cmd_id, match_result, " does not exist.");
15else
16return 0;
17endif
18return 1;

make_message

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1":make_message(sender,recipients,subject/replyto/additional-headers,body)";
2" => message in the form as it will get sent.";
3{from, recips, hdrs, body} = args;
4try
5fromowner = from.owner;
6except (E_INVIND)
7raise(E_PERM);
8endtry
9fromline = this:name_list(from);
10if (typeof(recips) != LIST)
11recips = {recips};
12endif
13recips = this:name_list(@recips);
14others = {};
15replyto = 0;
16if (typeof(hdrs) != LIST)
17hdrs = {hdrs};
18endif
19subj = hdrs[1];
20if (!valid(from))
21others = {"Probable-Sender:   " + this:name(fromowner)};
22"  others = {'Possible-Sender:   ' + this:name(player)}";
23"  if (caller_perms() != player)";
24"    others = {@others, 'Possible-Sender:   ' + this:name(caller_perms())}";
25"  endif";
26elseif (!is_player(from))
27others = {"Sender:   " + this:name(from.owner)};
28endif
29replyto = {@hdrs, 0}[2] && this:name_list(@hdrs[2]);
30if (length(hdrs) > 2)
31hdrs[1..2] = {};
32for h in (hdrs)
33if (match(h[1], "[a-z1-9-]+"))
34others = {@others, $string_utils:left(h[1] + ": ", 15) + h[2]};
35endif
36endfor
37endif
38if (typeof(body) != LIST)
39body = body ? {body} | {};
40endif
41return {time(), fromline, recips, subj || " ", @replyto ? {"Reply-to: " + replyto} | {}, @others, "", @body};

name

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1what = args[1];
2if (!valid(what))
3name = "???";
4elseif ((!is_player(what)) && $object_utils:has_callable_verb(what, "mail_name"))
5name = what:mail_name();
6else
7name = what.name;
8endif
9return tostr(strsub(strsub(name, "(", ""), ")", ""), " (", what, ")");

name_list

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1return $string_utils:english_list($list_utils:map_arg(this, "name", args), "no one");

parse_address_field

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1":parse_address_field(string) => list of objects";
2"This is the standard routine for parsing address lists that appear in From:, To: and Reply-To: lines";
3objects = {};
4string = args[1];
5while (e = index(string, ")"))
6if ((s = rindex(string[1..e], "(#")) && (#0 != (o = toobj(string[s + 2..e - 1]))))
7objects = {@objects, o};
8endif
9string = string[e + 1..$];
10endwhile
11return objects;

display_seq_full

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":display_seq_full(msg_seq[,preamble]) => {cur, last-read-date}";
2"This is the default message display routine.";
3"Prints entire messages on folder (caller) to player.  msg_seq is the handle returned by :parse_message_seq(...) and indicates which messages should be printed.  preamble, if given will precede the output of the message itself, in which case the message number will be substituted for \"%d\".  Returns the number of the final message in the sequence (which can be then used as the new current message number).";
4set_task_perms(caller_perms());
5{msg_seq, ?preamble = ""} = args;
6cur = date = 0;
7for x in (msgs = caller:messages_in_seq(msg_seq))
8cur = x[1];
9date = x[2][1];
10player:display_message(preamble ? strsub(preamble, "%d", tostr(cur)) | {}, caller:msg_full_text(@x[2]));
11if ((ticks_left() < 500) || (seconds_left() < 2))
12suspend(0);
13endif
14endfor
15return {cur, date};

display_seq_headers

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":display_seq_headers(msg_seq[,cur[,last_read_date]])";
2"This is the default header display routine.";
3"Prints a list of headers of messages on caller to player.  msg_seq is the handle returned by caller:parse_message_seq(...).  cur is the player's current message.  last_read_date is the date of the last of the already-read messages.";
4set_task_perms(caller_perms());
5{msg_seq, ?cur = 0, ?last_old = $maxint} = args;
6keep_seq = {@$seq_utils:contract(caller:kept_msg_seq(), $seq_utils:complement(msg_seq, 1, caller:length_all_msgs())), $maxint};
7k = 1;
8mcount = 0;
9width = player:linelen() || 79;
10for x in (msgs = caller:messages_in_seq(msg_seq))
11if (keep_seq[k] <= (mcount = mcount + 1))
12k = k + 1;
13endif
14annot = ((d = x[2][1]) > last_old) ? "+" | ((k % 2) ? " " | "=");
15line = tostr($string_utils:right(x[1], 4, (cur == x[1]) ? ">" | " "), ":", annot, " ", caller:msg_summary_line(@x[2]));
16player:tell(line[1..min(width, $)]);
17if ((ticks_left() < 500) || (seconds_left() < 2))
18suspend(0);
19endif
20endfor
21player:tell("----+");

rm_message_seq

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":rm_message_seq(msg_seq)  removes the given sequence of from folder (caller)";
2"...removed messages are saved in .messages_going for possible restoration.";
3set_task_perms(caller_perms());
4old = caller.messages;
5new = save = nums = {};
6next = 1;
7for i in [1..length(seq = args[1]) / 2]
8if ($command_utils:running_out_of_time())
9player:tell("... rmm ", old[next][1] - 1);
10suspend(0);
11endif
12start = seq[(2 * i) - 1];
13new = {@new, @old[next..start - 1]};
14save = {@save, {start - next, old[start..(next = seq[2 * i]) - 1]}};
15nums = {@nums, old[start][1], old[next - 1][1] + 1};
16endfor
17new = {@new, @old[next..$]};
18$command_utils:suspend_if_needed(0, "... rmm ...");
19save_kept = $seq_utils:intersection(caller.messages_kept, seq);
20$command_utils:suspend_if_needed(0, "... rmm ...");
21new_kept = $seq_utils:contract(caller.messages_kept, seq);
22$command_utils:suspend_if_needed(0, "... rmm ...");
23caller.messages_going = save_kept ? {save_kept, save} | save;
24caller.messages = new;
25caller.messages_kept = new_kept;
26if ($object_utils:has_callable_verb(caller, "_fix_last_msg_date"))
27caller:_fix_last_msg_date();
28endif
29return $seq_utils:tostr(nums);

undo_rmm

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":undo_rmm()  restores previously deleted messages in .messages_going to .messages.";
2set_task_perms(caller_perms());
3old = caller.messages;
4going = caller.messages_going;
5new = seq = {};
6last = 0;
7next = 1;
8"there are two possible formats here:";
9"OLD: {{n,msgs},{n,msgs},...}";
10"NEW: {kept_seq, {{n,msgs},{n,msgs},...}}";
11if (going && ((!going[1]) || (typeof(going[1][2]) == INT)))
12kept = going[1];
13going = going[2];
14else
15kept = {};
16endif
17for s in (going)
18new = {@new, @old[last + 1..last + s[1]], @s[2]};
19last = last + s[1];
20seq = {@seq, next + s[1], next = length(new) + 1};
21endfor
22caller.messages = {@new, @old[last + 1..$]};
23caller.messages_going = {};
24caller.messages_kept = $seq_utils:union(kept, $seq_utils:expand(caller.messages_kept, seq));
25if ($object_utils:has_callable_verb(caller, "_fix_last_msg_date"))
26caller:_fix_last_msg_date();
27endif
28return seq;

expunge_rmm list_rmm

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":list_rmm()    displays contents of .messages_going.";
2":expunge_rmm() destroys contents of .messages_going once and for all.";
3"... both return the number of messages in .messages_going.";
4set_task_perms(caller_perms());
5cmg = caller.messages_going;
6if (cmg && ((!cmg[1]) || (typeof(cmg[1][2]) == INT)))
7kept = cmg[1];
8cmg = cmg[2];
9else
10kept = {};
11endif
12if (verb == "expunge_rmm")
13caller.messages_going = {};
14count = 0;
15for s in (cmg)
16count = count + length(s[2]);
17endfor
18return count;
19elseif (!cmg)
20return 0;
21else
22msgs = seq = {};
23next = 1;
24for s in (cmg)
25msgs = {@msgs, @s[2]};
26seq = {@seq, next = next + s[1], next = next + length(s[2])};
27endfor
28kept = {@$seq_utils:contract(kept, $seq_utils:complement(seq, 1, $seq_utils:last(seq))), $maxint};
29k = 1;
30mcount = 0;
31for x in (msgs)
32if (kept[k] <= (mcount = mcount + 1))
33k = k + 1;
34endif
35player:tell($string_utils:right(x[1], 4), ":", (k % 2) ? "  " | "= ", caller:msg_summary_line(@x[2]));
36if ((ticks_left() < 500) || (seconds_left() < 2))
37suspend(0);
38endif
39endfor
40if (msgs)
41player:tell("----+");
42endif
43return length(msgs);
44endif

renumber

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":renumber([cur]) -- assumes caller is a $mail_recipient or a $player.";
2"...renumbers caller.messages, doing a suspend() if necessary.";
3"...returns {number of messages,new cur}.";
4set_task_perms(caller_perms());
5{?cur = 0} = args;
6caller.messages_going = {};
7"... blow away @rmm'ed messages since there's no way to tell what their new numbers should be...";
8msgs = caller.messages;
9if (cur)
10cur = $list_utils:iassoc_sorted(cur, msgs);
11endif
12while (1)
13"...find first out-of-sequence message...";
14l = 0;
15r = (len = length(msgs)) + 1;
16while ((r - 1) > l)
17if (msgs[i = (r + l) / 2][1] > i)
18r = i;
19else
20l = i;
21endif
22endwhile
23"... r == first out-of-sequence, l == last in-sequence, l+1 == r ...";
24if (l >= len)
25return {l, cur};
26endif
27"...renumber as many messages as we have time for...";
28chunk = {};
29while (((r <= len) && (ticks_left() > 3000)) && (seconds_left() > 2))
30for x in (msgs[r..min(r + 9, len)])
31chunk = {@chunk, {r, x[2]}};
32r = r + 1;
33endfor
34endwhile
35caller.messages = {@msgs[1..l], @chunk, @msgs[r..len]};
36if (chunk)
37player:tell("...(renumbering ", l + 1, " -- ", r - 1, ")");
38suspend(0);
39else
40player:tell("You lose.  This message collection is just too big.");
41return;
42endif
43"... have to be careful since new mail may be received at this point...";
44msgs = caller.messages;
45endwhile

msg_summary_line

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1":msg_summary_line(@msg) => date/from/subject as a single string.";
2body = ("" in {@args, ""}) + 1;
3if ((body > length(args)) || (!(subject = args[body])))
4subject = "(None.)";
5endif
6if (args[1] < (time() - 31536000))
7c = player:ctime(args[1]);
8date = c[5..11] + c[21..25];
9else
10date = player:ctime(args[1])[5..16];
11endif
12from = args[2];
13if (args[4] != " ")
14subject = args[4];
15endif
16return tostr(date, "   ", $string_utils:left(from, 20), "   ", subject);

parse_message_seq

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1"parse_message_seq(strings,cur[,last_old])";
2"This is the default <message-sequence> parsing routine for those mail commands that refer to sequences of messages (@mail, @read,...) on a folder.";
3"  caller (the folder) is assumed to be a $mail_recipient or a player.";
4"  strings is the <message-sequence> portion of the arg list.";
5"  cur is the number of the player's current message for this folder.";
6"Returns a string error message if the parse fails, otherwise";
7"returns a list {msg_seq, @unused_strings}, where";
8"   msg_seq is a handle understood by caller:display_seq_full/headers(), and ";
9"   unused_strings is the list of remaining uninterpreted strings";
10set_task_perms(caller_perms());
11{strings, ?cur = 0, ?last_old = 0} = args;
12if (!(nummsgs = caller:length_all_msgs()))
13return "%f %<has> no messages.";
14elseif (typeof(strings) != LIST)
15strings = {strings};
16endif
17seq = result = {};
18mode = #0;
19"... changes to 0 if we start seeing message numbers, to 1 if we see masks...";
20keywords = ":from:%from:to:%to:subject:body:before:after:since:until:first:last:kept:unkept";
21keyalist = {{1, "from"}, {6, "%from"}, {12, "to"}, {15, "%to"}, {19, "subject"}, {27, "body"}, {32, "before"}, {39, "after"}, {45, "since"}, {51, "until"}, {57, "first"}, {63, "last"}, {68, "kept"}, {73, "unkept"}};
22strnum = 0;
23for string in (strings)
24strnum = strnum + 1;
25$command_utils:suspend_if_needed(0);
26if (string && ((c = index(string, ":")) && ((k = index(keywords, ":" + string[1..c - 1])) && (k == rindex(keywords, ":" + string[1..c - 1])))))
27"...we have a mask to apply...";
28keywd = $list_utils:assoc(k, keyalist)[2];
29if (mode == #0)
30seq = {1, nummsgs + 1};
31endif
32mode = 1;
33if (k <= 27)
34"...from, subject, to, body...";
35pattern = string[c + 1..$];
36if (keywd in {"subject", "body"})
37elseif (keywd[1] == "%")
38pattern = $string_utils:explode(pattern, "|");
39else
40pattern = this:((keywd == "to") ? "_parse_to" | "_parse_from")(pattern);
41if (typeof(pattern) == STR)
42return pattern;
43endif
44endif
45seq = caller:(keywd + "_msg_seq")(pattern, seq);
46if (typeof(seq) == STR)
47if (strnum == 1)
48return seq;
49else
50seq = {};
51endif
52endif
53elseif (k <= 51)
54"...before, since, after, until...";
55if (typeof(date = this:_parse_date(string[c + 1..$])) != INT)
56return tostr("Bad date `", string, "':  ", date);
57endif
58s = caller:length_date_le((keywd in {"before", "since"}) ? date - 1 | (date + 86399));
59if (keywd in {"before", "until"})
60seq = $seq_utils:remove(seq, s + 1, nummsgs);
61else
62seq = $seq_utils:remove(seq, 1, s);
63endif
64elseif (k <= 63)
65"...first, last...";
66if (n = toint(string[c + 1..$]))
67seq = $seq_utils:(keywd + "n")(seq, n);
68else
69return tostr("Bad number in `", string, "'");
70endif
71else
72"...kept, unkept...";
73if (c < length(string))
74return tostr("Unexpected junk after `", keywd, ":'");
75elseif ((!(seq = caller:(keywd + "_msg_seq")(seq))) && (strnum == 1))
76return tostr("%f %<has> no ", keywd, " messages.");
77endif
78endif
79else
80"...continue building the present sequence...";
81if (mode)
82seq && (result = $seq_utils:union(result, seq));
83seq = {};
84endif
85mode = 0;
86if (!string)
87"...default case for @read: get the current message but skip to the next one if it's not there...";
88if (cur)
89i = min(caller:length_num_le(cur - 1) + 1, nummsgs);
90seq = $seq_utils:add(seq, i, i);
91else
92return "%f %<has> no current message.";
93endif
94elseif ((index(string, "next") == 1) && (!index(string, "-")))
95string[1..4] = "";
96if ((n = string ? toint(string) | 1) <= 0)
97return tostr("Bad number `", string, "'");
98elseif ((i = caller:length_num_le(cur) + 1) <= nummsgs)
99seq = $seq_utils:add(seq, i, min((i + n) - 1, nummsgs));
100else
101return "%f %<has> no next message.";
102endif
103elseif ((index(string, "prev") == 1) && (!index(string, "-")))
104string[1..4] = "";
105if ((n = string ? toint(string) | 1) <= 0)
106return tostr("Bad number `", string, "'");
107elseif (i = caller:length_num_le(cur - 1))
108seq = $seq_utils:add(seq, max(1, (i - n) + 1), i);
109else
110return "%f %<has> no previous message.";
111endif
112elseif (string == "new")
113s = last_old ? caller:length_date_le(last_old) | caller:length_num_le(cur);
114if (s < nummsgs)
115seq = $seq_utils:add(seq, s + 1, nummsgs);
116else
117return "%f %<has> no new messages.";
118endif
119elseif (string == "first")
120seq = $seq_utils:add(seq, 1, 1);
121elseif (n = toint(string) || (((string in {"last", "$"}) && -1) || ((string == "cur") && cur)))
122if (n <= 0)
123seq = $seq_utils:add(seq, max(0, nummsgs + n) + 1, nummsgs);
124elseif (i = caller:exists_num_eq(n))
125seq = $seq_utils:add(seq, i, i);
126else
127return (string == "cur") ? "%f's current message has been removed." | tostr("%f %<has> no message numbered `", string, "'.");
128endif
129elseif (((i = index(string, "..")) > 1) || ((i = index(string, "-")) > 1))
130if ((start = toint(sst = string[1..i - 1])) > 0)
131s = caller:length_num_le(start - 1);
132elseif (sst in {"next", "prev", "cur"})
133s = max(0, caller:length_num_le(cur - (sst != "next")) - (sst == "prev"));
134elseif (sst in {"last", "$"})
135s = nummsgs - 1;
136elseif (sst == "first")
137s = 0;
138else
139return {$seq_utils:union(result, seq), @strings[strnum..$]};
140endif
141j = (string[i] == ".") ? i + 2 | (i + 1);
142if ((end = toint(est = string[j..$])) > 0)
143e = caller:length_num_le(end);
144elseif (est in {"next", "prev", "cur"})
145e = min(nummsgs, caller:length_num_le(cur - (est == "prev")) + (est == "next"));
146elseif (est in {"last", "$"})
147e = nummsgs;
148elseif (est == "first")
149e = 1;
150else
151return {$seq_utils:union(result, seq), @strings[strnum..$]};
152endif
153if (s < e)
154seq = $seq_utils:add(seq, s + 1, e);
155else
156return tostr("%f %<has> no messages in range ", string, ".");
157endif
158elseif (string == "cur")
159return "%f %<has> no current message.";
160else
161return {$seq_utils:union(result, seq), @strings[strnum..$]};
162endif
163endif
164endfor
165return {$seq_utils:union(result, seq)};

_parse_from _parse_to

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

none

Source

1":_parse_from(string with |'s in it) => object list";
2":_parse_to(string with |'s in it) => object list";
3"  for from:string and to:string items in :parse_message_seq";
4if (verb == "_parse_to")
5match_obj = fail_obj = this;
6match_verb = "match_recipient";
7fail_verb = "match_failed";
8else
9match_obj = $string_utils;
10match_verb = "match_player";
11fail_obj = $command_utils;
12fail_verb = "player_match_failed";
13endif
14plist = {};
15for w in ($string_utils:explode(args[1], "|"))
16if (fail_obj:(fail_verb)(p = match_obj:(match_verb)(w), w))
17p = $string_utils:literal_object(w);
18if ((p == $failed_match) || (!$command_utils:yes_or_no("Continue? ")))
19return "Bad address list:  " + args[1];
20endif
21endif
22plist = setadd(plist, p);
23endfor
24return plist;

_parse_date

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1words = $string_utils:explode(args[1], "-");
2if (length(words) == 1)
3if (index("yesterday", words[1]) == 1)
4time = $time_utils:dst_midnight((time() - (time() % 86400)) - 86400);
5elseif (index("today", words[1]) == 1)
6time = $time_utils:dst_midnight(time() - (time() % 86400));
7elseif (typeof(time = $time_utils:from_day(words[1], -1)) == ERR)
8time = "weekday, `Today', `Yesterday', or date expected.";
9endif
10elseif ((!words) || ((length(words) > 3) || ((!toint(words[1])) || (E_TYPE == (year = $code_utils:toint({@words, "-1"}[3]))))))
11time = "Date should be of the form `5-Jan', `5-Jan-92', `Wed',`Wednesday'";
12else
13day = toint(words[1]);
14time = $time_utils:dst_midnight($time_utils:from_month(words[2], -1, day));
15if (length(words) == 3)
16thisyear = toint(ctime(time)[21..24]);
17if (100 > year)
18year = (thisyear + 50) - (((thisyear - year) + 50) % 100);
19endif
20time = $time_utils:dst_midnight($time_utils:from_month(words[2], (year - thisyear) - (year <= thisyear), day));
21endif
22endif
23return time;

new_message_num

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":new_message_num() => number that the next incoming message will receive.";
2set_task_perms(caller_perms());
3new = (msgs = caller.messages) ? msgs[$][1] + 1 | 1;
4if (rmsgs = caller.messages_going)
5if ((!rmsgs[1]) || (typeof(rmsgs[1][2]) == INT))
6rmsgs = rmsgs[2];
7endif
8lbrm = rmsgs[$][2];
9return max(new, lbrm[$][1] + 1);
10else
11return new;
12endif

length_all_msgs

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1set_task_perms(caller_perms());
2return length(caller.messages);

length_date_le

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1set_task_perms(caller_perms());
2date = args[1];
3msgs = caller.messages;
4if ((r = length(caller.messages)) < 25)
5for l in [1..r]
6if (msgs[l][2][1] > date)
7return l - 1;
8endif
9endfor
10return r;
11else
12l = 1;
13while (l <= r)
14if (date < msgs[i = (r + l) / 2][2][1])
15r = i - 1;
16else
17l = i + 1;
18endif
19endwhile
20return r;
21endif

length_date_gt

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1set_task_perms(caller_perms());
2date = args[1];
3msgs = caller.messages;
4if ((len = length(caller.messages)) < 25)
5for r in [0..len - 1]
6if (msgs[len - r][2][1] <= date)
7return r;
8endif
9endfor
10return len;
11else
12l = 1;
13r = len;
14while (l <= r)
15if (date < msgs[i = (r + l) / 2][2][1])
16r = i - 1;
17else
18l = i + 1;
19endif
20endwhile
21return len - r;
22endif

length_num_le

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":length_num_le(num) => number of messages in folder numbered <= num";
2set_task_perms(caller_perms());
3return $list_utils:iassoc_sorted(args[1], caller.messages);

exists_num_eq

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":exists_num_eq(num) => index of message in folder numbered == num";
2set_task_perms(caller_perms());
3return (i = $list_utils:iassoc_sorted(args[1], caller.messages)) && ((caller.messages[i][1] == args[1]) && i);

from_msg_seq

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":from_msg_seq(object or list[,mask])";
2" => msg_seq of messages from any of these senders";
3set_task_perms(caller_perms());
4{plist, ?mask = {1}} = args;
5if (typeof(plist) != LIST)
6plist = {plist};
7endif
8i = 1;
9fseq = {};
10for msg in (caller.messages)
11if ((!mask) || (i < mask[1]))
12elseif ((length(mask) < 2) || (i < mask[2]))
13fromline = msg[2][2];
14if (toobj(fromline[rindex(fromline, "(") + 1..rindex(fromline, ")") - 1]) in plist)
15fseq = $seq_utils:add(fseq, i, i);
16endif
17else
18mask = mask[3..$];
19endif
20i = i + 1;
21$command_utils:suspend_if_needed(0);
22endfor
23return fseq || ("%f %<has> no messages from " + $string_utils:english_list($list_utils:map_arg(2, $string_utils, "pronoun_sub", "%n (%#)", plist), "no one", " or "));

%from_msg_seq

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":%from_msg_seq(string or list of strings[,mask])";
2" => msg_seq of messages with one of these strings in the from line";
3set_task_perms(caller_perms());
4{nlist, ?mask = {1}} = args;
5if (typeof(nlist) != LIST)
6nlist = {nlist};
7endif
8i = 1;
9fseq = {};
10for msg in (caller.messages)
11if ((!mask) || (i < mask[1]))
12elseif ((length(mask) < 2) || (i < mask[2]))
13fromline = " " + msg[2][2];
14for n in (nlist)
15if (index(fromline, n))
16fseq = $seq_utils:add(fseq, i, i);
17endif
18endfor
19else
20mask = mask[3..$];
21endif
22i = i + 1;
23$command_utils:suspend_if_needed(0);
24endfor
25return fseq || ("%f %<has> no messages from " + $string_utils:english_list($list_utils:map_arg($string_utils, "print", nlist), "no one", " or "));

to_msg_seq

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":to_msg_seq(object or list[,mask]) => msg_seq of messages to those people";
2set_task_perms(caller_perms());
3{plist, ?mask = {1}} = args;
4if (typeof(plist) != LIST)
5plist = {plist};
6endif
7i = 1;
8seq = {};
9for msg in (caller.messages)
10if ((!mask) || (i < mask[1]))
11elseif ((length(mask) < 2) || (i < mask[2]))
12toline = msg[2][3];
13for r in ($mail_agent:parse_address_field(toline))
14if (r in plist)
15seq = $seq_utils:add(seq, i, i);
16endif
17endfor
18else
19mask = mask[3..$];
20endif
21i = i + 1;
22$command_utils:suspend_if_needed(0);
23endfor
24return seq || ("%f %<has> no messages to " + $string_utils:english_list($list_utils:map_arg(2, $string_utils, "pronoun_sub", "%n (%#)", plist), "no one", " or "));

%to_msg_seq

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":%to_msg_seq(string or list of strings[,mask])";
2" => msg_seq of messages containing one of strings in the to line";
3set_task_perms(caller_perms());
4{nlist, ?mask = {1}} = args;
5if (typeof(nlist) != LIST)
6nlist = {nlist};
7endif
8i = 1;
9seq = {};
10for msg in (caller.messages)
11if ((!mask) || (i < mask[1]))
12elseif ((length(mask) < 2) || (i < mask[2]))
13toline = " " + msg[2][3];
14for n in (nlist)
15if (index(toline, n))
16seq = $seq_utils:add(seq, i, i);
17endif
18endfor
19else
20mask = mask[3..$];
21endif
22i = i + 1;
23$command_utils:suspend_if_needed(0);
24endfor
25return seq || ("%f %<has> no messages to " + $string_utils:english_list($list_utils:map_arg($string_utils, "print", nlist), "no one", " or "));

subject_msg_seq

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":subject_msg_seq(target) => msg_seq of messages with target in the Subject:";
2set_task_perms(caller_perms());
3{target, ?mask = {1}} = args;
4i = 1;
5seq = {};
6for msg in (caller.messages)
7if ((!mask) || (i < mask[1]))
8elseif ((length(mask) < 2) || (i < mask[2]))
9subject = msg[2][4];
10if (index(subject, target))
11seq = $seq_utils:add(seq, i, i);
12endif
13else
14mask = mask[3..$];
15endif
16i = i + 1;
17$command_utils:suspend_if_needed(0);
18endfor
19return seq || (("%f %<has> no messages with subjects containing `" + target) + "'");

body_msg_seq

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":body_msg_seq(target[,mask]) => msg_seq of messages with target in the body";
2set_task_perms(caller_perms());
3{target, ?mask = {1}} = args;
4i = 1;
5seq = {};
6for msg in (caller.messages)
7if ((!mask) || (i < mask[1]))
8elseif ({@mask, $maxint}[2] <= i)
9mask = mask[3..$];
10"Old code follows. Lets save ticks and munge up the whole message body into one big string and index it. Don't need to know where target is in there, just that it is or isn't there";
11elseif (((bstart = "" in (msg = msg[2])) && (length(msg) > bstart)) && index(tostr(@msg[bstart + 1..$]), target))
12seq = $seq_utils:add(seq, i, i);
13"elseif ((bstart = \"\" in (msg = msg[2])) && (l = length(msg)) > bstart)";
14"while (!index(msg[l], target) && (l = l - 1) > bstart)";
15"$command_utils:suspend_if_needed(0);";
16"endwhile";
17"if (l > bstart)";
18"seq = $seq_utils:add(seq, i, i);";
19"endif";
20endif
21i = i + 1;
22$command_utils:suspend_if_needed(0);
23endfor
24return seq || tostr("%f %<has> no messages containing `", target, "' in the body.");

messages_in_seq

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":messages_in_seq(msg_seq) => list of messages in msg_seq on folder (caller)";
2set_task_perms(caller_perms());
3if (typeof(msgs = args[1]) != LIST)
4return caller.messages[msgs];
5elseif (length(msgs) == 2)
6return caller.messages[msgs[1]..msgs[2] - 1];
7else
8return $seq_utils:extract(msgs, caller.messages);
9endif

__convert_new

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

Source

1":__convert_new(@msg) => msg in new format (if it isn't already)";
2"               ^ don't forget the @ here.";
3"If the msg is already in the new format it passes through unchanged.";
4"If the msg format is unrecognizable, warnings are printed.";
5if (typeof(date = args[1]) != INT)
6date = 0;
7start = 1;
8else
9start = 2;
10if (!((colon = index(args[2], ":")) && (args[2][1..colon] in {"From:", "To:", "Subject:"})))
11return args;
12endif
13endif
14from = to = 0;
15subject = " ";
16blank = "" in {@args, ""};
17newhdr = {};
18for line in (args[start..blank - 1])
19if (index(line, "Date:") == 1)
20if (date)
21player:notify("Warning: two dates?");
22endif
23date = $time_utils:from_ctime(line[6..$]);
24elseif (index(line, "From:") == 1)
25if (from)
26player:notify("Warning: two from-lines?");
27endif
28from = $string_utils:triml(line[6..$]);
29elseif (index(line, "To:") == 1)
30if (to)
31player:notify("Warning: two to-lines?");
32endif
33to = $string_utils:triml(line[6..$]);
34elseif (index(line, "Subject:") == 1)
35subject = $string_utils:triml(line[9..$]);
36else
37newhdr = {@newhdr, line};
38endif
39endfor
40if (!from)
41player:notify("Warning: no from-line.");
42endif
43if (!to)
44player:notify("Warning: no to-line.");
45endif
46return {date, from, to, subject, @newhdr, @args[blank..$]};

to_text

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1":to_text(@msg) => message in text form (suitable for printing)";
2return {"Date:     " + ctime(args[1]), "From:     " + args[2], "To:       " + args[3], @(args[4] == " ") ? {} | {"Subject:  " + args[4]}, @args[5..$]};

is_readable_by is_writable_by is_usable_by

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

none

Source

1what = args[1];
2if ($object_utils:isa(what, $mail_recipient))
3return what:(verb)(@listdelete(args, 1));
4else
5"...it's a player:";
6"...  anyone can send mail to it.";
7"...  only the player itself or a wizard can read it.";
8return (verb == "is_usable_by") || $perm_utils:controls(args[2], what);
9endif

reserved_pattern

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1":reserved_pattern(string)";
2"  if string matches one of the reserved patterns for mailing list names, ";
3"  we return that element of .reserved_patterns.";
4string = args[1];
5for p in (this.reserved_patterns)
6if (match(string, p[1]))
7return p;
8endif
9endfor
10return 0;

is_recipient

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1return valid(what = args[1]) && (($mail_recipient_class in (ances = $object_utils:ancestors(what))) || ($mail_recipient in ances));

keep_message_seq

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":keep_message_seq(msg_seq)";
2"...If msg_seq nonempty {}, this marks the indicated messages on this folder (caller)";
3"...as immune from expiration.";
4"...If msg_seq == {}, this clears all such marks.";
5set_task_perms(caller_perms());
6msg_seq = args[1];
7if (!msg_seq)
8caller.messages_kept = {};
9return 1;
10endif
11prev_kept = caller.messages_kept;
12caller.messages_kept = new_kept = $seq_utils:union(prev_kept, msg_seq);
13added = $seq_utils:intersection(new_kept, $seq_utils:complement(prev_kept));
14if (!added)
15return "";
16endif
17"... urk.  now we need to get the actual numbers of the messages being kept.";
18nums = {};
19start = 0;
20for a in (added)
21nums = {@nums, (start = !start) ? caller:messages_in_seq(a)[1] | (caller:messages_in_seq(a - 1)[1] + 1)};
22endfor
23return $seq_utils:tostr(nums);

kept_msg_seq unkept_msg_seq

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":kept_msg_seq([mask])";
2" => msg_seq of messages that are marked kept";
3":unkept_msg_seq([mask])";
4" => msg_seq of messages that are not marked kept";
5set_task_perms(caller_perms());
6{?mask = {1}} = args;
7if (k = verb == "kept_msg_seq")
8kseq = $seq_utils:intersection(mask, caller.messages_kept);
9else
10kseq = $seq_utils:intersection(mask, $seq_utils:range(1, caller:length_all_msgs()), $seq_utils:complement(caller.messages_kept));
11endif
12return kseq;

msg_seq_to_msg_num_string

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":msg_seq_to_msg_num_string(msg_seq) => string giving the corresponding message numbers";
2set_task_perms(caller_perms());
3return $seq_utils:tostr($seq_utils:from_list($list_utils:slice(caller:messages_in_seq(args[1]))));

msg_seq_to_msg_num_list

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

none

Source

1":msg_seq_to_msg_num_list(msg_seq) => list of corresponding message numbers";
2set_task_perms(caller_perms());
3return $list_utils:slice(caller:messages_in_seq(args[1]));

send_log_message

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

none

Source

1"send_log_message(perms,from,rcpt-list,hdrs,msg) -- formats and sends a mail message. hders is either the text of the subject line, or a {subject,{reply-to,...}} list.";
2"KLUDGE.  this may go away.";
3"Send a message while supplying a different permission for use by :mail_forward to determine moderation action.";
4"Return E_PERM unless called by a wizard.";
5"Return {0, @invalid_rcpts} if rcpt-list contains any invalid addresses.  No mail is sent in this case.";
6"Return {1, @actual_rcpts} if successful.";
7{perms, from, to, hdrs, msg} = args;
8if (caller_perms().wizard)
9text = $mail_agent:make_message(from, to, hdrs, msg);
10return this:raw_send(text, to, perms);
11else
12return E_PERM;
13endif

parse_misc_headers

Spec this none thisFlags rxdOwner #36Definer #46

Referenced by

Source

1":parse_misc_headers(msg,@extract_names)";
2"Extracts the miscellaneous (i.e., not including Date: From: To: Subject:)";
3"from msg (a mail message in the usual transmission format).";
4"Extract_names is a list of header names";
5"=> {other_headers,bogus_headers,extract_texts,body}";
6"where each element of extract_texts is a string or 0";
7"  according as the corresponding header in extract_names is present.";
8"bogus_headers is a list of those headers that are undecipherable";
9"other_headers is a list of {header_name,header_text} for the remaining";
10"  miscellaneous headers.";
11"headers in msg";
12msgtxt = args[1];
13extract_names = listdelete(args, 1);
14extract_texts = $list_utils:make(length(extract_names));
15heads = bogus = {};
16for h in (msgtxt[5..(bstart = "" in {@msgtxt, ""}) - 1])
17if (m = match(h, "%([a-z1-9-]+%): +%(.*%)"))
18hname = h[m[3][1][1]..m[3][1][2]];
19htext = h[m[3][2][1]..m[3][2][2]];
20if (i = hname in extract_names)
21extract_texts[i] = htext;
22else
23heads = {@heads, {hname, htext}};
24endif
25else
26bogus = {@bogus, h};
27endif
28endfor
29return {heads, bogus, extract_texts, msgtxt[bstart + 1..$]};

resend_message

Spec this none thisFlags rxdOwner #2Definer #46

Referenced by

Source

1"resend_message(new_sender,new_rcpts,from,to,hdrs,body)";
2" -- reformats and resends a previously sent message to new recipients.";
3"msg is the previous message";
4"Return E_PERM if new_sender isn't owned by the caller.";
5"Return {0, @invalid_rcpts} if new_rcpts contains any invalid addresses.  No mail is sent in this case.";
6"Return {1, @actual_rcpts} if successful.";
7{new_sender, new_rcpts, from, to, hdrs, body} = args;
8if (typeof(hdrs) != LIST)
9hdrs = {hdrs, 0};
10elseif (length(hdrs) < 2)
11hdrs = {@hdrs || {""}, 0};
12endif
13hdrs[3..2] = {{"Resent-By", this:name_list(new_sender)}, {"Resent-To", this:name_list(@new_rcpts)}};
14if ($perm_utils:controls(caller_perms(), new_sender))
15text = $mail_agent:make_message(from, to, hdrs, body);
16return this:raw_send(text, new_rcpts, new_sender);
17else
18return E_PERM;
19endif

init_for_core

Spec this none thisFlags rxOwner #2Definer #46

Referenced by

none

Source

1if (caller_perms().wizard)
2this.reserved_patterns = {};
3`set_verb_code(this, "raw_send", verb_code(this, "raw_send(core)")) ! ANY';
4`delete_verb(this, "raw_send(core)") ! ANY';
5pass(@args);
6endif