Players may have multiple aliases; added alias() and fullalias() functions
authorAri Johnson <ari@cobramush.org>
Wed, 21 Feb 2007 00:19:23 +0000 (00:19 +0000)
committerAri Johnson <ari@cobramush.org>
Wed, 21 Feb 2007 00:19:23 +0000 (00:19 +0000)
18 files changed:
game/mushcnf.dst
game/txt/hlp/cobra_cmd.hlp
hdrs/conf.h
hdrs/externs.h
src/attrib.c
src/conf.c
src/db.c
src/function.c
src/fundb.c
src/funmisc.c
src/game.c
src/player.c
src/plyrlist.c
src/predicat.c
src/set.c
src/speech.c
src/utils.c
win32/funs.h

index 17a83b68899a7bae48de989e0709ad4ff1587116..39801bb37613480bedc62c383cd46d6d08eba11d 100644 (file)
@@ -399,6 +399,11 @@ log_wipe_passwd    zap!
 # actual maximum length you want.
 player_name_len        16
 
+# The maximum number of aliases a player may have simultaneously.
+# Setting this to 0 disables aliases. To allow an unlimited number
+# of aliases, set this to 4000 or so.
+max_aliases   3
+
 # Limit the number of objects players can own.
 use_quota yes
 
index 21fc1c65e5228e22d26339b669c41bc54d0c61d4..b2da3876f595fd4bddb696118d4438f79bf32c7e 100644 (file)
@@ -267,19 +267,29 @@ See also: leave, @leave, @oleave, ACTION LISTS
 
 See also: leave, @lfail, @olfail, ACTION LISTS
 & @alias
-  @alias <player>=<alias>
-  @alias is a special attribute. When a player sets an @alias, he is
-  effectively giving himself a secondary name; he can be paged by his
-  @alias, and matched with *<alias>, and all other game functions which
-  look up player names will also accept the alias. The attribute is
-  visible to all players.
-  
-  Aliases cannot be longer than the limit allowed for player names, 
+  @alias <player>=<name>;<alias>[;<alias2>[;<alias3>[...]]]
+
+  @alias is a special attribute that lists a player's names; players
+  can be paged by their aliases, matched with *<alias>, and all other game
+  functions which look up player names will also accept an alias.
+  The attribute is visible to all players.
+
+  A list of aliases, separated by semicolons, may be provided.
+  Players should include their usual @name in the alias list, because
+  the @name command allows setting name to any alias in the list.
+  The number of aliases allowed in the list may be limited by
+  the game's administrators through the 'max_aliases' @config parameter.
+
+  If the page_aliases config directive is on, the first alias in the
+  list is returned along with the player's name.
+
+  Each alias cannot be longer than the limit allowed for player names,
   cannot contain spaces, and must be unique -- no other player may
   have the same alias or name as any other player's alias or name.
 
   @alias has no effect on non-players.
+
+  See also: @name, alias(), fullalias()
 & @allhalt
   @allhalt
 
@@ -2202,9 +2212,15 @@ See also: go, @omove, @oxmove, @amove
   names, the name should be enclosed in quotes:
     @name me = "James Bond"
 
+  Players can change their name to any name not in use by another
+  player; players may "reserve" a set of names for their use by
+  setting them in their @alias.
+
   Changing the name of <object> will cause object to execute its
   ONAME and ANAME. The old name will be passed at %0 to these;
   the new name will be passed as %1.
+
+  See also: @alias
 & @newpassword
   @newpassword <player> = <password>
 
@@ -2802,6 +2818,10 @@ See also: @wall, @wizwall
   
   See "help @search3" for more.
 & @search3
+  If <class>=MINDB, only objects with dbrefs of <restriction> or
+  higher will be listed. If <class>=MAXDB, only objects with dbrefs
+  of <restriction> or lower will be listed.
+
   For the class TYPE=PLAYER, and for  PLAYER=<player-name>, anyone may
   obtain information on any player.  In all other cases, only Directors may
   obtain information about other players. This is computationally
@@ -2814,7 +2834,7 @@ See also: @wall, @wizwall
     @search Joe eval=1,100,200   <-- list objects from #100-#200 owned by Joe.
     @search eval=gt(money(##),10)     <-- list all objects owned by me  
                                           worth more than 10 coins.
-  
+
   See also: lsearch, lsearchr
 & @select
   @select <string>=<expr1>,<action1>[,<exprN>,<actionN>]...[,<default>]
index 65361d95371a7ef8bf5f28bd150095a81b9bd79a..24b3299a5585f022462a15e566a3065004606036 100644 (file)
@@ -52,6 +52,8 @@
 
 /* delimiter for lists of exit aliases */
 #define EXIT_DELIMITER ';'
+/* delimiter for lists of player name aliases */
+#define ALIAS_DELIMITER ';'
 
 #define QUIT_COMMAND "QUIT"
 #define WHO_COMMAND "WHO"
@@ -221,6 +223,7 @@ struct options_table {
   char ip_addr[64];    /**< What ip address should the server bind to? */
   char ssl_ip_addr[64];        /**< What ip address should the server bind to? */
   int player_name_spaces;      /**< Can players have multiword names? */
+  int max_aliases;             /**< Maximum allowed aliases per player */
   int forking_dump;    /**< Should we fork to dump? */
   int restrict_building;       /**< Is the builder power required to build? */
   int free_objects;    /**< If builder power is required, can you create without it? */
@@ -403,6 +406,7 @@ int cf_time(const char *opt, const char *val, void *loc, int maxval,
 #define RESTRICTED_BUILDING (options.restrict_building)
 #define NO_FORK (!options.forking_dump)
 #define PLAYER_NAME_SPACES (options.player_name_spaces)
+#define MAX_ALIASES (options.max_aliases)
 #define SAFER_UFUN (options.safer_ufun)
 #define NOISY_WHISPER (options.noisy_whisper)
 #define POSSESSIVE_GET (options.possessive_get)
index d7567e6b761d13eab6ce804ad976ba7fd3470b48..408a4b89a9a480489740fd2ba7d1c735e65bc128 100644 (file)
@@ -304,6 +304,7 @@ extern char *mush_crypt(const char *key);
 /* From player.c */
 extern int password_check(dbref player, const char *password);
 extern dbref lookup_player(const char *name);
+extern dbref lookup_player_name(const char *name);
 /* from player.c */
 extern dbref create_player(const char *name, const char *password,
                           const char *host, const char *ip);
@@ -319,8 +320,11 @@ extern int is_strict_integer(const char *str);
 
 /* From plyrlist.c */
 void clear_players(void);
-void add_player(dbref player, const char *alias);
+void add_player(dbref player);
+void add_player_alias(dbref player, const char *alias);
 void delete_player(dbref player, const char *alias);
+void reset_player_list(dbref player, const char *oldname, const char *oldalias,
+                      const char *name, const char *alias);
 
 /* From predicat.c */
 extern int pay_quota(dbref, int);
@@ -354,7 +358,8 @@ extern int get_current_quota(dbref who);
 extern void change_quota(dbref who, int payment);
 extern int ok_name(const char *name);
 extern int ok_command_name(const char *name);
-extern int ok_player_name(const char *name, dbref player);
+extern int ok_player_name(const char *name, dbref player, dbref thing);
+extern int ok_player_alias(const char *alias, dbref player, dbref thing);
 extern int ok_password(const char *password);
 extern int ok_tag_attribute(dbref player, char *params);
 extern dbref parse_match_possessor(dbref player, const char **str);
@@ -561,6 +566,8 @@ extern int safe_ansi_string2(ansi_string *as, size_t start, size_t len, char *bu
                                const char *check) __attribute_malloc__;
     extern void mush_free(Malloc_t RESTRICT ptr, const char *RESTRICT check);
     extern long get_random_long(long low, long high);
+    extern char *fullalias(dbref it);
+    extern char *shortalias(dbref it);
     extern char *shortname(dbref it);
     extern dbref absolute_room(dbref it);
     int can_interact(dbref from, dbref to, int type);
index 9300272fb600b69595a533a181ce013ae1136eb1..5ca70503b378191c32b9669dde8c7b19d1e205c1 100644 (file)
@@ -1711,20 +1711,18 @@ do_set_atr(dbref thing, const char *RESTRICT atr, const char *RESTRICT s,
   upcasestr(name);
   if (!strcmp(name, "ALIAS") && IsPlayer(thing)) {
     old = atr_get_noparent(thing, "ALIAS");
+    tbuf1[0] = '\0';
     if (old) {
       /* Old alias - we're allowed to change to a different case */
       strcpy(tbuf1, atr_value(old));
-      if (s
-          && (!*s
-              || (strcasecmp(s, tbuf1) && !ok_player_name(s, player)))) {
+      if (s && (!*s || (strcasecmp(s, tbuf1)
+                       && !ok_player_alias(s, player, thing)))) {
         notify(player, T("That is not a valid alias."));
         return -1;
       }
-      if (Can_Write_Attr(player, thing, old))
-        delete_player(thing, tbuf1);
     } else {
       /* No old alias */
-      if (s && *s && !ok_player_name(s, player)) {
+      if (s && *s && !ok_player_alias(s, player, thing)) {
         notify(player, T("That is not a valid alias."));
         return -1;
       }
@@ -1794,12 +1792,11 @@ do_set_atr(dbref thing, const char *RESTRICT atr, const char *RESTRICT s,
     return 0;
   }
   if (!strcmp(name, "ALIAS") && IsPlayer(thing)) {
-    if (s && *s) {
-      add_player(thing, s);
+    reset_player_list(thing, NULL, tbuf1, NULL, s);
+    if (s && *s)
       notify(player, T("Alias set."));
-    } else {
+    else
       notify(player, T("Alias removed."));
-    }
     return 1;
   } else if (!strcmp(name, "LISTEN")) {
     if (IsRoom(thing))
index 2d49958eb2b1ff323d8e555817672e49a0eba732..fe5a59ab8da5a5e4228a689a75c364fdc31c4871 100644 (file)
@@ -247,6 +247,8 @@ COBRA_CONF conftable[] = {
   {"player_name_spaces", cf_bool, &options.player_name_spaces, 2, 0,
    "cosmetic"}
   ,
+  {"max_aliases", cf_int, &options.max_aliases, -1, 0, "limits"}
+  ,
   {"ansi_names", cf_bool, &options.ansi_names, 2, 0, "cosmetic"}
   ,
   {"only_ascii_in_names", cf_bool, &options.ascii_names, 2, 0, "cosmetic"}
@@ -1166,6 +1168,7 @@ conf_default_set(void)
   strcpy(options.ip_addr, "");
   strcpy(options.ssl_ip_addr, "");
   options.player_name_spaces = 0;
+  options.max_aliases = 3;
   options.forking_dump = 1;
   options.restrict_building = 0;
   options.free_objects = 1;
index 333417534f16ef303a2a52fbf35fc308a5b2e219..2ddd94bf5d49bca88d43ae7e224b41de37876c87 100644 (file)
--- a/src/db.c
+++ b/src/db.c
@@ -1588,7 +1588,7 @@ db_read_oldstyle(FILE * f)
       }
       /* check to see if it's a player */
       if (IsPlayer(i)) {
-       add_player(i, NULL);
+       add_player(i);
        clear_flag_internal(i, "CONNECTED");
       }
       break;
@@ -1937,7 +1937,7 @@ db_read(FILE * f)
                    i);
        }
        if (IsPlayer(i)) {
-         add_player(i, NULL);
+         add_player(i);
          clear_flag_internal(i, "CONNECTED");
        }
       }
@@ -2122,7 +2122,7 @@ create_minimal_db(void)
   add_folder_name(god, 0, "inbox");
 #endif
   PUSH(god, Contents(start_room));
-  add_player(god, NULL);
+  add_player(god);
   s_Pennies(god, START_BONUS);
   local_data_create(god);
   current_state.players++;
index 8ed66b2bb0c8e6205452555272efac2e85e3fa56..8184a30217ac4de5b537ebb02b2c38463c4c583f 100644 (file)
@@ -273,6 +273,7 @@ FUNTAB flist[] = {
   {"ACCNAME", fun_accname, 1, 1, FN_REG},
   {"ADD", fun_add, 2, INT_MAX, FN_REG},
   {"AFTER", fun_after, 2, 2, FN_REG},
+  {"ALIAS", fun_alias, 1, 2, FN_REG},
   {"ALIGN", fun_align, 2, INT_MAX, FN_REG},
   {"ALLOF", fun_allof, 2, INT_MAX, FN_NOPARSE},
   {"ALPHAMAX", fun_alphamax, 1, INT_MAX, FN_REG},
@@ -378,6 +379,7 @@ FUNTAB flist[] = {
   {"FOREACH", fun_foreach, 2, 4, FN_REG},
   {"FRACTION", fun_fraction, 1, 1, FN_REG},
   {"FUNCTIONS", fun_functions, 0, 0, FN_REG},
+  {"FULLALIAS", fun_fullalias, 1, 1, FN_REG},
   {"FULLNAME", fun_fullname, 1, 1, FN_REG},
   {"GET", fun_get, 1, 1, FN_REG},
   {"GET_EVAL", fun_get_eval, 1, 1, FN_REG},
index 5cc8e046c75f52c33590392480821002c65e66ab..1ff3d5b9e90557f2162f8a2452073198e37f9898 100644 (file)
@@ -1419,6 +1419,42 @@ FUNCTION(fun_owner)
   }
 }
 
+/* ARGSUSED */
+FUNCTION(fun_alias)
+{
+  dbref it;
+
+  it = match_thing(executor, args[0]);
+  if (!GoodObject(it))
+    safe_str(T(e_notvis), buff, bp);
+
+  /* Support changing alias via function if side-effects are enabled */
+  if (nargs == 2) {
+    if (!command_check_byname(executor, "ATTRIB_SET")
+       || fun->flags & FN_NOSIDEFX) {
+      safe_str(T(e_perm), buff, bp);
+      return;
+    }
+    if (!FUNCTION_SIDE_EFFECTS)
+      safe_str(T(e_disabled), buff, bp);
+    else
+      do_set_atr(it, "ALIAS", args[1], executor, 0);
+    return;
+  } else {
+    safe_str(shortalias(it), buff, bp);
+  }
+}
+
+/* ARGSUSED */
+FUNCTION(fun_fullalias)
+{
+  dbref it = match_thing(executor, args[0]);
+  if (GoodObject(it))
+    safe_str(fullalias(it), buff, bp);
+  else
+    safe_str(T(e_notvis), buff, bp);
+}
+
 /* ARGSUSED */
 FUNCTION(fun_name)
 {
index df20f506b87d52a22a268db0a648de0386da5cf5..bb317fe5455eefbcc2ac4632fdfaec0f41e08b06 100644 (file)
@@ -54,7 +54,7 @@ FUNCTION(fun_valid)
   else if (!strcasecmp(args[0], "attrname"))
     safe_boolean(good_atr_name(upcasestr(args[1])), buff, bp);
   else if (!strcasecmp(args[0], "playername"))
-    safe_boolean(ok_player_name(args[1], executor), buff, bp);
+    safe_boolean(ok_player_name(args[1], executor, executor), buff, bp);
   else if (!strcasecmp(args[0], "password"))
     safe_boolean(ok_password(args[1]), buff, bp);
   else if (!strcasecmp(args[0], "command"))
index 316dc0228fa8738dfd1d2a7d8ff2be77c0d3745d..20b57dff2ee26459dda75f2040286cbf30d36fab 100644 (file)
@@ -695,7 +695,7 @@ do_restart(void)
        bp = buf;
        safe_str(atr_value(s), buf, &bp);
        *bp = '\0';
-       add_player(thing, buf);
+       add_player_alias(thing, buf);
       }
     }
   }
index e904b5cfedb74c9256743993fd3f7ea4a537ce2b..112264dcc98f1c470eef407ab730c246c0ad1689 100644 (file)
@@ -201,7 +201,7 @@ dbref create_guest(const char *host, const char *ip) {
                gst_id = NOTHING;  
                strncpy(guest_name, T(GUEST_PREFIX), BUFFER_LEN-1);
                strcat(guest_name, GUEST_NUMBER(i+1));
-               if(ok_player_name(guest_name, NOTHING))
+               if(ok_player_name(guest_name, NOTHING, NOTHING))
                  break;        
                else if((gst_id = lookup_player(guest_name)) != NOTHING && !Connected(gst_id))
                        break;
@@ -247,7 +247,7 @@ create_player(const char *name, const char *password, const char *host,
              const char *ip)
 {
   dbref player;
-  if (!ok_player_name(name, NOTHING)) {
+  if (!ok_player_name(name, NOTHING, NOTHING)) {
     do_log(LT_CONN, 0, 0, T("Failed creation (bad name) from %s"), host);
     return NOTHING;
   }
@@ -301,7 +301,7 @@ email_register_player(const char *name, const char *email, const char *host,
   dbref player;
   FILE *fp;
 
-  if (!ok_player_name(name, NOTHING)) {
+  if (!ok_player_name(name, NOTHING, NOTHING)) {
     do_log(LT_CONN, 0, 0, T("Failed registration (bad name) from %s"), host);
     return NOTHING;
   }
@@ -450,7 +450,7 @@ make_player(const char *name, const char *password, const char *host,
   /* link him to PLAYER_START */
   PUSH(player, Contents(PLAYER_START));
 
-  add_player(player,NULL);
+  add_player(player);
   add_lock(GOD, player, Basic_Lock, parse_boolexp(player, "=me", Basic_Lock),
           -1);
   add_lock(GOD, player, Enter_Lock, parse_boolexp(player, "=me", Basic_Lock),
index 5e13d50005c05285887bbfb81b9e35570c4dd326..c941715bfc226f9139524d74e6d80bb8c98e6aee 100644 (file)
@@ -19,6 +19,7 @@
 #include "mushdb.h"
 #include "dbdefs.h"
 #include "flags.h"
+#include "attrib.h"
 #include "htab.h"
 #include "confmagic.h"
 
@@ -49,19 +50,45 @@ clear_players(void)
 
 /** Add a player to the player list htab.
  * \param player dbref of player to add.
- * \param alias name to use as hash table key for player, if given.
  */
 void
-add_player(dbref player, const char *alias)
+add_player(dbref player)
 {
   long tmp;
   tmp = player;
   if (!hft_initialized)
     init_hft();
-  if (alias)
-    hashadd(strupper(alias), (void *) tmp, &htab_player_list);
-  else
-    hashadd(strupper(Name(player)), (void *) tmp, &htab_player_list);
+  hashadd(strupper(Name(player)), (void *) tmp, &htab_player_list);
+}
+
+/** Add a player's alias list to the player list htab.
+ * \param player dbref of player to add.
+ * \param alias list of names ot use as hash table keys for player,
+ * semicolon-separated.
+ */
+void
+add_player_alias(dbref player, const char *alias)
+{
+  long tmp;
+  char tbuf1[BUFFER_LEN], *s, *sp;
+  if (!hft_initialized)
+    init_hft();
+  if (!alias) {
+    add_player(player);
+    return;
+  }
+  strncpy(tbuf1, alias, BUFFER_LEN - 1);
+  tbuf1[BUFFER_LEN - 1] = '\0';
+  s = trim_space_sep(tbuf1, ALIAS_DELIMITER);
+  while (s) {
+    sp = split_token(&s, ALIAS_DELIMITER);
+    while (sp && *sp && *sp == ' ')
+      sp++;
+    if (sp && *sp) {
+      tmp = player;
+      hashadd(strupper(sp), (void *) tmp, &htab_player_list);
+    }
+  }
 }
 
 /** Look up a player in the player list htab (or by dbref).
@@ -72,8 +99,6 @@ dbref
 lookup_player(const char *name)
 {
   int p;
-  void *hval;
-  long tmp;
 
   if (!name || !*name)
     return NOTHING;
@@ -86,6 +111,18 @@ lookup_player(const char *name)
   }
   if (*name == LOOKUP_TOKEN)
     name++;
+  return lookup_player_name(name);
+}
+
+/** Look up a player in the player list htab only.
+ * \param name name of player to find.
+ * \return dbref of player, or NOTHING.
+ */
+dbref
+lookup_player_name(const char *name)
+{
+  long tmp;
+  void *hval;
   hval = hashfind(strupper(name), &htab_player_list);
   if (!hval)
     return NOTHING;
@@ -100,6 +137,7 @@ lookup_player(const char *name)
    */
 }
 
+
 /** Remove a player from the player list htab.
  * \param player dbref of player to remove.
  * \param alias key to remove if given.
@@ -107,8 +145,75 @@ lookup_player(const char *name)
 void
 delete_player(dbref player, const char *alias)
 {
-  if (alias)
-    hashdelete(strupper(alias), &htab_player_list);
-  else
+  if (!hft_initialized) {
+    init_hft();
+    return;
+  }
+  if (alias) {
+    /* This could be a compound alias, in which case we need to delete
+     * them all, but we shouldn't delete the player's own name!
+     */
+    char tbuf1[BUFFER_LEN], *s, *sp;
+    strncpy(tbuf1, alias, BUFFER_LEN - 1);
+    tbuf1[BUFFER_LEN - 1] = '\0';
+    s = trim_space_sep(tbuf1, ALIAS_DELIMITER);
+    while (s) {
+      sp = split_token(&s, ALIAS_DELIMITER);
+      while (sp && *sp && *sp == ' ')
+      sp++;
+      if (sp && *sp && strcasecmp(sp, Name(player)))
+      hashdelete(strupper(sp), &htab_player_list);
+    }
+  } else
     hashdelete(strupper(Name(player)), &htab_player_list);
 }
+
+/** Reset all of a player's player list entries (names/aliases).
+ * This is called when a player changes name or alias.
+ * We remove all their old entries, and add back their new ones.
+ * \param player dbref of player
+ * \param oldname player's former name (NULL if not changing)
+ * \param oldalias player's former aliases (NULL if not changing)
+ * \param name player's new name
+ * \param alias player's new aliases
+ */
+void
+reset_player_list(dbref player, const char *oldname, const char *oldalias,
+                 const char *name, const char *alias)
+{
+  char tbuf1[BUFFER_LEN];
+  char tbuf2[BUFFER_LEN];
+  if (!oldname) {
+    oldname = Name(player);
+    name = Name(player);
+  }
+  if (oldalias) {
+    strncpy(tbuf1, oldalias, BUFFER_LEN - 1);
+    tbuf1[BUFFER_LEN - 1] = '\0';
+    if (alias) {
+      strncpy(tbuf2, alias, BUFFER_LEN - 1);
+      tbuf2[BUFFER_LEN - 1] = '\0';
+    } else {
+      tbuf2[0] = '\0';
+    }
+  } else {
+    /* We are not changing aliases, just name, but we need to get the
+     * aliases anyway, since we may change name to something that's
+     * in the alias, and thus must not be deleted.
+     */
+    ATTR *a = atr_get_noparent(player, "ALIAS");
+    if (a) {
+      strncpy(tbuf1, atr_value(a), BUFFER_LEN - 1);
+      tbuf1[BUFFER_LEN - 1] = '\0';
+    } else {
+      tbuf1[0] = '\0';
+    }
+    strcpy(tbuf2, tbuf1);
+  }
+  /* Delete all the old stuff */
+  delete_player(player, tbuf1);
+  delete_player(player, NULL);
+  /* Add in the new stuff */
+  add_player_alias(player, name);
+  add_player_alias(player, tbuf2);
+}
index b5f4721ba1192173f9b0357af17d1840968edbd3..5e66ba682f9cd65b166a0c5eafc63850402ba144 100644 (file)
@@ -785,21 +785,23 @@ ok_name(const char *n)
          && strcasecmp((char *) name, "here"));
 }
 
-/** Is a name a valid player name?
+/** Is a name a valid player name when applied by player to thing?
  * Player names must be valid object names, but also not forbidden (unless
  * the player is a wizard). They are
  * subject to a different length limit, and subject to more stringent
  * restrictions on valid characters. Finally, it can't be the same as
- * an existing player name or alias.
+ * an existing player name or alias unless it's one of theirs.
  * \param name name to check.
  * \param player player for permission checks.
+ * \param thing player who will get the name.
  * \retval 1 name is valid for players.
  * \retval 0 name is not valid for players.
  */
 int
-ok_player_name(const char *name, dbref player)
+ok_player_name(const char *name, dbref player, dbref thing)
 {
   const unsigned char *scan, *good;
+  dbref lookup;
 
   if (!ok_name(name)
       || (forbidden_name(name) && !(GoodObject(player) && Director(player)))
@@ -816,9 +818,47 @@ ok_player_name(const char *name, dbref player)
       return 0;
   }
 
-  return (lookup_player(name) == NOTHING);
+  lookup = lookup_player(name);
+  return ((lookup == NOTHING) || (lookup == thing));
 }
 
+
+/** Is a alias a valid player alias-list for thing?
+ * It must be a semicolon-separated list of valid player names
+ * with no more than than MAX_ALIASES names, if the player isn't
+ * a wizard.
+ * \param alias list to check.
+ * \param player player for permission checks.
+ * \param thing player who is being aliased.
+ * \retval 1 alias is valid for players.
+ * \retval 0 alias is not valid for players.
+ */
+int
+ok_player_alias(const char *alias, dbref player, dbref thing)
+{
+  char tbuf1[BUFFER_LEN], *s, *sp;
+  int cnt = 0;
+
+  if (!alias || !*alias)
+    return 0;
+
+  strncpy(tbuf1, alias, BUFFER_LEN - 1);
+  tbuf1[BUFFER_LEN - 1] = '\0';
+  s = trim_space_sep(tbuf1, ALIAS_DELIMITER);
+  while (s) {
+    sp = split_token(&s, ALIAS_DELIMITER);
+    while (sp && *sp && *sp == ' ')
+      sp++;
+    if (!sp || !*sp)
+      return 0;                        /* No null aliases */
+    if (!ok_player_name(sp, player, thing))
+      return 0;
+    cnt++;
+  }
+  return ((cnt <= MAX_ALIASES) || Director(player));
+}
+
+
 /** Is a password acceptable?
  * Acceptable passwords must be non-null and must contain only
  * printable characters and no whitespace.
index 53780a1e7dbed2e21d1f1303de83402a7cdbce6a..d06ec838ccf2f45f4c884fcd39eaf6e3947e3a17 100644 (file)
--- a/src/set.c
+++ b/src/set.c
@@ -114,9 +114,7 @@ do_name(dbref player, const char *name, char *newname)
            password++;
        }
       }
-      if (strcasecmp(newname, Name(thing))
-         && !ok_player_name(newname, thing)) {
-       /* strcasecmp allows changing foo to Foo, etc. */
+      if (!ok_player_name(newname, player, thing)) {
        notify(player, T("You can't give a player that name."));
        return;
       }
@@ -141,7 +139,7 @@ do_name(dbref player, const char *name, char *newname)
       myenv[i] = NULL;
 
     if (IsPlayer(thing))
-      delete_player(thing, NULL);
+      reset_player_list(thing, Name(thing), NULL, newname, NULL);
     set_name(thing, newname);
     if(!IsPlayer(thing)) {
           char lmbuf[1024];
@@ -151,7 +149,7 @@ do_name(dbref player, const char *name, char *newname)
           set_lmod(thing, lmbuf);
     }
     if (IsPlayer(thing))
-      add_player(thing, NULL);
+      add_player(thing);
 
     if (!AreQuiet(player, thing))
       notify(player, T("Name set."));
index 92f49eec7fc450fdc6899f989c4f8e41e879e68c..ad3ca0c89c2b255b5e9d9cc74f9711c8c2e98167 100644 (file)
@@ -638,6 +638,7 @@ do_page(dbref player, const char *arg1, const char *arg2, dbref cause,
   int fails_lock;
   int is_haven;
   ATTR *a;
+  char *alias;
 
   tp2 = tbuf2 = (char *) mush_malloc(BUFFER_LEN, "string");
   if (!tbuf2)
@@ -866,8 +867,8 @@ do_page(dbref player, const char *arg1, const char *arg2, dbref cause,
   }
 
   /* Figure out the 'name' of the player */
-  if (PAGE_ALIASES && (a = atr_get_noparent(player, "ALIAS")))
-    current = tprintf("%s (%s)", Name(player), atr_value(a));
+  if (PAGE_ALIASES && (alias = shortalias(player)) && *alias)
+    current = tprintf("%s (%s)", Name(player), alias);
   else
     current = (char *) Name(player);
 
index 12efcc7e5d17d918574671afa2f04367beabc6c8..0304238af9db8baff69e247cf8a2834e40da6b6d 100644 (file)
@@ -533,6 +533,48 @@ get_random_long(long low, long high)
   return low + (n % x);
 }
 
+/** Return an object's alias. We expect a valid object.
+ * \param it dbref of object.
+ * \return object's complete alias.
+ */
+char *
+fullalias(dbref it)
+{
+  static char n[BUFFER_LEN];  /* STATIC */
+  ATTR *a = atr_get_noparent(it, "ALIAS");
+
+  if (!a)
+    return '\0';
+
+  strncpy(n, atr_value(a), BUFFER_LEN - 1);
+  n[BUFFER_LEN - 1] = '\0';
+
+  return n;
+}
+
+/** Return only the first component of an object's alias. We expect
+ * a valid object.
+ * \param it dbref of object.
+ * \return object's short alias.
+ */
+char *
+shortalias(dbref it)
+{
+  static char n[BUFFER_LEN];  /* STATIC */
+  char *s;
+
+  s = fullalias(it);
+  if (!(s && *s))
+    return '\0';
+
+  strncpy(n, s, BUFFER_LEN - 1);
+  n[BUFFER_LEN - 1] = '\0';
+  if ((s = strchr(n, ';')))
+    *s = '\0';
+
+  return n;
+}
+
 /** Return an object's name, but for exits, return just the first
  * component. We expect a valid object.
  * \param it dbref of object.
index 0210388c7b7cc4b1e0dd74057c5830e94eab66d3..b90c957fb6b6acbb120ed484b32c4311bb903f88 100644 (file)
@@ -5,6 +5,7 @@ FUNCTION_PROTO(fun_accname);
 FUNCTION_PROTO(fun_acos);
 FUNCTION_PROTO(fun_add);
 FUNCTION_PROTO(fun_after);
+FUNCTION_PROTO(fun_alias);
 FUNCTION_PROTO(fun_align);
 FUNCTION_PROTO(fun_allof);
 FUNCTION_PROTO(fun_alphamax);
@@ -113,6 +114,7 @@ FUNCTION_PROTO(fun_followers);
 FUNCTION_PROTO(fun_following);
 FUNCTION_PROTO(fun_foreach);
 FUNCTION_PROTO(fun_fraction);
+FUNCTION_PROTO(fun_fullalias);
 FUNCTION_PROTO(fun_fullname);
 FUNCTION_PROTO(fun_functions);
 FUNCTION_PROTO(fun_get);