final_realms_fluffos_v1/
final_realms_fluffos_v1/bin/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/ChangeLog.old/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/Win32/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/compat/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/compat/simuls/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/include/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/clone/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/command/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/data/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/etc/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/include/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/inherit/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/inherit/master/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/log/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/single/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/single/tests/compiler/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/single/tests/efuns/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/single/tests/operators/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/testsuite/u/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/tmp/
final_realms_fluffos_v1/fluffos-2.9-ds2.11/windows/
final_realms_fluffos_v1/lib/baseobs/guilds/
final_realms_fluffos_v1/lib/baseobs/misc/
final_realms_fluffos_v1/lib/baseobs/races/shadows/
final_realms_fluffos_v1/lib/cmds/god/
final_realms_fluffos_v1/lib/cmds/handlers/
final_realms_fluffos_v1/lib/cmds/handlers/cmds/
final_realms_fluffos_v1/lib/d/heaven/
final_realms_fluffos_v1/lib/d/heaven/heaven/ave/
final_realms_fluffos_v1/lib/d/mudlib/
final_realms_fluffos_v1/lib/d/newbie/
final_realms_fluffos_v1/lib/d/newbie/docs/
final_realms_fluffos_v1/lib/d/newbie/drow/armour/
final_realms_fluffos_v1/lib/d/newbie/drow/items/
final_realms_fluffos_v1/lib/d/newbie/drow/mobs/
final_realms_fluffos_v1/lib/d/newbie/drow/oldmobs/
final_realms_fluffos_v1/lib/d/newbie/drow/weapons/
final_realms_fluffos_v1/lib/d/newbie/duergar/weapons/
final_realms_fluffos_v1/lib/d/newbie/dwarf/weapons/
final_realms_fluffos_v1/lib/d/newbie/elf/cafe/
final_realms_fluffos_v1/lib/d/newbie/elf/chars/equip/
final_realms_fluffos_v1/lib/d/newbie/elf/items/armours/
final_realms_fluffos_v1/lib/d/newbie/elf/items/obj/
final_realms_fluffos_v1/lib/d/newbie/elf/items/weapons/
final_realms_fluffos_v1/lib/d/newbie/elf/quick_fix/
final_realms_fluffos_v1/lib/d/newbie/gnome/armour/
final_realms_fluffos_v1/lib/d/newbie/gnome/buildings/
final_realms_fluffos_v1/lib/d/newbie/gnome/items/
final_realms_fluffos_v1/lib/d/newbie/gnome/npcs/clones/
final_realms_fluffos_v1/lib/d/newbie/gnome/rooms/northrooms/
final_realms_fluffos_v1/lib/d/newbie/gnome/weapons/
final_realms_fluffos_v1/lib/d/newbie/goblin/armour/
final_realms_fluffos_v1/lib/d/newbie/goblin/items/
final_realms_fluffos_v1/lib/d/newbie/grads/log/
final_realms_fluffos_v1/lib/d/newbie/grads/npcs/
final_realms_fluffos_v1/lib/d/newbie/grads/rooms/
final_realms_fluffos_v1/lib/d/newbie/grads/rooms/cave1/
final_realms_fluffos_v1/lib/d/newbie/grads/temp/
final_realms_fluffos_v1/lib/d/newbie/guests/weapons/
final_realms_fluffos_v1/lib/d/newbie/half-elf/items/
final_realms_fluffos_v1/lib/d/newbie/half-elf/newroomss/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/castle/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/drows/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/savannah/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/secret/
final_realms_fluffos_v1/lib/d/newbie/half-elf/rooms/town/
final_realms_fluffos_v1/lib/d/newbie/halfling/
final_realms_fluffos_v1/lib/d/newbie/halfling/misc/
final_realms_fluffos_v1/lib/d/newbie/halfling/rooms/cave/
final_realms_fluffos_v1/lib/d/newbie/human/
final_realms_fluffos_v1/lib/d/newbie/human/armour/
final_realms_fluffos_v1/lib/d/newbie/human/monsters/
final_realms_fluffos_v1/lib/d/newbie/human/obj/
final_realms_fluffos_v1/lib/d/newbie/human/weapons/
final_realms_fluffos_v1/lib/d/newbie/lizard/armour/
final_realms_fluffos_v1/lib/d/newbie/lizard/items/
final_realms_fluffos_v1/lib/d/newbie/lizard/underwater/
final_realms_fluffos_v1/lib/d/newbie/lizard/weapons/
final_realms_fluffos_v1/lib/d/newbie/logs/
final_realms_fluffos_v1/lib/d/newbie/new_halfelf/
final_realms_fluffos_v1/lib/d/newbie/new_halfelf/npcs/
final_realms_fluffos_v1/lib/d/newbie/newdrow/npcs/
final_realms_fluffos_v1/lib/d/newbie/newdrow/rooms/
final_realms_fluffos_v1/lib/d/newbie/newelf/
final_realms_fluffos_v1/lib/d/newbie/newelf/chars/
final_realms_fluffos_v1/lib/d/newbie/newelf/npcs/
final_realms_fluffos_v1/lib/d/newbie/newelf/npcs/recopied/
final_realms_fluffos_v1/lib/d/newbie/newelf/obj/
final_realms_fluffos_v1/lib/d/newbie/newelf/quest_docs./
final_realms_fluffos_v1/lib/d/newbie/newken/
final_realms_fluffos_v1/lib/d/newbie/newken/chars/
final_realms_fluffos_v1/lib/d/newbie/newken/misc/
final_realms_fluffos_v1/lib/d/newbie/newken/npcs/
final_realms_fluffos_v1/lib/d/newbie/newken/obj/
final_realms_fluffos_v1/lib/d/newbie/newliz/
final_realms_fluffos_v1/lib/d/newbie/newliz/cave/
final_realms_fluffos_v1/lib/d/newbie/newliz/npcs/
final_realms_fluffos_v1/lib/d/newbie/orc/items/misc/
final_realms_fluffos_v1/lib/d/newbie/orc/items/weapons/
final_realms_fluffos_v1/lib/d/newbie/orc/tower/
final_realms_fluffos_v1/lib/d/vehicle/
final_realms_fluffos_v1/lib/doc/
final_realms_fluffos_v1/lib/doc/driver/
final_realms_fluffos_v1/lib/doc/driver/concepts/
final_realms_fluffos_v1/lib/doc/driver/driver/
final_realms_fluffos_v1/lib/doc/driver/efuns/arrays/
final_realms_fluffos_v1/lib/doc/driver/efuns/bitstrings/
final_realms_fluffos_v1/lib/doc/driver/efuns/communication/
final_realms_fluffos_v1/lib/doc/driver/efuns/core/
final_realms_fluffos_v1/lib/doc/driver/efuns/debugging/
final_realms_fluffos_v1/lib/doc/driver/efuns/filesystem/
final_realms_fluffos_v1/lib/doc/driver/efuns/interactive/
final_realms_fluffos_v1/lib/doc/driver/efuns/mappings/
final_realms_fluffos_v1/lib/doc/driver/efuns/objects/
final_realms_fluffos_v1/lib/doc/driver/efuns/security/
final_realms_fluffos_v1/lib/doc/driver/efuns/strings/
final_realms_fluffos_v1/lib/doc/driver/efuns/system/
final_realms_fluffos_v1/lib/doc/driver/efuns/types/
final_realms_fluffos_v1/lib/doc/driver/lpc/constructs/
final_realms_fluffos_v1/lib/doc/driver/lpc/types/
final_realms_fluffos_v1/lib/doc/driver/platforms/
final_realms_fluffos_v1/lib/doc/lpc/
final_realms_fluffos_v1/lib/doc/mail/
final_realms_fluffos_v1/lib/doc/man/
final_realms_fluffos_v1/lib/doc/man/html/
final_realms_fluffos_v1/lib/doc/man/html/applies/
final_realms_fluffos_v1/lib/doc/man/html/applies/parsing/
final_realms_fluffos_v1/lib/doc/man/html/driver/
final_realms_fluffos_v1/lib/doc/man/html/efuns/
final_realms_fluffos_v1/lib/doc/man/html/efuns/arrays/
final_realms_fluffos_v1/lib/doc/man/html/efuns/buffers/
final_realms_fluffos_v1/lib/doc/man/html/efuns/compile/
final_realms_fluffos_v1/lib/doc/man/html/efuns/floats/
final_realms_fluffos_v1/lib/doc/man/html/efuns/functions/
final_realms_fluffos_v1/lib/doc/man/html/efuns/general/
final_realms_fluffos_v1/lib/doc/man/html/efuns/numbers/
final_realms_fluffos_v1/lib/doc/man/html/efuns/parsing/
final_realms_fluffos_v1/lib/doc/man/local/
final_realms_fluffos_v1/lib/doc/man/local/applies/
final_realms_fluffos_v1/lib/doc/man/local/applies/interactive/
final_realms_fluffos_v1/lib/doc/man/local/applies/master/
final_realms_fluffos_v1/lib/doc/man/local/concepts/
final_realms_fluffos_v1/lib/doc/man/local/defines/
final_realms_fluffos_v1/lib/doc/man/local/driver/
final_realms_fluffos_v1/lib/doc/man/local/efuns/
final_realms_fluffos_v1/lib/doc/man/local/efuns/arrays/
final_realms_fluffos_v1/lib/doc/man/local/efuns/buffers/
final_realms_fluffos_v1/lib/doc/man/local/efuns/calls/
final_realms_fluffos_v1/lib/doc/man/local/efuns/compile/
final_realms_fluffos_v1/lib/doc/man/local/efuns/filesystem/
final_realms_fluffos_v1/lib/doc/man/local/efuns/floats/
final_realms_fluffos_v1/lib/doc/man/local/efuns/functions/
final_realms_fluffos_v1/lib/doc/man/local/efuns/general/
final_realms_fluffos_v1/lib/doc/man/local/efuns/interactive/
final_realms_fluffos_v1/lib/doc/man/local/efuns/internals/
final_realms_fluffos_v1/lib/doc/man/local/efuns/mappings/
final_realms_fluffos_v1/lib/doc/man/local/efuns/mudlib/
final_realms_fluffos_v1/lib/doc/man/local/efuns/numbers/
final_realms_fluffos_v1/lib/doc/man/local/efuns/objects/
final_realms_fluffos_v1/lib/doc/man/local/efuns/parsing/
final_realms_fluffos_v1/lib/doc/man/local/efuns/sockets/
final_realms_fluffos_v1/lib/doc/man/local/efuns/strings/
final_realms_fluffos_v1/lib/doc/man/local/efuns/system/
final_realms_fluffos_v1/lib/doc/man/local/historical/
final_realms_fluffos_v1/lib/doc/man/local/lfun/QC/
final_realms_fluffos_v1/lib/doc/man/local/lfun/events/
final_realms_fluffos_v1/lib/doc/man/local/lfun/monster/
final_realms_fluffos_v1/lib/doc/man/local/lfun/properties/
final_realms_fluffos_v1/lib/doc/man/local/lpc/
final_realms_fluffos_v1/lib/doc/man/local/lpc/constructs/
final_realms_fluffos_v1/lib/doc/man/local/lpc/types/
final_realms_fluffos_v1/lib/doc/man/local/standards/
final_realms_fluffos_v1/lib/doc/man/local/tutorials/
final_realms_fluffos_v1/lib/doc/man/local/tutorials/basic/
final_realms_fluffos_v1/lib/doc/man/local/tutorials/intermediate/
final_realms_fluffos_v1/lib/doc/man/mudos/applies/
final_realms_fluffos_v1/lib/doc/man/mudos/applies/interactive/
final_realms_fluffos_v1/lib/doc/man/mudos/applies/parsing/
final_realms_fluffos_v1/lib/doc/man/mudos/concepts/
final_realms_fluffos_v1/lib/doc/man/mudos/driver/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/arrays/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/buffers/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/calls/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/compile/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/filesystem/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/floats/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/functions/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/general/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/mappings/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/mixed/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/mudlib/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/numbers/
final_realms_fluffos_v1/lib/doc/man/mudos/efuns/parsing/
final_realms_fluffos_v1/lib/doc/man/mudos/lpc/constructs/
final_realms_fluffos_v1/lib/doc/man/mudos/lpc/types/
final_realms_fluffos_v1/lib/doc/races/
final_realms_fluffos_v1/lib/doc/races/old_race/
final_realms_fluffos_v1/lib/global/virtual/
final_realms_fluffos_v1/lib/global/wiz_backup/
final_realms_fluffos_v1/lib/net/config/
final_realms_fluffos_v1/lib/net/daemon/chars/
final_realms_fluffos_v1/lib/net/inherit/
final_realms_fluffos_v1/lib/net/intermud3/
final_realms_fluffos_v1/lib/net/intermud3/cmds/
final_realms_fluffos_v1/lib/net/intermud3/save/
final_realms_fluffos_v1/lib/net/intermud3/services/
final_realms_fluffos_v1/lib/net/obj/
final_realms_fluffos_v1/lib/net/old/
final_realms_fluffos_v1/lib/net/old/intermud/
final_realms_fluffos_v1/lib/net/old/intermud/adm/
final_realms_fluffos_v1/lib/net/old/intermud/services/
final_realms_fluffos_v1/lib/net/old/intermud/udp/
final_realms_fluffos_v1/lib/net/virtual/
final_realms_fluffos_v1/lib/obj/b_day/
final_realms_fluffos_v1/lib/obj/chars/
final_realms_fluffos_v1/lib/obj/handlers/lists/
final_realms_fluffos_v1/lib/obj/handlers/useless/
final_realms_fluffos_v1/lib/obj/monsters/
final_realms_fluffos_v1/lib/obj/roomgen/
final_realms_fluffos_v1/lib/obj/soul/
final_realms_fluffos_v1/lib/obj/vegetation/
final_realms_fluffos_v1/lib/obj/weapons/oldsys/
final_realms_fluffos_v1/lib/open/
final_realms_fluffos_v1/lib/players/g/
final_realms_fluffos_v1/lib/releasefiles/d/heaven/
final_realms_fluffos_v1/lib/releasefiles/d/mudlib/
final_realms_fluffos_v1/lib/releasefiles/d/newbie/
final_realms_fluffos_v1/lib/releasefiles/doc/
final_realms_fluffos_v1/lib/releasefiles/players/g/
final_realms_fluffos_v1/lib/releasefiles/save/
final_realms_fluffos_v1/lib/releasefiles/save/environ/
final_realms_fluffos_v1/lib/releasefiles/save/roomgen/
final_realms_fluffos_v1/lib/releasefiles/secure/
final_realms_fluffos_v1/lib/releasefiles/w/
final_realms_fluffos_v1/lib/releasefiles/w/god/
final_realms_fluffos_v1/lib/room/
final_realms_fluffos_v1/lib/save/
final_realms_fluffos_v1/lib/save/environ/
final_realms_fluffos_v1/lib/save/roomgen/
final_realms_fluffos_v1/lib/scripts/
final_realms_fluffos_v1/lib/secure/crerem/
final_realms_fluffos_v1/lib/secure/dom/
final_realms_fluffos_v1/lib/secure/log/
final_realms_fluffos_v1/lib/secure/misc/
final_realms_fluffos_v1/lib/std/adnd/
final_realms_fluffos_v1/lib/std/commands/shadows/
final_realms_fluffos_v1/lib/std/creator/
final_realms_fluffos_v1/lib/std/curses/
final_realms_fluffos_v1/lib/std/curses/old_sys/
final_realms_fluffos_v1/lib/std/curses/shadows/
final_realms_fluffos_v1/lib/std/dom/
final_realms_fluffos_v1/lib/std/effects/
final_realms_fluffos_v1/lib/std/effects/healing/
final_realms_fluffos_v1/lib/std/effects/other/
final_realms_fluffos_v1/lib/std/effects/poisons/
final_realms_fluffos_v1/lib/std/environ/
final_realms_fluffos_v1/lib/std/guilds/
final_realms_fluffos_v1/lib/std/guilds/priests/samples/
final_realms_fluffos_v1/lib/std/guilds/wizards/
final_realms_fluffos_v1/lib/std/living/baldy/
final_realms_fluffos_v1/lib/std/living/divstuff/
final_realms_fluffos_v1/lib/std/paran/
final_realms_fluffos_v1/lib/std/poisons/
final_realms_fluffos_v1/lib/std/poisons/shadows/
final_realms_fluffos_v1/lib/std/poisons/weapons/
final_realms_fluffos_v1/lib/std/race_groups/
final_realms_fluffos_v1/lib/std/room/
final_realms_fluffos_v1/lib/std/room/old/
final_realms_fluffos_v1/lib/std/rooms/
final_realms_fluffos_v1/lib/std/shadows/
final_realms_fluffos_v1/lib/std/shadows/test_shad/
final_realms_fluffos_v1/lib/std/socket/
final_realms_fluffos_v1/lib/std/spells/
final_realms_fluffos_v1/lib/std/vaults/
final_realms_fluffos_v1/lib/tmp/
final_realms_fluffos_v1/lib/w/
final_realms_fluffos_v1/lib/w/god/
final_realms_fluffos_v1/old/
final_realms_fluffos_v1/win32/
/* Hamlet, March 1996.  -- This holds an index for a menuing system,
                           basically.  Inheritable code.  Calleables
                           are at the top.
 * Major rework (to make it inheritable, and some added features)
   by Hamlet, Aug 1997, making this version 2.0
*/

/* All code copyright 1996 and 1997 by Isaac Charles (baked@potato.org).
   Permission is granted to use, copy, redistribute, and modify this
   code.  Credit must remain, changes should be marked as such.
*/

inherit "/std/basic/wildcard.c";

/* This one will store the directory structure as mappings within mappings.
   Will be used for the browsing system.
   The actual documents in the directory will be stored with an index
   of "." as an array.
*/
private mapping directories;

/* This one will be of the form  "document" : ({ "where/to/find",
    "where/else/to/find" }) for specific queries.  If the document 
   is the name of a directory, dir/README will be in the list.
*/
private mapping files;

/* this is the same list as above, except the "full path" to
   the file is used as an index.
*/
private mapping path_files;

/* This is used to keep work-in-progress during startup. */
private string *todo;
private static mapping global_aliases;

private static string index_root;    /* "Root directory" */
private static string *mergedirs;    /* Dirs under root to be merged */
private static string save_file;     /* For save_object() */
private static int no_file_security; /* All docs will be readable by all */
private static string g_alias_file;  /* Holds global aliases */

private static void sort_manual_dirs();
private mapping get_doc_dir(string dirname);
private static varargs void create(int recreate);
varargs int readable(string file, string path);

/* ****** These should be set in setup() of an inheritor. ****** */

/* Required call. */
nomask void set_index_root(string root) {
  string *tmp;

  tmp = explode(root, "/") - ({ "" });

  index_root = "/" + implode(tmp, "/") + "/";
}

/* Using this is optional.  Order the directories in decreasing
   relevance.  i.e. if a file appears in both mergedirs, which
   one will be used?
*/
nomask void set_mergedirs(string *dirs) {
  int i;

  if(!dirs || !arrayp(dirs) || !sizeof(dirs)) {
    mergedirs = ({ "" });
    return;
  }

  for(i = 0; i < sizeof(dirs); i++)
    if(dirs[i][<1] != '/')
      dirs[i] += "/";

  mergedirs = dirs - ({ "" });
}

nomask void set_save_file(string fname) {
  if((fname[<2..<1] == ".c") || (fname[<2..<1] == ".o"))
    save_file = fname[0..<3];
  else
    save_file = fname;
}

nomask void remove_file_security() {
  no_file_security = 1;
}

nomask void set_global_alias_file(string fname) {
  if(strsrch(fname, '/') == -1)
    g_alias_file = index_root + fname;
  else
    g_alias_file = fname;
}

/* ****** These are the things that can be queried. ****** */

string get_index_root() { return copy(index_root); }

string *get_mergedirs() { return (mergedirs - ({ "" })); }

/* This should receive a docname either in the form  path/file or file. */
string *get_doc_fnames(string docname) {
  string *matches;
  string *tmp;
  string *prim = ({ });
  string *secnd = ({ });
  string thedoc, adoc;
  int i;
  mapping t;

  if(!docname || !strlen(docname))
    return ({ "local/README" });

  if(path_files[docname])
    return filter(path_files[docname], (: readable :));
    
  if(files[docname])
    return filter(files[docname], (: readable :));

  /* More complex wildcard matching. */
  thedoc = wild2regexp(docname, 1);
  
  if(catch(matches = regexp(keys(files), thedoc))) {
    return ({ });
  };

  if(sizeof(matches))
    t = files; 
  else {
    matches = regexp(keys(path_files), thedoc);

    if(sizeof(matches))
      t = path_files;
    else
      return ({ });
  }

  if(sizeof(tmp = regexp(matches, thedoc + "$")))
    matches = tmp;

  foreach(adoc in matches) {
    i = member_array("", t[adoc]);

    if(i == -1)
      prim += t[adoc];
    else {
      prim += t[adoc][0..i-1];
      secnd += t[adoc][i+1..];
    }
  }

  return prim + ({ "" }) + secnd;
}

string *get_subdirs(string dirname) {
  mapping t;
  
  t = get_doc_dir(dirname);
  
  if(!t || !sizeof(t))
    return ({ });
    
  return sort_array(filter(keys(t) - ({ "." }), 
                           (: readable :), dirname), 1);
}

string *get_docs_in_dir(string dirname) {
  mapping t;
  
  t = get_doc_dir(dirname);
  
  if(!t || !sizeof(t))
    return ({ });
    
  return filter(t["."], (: readable :), dirname);
}

/* Is the index currently being built? */
int doc_index_building() {
  if(!todo)
    return 1;
  if(!sizeof(todo))
    return 0;
    
  return 1;
}

/* Diagnostics.  If these are different sizes, you have 
   name-collisions somewhere.  Not the greatest thing, but 
   I guess it can be lived with.
*/
int size_of_files() {  return sizeof(files);  }
int size_of_path_files() {  return sizeof(path_files);  }

/* ****** These rebuild the index ****** */

/* This one updates everything in the event that you've added pages. */
void rebuild() {
  create(1);
}

/* ****** Internal functions ****** */

/* Mask this one if some of your tree is viewable only by a 
   certain group.  if(path), the full filename is:
     index_root + path + "/" + file
   else, the full filename is:
     index_root + file
   Also, the file named "" should always be considered readable.
   It might be wise to do if(::readable(file, path)) somewhere in
     your function (keeps people from having choices they can't
     read anyway)
*/
varargs int readable(string file, string path) {
  if(no_file_security)
    return 1;

  if(file == "")
    return 1;

  if(path)
    return master()->valid_read(index_root + path + "/" + file, 
                                this_player(), "readable");
  else 
    return master()->valid_read(index_root + file, this_player(), 
                                "readable");
}

private mapping get_doc_dir(string dirname) {
  string *tmp;
  mapping t;
  int i;
  
  if(!dirname || !strlen(dirname))
    return directories;
    
  tmp = explode(dirname,"/") - ({ "" });
  t = directories;
  
  for(i=0;i<sizeof(tmp);i++) {
    t = t[tmp[i]];
    if(!t)
      break;
  }
    
  return t;
}

void init_global_aliases() {
  string *lines, *words;
  int i;

  global_aliases = ([ ]);

  if(!g_alias_file || (file_size(g_alias_file) <= 0))
    return;

  lines = explode(read_file(g_alias_file), "\n");

  for(i=0; i<sizeof(lines); i++) {
    if(strlen(lines[i]) && (lines[i][0] != '#')) {
      words = explode(lines[i], " ") - ({ "" });
      if(sizeof(words) < 3)
        continue;

      if(!global_aliases[words[0]])
        global_aliases[words[0]] = words[2..];
      else
        global_aliases[words[0]] += (words[2..] - global_aliases[words[0]]); 
    }
  }
}

/* This one builds the document data. */
private nomask void sort_manual_dirs() {
  string *dirs;
  int i,j,k,m, a;
  string *f;
  string *tmp, *tmp2, *tmp3;
  mapping t, aliases;
  int sz;
  string *newtodo = ({ });

  if(!index_root) /* Improperly defined indexer */
    return;
  
  if(!todo)  /* The system is just starting up... */
    todo = ({ "" });
  else if(!sizeof(todo))
    return;

  for(k=0;k<sizeof(todo);k++) {
    f = ({ });
    dirs = ({ });
    tmp = ({ });
    aliases = ([ ]);

    for(i=0;i<sizeof(mergedirs);i++) {
      tmp2 = get_dir(index_root+mergedirs[i]+todo[k]);

      if(tmp2)
        tmp += (tmp2 - tmp);

      if(index_root+mergedirs[i]+todo[k] == index_root)
        /* remove files beginning with '_' in the index_root dir */
        for(j=0; j<sizeof(tmp2); j++)
          if((tmp2[j][0] == '_') && (tmp2[j] != "_ALIASES"))
            tmp -= ({ tmp2[j] });

      if((member_array("_ALIASES", tmp2) > -1) &&
         (file_size(index_root+mergedirs[i]+todo[k]+"_ALIASES") > 0)) {
        tmp2 = explode(
                 read_file(index_root+mergedirs[i]+todo[k]+"_ALIASES"),
                 "\n" );
        for(j=0; j<sizeof(tmp2); j++) {
          if(!strlen(tmp2[j]) || (tmp2[j][0] == '#'))
            continue;
          tmp3 = explode(tmp2[j], " ") - ({ "" });
          if(sizeof(tmp3) < 3)
            continue;
          if(!aliases[tmp3[0]])
            aliases[tmp3[0]] = tmp3[2..];
          else
            aliases[tmp3[0]] += (tmp3[2..] - aliases[tmp3[0]]); 
        }
      }
    }

    tmp -= ({ "_ALIASES" });

    for(i=0;i<sizeof(tmp);i++) {
      if(tmp[i][<6..<1] == "README")
        continue; /* We'll deal with these later. */

      if(!aliases[tmp[i]])
        aliases[tmp[i]] = ({ });
      aliases[tmp[i]] += ({ tmp[i] });

      if(global_aliases[tmp[i]])
        aliases[tmp[i]] += global_aliases[tmp[i]];
      
      for(j=0;j<sizeof(mergedirs);j++)
        if((sz = file_size(index_root+mergedirs[j]+todo[k]+tmp[i])) != -1)
          break;
      if(sz == -2) { /* It's a directory */
        for(m=0;m<sizeof(mergedirs);m++)  /* Find the README */
          if(file_size(index_root+mergedirs[m]+todo[k]+tmp[i]+"/README") >= 0)
            break;
        
        if(m == sizeof(mergedirs))
          m = 0;

        for(a=0; a < sizeof(aliases[tmp[i]]); a++) {
          if(!files[aliases[tmp[i]][a]])
            files[aliases[tmp[i]][a]] = 
                ({ mergedirs[m]+todo[k]+tmp[i]+"/README", "" });
          else
            files[aliases[tmp[i]][a]] += 
                ({ mergedirs[m]+todo[k]+tmp[i]+"/README" });
          if(!path_files[todo[k]+aliases[tmp[i]][a]])
            path_files[todo[k]+aliases[tmp[i]][a]] = 
                ({ mergedirs[m]+todo[k]+tmp[i]+"/README", "" });
          else
            path_files[todo[k]+aliases[tmp[i]][a]] += 
                ({ mergedirs[m]+todo[k]+tmp[i]+"/README" });
        }
        newtodo += ({ todo[k]+tmp[i]+"/" });
        dirs += ({ tmp[i] });
      }
      else { /* It's a document. */
        for(a=0; a < sizeof(aliases[tmp[i]]); a++) {
          if(!files[aliases[tmp[i]][a]])
            files[aliases[tmp[i]][a]] = 
                ({ mergedirs[j]+todo[k]+tmp[i], "" });
          else
            files[aliases[tmp[i]][a]] += 
                ({ mergedirs[j]+todo[k]+tmp[i] });
          if(!path_files[todo[k]+aliases[tmp[i]][a]])
            path_files[todo[k]+aliases[tmp[i]][a]] = 
                ({ mergedirs[j]+todo[k]+tmp[i], "" });
          else
            path_files[todo[k]+aliases[tmp[i]][a]] += 
                ({ mergedirs[j]+todo[k]+tmp[i] });
        }
        f += ({ tmp[i] });
      }
    }
    
    tmp = explode(todo[k],"/") - ({ "" });
    t = directories;
    for(i=0;i<sizeof(tmp);i++)
      t = t[tmp[i]];
    
    for(i=0;i<sizeof(dirs);i++)
      t[dirs[i]] = ([ ]);
    t["."] = sort_array(f, 1); 
  }
  
  todo = newtodo;
  
  if(sizeof(todo))
    call_out("sort_manual_dirs",2);
  else {
    global_aliases = ([ ]);
    if(save_file)
      save_object(save_file);
  }
} 

private static varargs void create(int recreate) {
  if(!recreate) {
    seteuid(master()->creator_file(file_name(this_object())));
    this_object()->setup();

    if(!mergedirs)  mergedirs = ({ "" });

    if(!save_file || !restore_object(save_file) || sizeof(todo) ||
       !sizeof(files))
      recreate = 1;
  }

  if(recreate) {
    directories = ([ ]);
    files = ([ ]);
    path_files = ([ ]);
    todo = ({ "" });
    init_global_aliases();
    call_out("sort_manual_dirs", 2);
  }
}