Core Utility Help

$anon_webviewer

The WebGhost Viewer (Anonymous Webviewer, $non_webviewer) allows
anonymous web transactions to be used to browse the MOO. This web
viewer presents the MOO's rooms much like the $standard_webviewer,
but doesn't require the transactions be authenticated. It does not
allow users to manipulate objects, but only to examine them in ways
that don't change any of their characteristics.

The reason for this restriction is related to the source of the name
"WebGhost Viewer." When objects in the MOO change in some way, MOO
users expect it's because someone in the MOO has changed them or
because the object is somehow "active." If objects could be
manipulated by anonymous web transactions, it would appear as if the
object were being controlled by something outside the self-contained
reality that is the MOO. This would damage the integrity of the VR
visualization.

Instead, you can consider anonymous web transactions as being
initiated by "ghosts," who are able to see into and wander the MOO
but not manipulate anything inside. They have no "body" to
manipulate with. Note that there is a @web-option that allows MOO
users to detect when a web ghost visits the room, and it is possible
to implement some forms of "clairvoance" to allow people inside the
MOO to communicate to those outside in a near-real time manner. This
may be added in future version of the Biogate system.

The $anon_webviewer presents an HTML page similar in format to the
$standard_webviewer. However, it carries several verbs that have the
same name found on other BioGate System objects used for
authenticated transactions. Some, like the web_viewer_buttons verb
(corresponding to $player:web_viewer_buttons), are used to build up
the final web page. Others perform the equivalent of commands, like
interpret_teleport (which performs functions equivalent to the
$teleporter system).

There is a $anon_webviewer.ghost_home property that you can set to
the room (OBJ) that all web ghosts originate at when they enter the
MOO. This is different from $teleporter.central_room and
$player_start to allow you to present specialized messages (in the
room's description text) for anonymous web visitors.

The $anon_webviewer.max_lag value (NUM) is the maximum lag in
seconds, as compared to $lag_meter.samples[$], beyond which the
$anon_webviewer refuses to allow anonymous transactions.

 Note that the WebGhost Viewer is provided as a useful anonymous web
viewer but that wizards may make their own child of $webapp and set
the $anon_webviewer pointer to it. This allows MOOs to have their
own custom anonymous webviewer, with whatever features they wish.

$biglist

Generic BigList Utilities
----------------------------
$biglist is a collection of routines for maintaining huge persistent (sorted) lists in a format that is less likely to spam the server (which runs into a certain amount of trouble dealing with long ordinary lists --- btw we use `biglist' to refer to the huge data structure we're about to describe and `list' to refer to ordinary MOO lists {...}). The biglist in question lives on a particular object, to which we will refer in the discussion below as the `home' object, and its various elements appear as leaves of a tree whose nodes are kept in properties of the home object. It should be noted that the home object does not need to be (and in fact should *not* be) a descendant of $biglist one; $biglist merely provides utilities for manipulating the properties on the home object that are used in a particular biglist manipulation.

All of the utilities below refer to `caller' to locate the home object. Thus verbs to manipulate a given biglist must be located on or inherited by its home object itself. The home object needs to define the following verbs

  :_make(@args) => new property on home object with value args
  :_kill(prop) delete a given property that was created by :_make
  :_get(prop) => home.prop
  :_put(prop,@args) set home.prop = args
  :_ord(element) given something that is of the form of a biglist element
                    return the corresponding ordinal (for sorting purposes).
                    If you never intend to use :find_ord, then this can be a
                    routine that always returns 0 or some other random value.

See $generic_biglist_home or $big_mail_recipient for examples.

Those of the following routines that take a biglist argument are expecting
either {} (empty biglist) or some biglist returned by one of the other routines

  :length(biglist) => length(biglist) (i.e., number of elements)
  :find_nth(biglist,n) => biglist[n]
  :find_ord(biglist,k,comp) => n where n is
     the largest such that home:(comp)(k,home:_ord(biglist[n])) is false, or
     the smallest such that home:(comp)(k,home:_ord(biglist[n+1])) is true.
     Always returns a value between 0 and length(biglist) inclusive.
     This assumes biglist to be sorted in order of increasing :_ord values
     with respect to home:(comp)().
     Standard situation is :_ord returns a number and comp is a < verb.

  :start(biglist,s,e) => {biglist[s..?],@handle} or {}
  :next(@handle) => {biglist[?+1..??],@newhandle} or {}
     These two are used for iterating over a range of elements of a biglist
     The canonical incantation for doing
        for elt in (biglist[first..last])
          ...
        endfor
     is
        handle = :start(biglist,first,last);
        while(handle)
          for elt in (handle[1])
            ...
          endfor
          handle = :next(@listdelete(handle,1));
        endwhile

The following all destructively modify their biglist argument(s) L (and M).

  :set_nth(L,n,value) => L[n] = value
     replaces the indicated element

  :insert_before(L,M,n) => {@L[1..n-1],@M,@L[n..length(L)]}
  :insert_after (L,M,n) => {@L[1..n], @M,@L[n+1..length(L)]}
     takes two distinct biglists, inserts one into the other at the given point
     returns the resulting consolidated biglist

  :extract_range(L,m,n) => {{@L[1..m-1],@L[n+1..]}, L[m..n]}
     breaks the given biglist into two distinct biglists.

  :delete_range(L,m,n[,leafkiller]) => {@L[1..m-1],@L[n+1..]}
  :keep_range (L,m,n[,leafkiller]) => L[m..n]
     like extract_range only we destroy what we don't want.

  :insertlast(L,value) => {@L,value}
     inserts a new element at the end of biglist.
     If find_ord is to continue to work properly, it is assumed that the
     home:_ord(elt) is greater (comp-wise) than all of the :_ord values
     of elements currently in the biglist.

  :kill(L[,leafkiller])
     destroys all nodes used by biglist.
     Calls home:leafkiller on each element.

$byte_quota_utils

This is the Byte Quota Utilities utility package. It carries a set
of verbs used by the @quota and other MOO systems if byte quota is
enabled or if its just being routinely measured. Byte-quota is
measuring people's MOO use by the number of bytes their objects take
up in memory. Object-quota is measuring people's MOO usage by the
number of objects they own, regardless of size.

By default, the eduCore measures people's byte usage but controls
quota through object-quota mechanisms. However, wizards can modify
this behavior so that byte-quota is used instead.

By default, the eduCore comes set to use object-based quota. Under
this scheme, builders are granted a certain number of objects they
can build, and those objects can have any amount of text or other
customization on them. However, many MOOs will want to use
byte-based quota, where builders can make any number of objects, but
have a limit to the total amount of bytes those objects can take up
in memory. To change the MOO to use byte-based quota, use the
following commands:
  @set #0.quota_utils to $byte_quota_utils
  @set $object_quota_utils.byte_based to 1
  @set $byte_quota_utils.byte_based to 1
  start $byte_quota_utils
If there is already a byte measurement task running, "start
$byte_quota_utils" will issue a warning, but you can ignore it.
NOTE: Changing over from object-based to byte-based quota after the
MOO has been running a while can be quota a hassle, since you'll have
to reissue everyone quota limits by hand. You should make this
decision before you open your MOO.

To set the amount of quota builders start with, use:
  @set $byte_quota_utils.default_quota to {50000, 0, 0, 1}
where in that example, new builders have 50,000 bytes of quota to
start with.

Available commands:

start-measuring $byte_quota_utils
  This starts the periodic measurement task if such a task isn't
already scheduled. It can be used to set a time for the task to run
different from the default one, or to start the task anew if for some
reason the task was killed.

do_summary <object> with $byte_quota_utils

Related Topics:
@quota -- the command used to find and set use @quota levels
@measure -- measures byte usage of individual objects or all a person's owned objects

$container

The Generic Container (for programmers)

In addition to the command verbs described under `help containers'
and the _msg properties described in `help container-messages',
the following verbs and properties are available for use within programs

.opened == TRUE iff the container is open
.dark == TRUE iff the contents of the container may be seen
.opaque - describes the correlation between .open and .dark
   == 0 container is always !dark
   == 1 container is dark iff it is closed
   == 2 container is always dark

:set_opaque(newvalue)
  changes the .opaque value for the container
  => newvalue or E_PERM or E_INVARG

:set_opened(newvalue)
  opens/closes the container (updates .open and .dark) according to newvalue
  => newvalue or E_PERM

:is_openable_by(who)
 what the :open command uses to test whether the person should be able to open
 the container. By default this refers to .open_key (set by
 @(un)lock_for_open), but the object owner is free to customize this.

N.B.: There is no way to directly set .dark; .dark can be changed only by
changing one of .opaque or .opened. Use :set_opaque(0) and :set_opaque(2)
to have .dark change independently of the value of .opened.

$error

$error
======

NOTE: THIS OBJECT IS ESSENTIALLY OBSOLETED BY THE raise() BUILT-IN FUNCTION IN SERVER VERSION 1.8.0, BUT IS RETAINED FOR BACKWARD COMPATABILITY.

The Error Generator, $error, may be used to automatically generate errors. This is particularly useful if you are working in a !d verb but have occasion to -want- to crash with traceback. To raise a specific error, use $error:raise(error type) - for example, $error:raise(E_PERM) will produce traceback resulting from a Permission Denied error.

Random notes about $error:

+ The complete list of errors is stored in $error.names.
+ The seemingly useless :accept() verb on $error is so that $error:E_RECMOVE and $error:E_NACC will be guaranteed success (success meaning, of course, a termination by traceback).
+ There is, unfortunately, no way to raise the error E_NONE.

$exit

Exits
-----
An exit can be renamed by either the owner of the exit or the owner of its source.

The standard verbs that are called in exit movement are:

:move(object) - moves the object via this exit
:invoke() - equivalent to :move(player)

When an exit is invoked on a particular object (via exit:move(object)), the following occurs.

(1) The exit may be locked against the object, in which case we print the
   nogo messages and quit.

(2) (room=exit.dest):bless_for_entry(object) is called. Assuming that exit is recognized by room as being a legitimate entrance (i.e., is in room.entrances), this will enable room:accept(object) to return true.

(3) object:moveto(room) is called and the various messages (see `help exit-messages') are :announced/:told. Note that this, in accordance with the way the builtin move() (and hence the default :moveto()) works, we get a call to room:accept(object) which checks for the room itself being locked against the object, and otherwise returns true if the blessing in the previous step worked. The move is performed, here:exitfunc(object) and room:enterfunc(object) are called. In particular, room:enterfunc clears the blessing bestowed in (2) now that it is no longer needed.

In general, the move may fail, in which case we :announce the (o)nogo_msgs.

$feature

Feature objects are a mechanism for adding new commands to those a person has routine access, much as if the commands were on their character object. The $feature object is available as a generic for programmers to use, although any object with a
.feature_ok property set true or a :feature_ok verb that returns true can function as a feature object.

In order to function as feature object commads, verbs on the feature must:
  1. Be executable (+x).
  2. Have a argument set for which a valid command is possible (i.e. not `this none this').
  3. Have a verb name that is not already used by a verb that the standard MOO server matching will find, or on any object ahead of the feature in the user's .features property (a list of features they've added).

Features have an unusual `help' system, such that the help text
displayed is the contents of <feature>.help_msg, followed by the
header comments from each verb that has been flagged using the
$feature:@add_feature_verb command. Feature creators do not have to
use @afv to make the commands usable as a feature, but only to flag
them for the help system.

Note that verbs on $feature should not use `player' or `caller' for
security, but should use caller_perms() instead (as with all +x verbs
where the caller is not predictable).

Some properties:

.feature_ok
  The value returned by <feature>:feature_ok by default.

.guest_feature_ok
  This feature object may be used by guests.

.feature_info_byte_limit
  The maximum number of bytes a feature can store on a person's
character object through the <player>:set_feature_info command, if
that person has added the feature object to their list of features.
Note that this restriction is only in effect if byte-based quota is
enabled for the MOO.

Some verbs:
feature_ok
  Called when someone tries to add a feature object, and must return true if they are to be allowed. Returns the value of <feature>.feature_ok by default.

:feature_add
  Called after a feature has been added to someone's list of features.

:feature_remove
  Called when someone removes a feature object from their list.

:player_connected
:player_disconnected
  Called when a person connects to or disconnects from their character.

Related Topics:
features -- help for users and some notes for programmers

$frame_manager

The $frame_manager is a web application ($webapp) that performs
various functions related to building frames on the user's web page
and directing the proper information to each.
It ignores the WHAT portion of the information sent by the $http_handler, but uses the REST portion to determine what action to perform. The following are recognized:

frameset

This is an instruction to create a <FRAMESET> HTML document, defining
the frames and the URLs of the pages to be loaded into each. For
instance, a two frame page with a web document display above and a
java telnet client below might be specified. The
$frame_manager:make_frameset verb does the actual work.

javaclient

This command returns the HTML document containing appropriate <EMBED>
tags for placing a Java telnet client in the specified frame. The
$frame_manager determines which $jclient_handler to use with the
$frame_manager:get_jclient_html verb.

preload

This command retrieves the "preload" page to be displayed in the web
document frame until the full layout is complete. Completion is
generally marked by a call from the Java telnet client to display a
new page in the "html_frame" of the display. The preload page is
defined by the particular $jclient_handler that is being included on
the page in the "interaction_frame" frame. The
$frame_manager:preload_page verb creates the text.

$generic_db

Generic Database
----------------
This holds a collection of {string key, datum} pairs, where datum can be anything. At most one datum may be associated with any given string. Data may be anything (lists, strings, numbers, objectids). If you like, you can think of this as an array indexed by strings.
Verbs supplied include

  :find(string) => datum, $ambiguous_match or $failed_match
  :find_key(string) => full string key, $ambiguous_match or $failed_match
  :find_exact(string) => datum or $failed_match (no partial matches)
  :find_all(string) => list of all data corresponding to matching strings
  :find_all_keys(string) => list of all matching strings

  :insert(string,datum)
       if the string is already present in the db,
       changes the associated datum and returns {old_datum};
       otherwise enters a new {string,datum} pair and return 0.
  :delete(string)
       if there is a datum associated with string,
       remove this association and return {datum}; otherwise return 0.
  :delete2(string,datum)
       if the given datum is associated with string,
       removes that association and return {datum},
       if some other datum is associated with string, just return {other datum}
       otherwise return 0.
  :clearall([4|3])
       removes all associations from the database.
       optional argument changes the type of the database
       (4 is normal, 3 is a kludge for when the data are simply boolean flags
        i.e., this is a set of strings rather than a string-indexed array;
        more on this below)

  count [entries|chars] in this
        provide some vague statistics about how big this thing is.

N.B. As entries get made, properties belonging to $generic_db.owner will be created on the db object itself. These properties will be created having flags as specified by .node_perms, which by default is "r", but can be changed to "" should you want to ensure that randoms don't have access to the raw information.

Implementation notes
 - - - - - - - - - -
The representation is as a `trie', a tree in which each internal node corresponds to a prefix shared by two or more strings in the db.
Each internal node is kept in a property named " "+<prefix>, where <prefix> is a prefix shared by all strings in the subtree under this node.
The property value is a 4 element list

this.(" "+<prefix>)[1] = <common>
   maximal continuation shared by all strings beginning with prefix
   i.e., all these names actually begin with <prefix>+<common>

this.(" "+<prefix>)[2] = <continuations>
   string of all characters <c> that can follow <prefix>+<common> for which
   there is more than one string in the db beginning with <prefix>+<common>+<c>

this.(" "+<prefix>)[3] = <exact_matches>
   list of all strings in this subtree for which
   the character (or lack thereof) following the <prefix>+<common> substring
   suffices to determine the string.

this.(" "+<prefix>)[4] = <data>
   list of data corresponding to the strings in [3].

Child nodes are this.(" "+<prefix>+<common>+<c>)
       for all <c> in this.(" "+<prefix>)[2].
The root node is this.(" ").
If, e.g., there are 2 or more strings in the db beginning with a,
there will be a node this.(" a").
If all of these strings actually begin with "ani", then this.(" a")[1]=="ni".
The db consisting of the 5 correspondences

  {"animal", #1}
  {"anime", #2}
  {"anil", #3}
  {"anile", #4}
  {"banal", #5}

would be represented

this.(" ") =={"", "a", {"banal"}, {#5}}
this.(" a") =={"ni","lm", {}, {}}
this.(" anim")=={"", "", {"animal","anime"},{#1,#2}}
this.(" anil")=={"", "", {"anil","anile"}, {#3,#4}}

In some cases one may merely wish to hold a collection of strings without trying to associate a particular datum with each string. One may then instead set up a db without the fourth field on each of the properties. In this case the datum is taken to be the found string itself and that is what gets returned by :find*() in the event of a successful search. :find and :find_key are then equivalent as are :find_all and :find_all_keys. To setup the db this way, do a :clearall(3). :clearall(4) reverts to the above described type of db with a separately kept datum. Note that you can't change the type without emptying the db. 3 and 4 are currently the only db types allowed.

$generic_editor

The Generic Editor enables a person to edit a list of strings. While one might contrive to use it directly, it is rather intended as a parent for some actual editor. It supplies the following commands:

say <text> w*hat
emote <text> abort
lis*t [<range>] [nonum] q*uit,done,pause
ins*ert [<ins>] ["<text>]
n*ext,p*rev [n] ["<text>]
del*ete [<range>]
f*ind /<str>[/[c][<range>]]
s*ubst /<str1>/<str2>[/[g][c][<range>]]
m*ove,c*opy [<range>] to <ins>
join*l [<range>]
fill [<range>] [@<col>]
ind*ent [<range>] @<col> [<filler>]

$editor_help.(cmdname) descrbes cmdname
$editor_help.insert descrbes insertion points (<ins>)
$editor_help.ranges descrbes range specifications (<range>)

You'll notice that nowhere does it say how to load in a given list of strings or how and where one may save said list away when one is done editing. These commands are supplied by the child editor object. The generic editor contains only the code for editing lines, though it defines additional functions for use by the children:

  :loaded(player)
     returns the index (player in this.active) if text has been loaded
     from somewhere, otherwise returns 0.

     Note that, by default, there is a difference between

        having nothing loaded (:text(who)==0) and
        having loaded something with no text (:text(who)=={}).

     If you don't care about this distinction in a particular case,
     just do (player in this.active) instead of this:loaded(player).
     If you don't want your editor to make this distinction at all, do

        @stateprop texts={} for <youreditor>

     which changes the initial value of :text() to {}

In all functions below, 'who' is the index returned by :loaded(player)

BTW, be careful about using `player' in non-user (i.e., +x this-none-this) verbs - much better to have the user verb get the index with :loaded() and then pass that around.

Also be careful about suspend() and verbs that call suspend(). In particular, the character's index in the .active list can change during the suspend interval, so you must be sure to obtain the index (e.g., using :loaded()) again after the suspend() returns.

For your non-user verbs, we have

  :ok(who)
     returns E_PERM if the caller is not an editor verb and E_RANGE
     if 'who' does not point to a valid session.

which should take care of the more egregious security holes (but maybe not the less egregious ones). For getting and loading text, we have

  :text(who)
     the current text string list or 0 if nothing loaded yet.
  :load(who,text)
     loads the given list of strings as the text to be edited.
     this also resets the 'changed' flag and pushes the insertion
     point to the end.

and various flags and properties (all of the set_* routines return E_PERM when not called from an editor verb, E_RANGE if who is out of bounds, E_INVARG if something is wrong with the 2nd arg, or the new value, which may not necessarily be the same as the 2nd arg (e.g., set_insertion(..,37) on a 5 line text buffer returns 6).

  :changed(who)
     has the text been altered since the last save/load?
     (the child editor gets to define what "save" means).
  :set_changed(who,value)
     Any child editor command that is considered to save the text should do a
     :set_changed(who,0).
     Note that if the changed flag is 0, the session will be flushed when
     the character leaves the editor, so you may also want certain commands to
     do set_changed(who,1)...

  :origin(who)
     room where the person came from.
  :set_origin(who,room)
     can be used to change the room the person will return to when finished
     editing. Since origin gets set even in cases where the person teleports
     into the editor you probably won't usually need to do this.

  :insertion(who)
     current insertion point.
  :set_insertion(who,linenumber)
     linenumber needs to be a positive integer and will get

  :readable(who)
     whether the current editing session has been made globally readable.
  :set_readable(who,boolean)
     change the readability of the current editing session.
     This is used by the publish/perish verbs.

We also provide

  :invoke(...)
      If the person has a previous unsaved (i.e., :changed()!=0)
      session, we return to it, moving the character object to the editor.
      If the person is already in the editor, this has no effect other
      than to print a few nasty messages. In any case a :changed()
      session must be aborted or set_changed(,0) before anything else
      can be started

      Otherwise, we pass the arguments (which are assumed to be the
      result of some munging of the command line) to :parse_invoke(),
      move the character to the editor and load whatever parse_invoke()
      specified. The only interpretation the generic editor makes on
      the arguments is that if the boolean value of the first is true,
      this indicates that the person wanted to load something as
      opposed to resume a previous session. Usually a command calling
      :invoke will have a true (i.e., nonzero number, nonempty list or
      string) first arg iff the command line is nonempty, in which case
      'args' works fine for this purpose.

      If the command parses sucessfully (:parse_invoke() returns a list),
      we move the character to the editor if necessary and then call
      :init_session() to set things up.

The child editor is assumed to provide

  :parse_invoke(...)
     given :invoke()'s arguments, determines what the person wants to edit.
     It either returns 0 and reports syntax errors to `player',
     or it returns some list that :init_session() will understand.

  :init_session(who,@spec)
     where spec is something that was returned by :parse_invoke().
     Loads the text and sets the stateprops (below) to indicate that
     we are working on whatever it is we're suppose to be working on.

  :working_on(who)
     returns a string X as in "You are working on X."
     This is called by the 'w*hat' command, among other things.

Child editors may have their own properties giving state information for the various editing sessions. The value of each such property will be a list giving a value for each person in the editor. For each such property, you should, once the editor object has been created, initialize the property to {} and do one of

    @stateprop <propname> for <editor>
    @stateprop <propname>=<default-value> for <editor>
               (0 is the default <default-value>)

Henceforth, adding and deleting new editing sessions will amend the list held by the given property. The value of the property for a given session can be obtained via this.<propname>[player in this.active] and can be changed with a corresponding listset() call. The usual idiom for an editor command is

   if(!(who=this:loaded(player)))
     player:tell(nothing_loaded_msg());
   else
      ... various references to this.<propname>[who] ...
   endif

To remove such a property from the list of such state properties:

    @rmstateprop <propname> from <editor>

Note that you can only do this with properties defined on the child editor itself.

Sometimes you may wish to @stateprop a new property on an editor where active editing sessions exist. @stateprop will fail if the property in question does not hold a list of the correct length (== length(editor.active); one value for each editing session). You need to either give the @flush command to clear out all sessions and boot all characters currently in the editor or somehow manually initialize the property to a list of appropriate values and pray that nobody enters/exits the editor between the property initialization and the @stateprop command - this problem can be avoided by doing an eval() that does all of the initializations (beware of suspends()) and calls :set_stateprops directly.

Incidentally, the @flush command may be used at any time to clean out the editor or to remove all sessions older than a given date.

There are also numerous _msg properties that may be customized

    @depart announced at the origin when :invoke() is called.
    @return announced at the origin the character is returned there.
    @nothing_loaded printed when user attempts editing
                     before anything has been loaded.
    @no_text response to 'list' when :text()=={}
    @no_change printed by 'what' when :changed()==0
    @change printed by 'what' when :changed()==1
    @no_littering printed upon leaving the editor with :changed()==1.
    @previous_session printed by :invoke() when the person tries to start a
                     new session without aborting or saving the old one

The general procedure for creating a child editor:

. @create $generic_editor named <editor>

. define additional <editor> verbs/properties
    At the very least you need 'edit' and 'save' commands.
    Usually you can get away with just having 'edit' call :invoke();
    Presumably, you'll need at least a command to load text from somewhere
    as well as a command to save it back out.

. define a verb (somewhere) to invoke the editor
    This could be just a one-liner that calls <editor>:invoke(args,verb).
    Either that or
      . you have to set up an exit somewhere whose destination is <editor>
      . you have to advertise the object number so that people can
         teleport to it.
  
. @stateprop x for <editor>

. if you want the 'abort' command to boot the person from the editor do
    <editor>.exit_on_abort = 1;

. set <editor>.commands to be the list of additional commands defined
    by <editor>.
    Each element of the list is itself a list of the form {name,args}.
  set <editor>.commands2 to be the list of commands that should appear
    in the `look' listing, and should be a list of strings appearing
    as names in .commands on either <editor> or some editor ancestor.
  look at $verb_editor or $note_editor for an example.

. If you want to have help text for new verbs you define, create a child of
    $generic_help and add properties to this object for each of the topics
    that you want to provide help text.
    Finally, set <editor>.help = {this object} so that the help system
    knows to consult this object.

$generic_help

The Help System
---------------
When a person types help, the following list of objects is consulted for .help properties: the person's character itself, all ancestors of that character up to and including $player, and, if the current location is a room, the current location together with all ancestors of the current location back to and including $room. Each help property should have as value either an object or a list of objects (otherwise we just ignore it). These objects are then strung together as a list of `help databases' to be searched in order for the requested topic.

When a person uses the "help" command, the system:
  1. retrieves a list of help databases to search, with
     $code_utils:help_db_list();
  2. queries those help database's for matching topics using
     $code_utils:help_db_search();
    2.a. each database is checked in the order given
     (<db>:find_topics), with $help always being the final database
     checked, until one returns a non-false value;
    2.b. if $help is reached, it also checks to see if the topic name
     matches any object in the person's vicinity, and returns that as
     the topic if a match is found;
  3. passes the result to player.location:help_huh() (if it exists)
     in case the result should be modified;
  4. if no topics were identified so far, asks $help:cmd_verb_help()
     to find a match to any matching verb on the `player' or
     `player.location' that has header documentation;
  5. if still no matching topic is found, let
     $wiz_utils:missed_help() know, if
     $wiz_utils.missed_help_logging_enabled is true;
  6. if a match was found, then call the help database that reported
     the match (<db>:get_topic) and ask for the help text itself;
    6.a. If the database is $help, and the help topic matched is
         actually a nearby object, then <object>:help_msg() is called
         to retrieve the help text if that verb exists;
    6.b. If <object>:help_msg() doesn't exist or returns false, then
         the text of <object>.help_msg is used.

A help database (in the sense of anything that is usable by $player:help()) is any object having the following three verbs:

  :find_topics([string])
     where string is a supposed help topic, returns a list of strings,
     i.e., actual help topics that this db knows about, or some boolean
     false value in the event that this db is clueless...
     If no arguments are given, this should return a list of all topics
     in the db

  :get_topic(string)
     given one of the strings returned by :find_topics this either
     returns a list of strings (text to be spewed to the user) or
     returns 1 to indicate that it has already taken care of printing
     information to the user.

  :dump_topic(string)
     like get_topic, but instead returns the raw text of a help topic
     as a (download/upload) script

In short if :find_topic reports that a particular db knows about a given topic
it returns the full topic name, so that :get_topic may be called on it later.
:dump_topic is used by maintainers (see $wiz:@gethelp) to edit help topics.

$generic_help and $help
-----------------------
The Generic Help Database, $generic_help, is the parent class of a particular kind of help database of which $help is an instance. On help databases of this type, every help topic has a corresponding property, interpreted as follows:

  this.(topic) = string
      one-line help text.

  this.(topic) = {"*<verb>*",@args}
      call this:<verb>(args,dblist) to get text where dblist is the list of
      help objects that would have been consulted had the topic not been found
      on this object.

  this.(topic) = other list of strings
      multi-line help text

For the {"*<verb>*",...} form, the current verbs available are

  {"*forward*", topic, @rest}
     - get help text for topic and then append the lines of `rest'.
       rest may, in turn, begin with a "*<verb>*"...

  {"*pass*", topic, @rest}
     - get help text for topic from the first help database after this one
       that actually has help text for topic, and then append lines of `rest'.
       As with "*forward*" rest may, in turn, begin with a "*<verb>*"...

  {"*subst*", @lines}
     - All occurences of %[exp] in lines are replaced with the value of exp
         which is assumed to evaluate to a string.
       All lines beginning with %;exp are replaced with the value of exp
         which is assumed to evaluate to a list of strings.
       Evaluation is done using $no_one's permissions so exp in either case
       can only refer to public information.

  {*verbheader*, object:verb, @rest}
     - returns the verb header documentation lines for object:verb, with @rest appended

  {"*index*", title}
     - returns a list of all topics in this database, arranged in columns.
       title is used as a heading for this index.

Individual help dbs are free to define additional verbs that may be used in this context. $help itself defines the following additional such verbs:

  {"*index_list*"}
     - returns a list of all index topics in all databases in the search list.
       An index topic is one whose actual text is {"*index*", something}.
       When creating a help db, you should be sure to make an index topic.

  {"*full_index*"}
     - prints indices for all help databases in the search list.

It should be noted (once again) that help databases need not be children of $generic_help, so long as they have :find_topics/:get_topic/:dump_topic working as specified above.

$generic_option

Generic Option Package
----------------------
It occasionally happens that one has a command or set of commands for which one wishes to provide several options/flags that a person can set to customize the command's behavior for him/herself. Making each option a separate property is a bit expensive, especially when the option in question is merely a boolean flag that gets set to false in most cases. This package provides an alternative, as well as providing a uniform set of commands for setting these flags/options and checking that the values given are of appropriate types.

Instead of needing several properties, only one is required to store a list containing values for all of the options. An "option package" (pkg, below) is then an object of this class, which provides routines for manipulating such lists.

The set of option names is divided into a set of "real" options, those whose names will actually appear in a given list, and "extras" which are either synonyms for or represent combinations of real options.

 pkg:add_name(name) adds name to .names (remove it from .extras if there)
 pkg:add_name(name,1) adds name to .extras (remove it from .names if there)
    => 1 - ok, 0 - already added, E_INVARG - illegal name, E_PERM

 pkg:remove_name(name) remove name from either .names or .extras
    => 1 - ok, 0 - not present, E_PERM

(I added the commands "@addname <option> to <pkg>" and "@rmname <option> from <pkg>" to call these. EM)

Every option added should have an associated .show_foo property added to the pkg object (by hand). For instance,
  pkg.show_foo = {"Your foo setting is off.", "Your foo setting is on."}
where the first string is the -foo setting and the second the +foo setting.
Options with more complex settings (eg. @myoption complex="this is complex") should
implement a :show_foo verb as described below.

For setting or retrieving values we have

 pkg:get(options,name)
    => value (or 0 if name isn't a real option)
 pkg:set(options,name,value)
    => revised options (or string error message if something goes wrong)
 where "options" is generally "player.display_options" or whatever option property is being processed.

Note that simple boolean options can be checked using
    if (foo in player.pkg_options)
However, this breaks the encapsulation of the system, and therefore using pkg:get() is preferred.
A sample usage is: if ($mail_options:get(player.mail_options,"netmail"))
Most option packages have associated verbs on $player, that simplify this. For instance,
  if (player:mail_option("sticky"))
There are related verbs for: edit_option, display_option, list_option

By default, a given option can only be a boolean flag, having one of the values 0 (absent from the list), or 1 (present in the list). :set translates 0/""/{} to 0 and any other non-object value to 1.

One may however designate a wider range of possible values for an option "foo" by either installing one of

  pkg.type_foo
    - list of allowed types,
       e.g., {NUM,STR} => must be a number or a string
       e.g., {OBJ,{OBJ}} => must be an object or a list of objects
    for anything fancier use:

  pkg:check_foo(value)
    => string error message or {value munged as desired}

In general, the only restriction on option values is that 0 is the only false value; setting an option to "" or {} sets it to 0. Every option defaults to 0, and no matter what you install as .type_foo or :check_foo(), 0 will always be a legal value for option "foo".

When presented with an option that is in .extras, :set will typecheck the value as described, however, then :actual(name, value) will be called to obtain a list of {name-of-real-option, value} pairs indicating which combination of real options should be set.

Other verbs
  pkg:parse(args,...)
    parses the command line arguments of a @whatever_option command
    => {optionname, value} if the person wants to set an option
    => {optionname} if the person wants to view an option
    => string error message otherwise

  one may install pkg:parse_foo to parse arguments for option "foo"
    !foo => {"foo",0} (:parse_foo not called)
    foo= => {"foo",0} (:parse_foo not called)
    -foo => {"foo",0} (:parse_foo not called)
    +foo => pkg:parse_foo("foo",1)
    foo=word => pkg:parse_foo("foo","word")
    foo word1 word2 => pkg:parse_foo("foo",{"word1","word2"})
    foo is word1 word2 => pkg:parse_foo("foo",{"word1","word2"})

 pkg:show(options,name|list of names)
    => list of strings describing the current value of the named option(s).
       calls pkg:show_foo(options,list of names) or
       refers to pkg.show_foo to describe option "foo"
       The pkg:show_foo verb (if any) should return
        => {foo, string describing current setting for option foo}

(I added the command "@document <option> on <pkg>" for adding and changing the documentation on simple on/off options. EM)

(see sources for details... at some point I'll finish writing this... -Rog)

$generic_options

See: $generic_option

$gopher

An interface to Gopher internet services.
Copyright (c) 1992,1993 Grump,JoeFeedback@LambdaMOO.

This object contains just the raw verbs for getting data from gopher servers and parsing the results. Look at #50122 (Generic Gopher Slate) on LambdaMOO for one example of a user interface.

:get(site, port, selection)
  Get data from gopher server: returns a list of strings, or an error if it couldn't connect. Results are cached.

:get_now(site, port, selection)
  Used by $gopher:get. Arguments are the same: this actually gets the
  data without checking the cache. (Don't call this, since the
  caching is important to reduce lag.)
  
:show_text(who, start, end, site, port, selection)
  Requires wiz-perms to call.
  like who:notify_lines($gopher:get(..node..)[start..end])

:clear_cache()
  Erase the gopher cache.

:parse(string)
  Takes a directory line as returned by $gopher:get, and return a list
  {host, port, selector, label}
   host, port, and selector are what you send to :get.
  label is a string, where the first character is the type code.

:type(char)
   returns the name of the gopher type indicated by the character, e.g.
   $gopher:type("I") => "image"

$help

See: $generic_help

$help_webviewer

The Help Text WebViewer ($help_webviewer) is a web application that
serves help text pages from the MOO's help database system, or from
help texts on MOO objects themselves.

The routine form for a URL to retrieve a help text is:
  http://moo.du.org:8000/help/no_object/topic?mail
where in this example the help text for the "mail" topic is returned.

The form for returning the header text for a verb is:
  http://moo.du.org:8000/help/no_object/topic?$string_utils:space
The system can also return texts associated with objects:
  http://moo.du.org:8000/help/20
to return the help text for object #20 (usually $string_utils).

For objects that have their own help databases associated with them,
you can obtain the help text for a topic in one of those specialized
databases with:
  http://moo.du.org:8000/help/50/topic?fill
where in this case the object is the Verb Editor (#50), and "fill" is
the topic name.

The Help Text WebViewer also includes a search field, where people
can enter the name of a topic to display. At this time, the
WebViewer does not do keyword searches, although this functionality
could be added.
In order to minimize the potential for lagging the MOO through high
anonymous access of the WebViewer, the object will only accept at
most a certain number of simultaneous anonymous transactions. This
is set by $help_webviewer.max_anon_calls property (set to 4 by
default). Note that if an anonymous transaction is interrupted due
to a traceback error, that call's record will not be cleared, and as
a result the object will not know that it isn't still processing that
transaction. As a result, the $help_webviewer.current_anon_calls
property will no go back down to zero. Should several of these
events occur, the Help Text Webviewer may refuse any new anonymous
transcations, even though it isn't really processing any currently.
To fix this, just "@set $help_webviewer.current_anon_calls to 0" to
reset the value.

$housekeeper

The housekeeper is an object that can help keep other objects where they belong. New MOOs may want to add their own user interface for the housekeeper; here is some information that may be helpful.

To indicate what objects should be cleaned:

  :add_cleanup(object[, requestor[, where]])
    Ask the housekeeper to clean 'object' for 'requestor' to 'where'.
    Requestor defaults to `player'.
    Where defaults to object.location.

  :remove_cleanup(what[, requestor])
    Remove 'what' from the cleanup list at 'requestor's request.
    Will remove it only if 'requestor' made the original request and owns
    the object or the destination.

To actually get the housekeeper to clean stuff up:

  :cleanup([insist])
    Clean up character's objects. Argument is 'up' or 'up!' for manually
    requested cleanups. 'up!' means to clean things even if it's against
    the housekeeper's better judgement.

  :replace(object[, insist])
    Clean up the indicated object. 'insist' is as in :cleanup.

  :continuous()
    Starts the housekeeper cleaning continuously, killing any previous
    continuous task. This should be called only when starting up a new MOO,
    or if something has gone wrong, as normally it will just keep going
    without any help.

  :litterbug()
    Clean up all the places in housekeeper.public_places by getting rid of
    all contents not in their .residents lists. This is called by
    :continuous, so it doesn't need to be called directly.

To find out what's being cleaned to where for whom:

  :cleanup_list([whom])
    Show 'player' the personal cleanup list for 'whom', or the housekeeper's
    complete list if no argument is given.

  :clean_status()
    Show 'player' a brief summary of eir personal cleanup list.

$html_editor

 The $html_editor is a child of the generic editor that specifically
writes to object's associated URL/HTML data(#1.url). Instead of
having "string" and "list" modes, like the text editor, it has a
"URL" and an "HTML" mode. The URL mode writes a single string,
indicative of a URL, and the HTML mode writes a list of strings,
indicative of an HTML text.

Although it doesn't yet have any HTML-specific commands, these may be
added in the future to facilitate its use in creating HTML texts.
However, you can always create the HTML text in your favorite editor,
then paste the part between the <BODY and </BODY> tags into the HTML
editor to attach that HTML text to an object.

$http_handler

The $http_handler:handle_http10 is the primary mechanism for
processing web transactions, and is usually called by an $http_port.
It accepts a URI in the following forms, with the results given:

1) http://HOSTNAME:PORT
2) http://HOSTNAME:PORT/?WEBPASS
3) http://HOSTNAME:PORT/xxWEBPASS
4) http://HOSTNAME:PORT/xxWEBPASS/CODE
5) http://HOSTNAME:PORT/xxWEBPASS/CODE/OBJECT
6) http://HOSTNAME:PORT/xxWEBPASS/CODE/OBJECT/REST
7) http://HOSTNAME:PORT/xxWEBPASS/CODE/OBJECT/REST?SEARCH

Where HOSTNAME is currently bioinfo.weizmann.ac.il,
      PORT is 8888,
      xx are two random characters,
      WEBPASS is the user's web password and may be blank,
      CODE is the web application's identity,
      OBJECT is an object number (without the #),
  and REST is anything else you append to the URL.

When the MOO receives a web connection, it parses it as described
above, and does the following:

- a URL of type 1) will simply show the MOO's gateway page, unless
   there is a form attached (which is then evaluated for
   authentication information).
- a URL of type 2) or 3) will check the webpass.
  - if it's omitted then either web cookie or web "domain"
    authentication is used.
  - if it's bad, it will show the MOO's identification screen.
  - if it's OK, it will show the list of web applications.
- a URL of types 4), 5), 6) or 7) will check the CODE.
  - if there isn't a code of a valid web app, it will show the list
    of apps.
  - if it's a valid code, it will call the application's :method_get
    or :method_post giving it as parameters: (who, what, rest,
    search), which are: the user whose webpass is being used,
    the object number that was parsed, the REST, and the SEARCH
    if any.
_____________________________

Web transactions typically follow the pathway:

$http_port
   |
   V
/$http_handler:handle_http10
\$http_handler:handle_http09
   |
   | <-> parse_line
   |
   | <-> /web_authenticate
   | \cookie_authenticate
   |
   | <-> init_taskprop
   V
:process <-> /$webapp:method_get <-> /object:html
   | \$webapp:method_post | object:do_post
   | \object:get_vrml
   |
   | The `process' verb determines which $webapp to call and
   | processes the result into its final form.
   |
make_headerlist
   |
   V
tell_quick_and_die
_____________________________

These properties are defined on $http_handler

task_details
task_index
    These store information about the open web transactions
    that can be retrieved with $http_handler;retrieve_taskprop.
    Also, any verb called during the transaction can submit new
    task properties that can then be retrieved by any other
    verb when called. Some default properties can only be
    retreived by wizardly verbs.
total_webcalls
    Total number of web transactions handled by this object
    since its installation.
webpass_handler
    The object number of the webpass handler object. The
    webpass handler is not corified.
gateway_html
    The default web page displayed when someone connects to
    $network.site on a port with an $http_port object
    listening. This should have a form allowing authentication
    (see the default value for an example).
wizwebpass_disallowed
    Almost obsoleted mechanism for regulating which
    authentication system wizards may use to open a web window
    for their wiz character.
version
    The currently installed version of the BioGate system.
output_timeout
    If a transaction takes longer than this number of seconds,
    it is assumed to have failed (probably due to a traceback),
    and the connection is broken.
password_failed_text
    Text returned if a web transaction is incorrectly
    authenitcated.
exempt_from_pads
    By default, the $http_handler assumes transactions are
    requests for HTML documents, and builds a proper header and
    footer with the appropriate tags. Some transactions, like
    VRML requests, shouldn't have these and are "exempted from
    pads." Although the $std_vrml10viewer and $frame_manager
    are automatically exempt, any other kids of the $webapp you
    want exempted should be added here.
anon_access_limits
    A list of two elements, that set usage limits beyond which
    unauthenticated transactions are rejected. The first
    element is the maxiumum number of concurrent web
    transactions and the second is the maximum MOO lag in
    seconds.
lag_meter
    Object that tracks and reports lag. Found in most MOOs
    though not part of LambdaCore. If not set, lag-based
    features are disabled.
too_much_load_text
    HTML doc sent when the MOO has too high a load to process
    unauthenticated HTTP transactions.
java_clients
    List of Java telnet client handlers allowed to use the web
    system.
javaclient_codebase
    The subdirectory at the MOO's site where java clients are
    found. Used as $network.site +
    $http_handler.javaclient_codebase +
    $jclient_handler.client_name
login_is_http09
    If true, treats call transactions that come through $login
    as HTTP/0.9 (rarely used).
port_handlers
    List of objects permitted to call the handle_http09 and
    handle_http10 verbs. Generally kids of $http_port, and
    sometimes $login.
auth_ports
    Almost obsoleted mechanism for regulating which
    authentication system wizards may use to open a web window
    for their wiz character.
robots_txt
    Sent upon requests for "/robots.txt" and tells web spiders
    not to scan the MOO for web pages (which could cause CPU and
    networking load problems). Note that you can use this to
    restrict web spiders and other web cataloging robots to only
    portions of your MOO. By default, everything but the gateway
    page is off limits. For details on constructing a robots.txt
    entry, see:
    http://info.webcrawler.com/mak/projects/robots/robots.html

$http_port

  The $http_port listens on a MOO port for incoming HTTP transactions
has a few properties and verbs that provide its listening
functionality, and it also carries some properties used by the server
that are described in detail in the LambdaMOO Programmer's Manual
(server_options, connect_timeout, timeout_msg, recycle_msg, boot_msg,
redirect_from_msg, redirect_to_msg, create_msg, connect_msg, and
server_full_msg).

The $http_port:do_login_command verb is the main workhorse of the
object. It parses the incoming transaction's first line to
determine the method (GET/POST), the URI (specifies the requested
resource), and the protocol version (generally 1.0). Transactions
are then passed to $http_handler:handle_http09 or
$http_handler:handle_http10 depending on the HTTP version of the
incoming transaction.

User commands (wizardly use only) on the $http_port are:

@set-port <port number> on <listener>
   set the port to listen on
@startlistening on <listener>
   the object starts listening
@stoplistening on <listener>
   the object stops listening

These have executable equivalents, useful if your MOO automatically
starts listening with an $http_port upon startup. These
are: set_port, listen, and unlisten.

$jclient_handler

Child objects of the $jclient_handler carry verbs and properties that
allow the MOO to effectively communicate with their corresponding
java telnet applets. This includes information like where the applet
may be retrieved from, and how to tell the applet to update a web

Verbs on the $jclient_handler work with the Cup-O MUD client by
default, but can be overridden on child objects to give new
functionality.
page.

The "client_name" property must be set for the client handler to
function. This is actually the subdirectory and class file name to
be appended to $http_handler.java_clients when forming the URL for
retrieving the Java code.

For instance:
  $network.site = moo.site.org
  $http_port.handles_port = 8000
  $http_handler.java_clients = "/java/"
  <jclient_handler>.client_name = "CupOmud/CupOmud"

Would yield the URL:
  http://moo.site.org:8000/java/CupOmud/CupOmud.class

The "default_preload_page" property contains the text to be displayed
in the web page frame of the user's web browser window until the
telnet client finishes loading and issues a "display URL" command of
its own. You can use the default value if you wish.

The "client_windowname" and "html_windowname" properties give the
names of the frames that will hold the client applet and the HTML
text display, respectively.

The "float_client_frame" verb returns true if the client will be set
in a floating independent frame. Typically it just returns the value
of the "float_client_frame" property, but may also check user
preferences to determine a result.

The "make_applet_html" verb is called by the $frame_manager and
returns the HTML document containing <EMBED> tags that will load the
Java telnet client.

The "update_webframe" verb sends a command (using MCP in the case of
Cup-O MUD) to the the client that causes it to force the web browser
to load a new HTML document into a specified frame.

The "user_autoconnected" verb is called when a person first connects
to the MOO through a Java telnet client, typically through the
$login:preapproved system.

The "preload_page" verb returns the HTML document to be displayed in
the usual web page frame until the first "display URL" command is
issued by the Java telnet client.

$local

The following customizable properties are defined on $local:

.default_rooms
  These are rooms all users see with the @rooms command, and to which
  they can @go. Add and remove rooms with the @addroom and @rmroom
  command.

.guest_lines
  This property is a list of texts randomly chosen among to be
  displayed when a guest connects (see $limbo.con_guest). Each new
  section starts with a period, so a line without a period as the
  first character indicates a continuation line. This property can
  be customized.
  If your guests connect in quiet cubicles, these texts are
  irrelevent.

.purge_candidates
.vspo_purge_candidates
.purge_deadline
.purge_time
.purge_exceptions
.purge_notice_txt
.to_be_purged
  The purge system is a still incomplete set of utilities intended to
  aid in identifying and recycling outdated, unused characters and
  their posessions. The properties in this section can be ignored,
  at this time.

.desc_txt
.info_txt
.gend_txt
.home_txt
.wrap_txt
.msgs_txt
.no_bother_txt
.header
.presskey
  This section is for an as yet incomplete system, and its
  values can be ignored at this time.
  This section contains various messages displayed occasionally to
  characters with $player.newbie set true. Users can set this with
  "@newbie on|off" and it's intended as a gentle reminder to people
  to customize their characters. The $player:newbie_prompt scans the
  user's characteristics to determine which message should be
  displayed.

.banish_text
  The .banish_text is displayed to guests who are banished by users
  with the @banish command. This can be customized.
.tag_notify
  The .tag_notify property stores character objnums to be notified
  when they next connect that they have been @tag'd.
.banishing_disabled
.tagging_disabled
  The .banishing_disabled and .tagging_disabled properties store
  local user restrictions on banishing and tagging. See the help
  texts for the commands that modify these properties, @notag and
  #nobanish.

.first_time_connect_script
  This is a script, which if set is displayed to people the first
  time they connect. See $guest.login_script for and example of the
  format. This system is currently under revision.

.converted_msg
.oconverted_msg
  The .converted_msg and .oconverted_msg texts are displayed when a
  VSPO character is made into a regular character. These can be
  customized.

.auto_guest_log
  Guests from sites whose names match the strings in this list are
  automatically logged when they connect, as if someone immediately
  typed @witness right after they connected. The logs are not
  stored unless someone uses @banish on them. The verb
  $local:check_auto_guest_log checks this property. This property
  can be customized by hand (using @set).

.projects
.projects_mail_recipient
  These properties are part of the wizard projects system. See "help
  @projects" for more info.

.out_exit_target
  This is used by the @testexits command to check if rooms are
  properly linked to the main MOO with exists aliases as "out."
  It's only relevent if you have such a construction policy, that
  people should be able to reach the room this property identifies,
  by repeatedly typing "out" until they arrive. If the MOO lacks
  such a policy, both this property and the $builder:@testexits
  command can be removed.

.checkpoint_started_msg
.checkpoint_finished_msg
.broadcast_checkpoint_messages
  This section causes every connected user to be told when
  checkpoints start and end. Some administrators may find it
  appeases the users a bit if your MOO lags a lot during
  checkpoints, since people will at least understand why. If
  .broadcast_checkpoint_messages is true, then the two messages are
  displayed appropriately. All three of these properties can be
  customized by hand (using @set).

.nope_header_txt
.nope_footer_txt
.nope_txt_substitutions
.name_nope_txt
.reason_nope_txt
.info_nope_txt
.vspo_nope_txt
  These properties are used by the @rejected command system to create
  an email to send (with $wiz_utils:compose_nope_txt). They can all
  be customized for the MOO, generally with @edit. The .nope_header_txt
  is always used at the top of the letter, and the .nope_footer_txt
  always included at the end. In between are any of the
  <reason>_nope_txt properties chosen by the person rejecting the
  application. See "help $local:nope_header_txt" for details of how
  to use the .nope_txt_substitutions property.

.new_player_email_txt
  This property holds the text of the email sent to characters newly
  made with @created. It should be customized for the MOO.

.idle_check_enabled
.idle_check_interval
.idle_limits
.idle_boot_protect
.idle_warning_text
  If .idle_check_enabled is true, then people idle for longer than
  the values in .idle_limits are warned (with .idle_warning_text)
  and then disconnected, unless their character's object number is
  in the .idle_boot_protect list or they are a Wizard or Manager.
  Characters are checked for idleness every .idle_check_interval
  seconds. By default, the values in .idle_limits (read by
  $wiz_utils:idle_check, where there is further documentation) are a
  warning after 55 minutes and booted after 60 minutes idle.

.autosubscribe_lists
  This is a list of oject numbers, each of which should be a child of
  $mail_recipient. All newly created characters are automatically
  subscribed to the mail-folders in this list. It should be
  customized by hand (using @set).

.character_lists
  This is a list of property references in the form { {$pointer STR,
  propname STR}, ... } referencing lists of character object numbers
  that should be cleaned when a character is recycled. It should be
  customized only if the core is modified such that new lists of
  character objnums are used. Quoting from $player:recycle...
  The next lines remove the character from various other places
  where character references appear. It presumes the caller
  will have perms to modify these, else they're skipped.

.rintintin
  This property is used by $player.@locate only, to insure people
  only have one such search running at a time. The property is
  unused until $player:@locate is modified to fit corification and
  not routinely deleted during core extraction.

.not_builder_msg
  This is the message displayed when someone who is not a builder
  tries to use the @dig or @create command. It should be customized
  for the MOO so that people are told how they may get builder
  permissions.

.last_creation_check
.mailto_creation_check
  These properties are used by the object creation check system,
  which sends daily mail to all characters listed in
  .mailto_creation_check about what objects have been created during
  the last 24 hours. This can be useful for noting what areas of
  the MOO are being build, and who is working on what. The object
  creation check system is run once per day, launched by the
  $local:checkpoint_hook verb. The .mailto_creation_check property
  can by edited by hand (using @set).

.scandal_mongers
.watch_mail_interval
.watched
.logs
  The log mailing system is currently under development. Unless the
  $wiz_utils:period verb is running (activated by hand), it won't
  function.
  Every .watch_mail_interval seconds, the $wiz_utils:periodic verb
    runs. Each character listed in .watched (each of which presumably
    has permanent logging activated; i.e. their $player.permanent_log
    property is set) has their collected log sent to each person
    listed in .scandal_mongers, and their $player.log property is
    transferred to .logs and then cleared. Note that if mailed
    logging is activated, the $local.logs will grow endlessly until it
    is cleared by hand (with "@set $local.logs to {}").
  
.email_address_required
   If this is set, then people with a blank email address
 ($player.email_address=="") are issued the message in
  $local.email_missing_text when they connect.

.trustees
  This property is specific to DU MOO and is removed during the
  eduCore extraction process.

$login

$login
------
This object manages command parsing for unconnected people and governs the initiation of an actual connection. There are verbs pertaining to registration, controlling user character creation, and doing site-locks (see `help blacklist' on $wiz_help).

COMMANDS FOR UNCONNECTED USERS

Recall that for each line that an unconnected person types, the server parses that line into words (the same way normal commands are parsed into a list of words that is then assigned to `args') and then #0:do_login_command is called.

  :parse_command (@args) => {verb, @args}
    given the sequence of arguments that were fed to #0:do_login_command
    this returns the name of a verb on $login to be called together with a
    list of arguments to be passed to it.

By default this just returns args iff args[1] names an actual verb on $login that is +x and has args {"any","none","any"}. Otherwise, it returns one of

  .blank_command - verb to call if command line is empty
  .bogus_command - verb to call if command line otherwise unintelligible

In both cases :parse_command returns a verbname followed by the entire args list passed to it (including the would-be verb at the beginning if any).

Currently the following verbs are availabe to non-connected people

  h*elp @h*elp - print .welcome_message
  ? - print a short list of available commands
  w*ho @w*ho - print a list of logged in people (excluding wizards)
  co*nnect @co*nnect - connect to an existing character
  cr*eate @cr*eate - create a new character
  up*time @up*time - tell how long the server has been running
  version @version - tell which version of the server is running
  q*uit @q*uit - logoff

Adding a new command is fairly straightforward; just create a verb on $login, making sure a previous verb doesn't already match the name you want to give it. Then give it args of "any" "none "any" and make sure it is +x. Such a verb should begin with `if (caller != #0) return E_PERM; ...' so as to prevent anyone other from a not-logged-in person from making use of it.

CUSTOMIZATIONS

  .welcome_message
    - the message for "help" to print.
  .create_enabled
    == 0 => `create' prints .registration_string if one tries to use it
    == 1 => anyone from a non-blacklisted site (see `help blacklist')
            may use `create' to make a new character

  .registration_address
    - an email address for character creation requests
  .registration_string
    - string to print to people to give them information about how to get
       a character created for them, .registration_address is substituted
       for %e, % for %%
  .newt_registration_string
    - string to print to @newted characters (see `help @newt').
       same substitutions as for .registration_string.

Other verbs
   :registration_string() => .registration_string with substitutions
   :newt_registration_string() => .newt_registration_string with substitutions
   :player_creation_enabled(connection)
       decides whether someone on connection should be allowed to create
       a character. If you decide this shouldn't depend strictly on the blacklist
       and on the value of .create_enabled, here's where the extra code can go.
   :check_for_shutdown()
       prints a warning message to append to the login banner in the event
       that the server will be going down soon.
   :check_player_db()
       prints a warning message to append to the login banner in the event
       that $player_db is being reloaded to warn people that their character
       names might not be recognized.

SITE LOCKS
see `help blacklist'

$mail_agent

$mail_agent

This object contains a two distinct sets of routines:

  1. utilities for performing basic mailsystem functions, e.g.,
      matching on recipient names, resolving mail forwarding,
      formatting messages, sending messages

Recipient Matching

match - match on a $mail_recipient
match_recipient - match on either a $mail_recipient or a character object
match_failed - print angry messages to the user for $failed/ambiguous_match

look_self - provides a list of available $mail_recipients
check_names
touch
accept

Message Format

make_message - produces a message in the canonical transmission format
name - single recipient => string for address field
name_list - list of recipients => string for address field
parse_address_field - address field string => object list

Sending Messages

send_message - advertised message sending routine.
raw_send - raw message sending routine
                (only called by $mail_editor:send and this:send_message)
resolve_addr - converts a given list recipients into a list of actual
                recipients and objects to be notified.
sends_to - Does X forward (transitively) to Y

Mail Options

option
option_verbose

  2. canonical versions of mail_recipient verbs

Ideally, the verbs to perform operations on a given mail recipient would be located on the recipient itself, except for the fact that these verbs also need to be located on characters, which for various reasons, shouldn't be children of $mail_recipient. Multiple inheritance would solve our problems, but we don't have it yet. Ergo, both $mail_recipient and $player refer to the following verbs here:

display_seq_full print entire text of messages (@read)
display_seq_headers print headers of messages (@mail)
rm_message_seq remove messages (@rmm)
undo_rmm undo last rm_message_seq (@unrmm)
expunge_rmm flush removed messages (@unrmm expunge)
list_rmm list removed messages (@unrmm list)
renumber renumber messages (@renumber)
msg_summary_line msg header => display_seq_headers/list_rmm summary line

parse_message_seq command line msg sequence spec => message sequence
new_message_num => message number of next new message
length_all_msgs => number of messages (total)
length_num_le => number of messages numbered <= some number
length_date_le => number of messages dated <= some date
exists_num_eq => true iff there exists a messsage with the given number
from_msg_seq => message sequence of msgs from given sender(s)
to_msg_seq => message sequence of msgs to given recipient(s)
subject_msg_seq => message sequence of msgs with subjects containing text
body_msg_seq => message sequence of msgs with bodies containing text
messages_in_seq => list of {message number, message} pairs

messages == :messages_in_seq(1,:length_all_msgs()+1) (obsolete)

The $mail_agent versions of these verbs are set_task_perms(caller_perms()) and perform their operations on caller, which in turn is assumed to have done any necessary security checks.

$mail_browser

  The $mail_browser is a web system tool for reading MOO mail
folders.It has two customizable properties on it:

   The "headerlist_len" property is the length of the headers list
 displayed when someone browses a folder.

   The "guest_subscribed_folders" is the list of mail folders (as a
 LIST of OBJ numbers) that guest and anonymous web users are shown as
 their "subscribed" folders. They can access the others (that are
 public) through the "list all folders" link, but this is basically

$mail_recipient

Generic Mail Recipient
----------------------
A "mail recipient" is, by definition, an object that can be sent mail.
Mail recipients must either be character objects or descendants of $mail_recipient.

One source of confusion is that the terms "mail recipient", "mail folder", "mailing list", and "mail collection" really all refer to the same kind of object. It so happens that $mail_recipient serve several distinct functions and we tend to use whatever term happens to best match the application under discussion, e.g., it's a "mailing list" if we're playing with its .mail_forward property but it's also a "mail folder" if we're examining the messages that have been saved in it.

Note that, by default, a freshly created recipient is accessibly only by you. If you wish to make a publically accessible recipient, set .readers=1. Furthermore, if you want to allow a message on your recipient to be removed by its sender without your intervention, set .rmm_own_msgs=1. Finally, in order for other people to be able to refer to your recipient by name, the object must reside in $mail_agent. $mail_agent will not accept the object unless it has an actual description and a name distinct from all other mail recipient names/aliases.

Topics:

  MR-access -- controlling read, write and send access to a recipient
  MR-naming -- naming conventions and how to match on recipient names
  MR-sequences -- message sequence arguments to $mail_recipient verbs
  MR-reading -- reading messages/headers on recipients
  MR-searching -- searching message lists for patterns in certain fields
  MR-writing -- removing and renumbering messages
  MR-subscribing -- updating .mail_forward, .mail_notify
                       and the story of .current_message
  MR-setup -- Setting or changing the configuration for a mail recipient

$manager

  The $manager class confers various near-wizardly abilities and
responsibilies. These are listed in $manager.abilities, along with
the property name on $manager that controls them. A given Manager
may have any or none of the various abilities that can be conferred.
The primary tool for creating and managing Managers is the @manager
command.
  The ability of Managers to actually function is dependent on the
system they control actually granting that ability. Generally, the
system should check if the person has their manager property set and
if the property conferring the specific ability is also set. This is
properly accomplished by calling
  $perm_utils:manager_controls(who OBJ, activity STR)
to check if `who' has permission for `activity' where `activity' is
actually the name of the relevent property on $manager.
  Managers, like wizards, are protected from being booted if idle
longer than the $local.idle_limits values.

Some Manager commands may be available to all managers, irregardless
of their assigned responsibilities.

Related Topics:
@manager -- wizardly command for managing Managers

$map

The $map is used to store ASCII art maps of various sites in the MOO.
Users can always type "map <map name>" to get a map for the <map
name> area, or just "map" to get a general map for the MOO.

This system will eventually be adjusted to supply location-sensitive
maps, keyed to the user's location, but for now using "map" alone
returns the map in the "text" property of $map. It will also be
integrated with the $domain system. the MOO in general.

Using "@edit map" edits the main map, which is returned when someone
just types "map" without specifying any particular one. Other maps
are entered as properties on the $map object, with the property name
as the name of the map to the map library. To add a new map, you
can:

  @addmap <note> to $map

where <note> is any $note whose text is the ASCII art map that should
be added. After entering the command, you'll be prompted for the
name of the map, which should have no spaces in it.

$new_player_log

A $biglist with an entry for every character created in the MOO. You can use @mail to search the listing with the following key-expresions:

from:<who> - created by <who>
subject:<who> - character created named <who>
body:<email> - posting for person with given <email>

$new_prog_log

A $biglist with an entry for every progbit set in the MOO. You can use @mail to search the listing with the following key-expresions:

from:<who> - progbit set by <who>
subject:<who> - progbit set on character named <who>

$news

The News Article Database ($news) features a couple of verbs for
adding or removing news items to/from it. If you want to add news to
the database, you must have added $news to your list of features
(@addfeature $news), then follow these steps:

1. @create $news_item called <whatever>
2. @edit <whatever>
     (compose the body of the news item and save it
3. @announcement <whatever> is <message displayed to users at login>
4. @addnews <whatever>

The @addnews command moves the news item to the News Article Database
($news), and announces the new news item to all connected users.

Note that if you edit a news item that has previously been added to
the news database (with @addnews) and save the changes, the news item
will be considered `fresh out of the press' once again, and announced
to everyone all over again. You can use `@contents $news' to see
what news item objects are currently published.

News articles are note objects, made from the Generic News Item ($news_item).

Below is a brief description of the two user-verbs associated with $news.

$news:@addnews

Syntax: @addnews <news>
Add <news> to the news article database ($news).
<news> should be a child of the $new_item (the Generic News Item)

$news:@rmnews

Syntax: @rmnews <news-index>
Remove <news-index> from the news article database ($news).
<news-index> is the news article number, from the `news' listing.

$no_one

$no_one
-------
..is a powerless character. It owns no objects, not even itself; nor it own any verbs. It is, however, a programmer and thus may use eval().
In fact his sole purpose is to evaluate questionable code.
`questionable' could be in either or both of the following senses

(1) Its origin is sufficiently uncertain so that there is no obvious way of deciding whose permissions it should run under.
(2) The code itself is potentially malicious, i.e., to the extent that one does not want to be evaluating it using one's own permissions.

set_task_perms($no_one); is thus the canonical idiom in wizard code for rendering anything that follows mostly harmless. For use by ordinary programmers, we have:

    $no_one:eval(string)

which attempts to evaluate an arbitrary string using $no_one's permissions.
string is either an expression or ";" followed by one or more statements, of which the final semicolon may be omitted. return values are what eval() would return (either {1,value} or {0,@error_messages}).

$object_quota_utils

This is the default package that interfaces to the $player/$prog
quota manipulation verbs.

To set the initial amount of object quota people have, set the
following properties:
  $object_quota_utils.default_player_quota
  $object_quota_utils.default_builder_quota
  $object_quota_utils.default_programmer_quota
using "@set $object_quota_utils.default_player_quota to 0" for
instance. To be extra cautious, you should set the same values on
each character class generic:
  $player.ownership_quota
  $builder.ownership_quota
  $builder.ownership_quota
  $prog.ownership_quota

See `help $byte_quota_utils' for information about byte-based quota.

$player_db

Database of Users
-------------------
This is an instance of the Generic Database ($generic_db) that
holds the {name/alias,#objectid} pairs for every
name and alias of every character object in the MOO.

Commands availble are:

look $player_db
  Shows when the last check and last load were performed.

@check $player_db
  Checks the database for recycled or @toad'ed characters and removes
them.

@reload $player_db
  Completely clears and reloads the $player_db with all currently
valid character's names and aliases.

Executable verbs supplied include

  :find(string) => character obj or $ambiguous_match or $failed_match
  :find_exact(string) => character obj or $failed_match (does not do partial matches)
  :find_all(string) => list of all matching registered characters

  :insert(string, who)
       records that string is now a name or alias of <who>
  :delete(string)
       removes string from the db
  :available(string)
       returns 1 if string is available as a character name or alias,
       an object if string is in use, or 0 if string is otherwise unavailable.
  :load()
       resets the db, inserting all current registered character names and aliases. The time() of the last load is stored in $player_db.last_load
  :check()
       checks for recycled and toaded players that managed not to get
       expunged from the db. The time() of the last check is stored in $player_db.last_check

The internal representation and all of the above verbs (except :load() and
:available()) are as described for $generic_db.

It should be noted that for any application that involves resolving a character name from a command line, you should be using $string_utils:match_player() rather than $player_db:find(), since the former will deal correctly with other ways of referring to people apart from their names and aliases (e.g., literal object numbers, "me", "$no_one"...).

:load() needs to be done periodically as it is possible for the $player_db
to get out of synch with reality. In particular, there is currently no way
to block someone writing his own character's :recycle() verb that neglects to
remove that person's names from the $player_db.

While a :load() is in progress the .frozen property is set to 1 to indicate that any results of :find*() are not to be trusted.

$recycler

$recycler
=========

Rather than having the server built-in recycle() and create() functions handle the creation and destruction of objects, a recycling center has been created to simulate these actions by changing objects that would have been recycled into children of $garbage (The Generic Garbage Object) and making them owned by Hacker, and then when they're needed again, to avoid a raw create() command, those objects are given to whoever's asking for them.

Most Useful Verbs
-----------------

$recycler:_recycle( object )
  This will effectively recycle an object. (As a point of fact, it changes ownership of the object to Hacker and makes the object a child of $garbage.) It handles .ownership_quota and .owned_objects properly. Generally, use this instead of a recycle() in your verbs.

$recycler:_create( parent object [ , new owner object ] )
  This effectively creates an object (with the specified parent, if possible, and with the specified owner, if possible; these are the same restrictions as on the server create() builtin). This is what should generally be used instead of create() in your programming.

$recycler:valid ( object )
  This is a variant of the server built-in valid() except that it handles the $garbage objects as well. It returns a 1 if the object specified -is- valid and is -not- a $garbage object.

Other Notes
-----------

request <object> from <recycler>
  This is not an internal verb (it's !x). It is, however, a command-line verb that can be used to request a specific object from the recycler. It's also useful for the creation of objects like a Magic Number Repository. When the object is removed from the recycler, the .announce_removal_msg is announced to the room if it's set (it's piped through $string_utils for pronoun substitution).
NOTE: This verb has been disabled from the original LambdaCore version. See $recycler:take_object instead.

show-history <recycler>
  This is a wizardly verb which allows wizards to check the `history list' of the recycler. The history maintains the latest ($recycler.nhist) entries.

$recycler.orphans
  This maintains a list of objects for which the recreation process got mangled. It ought to be checked every once in a while to see what's up.

@clear-orphans from <recycler>
This command will step you through each item in <recycler>.orphans, providing information and making a recommendation about how to deal with that object. It also allows you to remove the item from the list.

$registration_db

The $registration_db stores the e-mail address for every character
ever registered in the MOO. It provides a variety of verbs for
specialized searching of the database, as well as the usual
$generic_db search tools. It also has a custom :add verb that allows
a comment to be associated with the address along with the character
object number.

Executable verbs are:

add(who OBJ, email STR, comment STR) -> none
  Add a new character email registration.

find(email STR) -> { {who OBJ [,comment STR]}, ...}
  Returns a list of character object numbers (with associated
comment, if any), that have been associated with the specified
`email' address. Note that some may correspond to characters that
have been recycled. Returns $failed_match if no match, or
$ambiguous_match if the `email' is a prefix for more than one
registered email address..

find_exact(email STR)
  Like :find but returns list of characters that match or
$failed_match (nerver $ambiguous_match).

find_all(email STR)
  Like :find but returns all registered entries with addresses for
which `email' is a prefix. Note that only searching by userid is
really an appropriate use for this. Use :suspicious_address for a
method that properly examines the internet address structure.

suspicious_address(email STR) -> {email STR, ...}
  Returns a list of email addresses that are related to the specified
one, suggesting they may belong to the same person. For instance,
searching for "person@school.edu" will also match
"person@node.school.edu".

suspicious_userid(userid STR) -> BOOL
Return true if userid is root or postmaster or something like that.

describe_registration(find_result LIST) -> description LIST
Accepts the successful results of one of the :find verbs, and returns
a list of strings giving a plain language description of the
information.
Each line has the form:
  <character> (<objnum>) current email: <email> [<comment>]

$request_booth

  Here are the 4 user-verbs of the Character Request Booth which
wizards that have $request_booth added as a feature can use to The
$request_booth is the room where guests and VSPO's using the @request
command are taken so that they can fill out the application
undisturbed. Wizards can change the application by adding the
$request_booth as a feature, then using the commands described below.
display and rearrange questions of the character request form.

$request_booth:@addq*uestion

Syntax: @addq*uestion <subject>

Adds a question about <subject> to the character application for
guests or VSPOs. The verb prompts you for the exact wording of the
question and a string that will appear as an entry-prompt (the words
you see in the first half of the standard [] prompt).

$request_booth:@removeq*uestion @rmq*uestion

Syntax: @removeq*uestion <subject>

Get rid of the question for <subject> in the character application form for guests and VSPOs. If you aren't sure what subjects there are enter '@listq subjects' and you'll get a list of them, complete with indices.

$request_booth:@moveq*uestion

Syntax: @moveq*uestion <index1> to <index2>

Moves the question currently at position <index1> in the character
application for guests and VSPOs to the position <index2>.

$request_booth:@listq*uestions

Syntax: @listq*uestions [<subject>|<index>|subjects|all]

This verb allows you to view those questions contained in the
character application form for guests and VSPOs.

Args: 'all'|<none> to see a list of subjects and corresponding questions
      <subject>|<index> list the question and prompt for a specific subject.
      'subjects' list question subjects and their indices.

The following additional properties are defined on the $request_booth
and should be appropriately customized using the @edit command (e.g.
@edit $request_booth.introduction_msg):

$request_booth.introduction_msg
$request_booth.vspo_introduction_msg
  One of these messages is displayed to the applicant when they use
    the @request command and are moved into the $request_booth. If
    they are a VSPO applying for a regular character, they see the
    vspo_introduction_msg, else they see the introduction_msg. It
    should explain that they are going to be asked some questions,
    and why.

$request_booth.last_words
    Displayed after the person has completed the application, just
    before they are returned to the room they came from. It should
    give the person some idea when they can expect to hear from you.

$room

The Generic Room ($room)
----------------

(1) Announcements

:announce (@text) => broadcasts to all except `player'
:announce_all (@text) => broadcasts to all
:announce_all_but (objects,@text) => broadcasts to all except those in objects

say, emote

(2) Command recovery

:huh (verb,args) - server hook: last chance to make sense of verb
:here_huh (verb,args) - room's last attempt to parse something
:here_explain_syntax (this,verb,args) - attempts to explain usage of verb

(3) Residency

free_home - true => @sethome allows anyone to set his .home to be here
residents - objects on this list may teleport in and/or set their homes here.

:accept_for_abode(player)
            => true if person should be allowed to set .home to this room.

@resident*s

(4) Looking

dark - true => contents are not visible
ctype - 1..4 for four different styles of .contents lists

:match (string) => exit or object in room's .contents
:tell_contents (objects,ctype) - format objects according to ctype, tell `player'

l*ook

(5) Entrance and exit.

:accept (object) - Called by move() and :moveto() before an object enters a room, if false is returned, movement is prevented. Protocol permits this verb to make noise (though this is discouraged) as this is the only place the room will learn the object's original location.

:acceptable (object) - Called by verbs which wish to check whether movement will be possible. Protocol prohibits this verb from making noise and requires it to return the same value as :accept would for the same arguments.

:is_unlocked_for (object) - interface with the @lock protocol. Returns true or false depending on the state of locks for the object with the room. Other things may prevent entrance even if this returns true. Protocol prohibits this verb from making noise.

:enterfunc (object) - called after entrance has succeeded. Noise is fine.

:exitfunc (object) - called after an object has successfully left. Noisemaking is fine.

(6) Topology and Movement via Exits

See `help $exit' for an explanation of how the generic $exit works.

free_entry - true => `teleporting' in is allowed
                  false => only residents may teleport in
exits - list of invokable exits leading from this room
entrances - list of recognized exits leading to this room
blessed_object - object currently entering via an exit
blessed_task - task_id for entering object

:match_exit (string) => exit whose name matches string
:bless_for_entry (object) - set up room to accept object arriving from entrance
:add_exit (exit)
:add_entrance (exit)
:remove_exit (exit)
:remove_entrance (exit)

e/east/w/west/s/south/n/north/ne/northeast/nw/northwest/se/southeast/sw/southwest/u/up/d/down, go, @add-exit, @add-entrance, @remove-exit, @remove-entrance, @exits, @entrances

(7) Ejection

victim_ejection_msg/oejection_msg/ejection_msg
:*_msg() messages

@eject

$section_editor

The Section Editor is basically exactly like the Text Editor (aka Note Editor) in its operation and commands, except that instead of being designed to work on note objects or object properties, it has been designed to edit more arbitrary "sections" of objects.

A "section" can be defined by an object's programmer to be any bit of text associated with that object which might be appropriate for editing, such as chapters in a book or notices on a notice board, which aren't necessarily directly associated with individual properties on that object. It is intended to be called via $player:@edit with the syntax '@edit <object>|<section>' (i.e. '@edit book|1', for chapter 1 of a book named "book").

Pretty much any generic which is appropriate can be easily modified to take advantage of this editor simply by providing the following verbs:

:get_section(<section-name> [,<test>]) - Retrieve the text of a section identified by the string <section-name>. If no such section exists, this verb should return E_INVARG instead. the second parameter (<test>), if supplied, is a boolean value indicating that the call to this verb is only to determine whether such a section exists, and the actual text need not be returned (this type of call is used by the Section Editor to determine whether a section is valid before actually invoking the editor. Most applications can ignore any second argument. Indication is given simply in case a particular implementation involves a lot of processing or time-consuming operations to obtain the actual text of a section)

:set_section(<section-name>, <text>) - save new text for the section <section-name>. Implementations should check the type of the <text> parameter if it is important, as the Section Editor (like the Text Editor) can operate in either "string" or "list" mode.

(optional) :section_msg(<section-name>) - Return a string indicating the appropriate way to refer to <section-name>. If this verb is not present, a string of the form "section <section-name>" is used. (for example, a book's :section_msg verb might return a string of the form "chapter <chapter-number> (<heading>)" instead of the default, providing a more informative and descriptive identificaiton of what's being edited.)

(Note: All calls to :get_section and :set_section are made with caller_perms() set to the player who's doing the editing.)

$site_db

Database of places
------------------
i.e., places people have connected from.

  :add(sitename, who)
      records the fact that character connected from sitename.
  :load()
      clears the db and reloads all of the character connection info.

  .domain
      default domain for unqualified sitenames given to :add.
      
For each domain we keep a list of characters and subdomains.
For example, :add("doc.ic.ac.uk",#666) enters #666 on the lists for "doc.ic.ac.uk", and, if we have to create an entry for "doc.ic.ac.uk", we enter "doc" on the list for "ic.ac.uk", "ic" on the list for "ac.uk", etc.... In this case, :find("ic") will return the "ic.ac.uk" list if there is no other domain in $site_db starting with "ic". Note that the "ic.ac.uk" list may contain both objects, i.e., namely people that have connected from the site "ic.ac.uk", and strings, i.e., subdomains of "ic.ac.uk" like "doc".

  :find_exact(string) => character/subdomain list or $failed_match
  :find_all_keys(string) => list of all domains that begin with string
  :find_key (string) => unique domain that begins with string,
                            $ambiguous_match or $failed_match

The other $generic_db functions (:find, :find_all) are also available, though admittedly less useful.

$standard_webviewer

  The $standard_webviewer is provided to serve as a major interface
for people using the web interface to access the MOO's multimedia
information. Other such interfaces may be created and used, and even
set to be the standard webviewer themselves, but the BioGate System
comes with this viewer that you can use immediately. Note that users
can select a different default web viewer application to be used with
their character the "viewer" @weboption.
  The $standard_webviewer is different from the $anon_webviewer in
that the latter may be used by people without any telnet connection
into the MOO, who are essentially browsing anonymously. The
$standard_webviewer may only be used by people connected by telnet to
a MOO character. The reason is that the MOO is a self-contained
world, and people using it expect changes in the world to be due to
people or automatec processes within that world. Therefore,
unattributed transactions like those from the web without a matching
telnet connection, are restricted. People without registered
characters can use the $standard_webviewer by connecting to a guest
character, thereby giving themselves a "presence" within the VR
world. The $standard_webviewer extends the simple browsing with the
ability to move the user's MOO character, communicate with others,
and manipulate MOO objects, all through the web interface.

  The $standard_webviewer is called by $http_handler:process through
the usual indentification of the ".code" property, which is "viewer"
by default. The :method_get (or :method_post) verb is called with
args {who, what OBJ, rest STR, search STR, form STR}, where "what" is
the object to be viewed. If no object is specified, the user's
location (player.location) is assumed. Note that authentication is
performed earlier by the $http_handler, which sets the "player" value
before the call. The :method_get verb builds the various portions of
the final web page, then combines them and returns the text and a
title for the web window ({title STR, text LIST}).
  The :method_post verb is only called when the user selects an item
on the optional "command form" that may be included in the basic web
page by the "commandform" web option, if the user chooses.

  The components of the web page are assembled as follows:
1. If there are option toggles, indicated by flanking "+" symbols in
   the "rest" portion, these are used to set user display options.
2. The "focus" object's HTML text is retrieved by a call to
   what:html(rest, search, line). If the value returned is a list
   of STRings, it is assumed to be an HTML text fragment. If it is
   in the form {where OBJ, what OBJ} then it is a redirection to a
   new "what" with a new base location (replacing
   "player.location"), and the new what:html() is called without
   additional arguments. The inability to redirect the
   rest/search/form arguments is for security purposes. A maximum
   of four redirections is permitted. If what:html() returns the
   value $nothing, then "what" and "where" are set to
   "player.location" and a fresh call (without args) to what:html()
   is performed.
3. The attributes to be inserted into the page's <BODY> tag are
   retrieved from web setting named "bodytag_attributes" if one is set
   [what:get_web_setting()]. Also, the "hide_banner" web setting is
   checked for.
4. The "button bar" is generated by a call to
   player:web_viewer_buttons(viewer.code STR, what OBJ).
5. A map is inserted if the "map" web option has been set, which is
   generated by $teleporter:html(who, 0, 0).
6. The "You are at" and "examining...<what>" lines are generated as
   links to the $object_browser view of the given objects.
7. The list of exits is generated by
   $standard_webviewer:generate_exitlist(where).
8. A list of carried object is included if the "inv" web option is
   set, generated by $web_utils:list_english_list_with_urls(player OBJ,
   viewer.code STR, objects LIST).
9. The "command form" is generated if the "commandform" web option is
   set, and generated by $standard_webviewer:command_form().
10. An <EMBED> portion for the VRML view is included if the
   "embedVRML" web option is set, generated by
   $standard_webviewer:embedVRML(what).
11. Finally, the fragments are assembled in the appropriate order and
   the complete web page body is returned to the $http_handler.

$std_vrml10viewer

The $std_vrml10viewer is a webapp that displays a static VRML/1.0
view of a given room. Although it will pass VRML/2.0 information, it
doesn't have any facilities for live VRML display control. It does
dynamically create the room view, though, so the returned VRML file
describes the room at the moment of the request.

It is usually invoked with a URL in the form:

  http://moo.site.org:8000/99anon/vrml10/5555/room.wrl

Where "anon" specifies an unauthenticated transaction, "5555" is the
room or other object whose VRML description will be returned, and
"room.wrl" is appended for web browsers that use the file extension
instead of the MIME information in the HTTP header to determine
processing. All HTP/1.0 transactions processed by the
$std_vrml10viewer are of "x-world/x-vrml" MIME type.

The transactions follow the general form:

$http_handler
   A
   |
   V
$std_vrml10viewer:method_get
   A
   |
   V
<room>:get_vrml <-> .vrml_interior_desc
   A
   | The room retrieves the VRML file fragment for each
   | object inside, and adds cameras for each child
   | of $player. It also adds a standard "to web page" link
   | and a "to outside room" link of the room is "interior."
   |
   V
<objects>:get_vrml() <-> :get_vrml_desc
                         :get_vrml_translation
                         :get_vrml_rotation
                         :get_vrml_scale

Key data is stored on #1.vrml_desc, #1.vrml_coords, and
#1.vrml_settings. The first is a list of strings, comprising the
VRML file fragment describing the object's structure. The vrml_settings contains various VRML-related settings that are specific to the room. See the help text for "@set-vrml" to see which are currently defined for all rooms.

The vrml_coords property has the form:
    { {NUM, NUM, NUM}, {NUM, NUM, NUM}, {NUM, NUM, NUM} }
Where the first triplet is the XYZ translations from the room's
origin in milliunits, the second set is the XYZ rotations from the
origin in millirads, and the third set is the XYZ scaling in
milliunits. This allows a minimum translation of 1 milliunit and a
maximum of2147483. In most cases, a VRML unit is perceived as about
.75 meters, giving a translation range between .75 mm and 1612 km.

$teleporter

The General Teleporter ($teleporter) is a set of utilities for
teleporting users that consolidates all message display and other
functions. It is used by the BioGate System for teleporting users who
jump using the MOO's web system.

The main verbs on the $teleporter are:

$teleporter:teleport_user(who OBJ, where OBJ [, @ optional messages])

This is the non-web utility for moving characters, and performs all
appropriate testing of if the character was successfully moved and
presenting appropriate messages to their former and subsequent
location. If no optional messages are given, then those on the
character or the $teleporter are used as needed. See the help for
$teleporter:teleport_user for details of the optional messages.

$teleporter:move_user_for_web(who OBJ, where OBJ)

This verb performs user character movement for the web system,
including the VRML system. It is not generally used by other
systems, which should use $teleporter:teleport_user instead.

There are several properties on the $teleporter, some of which are
important for the web system.

.image_map - A STR with the URL of the MOO's default image map,
presented as part of the Web Viewer page if no room enclosing the
character has its own image_map property.

.imagemap_regions - A LIST in the form used by
$web_utils:interpret_map that divides the graphic given by the
image_map property into selectable regions.

.imagemap_rooms - A LIST of OBJ's, with each object a room
corresponding to the indexed region in the imagemap_regions property
(ie. the first room given is the place to move users who select the
first region specified in imagemap_regions).

.central_room - An OBJ specifying where the "center" of the MOO is.
This is used by some Web Viewers to present a button that returns
people to the MOO's center. Set to #11 by default, and generally
equal to $player_start.

default_mapsize - A LIST in the form {NUM, NUM} cotaining the
{length, width} in pixels of the image specified by the "image_map"
property. Some web viewers will force all image maps to this size,
which helps keep the display consistant. Note that if your map does
not conform to this size, the regions in the imagemap_regions may not
be correctly selected.

$vspo_registry

The VSPO Registry is the main database for information regarding the VSPO system. It is generally accessed using the $vsfo Feature Object.

Customizable properties:

.recycle_age
.max_quota
.expire_email_txt
.keepowned_expire_email_txt
.first_warning_time
.second_warning_time
.student_expire_mail_txt
.last_warning_txt
.admin_mail_recipient
.default_expiration_duration
.student_expire_confunc_text
.default_FOs
.groupowner_advance_time
.groupowner_advance_txt
.groupowners_visible

Structure of $vspo_registry.groups is:

.groups[group][1] OBJ group owner
.groups[group][2] STR group name
.groups[group][3] LIST group VSPO members {OBJ, OBJ, ...}
.groups[group][4] INT expiration date in time() format
.groups[group][5] LIST group non-owner controllers {OBJ, OBJ, ...}
.groups[group][6] LIST group flags {STR, STR, ...}
.groups[group][7][1] INT creation date in time() format
.groups[group][7][2] OBJ group creator
.groups[group][7][3] LIST group description {STR, STR, ...}
.groups[group][7][4] STR type of class
.groups[group][7][5] STR group charge type
.groups[group][7][6] STR group suffix

$webapp

Web applications (child objects of $webapp) generate the text that is
returned as a result of an HTTP transaction. For instance, the
webapp that creates the standard web page view of MOO rooms is the
$standard_webviewer, and the one that generates the VRML description
of rooms is the $std_vrml10viewer. Other webapps perform tasks such
as user character customization, browsing and setting the
characteristics of objects, or reading the MOO's mail folders. By
interposing webapps between the $http_handler and the general MOO
objects, functions are encapsulated in a way that 1. allows security
restrictions for broad functional catagories, 2. segregates the web
system into distinct parts, making debugging and extension of the
system easier.

The webapp to use in a transaction is specified by the CODE portion
of the URL, given the general format:
  http://HOSTNAME:PORT/xxWEBPASS/CODE/OBJECT/REST?SEARCH
The $http_handler:process verb determines which webapp is targeted by
checking the "code" property of each child of $webapp, and matching
the values. Note that if you want to restrict valid webapps to only
first generation decendents of $webapp, you should modify the
appropriate lines in $http_handler:process and
$http_handler:provide_menu so that the list of valid webapps is
children($webapp) instead of $object_utils:descendents($webapp).

Once the appropriate webapp has been identified, a call is made to
either its "method_get" or "method_post" verb, depending ont he type
of the transaction. Webapps may have a single verb with both names
as aliases. The call has the form:

method_get(who, what, rest, search)
method_post(who, what, rest, search, line)

where:
  who - originally set to `player' and now no longer used but
           retained for backward compatability.
  what - the object specified as OBJECT in the URI, or #0 if the
           object is not valid.
  rest - The REST portion of the URI.
  search - The SEARCH portion of the URI.
  line - The unparsed form line of a method POST transaction,
           generally processed by the webapp with
           $web_utils:parse_form.

The webapp is expected to use this information to create the text
that is the result of the HTTP transaction. By default, the webapp
is expected to return the <BODY> portion of the text for an HTML
document, and the $http_handler:process verb adds the <HEAD> and
other information. However, webapps listed in
$http_handler.exempt_from_pads are not treated this way, and the text
they return is directly sent to the transaction port.

Webapps that return HTML document text should do so in the form:
  { "<title>", {<lines of text>} }
Where <lines of text> are the strings composing the HTML text, and
<title> is the title that will head the web browser's window. See
the help for "$web_utils:format_webapp_result_to_html" for details of
the formats $http_handler:process will accept results in from a
webapp.

admin-mail-recipts

The following mail-folders are part of the core. Most are not
located in $mail_agent by default, so you must first subscribe to
them by object number before you can use the "*" prefix shortcut to
refer to them by name.

*Player-Creation-Log ($new_player_log)
    A low-level record of all created MOO characters. Not usually
    someone one would subscribe to.
*New-Prog-Log ($new_prog_log)
    Record of who's been given MOO programmer permissions.
*wizards ($system_mail_recipient)
  For messages to and between MOO Wizard characters. This mail
    folder can be posted to but not read by the general MOO community.
*Quota-Log ($quota_log)
    Record of whose quota has been changed and why.
*Site-Locks ($site_log)
    Notes on annoying sites and user connection restrictions.
*tags ($tag_log)
    A database of tags. Not normally accessed through the mail
    system commands, although it's a child of $mail_recipient.
    Administrators will want to subscribe to $witness_logs and not this.
*Helpful-People (&helpful-people_list)
    A mailing list for issues relating to Helpful People and the
    Helpful Person System. This is a public mail folder.
*VSPO-administration ($vspo_admin_list)
    A mailing list that receives administrative messages regrading
    the VSPO system.
*account-locks ($account_locks)
    This logs various site and user connection restriction changes.
*undecided ($undecided)
    A temporary place for character applications still under
    consideration.
*Character-Request-Pool ($request_pool)
    Requests for MOO characters are sent here.
*Manager-Log ($manager_log)
    This mail folder records addition and removal of managerial
    responsibilities for people of the $manager character class.
*created ($created_chars)
    This is a list of character applications that have been accepted.
*rejected ($rejected_chars)
    This is a list of character applications that have been rejected.
*witness-logs ($witness_logs)
    Logs of guest witnessing are sent here after a guest boot, and
    also registered user @witness'ing.
*Wiz-Projects (&ProjectsList)
    A platform where updates regarding the progress of projects that
    wizards are working on are pooled. This system is working, but
    still under development to extend it to Managers also.

biogate-setup

INITIALIZING AND CUSTOMIZING THE BIOGATE SYSTEM

This text describes what properties need to be initialized after you
have installed the BioGate System in your MOO. It provides a list of some
items you can customize. A more detailed description of nearly every
property in the BioGate System can be found in the help texts
installed in $core_help for each of the BioGate System objects. The
properties listed here are only the one's that must be customized for
the system to function properly, and for which setup instructions are
not given elsewhere in the installation package instructions.

On $http_handler
----------------
lag_meter
  Object number of a lag meter object, with a .samples property
  listing recent lag values. This object is common in MOOs, but if
  you don't have one, this property can just be set to a #-1 value.

gateway_html
  A text displayed as the MOO's web gateway page if there is no FUP
  system installed or no web/gateway.html file accessible. See the
  text of the sample gateway.html file for embedded comments
  describing the contents of that page.

webpass_handler
  The object number of the Webpass Handler object installed with the
  BioGate System.

On $web_utils
-------------
page_banner
  A fragment of HTML used to insert a "banner" across the top of each
  web page the MOO generates. This is NOT just a URL, but is a
  compelte <IMG> tag. The reason is that instead of just an image,
  you may want to use an imagemap or something more complex as the
  banner. The entire value for this property is inserted into the
  web page whole.

interior_rooms
  A list of object numbers for rooms that are "interior" or
  "portable" (in the usual MOO lingo). These are rooms with a verb
  having the name or alias "exit" for which that command can be used
  to exit the room into the enclosing room. By knowing which rooms
  have this feature, the Biogate System knows to add an "exit" link
  to the list of exists displayed, even though the exit named "exit"
  isn't generally displayed by the usual MOO $room exits listing.

web_helppage
  The URL for a "help page" for this MOO, which usually should have
  instructions for new MOO users.

MOO_home_page
  The URL of the MOO's "home page," which can be different from its
  web gateway page or identical.

uparrow_icon
  The URL for an icon embedded on web pages to indicate "go to the
  top of the page." Available to help promote a common look among
  MOO-generated web pages, but ignored if this value is set to an
  empty string.

std_bgcolor
std_textcolor
std_linkcolor
std_vlinkcolor
std_alinkcolor
std_bkgnd
  These are strings giving various default web page display values,
  that can help you establish a basaic "look" for web pages the MOO
  generates. However, they can be overridden by various means, and
  really just serve to promote a basic appearance. The only one most
  people will want to set is the .std._bkgnd property, which should
  be the URL for an image to be used as the standard background for
  all MOO-generated web pages that don't override the default.

wizards_choice
  Object number of a "Wizard's Choice" object, whose :html verb
  generates a page pointing out some of the more interesting sites to
  visit in the MOO. Used by the $anon_webviewer and
  $standard_webviewer to generate their button bar. If set to #-1,
  then no "Wizard's Choice" link is included in the button bar.

On $teleporter
--------------
image_map
  The URL for an image to be used as a map of the MOO, and added to
  the bottom of pages generated by the $standard_webviewer and
  $anon_webviewer. Other properties on $teleporter give further
  information concerning this imagemap.

central_room
  The "center" of the MOO. May be $player_start or some other room.
  Used by the $teleporter with certain web objects that send the user
  to the "central room" if one has been designated.

default_mapsize
  The size to display the MOO imagemap at.

imagemap_regions
  An ordered list of imagemap regions in $web_utils:interpret_map
  format. Indexed to the .imagemap_rooms property, so that each
  region corresponds to a room.

imagemap_rooms
  A list of rooms to teleport the user to when they select different
  regions of the imagemap. Those regions, indexed to this list of
  rooms, are specified in the .imagemap_regions property.

On $anon_webviewer
------------------
ghost_home
  The object number of the room where people using the WebGhost
  Viewer start. By default, it's the same as $player_start.

biogate-system

  This MOO has installed the Biogate System, a set of MOO objects and
associated code that allow a MOO to function and a web server, and to
dynamically create HTML and VRML descriptions of MOO rooms and other
objects.
 The version installed is: 1.3b

The general flow during a web transaction is:

    port-handler -> $http_handler <-> web-application

The $http_handler sends out the retrieved information and then breaks
the connection.

In addition, the web-application commonly will call individual
objects. For instance, the $standard_webviewer calls <object>:html()
and the $std_vrml10viewer calls <object:get_vrml() to retrieve
appropriate information about the object's current state. Objects
usually supply fragments of the final text that is compiled by the
web-application and sent back to the $http_handler.

The following components of the web system have their own core help
texts:

$http_port -- listens on a MOO port for HTTP transactions
$http_handler -- determines what type of resource is being requested
                  (eg. HTML or VRML), retrieves the relevent data
                  (possibly using a $webapp), sends out the info and
                  closes the connection
$webapp -- The "web applications" that generate the text
                  returned for a web transaction.
$frame_manager -- Performs various functions related to building
                  frames on the user's web page and placing the proper
                  information in each.
$jclient_handler -- Carries the verbs and data used to allow telnet
                  clients written in Java to connect to the MOO,
                  and interact appropriately. Each telnet client
                  uses a different child of the $jclient_handler.
$std_vrml10viewer -- This webapp displays a static VRML/1.0 view of a
                  given room. Although it will pass VRML/2.0
                  information, it doesn't have any facilities for
                  live VRML display control. It does dynamically
                  create the room view, though, so
                  the returned VRML file describes the room at the
                  moment of the request.
$html_editor -- A child of the generic editor that specifically
                  writes to object's associated URL/HTML data
                  (#1.url).
$web_options -- Options package for setting various
                  user-customizable aspects of the web system.
$web_utils -- A collection of utility verbs used by the web
                  system and web system programmers
Webpass Handler - The object that stores temporary web passwords for
                  users interacting with the MOO's web system (no
                  further help text is available for this object).
                  Referenced as $http_handler.webpass_handler
$teleporter -- The General Teleporter object is used by the web
                  system to move characters when they teleport. It
                  is a general purpose tool for this, though, and
                  can be used by non-BioGate systems.
$anon_webviewer -- A Web Viewer that allows anonymous web
                  transactions to be used to browse the MOO. This
                  web viewer presents the MOO's rooms much like the
                  $standard_webviewer, but doesn't require the
                  transactions be authenticated. It does not allow
                  users to manipulate objects, only to examine them
                  in ways that don't change any of their
                  characteristics.
$standard_webviewer -- The default web viewer for browsing the MOO
                  with authenticated transactions. It dynamically
                  creates web pages displaying the rooms and other
                  objects found in the MOO.
integrated-web-telnet -- Describes the innards of the integrated
                  web/telnet system, using the Cup-O MUD Java
                  telnet client as an example.

Additional topics:

web -- introduction to the MOO's web system
@web-options -- user options for cutomizing web system actions
web-programming -- how to program objects to be "web aware"
web-security -- how the web system's authentication system works

core-extraction

Documentation of the DU Core extraction and maintenance system

OVERVIEW

The purpose of the core extracting system is to create a "DU Core"
which contains the core objects and utilities which can be used by
other MOOs, without containing DU specific objects. Utilities are
included to assure that the core functions satisfactorily after being
extracted, without having to be extensively modified after creation.
Thus, the underlying DU database contains all the information needed
to create and appropriately initialize a new core DB.

The core database is created by running a minimal DB on a remote MOO,
opening a network connection to it, and then transferring all the
core objects to it. All property and verb changes needed to
initialize the object for the new core are made by the verbs doing
the transfer, and all absolute number references in properties are
checked and changed where appropriate. The object itself on the
source MOO is not modified, the information about any needed property
or verb initialization is taken from the object's "initcore_data"
property. After all objects are transferred to the remote MOO, the
init_for_core verbs on all objects there is run do whatever
initialization is required beyond simple property or verb changes
(such as moving things, etc.) This is quite different from the
standard LamdbaCore method, where the new core is created by deleting
all non-core objects from the MOO, renumbering the remaining core
objects, updating the object number references on #0, running
init_for_core verbs to initialize the objects, and then dumping the
database.

The DU core system also uses the object's "unique_id" property to
determine if it is in the core. Non-core objects have their
unique_id set to 0 when they are created (or they should). All core
objects have a unique_id set to a list of three elements: (1) the
unique name for the object (or the $name for objects named on #0);
(2) the core set identifier which is used to indicate whether this is
part of the basic core or a "core option" which can be optionally
included or not; and (3) date this object was transferred from a core
extraction, or 0 if it is on the source MOO. This differs from the
LamdbaCore system, which uses all objects defined as a property on #0
(i.e, as $<name>), or their parents, as the set included on the core.
In the DU system, objects which are not on #0 can be included in the
core even if they are not parents of such objects, and objects on #0
need not be included. However, in the latter case, care should be
taken that references to the corresponding $<name>'s not be in the
core objects,

The DU core system, and its associated utilities, are designed so
that if the core objects have their initcore_data property and (where
applicable) init_for_core verbs set properly, they should function
without need for further modification after being transferred to the
new core MOO. Several utility verbs are available to test the
property initialization in the initcore_data for an object, which
give warnings if there are object numbers which would be undefined on
the new core, or if there are properties with an excessive amount of
data that perhaps shouldn't be part of the core. Utilities are also
available to check the verbs for absolute object number references,
or references to $names which will not be on the new core.

The system also allows "core options", i.e., sets of objects that you
can optionally include in the core or not, depending on its intended
use. For example, teaching tools and generics could be included in a
core intended for educational use, but not included in a core
extracted for other purposes. The second string in the initcore_data
list identifies the core option that the object is associated with.
If that string matches the base core option id ("DUcore" at DU), then
the object is included on all cores regardless of which options are
selected.

Most of the verbs, properties, and utilities for the core preparation
system are on $core_utils, which is a FO which a wizard must add to
his features to extract a core database. However, verbs to corify an
object, define an object as part of a core option, or to define a new
core option set, are on $wiz. All of the user-callable verbs should
have a "help" stating what they do. "Help $core_utils" will give a
summary of the verbs on that FO. "@about $core_utils" will output
this text, and "@mailme $core_utils" will mail it.

MAKING AN OBJECT PART OF THE CORE

SETTING INITCORE_DATA. As part of making an object part of the core,
you have to put all the necessary property and verb initializations
in the object's .initcore_data property. This property should
contain text (a list of strings) giving the specifications for
changes to be made in properties or verbs in objects when they are
transferred to the new core. It can be used to specify which verbs
or properties are not to be included, property initializations, or
reprogrammed verbs. For example, a typical line would be '<property
name> = <initial value>', such as initializing a list to {}, etc.
For a DB object, it might specify that no properties defined on the
object are to be transferred except perhaps for a specified few.
This property thus serves the same function as the init_for_core verb
did in the LambdaCore system, making separate init_for_core verbs
unnecessary for most objects. See 'help initcore-data' for a
detailed description of how to set up this property. NO WIZARD
SHOULD CORIFY AN OBJECT WITHOUT UNDERSTANDING INITCORE_DATA.

TO CORIFY AN OBJECT. The objects which are included in the core are
specified using the @corify or @uncorify command. The player must be
a wizard but need not have the $core_utils as a feature. For more
information on these commands, see 'help $core_utils:<verb>'.

The '@corify <object> as [$]<unique name> [<core option set>]'
command is used to make an object a part of the core (or a core
option set) which was not such previously, or to change the core
option set of an already corified object. If a core option set is
not specified, the object is part of the base core, i.e., it is part
of the core regardless of which core options are selected. The
'unique name' must be different for each core object, regardless of
whether it is in the base core or a core option. If a '$' precedes
it, it is added as a property on #0 with that name (i.e., it is
'corified' in the Lambdacore sense).

The @corify command sets the unique_id of the property to {<unique
name>,<core option set>, 0}. If the object is to be part of the base
core, the <core option set> string in the unique_id is the string at
$core_utils.core_id, which is "DUcore" at DU. The command also puts
the object number on the DB objects for the main core or the core
option set (see below), and updates any relevant properties on
$core_utils, as appropriate.

The '@uncorify <object>' command removes an object from the core, but
does not recycle it, nor does it remove it from #0 (it's $name), if
applicable. The object's core option set identifier in its unique_id
(the second element) is set to "", and its object number is removed
from the DB for the core option set it was on.

The @corify command checks the properties as processed by the
initcore_data on the object and gives warning messages for any object
numbers in the properties which may not be defined when the object is
transferred to a new core. It also checks all verbs in the object
for absolute object number of $name references which may not be on
the new core.

The @check-for-core command can be used to re-check the property
initialization or verbs in an object that is already corified. This
is useful if @corify indicated problems which had to be fixed, or to
periodically check objects which have been modified.

NOTE: If you get a traceback running @corify or @check-for-core, run
'@list-core-objects' and try again. If that fails, try
@search-core-objects (which takes longer). These commands are
necessary to assure that the data bases used by the core checking
system are up-to-date. They are described below.

The @core-id command can be used to identify whether a particular
object is a core object or part of a core option set (see below), and
to determine if it can be referenced by a $<name>. It is also useful
for getting the object number of a core object given its "core id
name", which is the name in its unique_id[1].

CORE OPTION SETS

A core option set is a group of objects which are not essential to
the core but can be included as options. Each core option set
(including the base core set) has a database object defining the
object numbers in that in its properties, and also containing text
describing it. To use core option sets, one must (1) use
@create-core-option to create the core option set database and input
its descriptive text, and then (2) use @corify to identify which
objects are on that set. An object can be taken off the set by using
@uncorify, or using @corify to assign it to another option set or the
base core.

Note that the processing of the initialization assignments in the
.initcore_data property can allow for properties to be initialized or
transferred differently depending on whether a particular core option
set is selected. For example, it may be appropriate to remove verbs
on base core objects which are used only if a particular option is
selected. This can be done using the %if <option> ... %endif
construct in initcore_data. See 'help initcore'.

The @core-options command can be used to list the currently selected
and available core option sets. A 'selected' core option set is one
whose objects will be included in the next core extraction, as
discussed later.

CREATING A CORE OPTION SET. To create a new option set, use the
command '@create-core-option <name>', where <name> is the name of the
option set. Each core option has a unique name, which must be
different from the unique name in the unique name (unique_id[1]) of
all the other core objects, as well as from any other core option
set. The command will then do the following:

 - Create a new database for this option, as a descendent of the
Generic Core Option Database. This object is automatically added to
this new core option set (so is a useful place for putting an
init_for_core verb that may be needed to initialize the set, such as
moving members into the appropriate locations).

- Updates the properties on $core_utils which give the lists of all
available core options. By default, a newly create core option set
is not selected for use and its objects will not be included in the
next core extraction unless it was selected using the
@select-core-option command (see below).

- Prompts the user to give a short 1-line description of the set
which is output with the @core-options command which lists the
selected and available core options (see below).

- Prompts the user to give the full about_text property which
documents the option set. This is the text which is output with
@about <option DB> or @mailme <option DB>. You should have prepared
this documentation text before you run @create-core-option so you'll
be ready to paste it in when prompted.

An @abort at the prompts for the short_description or about_text will
terminate the command, but the option set will be fully created and
ready to use. However, you will need to input these properties
manually. The short_description property must be a single string,
but about_text is a list of strings. At a minimum, the
short_description property must be defined. The about_text can be
updated later as the set becomes documented.

DELETING A CORE OPTION SET. The command @delete-core-option is used
to remove a core option set from the available core options. The
user is asked if the DB is to be recycled. He/she must select 'yes'
or it won't be removed. Then the user is asked if the references to
the object are to be removed from the unique_id[2]'s of all the
objects in the set. If "yes" is selected, these are set to ""
indicating they are no longer on the core. If "no" is selected, the
name of this set is still on the objects, but since the option DB
doesn't exist, the core utilities don't recognize them as part of any
valid core option, and they can't be included on the core. If a new
core option set is created with this same name, these objects would
become part of that set. However, they won't be on the DB. The
'search-core-objects' command will fix this (see below).

SELECTING A CORE OPTION SET. The command @select-core-option <name>
selects an option set to be included in the core.
@unselect-core-option <name> unselects it. You need to have the
$core_utils as a feature to use these commands. Use of this feature
should be reserved to the person actually in charge of creating the
core database.

PREPARING AND CHECKING THE SOURCE DATABASE.

Although the @corify and @check-for-core prepare core objects and
update the core utilities database on an object-by-object basis,
before actually extracting a core it is a good idea to be sure the
core utilities and various core options databases are completely
up-to-date, and to check all the core objects. Commands to do this
are summarized below.

'@search-core-objects' and '@list-core-objects' are the basic
commands for assuring that the core utilities and core options
databases are completely consistent with the source MOO and up to
date. This must be done before transferring a core database, and
also may be necessary for the core object checking verbs used by
@corify and @check-for-core to work. @search-core-objects searches
all objects in the database, checks their unique_id's, and updates
the core databases accordingly. This takes a long time, but should
always be run shortly before starting the core DB transfer process.
'@list-core-objects takes the list of core objects from the core
option databases, and is sufficient as long as these databases are
correct. (@corify and @uncorify should keep them up to date, but if
the unique_id's of objects were changed manually, or if any core
objects were recycled, then the databases would be inaccurate, and
this can only be corrected by '@search-core-objects'.) A note named
'core-list' is also produced, giving a listing of core objects and
other relevant information.

The '@test-initcore' command should also be run (after running one of
the above) to check for problems in the selected set of core objects.
If run without any arguments, it is the same is running
@check-for-core on ALL the selected core objects. In addition to
producing output with the warning messages, it also saves the warning
messages about bad object number references in properties (but not in
verbs) on the on $core_utils.unreferenced_log which can be viewed
using the @core-logs command.

The @check-verbs' command can also be used to scan objects for
undefined object references in verbs. If an object name or core id
name is given, then only the verbs in that object are scanned, and
the results are output to the player. If no arguments are given,
then verbs in all selected core objects (objects in base core +
selected core options) are scanned, and the results go to
$core_utils.unreferenced_log, where they can be viewed by the
'@core-logs' command.

Note that the wizard has to have $core_utils as a feature to run
these commands, and all those discussed below.

CORE DB TRANSFER PROCESS

As indicated above, the core database extraction is carried out by
transferring, via a network connection, the verbs and (initialized)
properties of the core objects from the running source MOO to a
recipient MOO initially running a minimal DB. Because this is
essentially a bootstrap process starting with a minimal DB with
essentially nothing, the recipient MOO is referred to as the BootMOO
in the subsequent discussion. Once the core is transferred to the
BootMOO, it will be referred to as the Core MOO.

To do the transfer process, the wizard must have $core_utils as a
feature. If you wish to use your programmer character for the
transfer process (which is time-consuming), use @add-owner <name> for
$core_utils, then add $core_utils as a feature of that character.
Then your character can add this feature, and use do the transfer
commands.

SETTING UP MINIMAL DB The starting point in the core transfer
process is to set up and run a minimal DB MOO at a site which can be
reached by the source MOO via a network connection. The server
should use all the extensions and features as the server running the
source MOO. Note that a special minimal DB must be used - where the
only object is #0, and the only verbs are an empty #0:eval and a
#0:do_login_command whose verb code consists only of "return #0;".
Such a minimal DB is on $core_utils.minimal_db, and can be e-mailed
using '@mailme minimal on $core_utils'. Once the minimal DB is
copied to the appropriate site, the BootMOO can be run by using the
usual commands to start the MOO program with the input file being the
minimal DB. One can connect to this MOO to make sure it is working,
but all you will see is 'I couldn't understand that.' messages; no
commands work except .program.

The actual work is done by connecting to the BootMOO through a
network connection running on the source MOO. Before doing this, THE
PROPERTY $CORE_UTILS.BOOTMOO_ADDRESS MUST BE SET TO THE ADDRESS OF
THE BOOTMOO, given as a list containing a string with the address and
a number containing the port, e.g, @set $core_utils:bootmoo_address
to {"computer.site.domain",7777}.

The command 'connect-bootmoo' (in the source MOO) will connect you to
the BootMOO. If it isn't running or you gave a bad address or it is
not accessible over the network, you'll get a traceback. If
successful, everything you type will go to the bootmoo, and
everything it outputs back to you will be preceded with a string like
'#-12345: ', where object number is the connection object ("player")
at the source MOO. (This is like an un-logged-in player - you will
see it as a "dead" player on the @forked output.) WHEN IN THIS MODE,
EVERYTHING YOU TYPE GOES TO THE BOOTMOO EXCEPT COMMANDS WHICH START
WITH '%'. However, you will see output to you from the MOO, such as
pages, etc. You will need to get out of this mode to respond.

To get out of the BootMOO connection mode without actually closing
the connection, give a single '%' (+ return) command. Use
'connect-bootmoo' to resume the connection where you left off.

Additional BootMOO commands, in the order you'd normally give them,
are as follows. (They are shown in caps for emphasis, but case
doesn't matter.)

  %BOOT ... This boots a brand-new minimal DB by programming all the
verbs on #0 needed to do the transfer. You must give this command
first, and then not again. The commands sent to the minimal DB to
bootstrap it is on the property $core_utils.bootcode. No
'handshaking' is done; you'll know its done when you stop seeing
output - the last message output is "Ok. #0 (System
):boot_inits_for_core programmed.".

  %INITIALIZE ... Creates and initializes all the selected core
objects on the BootMOO, but doesn't transfer any verbs or properties.
If any objects have been created or transferred before, they are
deleted. Use this right after %boot, or if you want to start fresh.
This may take 2-3 minutes. The message 'Finished with
initialization' will indicate it is finished.

  %TRANSFER, %TRANSFER_ALL, %TRANSFER <object id> ... Starts
transferring properties and verbs for either the next untransferred
core object, all untransferred core objects, or the core object whose
unique_id[1] is the given <object id>. Note that this spams the user
continuously with messages indicate when each property or verb has
been transferred. (For this reason, it is best run using a secondary
character so the wizard can do other work through a different
connection while this is going on.) Transferring a large object such
as $player may take about a half an hour or so. '%transfer_all may
take perhaps half a day. This process can take many hours to
complete, though it can be aborted. The 'stop_transfer' command
given by another $core_utils feature owner will stop a %transfer_all
after the current object is completed. (That's why it's useful to
use a secondary character to run this command.) NOTE: do not
transfer objects out of order. The parent should be transferred
before any of its descendants. Refer to the <object id> only to
re-transfer an object that was transferred before, but somehow failed
or needs to be done again.

  %UPDATE, %UPDATE_ALL ... Transfers all properties and verbs on the
next (or all) core object which either hasn't been transferred, or
whose last_modified property has changed on the source MOO since it
was transferred. Essentially operates the same as %transfer or
%transfer_all except that the latter doesn't transfer objects which
have been transferred before but may have changed.
 
  %GET_NEW_NUMBER ... Gets from the BootMOO the number of objects
which have been transferred and need to be transferred. This
information is displayed using the @core-logs command. Useful if the
logs were cleared using @clear-core-logs. This is not normally
needed, since this is updated automatically anytime %transfer or
%update is run.

  %FINISH_UP ... Completes the MOO initialization process and runs
the init_for_core verbs on all objects. First checks to be sure
everything has been transferred, and gives an error message if not.
This should usually be run again if any objects have been updated
(using %update), unless you know that the transferred objects don't
have an init_for_core verb, or aren't modified by any other object's
init_for_core. After this is run, the MOO is ready for normal
logins.

  % ... As indicated above, allows the user to suspend the network
connection so he can interact with the source MOO normally.
'Connect-bootmoo' will resume the connection mode to the existing
connection.

  %QUIT ... Closes the network connection ends the connection mode.
The BootMOO or core MOO is still running. 'Connect-bootmoo' will
start a new connection, and the user will have to either do the
minimal DB login (if %boot but not %finish_up has been run) or the
system core login (if %finish_up has run) to resume the transfer or
shut down the MOO - see below.

  %CLOSE ... Shuts down the BootMOO or Core MOO and closes the
network connection. The partially or completely transferred database
is saved in the output DB.

After the verbs on #0 have been transferred, you may get the message
'property not found' after each command. This is due to the
#0:do_command verb, and does no harm in this process, and can be
ignored.

If someone connects to the BootMOO in the state it is in between
running %boot and %finish_up, the 'welcome screen' will be something
like:
      Not logged in.
      Your ID = #-3
      Max Object = #184
To log in, give the command 'minimal DB login'. Anything else will
just result in this output being repeated. Note that when you log in
this way, the player is the system object (#0), and you do not have
access to the normal player commands even if $player may have been
transferred.

If you have run %finish_up, normally you would be finished with the
core creation process. However, if you need to update some objects
(such as may have initialization problems) AND NOTHING HAS BEEN DONE
TO THE SOURCE MOO THAT YOU DON'T MIND OVER-WRITING with fresh core
objects and re-initialization, you can connect again as the system
object by giving the command 'system <core id> login', where <core
id> is the name on $core_utils.core_id, which is also the
unique_id[2] of all the base (non-optional) core objects. For
example, for the DUcore the command would be 'system DUcore login'.
(Alternately, if the property $login.system_password is nonblank,
then the login should be system <password>', where <password> is the
password stored (in crypted form) on that property. Normally, that
property should be set as blank in $login.initcore_data to simplify
system logins for a new core, but it should be set to "impossible
password to type" once the MOO is customized.) Note that this will
fail if #0 is not a player (see below). Once you have done that, you
can run %update, %finish_up and even %initialize and %transfer_all
again.

INVALID OBJECTS. If a transferred property has an object number
which does not exist on the new core MOO, a message will be output
during the transfer (and in the logs) saying so. A 'placeholder'
object is created at the new Core MOO for this unreferenced object,
and the object number in the property becomes the object number of
the placeholder. The placeholders are all descendants of a 'Generic
Undefined Object Number Reference' object,
(unique_id[1]="undefined"), and thus can be located in this way. The
placeholder's name contains the name of the object it represents and
its description contains its object number at the source MOO, but
none of its properties or verbs are transferred. Any objects with
properties referencing such invalid objects should have their
initcore_data edited ON THE SOURCE MOO to eliminate them, and be
re-transferred.

CHECKING STATUS. The '@core-logs' command can be used to check the
status of a transfer and determine if any invalid object number
references were encountered, or if any transfer attempts failed, and
how much is left to transfer. (It is also useful for checking core
objects, as discussed above.) the '@clear-core-logs command resets
it. The number of objects transferred or needing to be transferred
is updated during the next %transfer or %update command.

A wizard other than the one running the transfer can check on the
status of the transfer process using the @check-transfer' command.
This indicates which object, property, or verb was the last
processed.

DEALING WITH PROBLEMS. The transfer process has an elementary form
of handshaking' where the transfer verbs wait for output from the
BootMOO starting with "Ok" or "Error" to indicate the status of data
sent to it. If no such output is received, the process hangs up.
The @abort-bootmoo' command can then be used to simulate receipt of
an Error" record from the BootMOO, and end the hang-up.

The @stop-transfer' command can be used if you want to stop a long
multi-object transfer. The transfer of the object currently being
processed is completed, but the next object is not transferred.

You must exit from the connect-bootmoo mode (using %") before giving
these commands, or (if the transfer is being done by a secondary
character), the separate wizard character may give them.

COMPLETING THE CORE MOO

Once the transfer is complete and %finish_up has been successfully
run, you can log in as #2 and complete the core preparation as a
normal wizard. In the core MOO, #2 is 'Owner', and its password is
blank (""), so to log in as #2 give the command 'connect owner' at
the login screen.

Check the new MOO for problems. If there is a problem with an object
FIX IT ON THE SOURCE MOO AND TRANSFER IT AGAIN; DON'T FIX IT ON THE
CORE MOO. For example, if properties are not being initialized
property and have object numbers of non-core objects, fix the
initcore_data on the source MOO, check it with @check-for-core, and
(if it checks ok) transfer it again.

Once the core MOO is transferred and verified, the final task is to
remove the bootstrap verbs from #0, and remove the its wizard and
player status. This is done by logging in as a wizard and doing the
@disable-system-login' command. Make sure the transfer is completed
OK and all errors have been corrected before doing this, because the
system login is necessary to do the core transfer, and it is
difficult to re-enable this. Messages output after
@disable-system-login is complete give the steps involved.

UPDATING THE CORE MOO AFTER IT HAS BEEN CUSTOMIZED

The core objects in the new MOO can be updated after it has been
customized, provided that changes have not been made to them that are
necessary for the desired customizations. LOGINS AS THE SYSTEM
OBJECT SHOULD NOT BE USED FOR THIS PURPOSE, since this process may
cause loss of custom information. Instead, a separate process, using
logins as a special player object designated system-updater (and
corified as $system_updater), is used. Other than this separate
login, the update process is very similar to the core transfer
process, except that some of the commands used for core transfer are
not available to the system-updater. Since the MOO which will
receive the updates may no longer be a core MOO, it is referred to as
the "destination" MOO in the subsequent discussion.

PREPARING FOR SYSTEM UPDATES. Only persons who have wizard
characters on both the source and destination MOO can do the updates.
To do the transfer, you must be able to log in as system-updater on
the destination MOO. To do this, you must first log on the
destination MOO as your wizard character, then give the command
@system-updater'. It will tell you if some other wizard is using its
password. If so, check and make sure you're not working at
cross-purposes. Then give the command @system-updater me'. This
copies your password to that of system-updater, so you can log in as
this character using your own password. Once this is done, your
wizard character is no longer needed at the destination MOO, though
you will find it useful for testing and making any adjustments
needed.

To start the update process, log into the source MOO as either a
wizard character or a second character which is an additional owner
of $core_utils. In either case, this character must have $core_utils
as a feature.

Use @core-options' to select the core options to be transferred to
the destination MOO. The options chosen should be the same or a
supersede of those used when the core for the destination MOO was
created, and must be compatible. NOTE: If adding new core option,
make sure the existing core does not have objects whose
.initcore_data have conditional input which depends on whether that
is an option. If it does, any core object with such input must be
re-transferred. However, the system doesn't know when that is
necessary, so you will have to %transfer (not %update) them by name.
All custom properties on those objects would be lost. It is not
recommended that core options involving conditionals on base core
objects be added to an existing MOO.

Note also that system-updater does not run init_for_core verbs, even
for newly transferred objects. If it is absolutely essential that
init_for_core be run for a new object, or re-run for a modified one,
then the wizard character (not system-updater) must do it manually.
However, the %finish_up' command used by system-updater does run
init_after_transfer' verbs on the core objects, so if initialization
is required (which does not involve loss of custom information), such
a verb can be created on the object for this purpose. (For example,
normally core objects are owned by either $owner or $hacker, so for
$system_updater to be owned by itself, a
$system_updater:init_after_transfer verb was created has the
necessary call to $wiz_utils:grant.)

Once the desired core options are chosen, run@search-core-objects' to
make sure the core-database in $core_utils are up-to-date.

UPDATING PROCESS. At the source MOO, give the connect-bootmoo'
command to log in, just as in a core transfer. But at the welcome
screen, do connect system-updater <password>', where <password> is
your own wizard password at the destination MOO. System-updater's
confunc causes @search-core-objects' to be automatically run, and no
commands can be given until this is finished. This is necessary so
the updater can be confident that the properties in $core_utils which
list the core objects at the destination MOO are up-to-date and
complete. Thus, if the destination MOO is large, the confunc may
take a while to complete. Once it is complete, system-updater is
connected to $player_start, and can give the update commands,
described below. Unlike the system object logins, system-updater can
also give all the player and room commands available to any
programmer. Although the system-updater is not a wizard as such, it
has access to verbs which can change any object. Because of this,
only wizards should use this character, and all connected wizards are
notified when system-updater logs on and off.

It is best but not essential that the destination MOO not be occupied
by too many other players when the update is being done. BUT SEE
WARNINGS BELOW. To avoid other players (or the system) sending
output to system-updater which may be mixed with data being sent to
the source MOO, system-updater's notify() verb gags all players but
itself. This can be changed by giving the command @set me.gagall to
0', but this is not recommended. Gagging is turned back on again
when system-updater logs on.

Once system-updater is logged into the destination MOO through
running connect-bootmoo at the source MOO, much of the same commands
as given in the core transfer process can be given. However, in some
cases, the commands operate slightly differently. These are as
follows:

    %UPDATE, %UPDATE_ALL. If given without an argument, one or
    all of the core objects which have changed (as indicated by their
    .last_Modified property), or which have been newly created, are
    updated. This involves transferring all their verbs and
    non-initialized properties. Unlike %UPDATE when logged in as
    system, properties which are initialized in the object's
    .initcore_data property (except for "name" and "alias") are not
    transferred. These properties are assumed to be customized on
    the destination MOO, so updating them would not be desired. If
    %UPDATE is given with an object id (it's unique_id[1]), that
    object is updated regardless of it's last_modified property.

   %TRANSFER, %TRANSFER_ALL. If given without an argument, one
    or all of the core objects which have been newly created are
    updated. If given with an object id, the object is updated
    regardless. In this case, properties which are initialized in
    the object's .initcore_data are also transferred. THEREFORE, DO
    NOT USE THIS NAMING EXISTING OBJECTS ON THE DESTINATION MOO WHICH
    HAVE CUSTOM PROPERTIES you want to preserve. However, this must
    be used (with the object named) to re-transfer any core-object
    whose .initcore_data have conditional statements involving core
    options which have been added since the core was created.
    Specifying %transfer' without a name is safe, since this would
    affect only objects which are newly created, i.e., core objects
    which did not exist when the core was originally created.

   %FINISH_UP. This should be done after all objects are
    updated. The system will check to make sure all newly created
    objects have been transferred, but not whether all updates have
    been completed. (To make sure all updates are completed, give
    either %update_all or %update without an object id. If nothing
    is transferred, then everything should be updated.) This runs
    init_after_transfer verbs on all core objects, and makes sure #0
    is set up OK for normal logins. Note this is different from when
    %finish_up is run during a core transfer, where init_for_core is
    run for all objects. Since running init_for_core verbs can
    result in loss of custom information, they should not be run in
    MOOs which have already been customized.

   %QUIT, %, %GET_NEW_NUMBERS. These operate exactly the same
    way as for core transfers. The first closes the connection, the
    second temporarily suspends connect-bootmoo without closing the
    connection, and the third updates the database on the source MOO
    concerning objects on the destination without transferring
    anything. See above for details.

    %CLOSE. This operates like %QUIT. System-updater cannot
    shut down the destination MOO.

    %BOOT, %INITIALIZE. These commands, which are available
    during the core transfer using the system login, SHOULD NEVER BE
    USED WHEN DOING A TRANSFER AS SYSTEM-UPDATER. To protect the
    database against the effects of these destructive commands,
    system-updater is immediately booted if they are given.

The normal process after connection is to do "%transfer_all" to
assure that all new objects are transferred, then "%update_all" to
assure that everything else is updated. If any objects need to be
specifically transferred and re-initialized, then %transfer <object
id> should be used. Finally run "%finish_up" to do any
re-initializations that may be required, and then %quit to log out.

Although the updates can be done when both the destination as well as
the source MOO are running normally, IT IS STRONGLY RECOMMENDED THAT
THE DESTINATION MOO DATABASE BE SAVED IMMEDIATELY BEFORE THE UPDATES,
AND THAT ORDINARY USERS EITHER NOT BE ALLOWED TO LOG IN, OR TOLD THAT
THEIR WORK MAY BE LOST. After the update, the destination MOO should
be thoroughly tested, and if it looks like it was seriously damaged,
the saved database should be restored. It may be that certain
objects should not be updated, or may have to be appropriately
changed on the source MOO before re-transfer. Only after thorough
testing should the destination MOO be put back into normal operation.

_______________
Additional Help

$core_utils -- specific documentation of $core_utils feature object commands
initcore-data -- description of the .initcore_data property
core-options -- controlling which segments of the MOO are included in a core
unique-id -- description of the .unique_id property

core-index

$anon_webviewer$http_port$section_editormail-format
$biglist$jclient_handler$site_dbmail-receiving
$byte_quota_utils$local$standard_webviewermail-resolve
$container$login$std_vrml10viewermail-sending
$error$mail_agent$teleportermail-system
$exit$mail_browser$vspo_registrymaintenance
$feature$mail_recipient$webappMR-access
$frame_manager$manageradmin-mail-reciptsMR-naming
$generic_db$mapbiogate-setupMR-reading
$generic_editor$new_player_logbiogate-systemMR-searching
$generic_help$new_prog_logcore-extractionMR-sequences
$generic_option$newscore-indexMR-setup
$generic_options$no_onecore-optionsMR-subscribing
$gopher$object_quota_utilscreation_enabledMR-writing
$help$player_dbdiskmailobject-matching
$help_webviewer$recycleremail-permeabilityunique-id
$housekeeper$registration_dbguest-accessweb-security
$html_editor$request_boothinitcore-dataweb-system
$http_handler$roomintegrated-web-telnet

core-options

A core option set is a group of objects which are not essential to the core database but can be included as options for specific core database extractions. Each such set is identified by a unique name, and each object in the set has this name in its unique_id[2] property. See 'help unique-id', '@about $core_utils' or '@mailme $core'_utils for details.

The following commands are used to display, create, or delete core options:

  @core-options

Lists the available core options, and the ones that have been selected for inclusion in the next core extraction.

  @create-core-option <name>

Creates and names a new core option set, and creates the database object used to keep track of which objects are on it. Each core option has a unique name to identify it. This name cannot be the same as the core id name of any other core objects. (See 'help unique-id'.) The user is prompted to give a short 1-line description of the set which is output with the @core-options command, and the more extensive '@about' text to document it. You should have prepared this documentation text before you run @create-core-option so you'll be ready to paste it in when prompted.

  @delete-core-option <name>

Removes a core option set and deletes its database object. The user is asked if the references to the object are to be removed from the unique_id[2]'s of all the objects in the set. If so, these are set to "" indicating they are no longer on the core. Otherwise, the name of this set is still on the objects, but since the option DB doesn't exist, the core utilities don't recognize them as part of any valid core option.

The @corify command is used to identify objects as part of particular core options, or to change the option they are a part of. See 'help @corify'. The @uncorify command can be used to remove an object from any core option.

creation_enabled

If the MOO has "new user creation enabled" then people can create a
character for themselves right from the welcome screen. Most MOO
admnistrators will want to leave this disabled, and have people
connect as guests and use the @request command to submit an
application.

However, the system may be enabled by entering:
  @set $login.create_enabled to 1
The system can be disabled with: @set $login.create_enabled to 0

If the creation system is disabled, then people using the `create'
command at the welcome screen will see the message set with:
  @set $login.registration_string "Put your message here."

diskmail

  The default eduCore used an in-DB MOOmail system, such that mail
folders and characters' mail is stored on the MOO objects as
properties. The eduCore can optionally use a "disk-mail" system,
which stores the actual messages as files outside the MOO database
itself. The disk-mail system uses the BioMOO File Utilities Package
(FUP), which has to have been installed when the MOO server was
compiled.
  To set up the MOO to use disk-mail, you should first prepare the
file structure on the system where the MOO is running. There must be
a directory called "files" in the directory from which the MOO is
run. Inside the "files" directory should be another named "mail"
that will hold the disk-mail. Both the "files" and the "mail"
directory must be readable and writable by the user under whose
permissions the server is running. To summarize the file structure:
  moo/moo.db
  moo/files/
  moo/files/mail/
Once the file structure is set up, you can test the FUP system with:
  ;filelist("")
and you should see something like:
  => {{}, {"mail"}}
where the first bracket (here empty) lists the files in the "files"
directory, and the second lists the subdirectories. If instead you
see "Line 1: Unknown built-in function: filelist" then FUP is either
not installed or not functioning. Once you've confirmed that FUP
is installed and functioning, you can direct the MOO to use disk-mail
as follows:
  1. Change the default mail-folder agent with:
      @set $mail_recipient.mail_agent to $disk_mail_agent
  2. Change the default user character agent with:
      @set $player.mail_agent to $disk_mail_agent
If all the the user characters and mail-folders have clear
.mail_agent properties, then you are all done. If some have
.mail_agent explicitly set to $mail_agent, you'll have to either
change that value or just clear it. To clear all the mail-folder and
character agents, you can use (all one line):
  ;for o in ({@$object_utils:descendents($player),@$object_utils:descendents($mail_recipient)}) clear_property(o,"mail_agent") endfor

WHAT TO DO WHEN THERE ARE TOO MANY FILES TO RESYNC

When there are a *lot* of messages, and therefore a lot of files, the MOO can sometimes run out of seconds just trying to get a list of them. This typically happens when the mail folder resynchronizes itself to generate a file listing, or is expunging deleted messages. When this happens, you should either, 1. archive the mail folder and start a new one, or 2. tell the person with all those messages to @netforward and delete some.

However, if you need to just get the synchronization done, or if it is a long-term archive to which new messages are no longer being posted, you can create a "hard" directory list that the disk-mail system will use if it's there. This listing won't be updated if new messages are posted or messages are deleted, so it is only good as a temporary measure or for an archive.

To create a "hard" directory listing:

1. Log onto the server on which the MOO is running, and "cd" to the "files" subdirectory of the directory in which the MOO database is run from (e.g. cd "~du/moo/files/mail").
2. Change to the directory for the problematic mail recipient. For instance, if the problem was *general (#1017), you would "cd #1017" to do this.
3. Type "ls > .file.list" to make a "hard" directory list
4. Force the MOO's mail folder to resynchronize. For instance, you could type "@mail on *general" for resync *general. If you are creating a permanent "hard" directory for an archive, you're done. Otherwise, go on.
5. Wait for the resynchronization is compelte. In the example here, that would be demonstrated when the MOO showed you the list of messages on *general.
6. Remove the temporary file by typing "rm .file.list" on the server.
7. Back up to the mail subdirectory ("cd ..") and repeat the process with all mail recipients that are unable to resynchronize or expunge themselves without running out of time.

When someone gets a chance, they should write a "help $disk_mail_agent" text, to explain in detail how the system works.

email-permeability

The Internet Email Permeability System for MOO was developed by
Diversity University for SRI International. It consists of a set of
new MOO objects, modifications of existing MOO objects, and server
sendmail.conf changes. The system allows MOO users and mail folders
to receive email from and send email to the Internet, with the MOO
serving as the user interface. It provides these functions by
allowing the use of Internet email addresses where ever MOO character
names are typically used within the MOOmail system.

All MOOmail commands that accept a MOO character name or mail folder
as the recipient may be given an Internet email address instead. For
instance, just as users can "@send Jane" to send a internal MOOmail
message to the character named Jane, they can "@send
johnd@outside.net" to send an Internet email message to the person at
the "johnd@outside.net" address.

Similarly, people outside the MOO can send email to specific
characters within the MOO, and that mail will be accepted by the
Email Permeability System and presented to that character as MOOmail.
The outside person would typically send to "jane@moomail.oursite.edu"
in order to send a message to the character named "Jane" at the MOO
running at the "oursite.edu" site. The specific format of the
address depends on how the sendmail.conf file has been modified on
the UNIX system where the MOO's mail is received. The
$network.inet_mail_host property carries the correct site to use for
addressing Internet email to MOO characters and mail folders.

Finally, MOO mail folders may also receive email from the Internet,
typically with something like "announcements-list@moomail.oursite.edu"
being the format to send Internet email to the *announcements mail
folder (the "-list" appended to the name indicates a mail folder).
This function, together with the ability of mail folders to send
Internet email directly, allows mail folders to serve as the in-MOO
proxy for an outside email list. For instance, a mail folder that
was subscribed to an outside email list, and also forwarded messages
to that list, would function in that way. Any users who subscribed
to the in-MOO mail folder would essentially be subscribing to that
external email list, and mail sent to the MOO mail folder would be
forwarded to that external list.

For Administrators:

Note that #0.mail_agent ($mail_agent) must be set to the
$inet_mail_agent for the Email Permeability system to function. Any
$mail_recipients in the old $mail_agent should be moved to the new
one.

Access to email permeability functions may be restricted or provided
to all MOO users and mail folders. This is controlled by an
"inet_mail" property found on $player and on $mail_recipient. It is
a LIST, which may contain any or none of "can_receive" indicating the
object may receive incoming Internet email, and "can_send" indicating
it can send mail to Internet addresses.

The @email-access command on $wizard is provided to set this
property, which can be set directly on $player or $mail_folder for
broadly enabling the email permeability functions.

The $network.inet_mail_host property (a STR) must be set in order to
enable outgoing email to have a proper "reply-to" address. This
property should be the Internet site where mail to a MOO character or
mail folder is to be sent (i.e. the MOO's outside maildrop). There
must, of course, be a $popmail_MOOagent that will retrieve the mail
from that site, and the specified site should have its sendmail.conf
modified to accept mail for the MOO. This property is also used to
create the "postmaster@site" address for email the MOO bounces for
some reason.

See `help $popmail_MOOagent' and `help $pop3_utils' for information
about properties on those objects that must be set to enable the MOO
to retrieve its mail from the outside mail drop site.

For Programmers:

Additional detailed information about each part of the system is
available on the appropriate MOO objects. The specific objects,
properties, and verbs that are unique to the Internet Email
Permeability System are:

$core_help.email-permeability
POP3 email utilities ($pop3_utils)
Internet Forwarding Mail Recipient ($inet_mail_recipient)
POP3 email to MOO agent ($popmail_MOOagent)
Internet Email Mail Agent ($inet_mail_agent)
Core Help ($core_help)
  .email-permeability
Wizard Help ($wiz_help)
  .@email-access
generic player ($player)
  .inet_mail
Generic Mail Recipient ($mail_recipient)
  .inet_mail
Network Utilities ($network)
  .inet_mail_host

Outside the MOO, the sendmail.conf of the MOO's mail-drop must be modified.

In addition, the following existing verbs and properties were
modified to support email permeability:

System Object ($sys)
  .mail_agent

generic player ($player)
  :notify_mail
  :@nn

Generic Mail Recipient ($mail_recipient)
  :is_usable_by

Mail Room ($mail_editor)
  :parse_invoke
  :parse_recipients
  :parse_msg_headers

Network Utilities ($network)
  .initcore_data
  :return_address_for
  :invalid_email_address

General Help Database ($help)
  .mail
  .@send

guest-access

Guest access and abilities can be regulated in many ways.

Commands:

@banish -- boot a guest off and save the collected @witness log
@guests -- lists all connected @guests and their origin site
@request -- what guests use to request characters (moves them to the $request_booth)
@make-guest -- make a new guest character, adding to the available set
@blacklist -- restrict guest access from an internet site

Significant properties:

$guest.domain_login_threshold
    The maximum number of guests that can connect from a single
    domain. Useful for preventing "mobbing" of the MOO by guests from
    one site. (NUM)
$guest.default_gender
    The default gender for guests. (STR)
$guest.default_description
    The default description for guests. (LIST)
guest.extra_confunc_msg
    A message displayed to all guests when they connect. (STR)
$guest.toomany_message
    Displayed when all the guests characters are taken and someone
    tries to connect as a guest. (STR)
$guest.default_drawing_mode
    Are guests shown ASCII art drawings by default. (BOOL)
$guest.default_user_options
    The default value for $guest.user_options. (LIST)
$guest.huh_help
     If 1, give guests some hints if they type in something the MOO
    doesn't understand. (BOOL)

Additional topics:

guest-banishing -- about using the @banish command
$request_booth -- the place people who @request are moved, and
                        the object that presents an application for
                        them to fill out. It has many settings that
                        should be customized for the MOO.
creation_enabled -- for allowing people to make characters for
                        themselves right from the welcome screen
                        (rarely useful).
access-restrictions -- a summary of access restriction commands
                        relevent for all character types

initcore-data

Initcore_data: Property initialization for core db extractions.

The DU core extraction system uses the .initcore_data property on each object to give property and verb initialization information necessary for the object to operate properly in a newly extracted core. This property should contain text (a list of strings) giving the specifications for changes to be made in properties or verbs in objects when they are transferred to the new core. It can be used to specify which verbs or properties are not to be included, property initializations, or reprogrammed verbs. For example, a typical line would be '<property name> = <initial value>', such as initializing a list to {}, etc. For a DB object, it might specify that no properties defined on the object are to be transferred except perhaps for a specified few. This property thus serves the same function as the init_for_core verb did in the LambdaCore system, making separate init_for_core verbs unnecessary for most objects.

The following are valid inputs in an .initcore_data property:

<name> = <value> ............... Initializes a property. <value> must be a
                                  string which is decodable as a value in an
                                  eval. It should NOT contain absolute
                                  object numbers.
% <comments> ................... to add comments which are ignored.
%delprop <property to delete> .. to delete or clear a property.
%delverb <verb to delete> ...... to delete a verb. The verb must be
                                  identified by its name + all aliases as
                                  given in verbs().
%verbcode <verb to re-program> .. to change verb code. The verb must be
<verb code> identified by its name + all aliases
%end as given in verbs().
%noverbs ....................... to delete all verbs defined on the object.
%clearprops .................... to clear or delete all properties except
                                  those listed, builtin properties,
                                  unique_id, last_modified, creation_date,
                                  and initcore_data.
%noprops ....................... Delete all properties defined on the
                                  object except those whose values are given
                                  explicitly. (Inherited properties are not
                                  cleared.)
%saveprop <property to save> ... (used in conjunction with %noprops) Do not
                                  delete this property.
%saveverb <verb to save> ....... (Used in conjunction with %noverbs) Do not
                                  delete this verb.
%nocopydb ...................... Don't copy any properties whose name start
                                  with a blank.
%if [!|-]<option> ............... following code to '%endif' is to be used
                                  if the indicated core option is (or isn't)
                                  selected.
%endif .......................... ends '%if' block.

The command '@check-for-core <object>' can be used to determine if the object has problems with property initialization, and if there are errors in the object's .initcore_data property. If there is output saying **new** or that something is set to a different object number, it means that there are absolute object number references in the object. This almost always means that the property involved needs to be initialized in the .initcore_data text.

integrated-web-telnet

The integrated web/telnet system uses frames to divide the user's web
browser window into sections, and has the browser load different
functional units of the system into different frames. At a minimum,
frames are used for displaying an HTML document (in the web frame)
and a Java-based Telnet applet (in the live interaction frame, aka
telnet frame).

This text describes the system that builds and manages the integrated
interface display. See the BioGate System installation instructions
for instructions on setup.

The trajectory of the web transaction that creates the user display
is as follows:

<http_port>:do_login_command -> $http_handler:handle_http10
 :handle_http10 checks if the transaction is an authentication
request (empty URI with a form submitted), and if it is then looks,
using a call to $http_handler:preprocess_URL, to see if there is an
"integrated_web_interface" form entry (the value is ignored. This
may be present because the name of the SUBMIT button for the
integrated interface on the web Gateway page is
"integrated_web_interface" so if the user selects that button then a
form entry with that name will be included. If they select the
button for an independent web window (usually named
"independent_web_window") then that would be the form entry included
instead).

  If the integrated web interface has been selected, the
authentication is set to $no_one (anonymous), the URI is set to
"/frame_mgr/0/frameset" and the transaction continues based on the
new value.

 -> $http_handler:process -> $frame_manager:method_post
   -> $frame_manager:make_frameset
The :make_frameset verb builds the HTML page including the <FRAMESET>
tags, defining the frames layout. It checks the submitted form for
an entry named "client" and uses the value (a number) to determine
the object number of the $jclient_handler to use. It also identifies
an "interaction_frame_height" that is the percentage of the browser
window taken up by the interaction frame, and any @weboption settings
to be initialized after the user connects.

   The :make_frameset verb then calls the
<jclient_handler>:preload_page to retrieve the URL for the HTML doc
displayed in the web frame until the telnet client connects and sends
its first "display url" command. The :preload_page verb checks the
<jclient_handler>.default_preload_page property. If it's a STR then
it is assumed to be a URL for the preload page, else if it is a LIST
it is assumed to be the text of

  The :make_frameset verb specifies a URL for the interaction frame
that includes the form data as a "method GET"-encoded form (appended
to the URL after a "?"). This URL will cause the browser to retrieve
a web page generated by $frame_manager:get_jclient_html the HTML page
itself, in a separate transaction initiated automatically by the web
browser when it seeks to fill the frames..
  The :get_jclient_html verb calls <jclient_handler>:make_applet_html
to retrieve the HTML text to be loaded into the "interaction frame"
that contains the Java Telnet applet itself. This text typically
contains the <APPLET> section that loads the applet. The
:make_applet_html verb extracts various applet settings from the
submitted form, which are specific to the applet it handles. If the
applet is capable of issuing a command upon connection tot he MOO,
the :make_applet_html verb can use the user_name and password fields
to issue a "preapproved <username> <password>" line that will
automatically connect to the correct user. The password is a
temporary password valid for only a few minutes after its generation,
and issued specifically to allow the applet to automatically connect
without giving away the user's true connect password.

  To summarize, the presence of field named "integrated_web_system"
in the submitted Gateway form leads to a <FRAMESET> page being
issued. The web frame contents are determined by
<jclient_handler>:preload_page and the interaction frame's contents
are determined by <jclient_handler>make_applet_html. Once the telnet
applet connects, it is expected to issue an MCP "display-url"
directive that replaces the top frame's contents with a view of the
room the newly connected character is in.

mail-format

Mail Transmission Format
------------------------
There is a standard message format used for transmitting messages. This is the format that $mail_editor:make_message produces, and that :receive_message verbs on characters and $mail_recipients expect to see. The (currently experimental) @refile and @copym commands also use this format to transfer messages.

This *transmission* format is distinct from the *storage* format, though, for convenience this same format is often used as well for storing messages in users' collections and ordinary $mail_recipient children though, in general, there is no requirement that this be the case.

A transmitted message is a list in the following form

   date (number),
     the time() value at the time the message was sent.
   from (string),
     the sending object (address list form)
     if this is not a character, an additional header will indicate the
     current ownership of the object.
   to (string),
     recipients (address list form) which can either be characters
     or $mail_recipient descendents.
   subject (string),
     subject of the message, or " " if there is no subject,
  @additional optional headers (list of strings),
     each header has the form "<header-name>: text" where <header-name>:
     is padded out to a width of 10 columns for the convenience of
     :display_message. Currently "Reply-to: <address list>" is the only
     additional header in use,
   "",
  @body of message (list of strings)

Note that the from, to and subject lines do *not* include a header name like "From:", "To:", or "Subject:". The @'s indicate that the lists in question get spliced in (as usual), thus the entire message is a list whose first element is a number and the rest are strings.

The address lists that appear in the from and to lines is a string in the form a sequence of object ids, each enclosed in parentheses and preceded by optional text, e.g.,

  "*Core-DB-Issues (#8175), Rog (#4292), and Haakon (#2)"

The text is intended to give the current name of each object for the benefit of human readers, but is actually ignored by all header parsing routines. The convention is that the text is either a character name or a * followed by a mailing list name.

mail-receiving

Receiving Mail
--------------
By definition a recipient "receives" a mail message when its :receive_message verb is called with that message as an argument.

:new_message_num()
=> number that will be assigned to the next incoming message.
By default this returns the maximum of the message numbers appearing in
messages or .messages_going, incremented by 1. If the recipient is a character
then the value returned will be 1 higher if it conflicts with the person's
current message number for him/herself.

:receive_message(msg,sender)
By default this first calls this:new_message_num to obtain a message number to assign to the incoming message and then appends {num,msg} to this.messages.
`sender', the original sender, is supplied in case one wants different
action depending on who is sending the message (e.g., mail-gagging).
The return value should be an error or string if :receive_message is considered to have failed in some way. Otherwise, a number should be returned - this number is given to any :notify_mail routines that are called and is expected to either be 0 or the number assigned to the incoming message.

Note that :receive_message can do arbitrary things, including resending the same message to a new destination. Hacking :receive_message to resend messages is different from using .mail_forward in the following respects
  (1) the resent message is considered to be a distinct message having this
      object as its "author" - i.e., the From: line will necessarily be
      different.
  (2) since this "forwarding" is invisible to the mailsystem,
      there is no protection against loops and multiple copies.

mail-resolve

Resolving Mail Forwarding & Notification
----------------------------------------
For each recipient of a given mail message, the following two verbs are called to determine where the message should actually go and who should be notified about it:

:mail_forward([from])
    should return either
     . a list of objects (either characters or $mail_recipients)
         to which mail for this recipient will be redirected.
     . a string error message to be printed to the person sending the message.
         If this recipient is one of the original destinations (i.e., not the
         result of a previous forwarding), no mail is actually sent.

    If :mail_forward returns a nonempty list, the recipient itself will *not*
    actually receive the mail message unless it is included in the list.
    #-1 is allowed to be on the list; it is ignored but does make the list
    nonempty. Thus, having :mail_forward() return {#-1} is the canonical way
    to have arriving mail disappear without being kept or forwarded.

:mail_notify([from])
    should return a list of objects that are to be told about any mail sent
    to this recipient (whether or not the recipient actually receives it).
    Said objects must have a :notify_mail verb, but other from that, there
    is no restriction on what these can be.

    object:notify_mail is called with the arguments
    (sender,recipients,msgnumbers) where
      recipients == list of recipients including object in .mail_notify
      msgsnumbers == corresponding list of :receive_message return values
                 (or 0 if :receive_message is not actually called, which
                  will be the case if the recipient forwards without keeping)

When called as part of a mail send, the `from' argument is the immediate predecessor on the forwarding chain. The default versions of these verbs return the values of .mail_forward and .mail_notify respectively (pronoun_subbing if the value is a string), unless this is a moderated mailing list and `from' is an unapproved sender (see `help MR-access') in which case the following verbs are called instead:

:moderator_forward(from)
    what :mail_forward should return for mail coming from unapproved senders
    This returns .moderator_forward (pronoun_subbed if a string) by default.

:moderator_notify(from)
    what :mail_notify should return for mail coming from unapproved senders
    This returns .moderator_notify (pronoun_subbed if a string) by default.

Since the :mail_forward verbs only see the previous sender in the forwarding chain, if, e.g, B is moderated but A can send to B (i.e., B:mail_forward(A) returns an actual list), then any mail sent to A goes to B even if the original sender isn't normally allowed to send to B directly.

These verbs should all allow `from' to be omitted in which case they should return as if `from' were a generic approved sender (e.g., wizard).

It should rarely be necessary to actually modify any of :*_forward/*_notify verbs, since one has a fair amount of control over their behavior via the following properties

  .mail_forward
  .mail_notify
  .moderated (see `help MR-access')
  .moderator_forward
  .moderator_notify

mail-sending

Sending Mail
------------
$mail_agent:send_message(from,recipients,headers,body)
  from: sender of the message
               (this must be you or something you own; otherwise => E_PERM)
  recipients: object or list of objects (must all be characters or
               $mail_recipient descendants)
  headers: either a string (contents of the Subject: line)
               or a list {subject,replytos} replytos is a list
               of objects designated to receive replies.
               Use {"",replytos} to have a Reply-to: without a Subject:

This is the canonical way to send a mail message from a program.
This calls $mail_agent:make_message to format the arguments into an actual message (see `help mail-format') and then $mail_agent:raw_send to do the actual sending which goes as follows:

  (1) Call :mail_forward on all recipients add any new recipients thus obtained to final recipient list, keep calling mail:forward on the new recipients until we obtain no additional recipients. If one of the initial recipients is invalid, is not a user character or $mail_recipient, or has its mail_forward return a string error, then we print the error message and abort at this point with no mail being sent. If one of the later recipients bombs similarly, error messages are printed, but in this case mail still goes out to the other recipients.

  (2) Call :mail_notify on all recipients encountered in stage (1) to get a list of objects to notify.

  (3) All final recipients receive the message (see `help receive-mail')
  (4) All notifications are delivered (using :notify_mail())

We return {0, @failed_recipients} if we bombed out at step 1.
Otherwise return {1, @actual_rcpts} indicating what mail was sent.

mail-system

Mail System
-----------
The following topics describe the guts of the LambdaCore mail system

mail-sending -- how to send mail from a program; what happens.
mail-forwarding -- how to do mail forwarding/notification (the simple version)
mail-resolve -- how mail forwarding/notification works, in gory detail
mail-receiving -- what :receive_message should do
mail-format -- format of transmitted messages

$mail_recipient -- generic non-user character mail recipient
$mail_agent -- mail utility object
$disk_mail_agent -- a $mail_agent for FUP-based external mail

maintenance

  There are several wizardly tasks that should be performed periodically to insure the MOO continues working efficiently.

DAILY

@forked
  Check the @forked list and become familiar with what tasks are
usually there. Sometimes tasks will hang in endless loops and the
@forked list is the only place they will appear. The task's code can
be checked, and the programmer can be contacted to insure tasks that
don't get cleared are supposed to be continuously running. Use the
@tasks command if the @forked list is long.
@memory
  Check @memory and note if the RAM or disk usage has changed
dramatically from previous values. RAM usage may not be enabled on
your server, but disk DB size should be. Large increases in size
usually indicates that either someone has created a huge object, or
that there is a running task storing some huge value.
@big-objects
  Use @big-objects to see what the largest objects in the DB are. If
you do not have byte-based quota, users may occasionally create
(accidentally or on purpose) a large object that you may wish to have
them recycle.
Checkpointing
  Use `look #0' to check the system object for the time of last
backup and to verify it succeeded. If checkpoints fail, a message is
also generally sent to *wizards. Note the amount of time the
checkpoint took to run. When checkpoints start taking unusually
long, it's typically curable by restarting the MOO (presumably there
is a memory leak responsible).
  Use `@trend-db' to note the size on disk of recent checkpoint
files. Rapid size increases (more than 5%) are an indication that
either someone has created something that uses a lot of data (in
which case it may show with `@big-objects' on the next daily
measurement) or there is a memory leak. If nothing shows with
`@big-objects' look again at the @forked list for new tasks. You may
need to check the code for any new ones to see if they are building
some variable, usually a LIST, that is growing out of control. If
none of these are the case, you may want to restart the MOO since
this typically cures server-based memory leaks.

WEEKLY

Database Backups
  Once a week, at least, someone should check the MOO's backups on
the server, to see if they are getting archived properly.

MONTHLY

Once every month or two, the MOO server should generally be shut down
and restarted, to clear out memory leaks. You should find that the
in-memory size of the MOO and the checkpoint time decrease (sometimes
up to 15%) after such a restart. If the the restart results in an
in-memory size decrease of more than 20%, there is probably a serious
memory leak and you may want to consult with people experienced in
MOO server internals.

QUARTERLY

Checking the Character Registry Database
  It's usually worthwhile to update the Character Registry Database
quarterly or so, and clear out names and addresses for recycled
characters. This is faster than the yearly @reload activity. Use
`@verify $player-db' to check the Character Registry Database for
recycled characters.
Verify Rooms without Domains
  If the MOO is using the domain system (see "help domain-system"),
has a $domain.domainless set, and uses "out" aliased exits to assign
domains, you should verify the domainless rooms periodically and
assign them to domains as appropriate. Determine the object number
for the "Domainless Rooms Domain" (@d $domain.domainless), and then
use "@verify <domain>" to have each room automaticaly evaluated.

YEARLY

Mail Folder Archiving
  When the mail folders get extremely large, they are very time
consuming to search. An effective method for keeping popular mail
folders small is to annually rename them with "-archive#" at the end,
and start a new mail folder with the original name. If you do this
for one of the mail folders that new users are automatically
subscribed to, you will want to update the $local.autosubscribe_lists
list.
Reloading the Character, Site, and Registration Databases
  The databases that store all character names ($player_db), places
they've connected from ($site_db), and all registered email addresses
($registration_db) continue to grow unless they are reloaded
periodically. Reloading them generally needs to be done every one or
two years. Since they serve an important security function, keeping
records of recent changes to critical data, they probably shouldn't
be cleared more often than annually. Use the "@reload" command on
each to reload each database (e.g. @reload $player_db).
  You should reload these databases when few or no people are
connected. Various functions, including new character creation and
connecting to characters, may be disrupted while they are reloading.
  Note that if you start running out of ticks when new characters are
created, it might be that one of these databases has grown too large
and needs to be reloaded.
Flushing the Editors
  Use "@peepeditor in <editor>" to check each of the $note_editor,
$mail_editor, $list_editor, $html_editor, and $verb_editor for
sessions that are invalid (the session belongs to a non-$player
object) or ancient (sessions older than 6-12 months, depending on
your policy). Use "@flush <editor> for <object>" to delete a stored
editing session that are invalid or ancient.

ON STARTUP
  The following tasks should initiate automatically upon startup,
and appear in the @forked list:

$byte_quota_utils:measurement_task
  Performs periodic measurement of objects' size, adjusting people's
  `size_quota' to reflect the update. Use `start $byte_quota_utils'
  if this task dies.

$wiz_utils:idle_check
  This checks if people are idle longer than the specified limits,
gives them a warning, and then disconnects them. If the task doesn't
initiate properly, you can use `@start-idlechecking on $local' to
start it.

$player_start:keep_clean
  This verb keeps the player start room clean of all but connected
players and resident objects.

$net_ncp:netwho_poll
$eDUnet:network_pollmaster
  These may be active if your MOO is part of an EduNet system.

$lag_meter:lag_cycle
  This is the $lag_meter task that measures how long after being
scheduled forked or suspended tasks are actually being run. When lag
iz zero, they run at exactly the scheduled time. If the lag_cycle
task has died or not started, you can use `@startup $lag_meter' to
initiate lag measurement.

MR-access

Controlling Access to Mail Recipients
-------------------------------------
:is_writable_by(one) - one may alter/add/remove saved messages
:is_readable_by(one) - one may read messages.
:is_usable_by(one) - one may send to this list

By default, these verbs refer to the following properties:

writers - list of people other from the owner who can do anything
readers - if == 1, indicates a public mailing list.
             list of additional readers (by default anyone who receives mail
             sent to the list can read the saved messages).
moderated - if false, indicates a normal mail recipient everyone can send to.
             otherwise this should be a list of approved senders (or
             1 if noone but the owner and wizards can send).
restricted - list of people who specifically may not send to the list

Terminology:
  A mailing list is "public" if everyone can read it.
  A mailing list is "moderated" if not everyone can send to it.

Note that while being able to write to a recipient implies being able to read from it or send to it, neither of read-ability or send-ability implies the other.

It is highly recommended that if you are creating custom mail recipients with variable reader/sender lists, i.e., you find you need to write your own :is_readable/usable/writabe_by verbs, you are best off if such verbs are of the form

  return pass(@args) || << your_test(args[1]) >>

and have .writers == .readers == {} and .moderated == 1. This will ensure
 (1) wizards having write access
     --- necessary in order for :receive_message to work
 (2) writers being able to read and send (the converse being a ludicrous
     situation),
 (3) persons on the mail_forward list of someone with reader access will also
     have read access (convenient).

The $mail_recipient was extended to allow Manager class access,
though the .manager_readers, .manager_writers, .manager_unsealed_for,
and .manager_moderators properties. These are LISTs with each
element a STR naming a property on $manager that indicates a
managerial area of responsibility. Any $manager in a listed area of
responsibility has access corresponding to the readers, writers, or
moderators abilities. The .unsealed_for indicates those managers can
read sealed msgs.

MR-naming

One may always refer to a list by its object number. In order to refer to it by name, it must be contained in $mail_agent, which holds all mailing lists, i.e., those that you want others to be able to refer to by name.

The .aliases field holds the names by which one may refer to the list, but only those names not containing spaces actually count for anything. As with certain other types of objects (e.g., character objects), set_aliases() needs to be called in order to change the .aliases field.

$mail_agent:match(name)
    is the canonical way to obtain the objectid of a mailing list
    given the name ("*" is assumed; an initial "*" will be dropped).

$mail_agent:match_recipient(name)
    is the canonical way to obtain the object id of a list or person
    matching the given name. An initial "*" indicates that this is
    supposed to be a list.

$mail_agent:match_failed(objid,name)
    is the mail_recipient counterpart to $command_utils:object_match_failed

MR-reading

Read verbs
----------
The following verbs may be used to extract headers/messages from readable mail recipients/characters;

:display_seq_headers (message sequence, current message number, last_read_date)
  Does a @mail listing of the given message sequence. If current message
  number is given and the sequence includes it, we mark it with a `>'.
  Likewise if the sequence includes any new messages (i.e., dated after
  last_read_date), these are also indicated as such.

display_seq_full (message sequence, preamble)
  Does a @read listing of the given message sequence. Each message is preceded
  by preamble.
  => {new current message number, new last_read_date}

:messages_in_seq (index)
  => {n, msg}
:messages_in_seq (message sequence)
  => {{n_1,msg_1},{n_2,msg_2},...}
  where the n_i are message numbers and the msg_i are messages in transmission
  format (see `help mail-format')

:list_rmm ()
  Does an `@unrmm list' listing of messages in .messages_going

MR-searching

Search verbs
------------
The following verbs can be used on a readable mail-recipient/character to search for messages with fields matching a given pattern.

from_msg_seq (objectid or list [,mask])
  => message sequence: messages from (one of) the given objectid(s)

%from_msg_seq (string or list [,mask])
  => message sequence: messages with (one of) the given string(s)
     in the From: line

to_msg_seq (objectid or list [,mask])
  => message sequence: messages to (one of) the given objectid(s)

%to_msg_seq (string or list [,mask])
  => message sequence: messages with (one of) the given string(s)
     in the To: line

subject_msg_seq (string [,mask])
  => message sequence: messages with given string occurring in Subject:

body_msg_seq (string [,mask])
  => message sequence: messages with given string occurring in body of message

In all cases `mask' is a message sequence which one may supply to limit the range of the search. One way of looking at it is that the message sequence to be returned is first intersected with mask.

MR-sequences

Message Sequences
-----------------
A "message sequence" is a handle by which one may refer to a particular subset of a mail recipient's (character or $mail_recipient-descendant) saved messages. Routines like rcpt:display_seq_headers or rcpt:display_seq_full need to be supplied with message-sequence arguments to deterimine which headers or full-messages to display.

Message sequences can in turn be obtained from routines like rcpt:parse_message_seq, which takes a command-line description of a message sequence on that particular recipient and returns the corresponding message sequence handle.

The actual form of a message sequence (though you shouldn't actually need to make use of this) is that of a set of integers in the format used by $seq_utils (see `help $seq_utils'). It should however be noted that these integers are *not* themselves message numbers, but rather indices into the list of saved messages. For example, if a particular recipient holds 5 messages numbered 1,3,5,7,9. Then the message sequence handle representing messages 3,5,7 collectively, would be {2,5} which is $seq_utils-ese for the range 2..4, namely the second, third and fourth messages saved on that recipient.

The following verbs are available for obtaining indices to use in message sequences

  :length_all_msgs() => total number of messages, or equivalently,
                        => index of last message
  :length_num_le(n) => number of messages numbered <= n, or equivalently,
                        => index of highest numbered message <= n
  :exists_num_eq(n) => 0 unless there exists a message numbered n in which
                           case we return the index of that message.
  :length_date_le(date) => number of messages dated <= date, or equivalently,
                        => index of most recent message dated <= date

  :length_date_gt(date) => number of messages dated > date

Note that r:length_date_gt(date) == r:length_all_msgs()-r:length_date_le(date).
The only reason :length_date_gt is provided as a separate routine is in order
to do quick checks for the existence of new mail (as @rn needs to do).

MR-setup

See: mail-recipients in Builder Help

MR-subscribing

Subscribing to Mail Recipients
------------------------------
There are two notions of being "subscribed" to a mailing list/recipient.

(1) Hard subscribed == being on the recipient's .mail_forward list so that mail sent to this list is forwarded to one's own .messages as well (see `help mail-forwarding').

(2) Soft subscribed == keeping track of a current message for this recipient and (optionally) being on the recipient's .mail_notify list.

Each character has a .current_message property that contains, for each recipient the person cares to keep track of, a current message number and a last read date.

player:current_message(rcpt) (somewhat obsolete)
 => person's current message number for rcpt

player:get_current_message(rcpt)
 => person's {current message number for rcpt, last-read-date for rcpt}

player:make_current_message(rcpt)
 => adds a current_message entry for rcpt (NOOP if rcpt == player)

player:set_current_message(rcpt,n|E_NONE,[,date])
 => sets person's current message number for rcpt to n iff n!=E_NONE
    updates the last-read-date for rcpt to date iff date > last-read-date

player:kill_current_message(rcpt)
 => removes current-message info for rcpt (NOOP if rcpt == player)

On $mail_recipient, .mail_forward and .mail_notify are -c so one needs to use the following verbs to actually modify them.

    :add_forward(@new_recipients)
    :delete_forward(@recpients)
    :add_notify(@new_notifiees)
    :delete_notify(@notifiees)

A recipient's owner is, of course, allowed to make arbitrary changes to .mail_forward and .mail_notify. However, the default versions of these verbs also allow anyone to add him/herself to a recipient's .mail_forward or .mail_notify if the recipient is readable (see `help MR-access') by him/her.

Likewise anyone may use the :delete* verbs to delete him/herself from any .mail_forward/.mail_notify list, regardless of his actual access to the list.

Note for wizards:
You can set the list of mail folders to which new characters are
automatically subscribed by changing the
$wiz_utils.autosubscribe_lists value (set to {} by default).

MR-writing

Write verbs
-----------
The following verbs can be used to manipulate writable mail recipients/characters:

:rm_message_seq (message sequence)
  Does an @rmmail. Messages in message sequence are removed from this
  recipient's saved .messages and written to .messages_going.

:undo_rmm ()
  Does an @unrmm. Messages in .messages_going are copied back to .messages.

:expunge_rmm ()
  Does an @unrmm expunge. Blows away .messages_going.

:renumber ()
  Does a @renumber.

object-matching

Which :match...() Verb Do I Call?
---------------------------------
There are many situations where one wishes to obtain an object from a room or a character's .contents whose name/aliases matches a particular string. There are four main verbs available for this and it is important to understand the distinctions between them and how they are supposed to be used.

(*) LOC:match("X")
     - what you get looking for something that is inside LOC and named "X".
        By default, this looks through LOC.contents to find a unique object
        having a name or alias that has "X" as a prefix.

Essentially, you can think of :match as a contents-matching verb, though, e.g., for rooms you also get matches on exits as well.

(*) LOC:match_object("X", YOU) [YOU defaults to `player']
(*) YOU:my_match_object("X", LOC) [LOC defaults to player.location]
     - what YOU get being located at LOC and looking for something named "X".
        By default these both return $string_utils:match_object("X",LOC,YOU)

(*) $string_utils:match_object("X", LOC, YOU)
   - what you *would* get *if* YOU were a typical user, YOU were inside LOC,
      YOU were looking for something named "X", *and* LOC were a typical place.

In other words, $string_utils:match_object describes the :match_object() algorithm for "typical places" and the :my_match_object for "typical user characters":

    (1) check for "X" being one of "", "me", "here", "$something", or "#n"
    (2) try YOU:match("X") i.e., something in your inventory (maybe)
    (3) try LOC:match("X") i.e., some object in the room (maybe)

The distinction between these location:match_object and player:my_match_object has to do with whether the user character object or the location should determine what the matching algorithm is. Which one you should use depends on the command that you are writing. If you are writing a command with a virtual-reality flavor, then you should be respecting the room owner's idea of which objects you can "see" and thus the command should be calling the location's :match_object verb. If you are writing a building/programming command where it is appropriate for the character object to determine the matching algorithm - whether because the current location is irrelevant, not to be trusted, or both - then the character's :my_match_object verb should be called.

Examples:

  `look diamond in box'
      calls box:match("diamond"). This is a match on the contents of box.

  `take ball',
      calls player.location:match_object("ball")
      to determine which "ball" to take. Note that if the room is dark,
      we might not be able to find any "ball".

  `@program widget:foo',
      calls player:my_match_object("widget") to get the character's own idea
      of what "widget" should be. Note that if I were carrying something
      named "widget" and expecting to be programming a :foo() verb on it,
      it would be potentially disastrous should the room where I am decide
      for me to be programming something else (not even necessarily
      called "widget").

Object Matching Failures
------------------------
As with other matching routines, one gets back

  $failed_match in the case of no matching object
  $ambiguous_match in the case of more than one matching object
  $nothing in the case of a blank string argument

or an object-id. In these first 3 cases, one usually wants to translate these nonresults to the user character; this is what $command_utils:object_match_failed. The standard idiom to mimic what the builtin parser does, say, with the direct object is

  dobj = foo:match_???(dobjstr);
  if($command_utils:object_match_failed(dobj, dobjstr))
    "...give up. nothing to do. error message has already printed...";
  else
    "...dobj is something useful. Continue...";
    ...
  endif

unique-id

The unique_id property uniquely identifies any object which is, or might be, part of a core MOO database. Normally, objects are created with this property set to 0. If the object is to be part of a core database (or a core option set - see 'help @core-options'), it is a list of at least three elements, as follows:

Unique_id[1]: A string giving a unique name for the object. This is also refered to as the object's 'core name'. It must be different for each object.

Uniuqe_id[2]: A string identifying whether this is part of the basic core which must be in any core database, or whether the object is part of a "core option" set, which can be optionally included or not. If the string is the same as $core_utils.core_id, the object is part of the base core. If it is a blank string, it is not a core object. If it is anything else, it is part of a core option set of that name. (See 'help @core-options')

Unique_id[3]: The date this object was transferred from a core extraction, or 0 if it is on the source MOO.

This differs from the LamdbaCore system, which uses all objects defined as a property on #0 (i.e, as $<name>), or their parents, as the set included on the core. In the this system, objects which are not on #0 can be included in the core even if they are not parents of such objects, and objects on #0 need not be included. However, in the latter case, care should be taken that references to the corresponding $<name>'s not be in the core objects,

See @about $core_utils or @mailme $core_utils for more details.

web-security

There are three alternative mechanisms for authentication that the
web system can use. The method used depends on the setting of the
"authentication_method" property on the $http_port that is handling
the transaction Transactions through $login are assumed to be cookie
authenticated unless $http_handler.login_is_http09 is true, in which
case they are webpass authenticated. Note that for HTTP/0.9
transactions, only webpass authentication is available, and that
$login can't perform web-authentication. Alternative settings are:
webpass, cookies, and web-authentication. The "cookies" setting is
strongly recommended. Information on web cookie authentication may
be found at "http://home.netscape.com/newsref/std/cookie_spec.html"
and on web authentication in the IETF draft for HTTTP/1.0
specification 3 (draft-ietf-http-v10-spec-03.html).

1. URL-embedded "webpass" system

In this system, a password is embedded into the URL for the
transaction. A webpass of "anon" or "anonymous" always gives the
transaction the permissions of $noone. The webpass is a temporary
value associated with the user for the duration of the session. It
is erased from the $http_handler.webpass_handler database when the
user disconnects from their character. Since the temporary webpass
appears within the URL, visible to whoever is looking over the user's
shoulder, it is not as secure as the web cookie system.

2. web cookie system

In this system, a temporary webpass is generated but appears as a web
cookie within the header lines of the transaction, and not in the
URL. If an $http_port is set to use web cookies and the user's
browser doesn't recognize them, then the system automatically uses
URL-embeded webpasses instead. Detection of the browser's web cookie
function is performed by sending a cookie (named "cookies_ok") with
the gateway page, and then checking for it on the subsequent
authentication form submission. If the browser can't handle web
cookies, then the system automatically switched to URL-embedding of
the webpass. The web cookie system is considered the most secure and
recommended for general use.
  Note that users can "clear" their authentication in two ways under
the web cookie system. One is to chose the "List of Application"
where there is a button that performs this task. The other is to
return the the MOO's gateway page. A "clear" cookie is always sent
to the user's browser when that page is sent by the MOO, insuring
that the user can reauthenticate without any lingering cookies to
complicate the process.

3. "web authentication" system

This uses the authentication method given in the HTTP/1.0
specification. As stated there, it is not intended for highly secure
activity since the password is essentially sent in the clear, even
though it is hidden from the casual user by its incorporation into
the HTTP header lines. In this system, the user is presented by the
browser with a request for their character's name and password. This
information is thereafter included in every transaction to the MOO
until the browser is reinitialized, generally by quitting and
restarting. For this reason, this "web authentication" method is not
recommended, although it is a capability of the BioGate System.

web-system

See: biogate-system