// flags.cpp -- Flag manipulation routines. // // $Id: flags.cpp,v 1.21 2005/10/16 09:08:10 rmg Exp $ // #include "copyright.h" #include "autoconf.h" #include "config.h" #include "externs.h" #include "command.h" #include "powers.h" /* --------------------------------------------------------------------------- * fh_any: set or clear indicated bit, no security checking */ bool fh_any(dbref target, dbref player, FLAG flag, int fflags, bool reset) { // Never let God drop his/her own wizbit. // if ( God(target) && reset && flag == WIZARD && fflags == FLAG_WORD1) { notify(player, "You cannot make God mortal."); return false; } // Otherwise we can go do it. // if (reset) { db[target].fs.word[fflags] &= ~flag; } else { db[target].fs.word[fflags] |= flag; } return true; } /* --------------------------------------------------------------------------- * fh_god: only GOD may set or clear the bit */ bool fh_god(dbref target, dbref player, FLAG flag, int fflags, bool reset) { if (!God(player)) { return false; } return (fh_any(target, player, flag, fflags, reset)); } /* * --------------------------------------------------------------------------- * * fh_wiz: only WIZARDS (or GOD) may set or clear the bit */ bool fh_wiz(dbref target, dbref player, FLAG flag, int fflags, bool reset) { if (!Wizard(player)) { return false; } return (fh_any(target, player, flag, fflags, reset)); } /* * --------------------------------------------------------------------------- * * fh_wizroy: only WIZARDS, ROYALTY, (or GOD) may set or clear the bit */ bool fh_wizroy(dbref target, dbref player, FLAG flag, int fflags, bool reset) { if (!WizRoy(player)) { return false; } return (fh_any(target, player, flag, fflags, reset)); } /* * --------------------------------------------------------------------------- * * fh_restrict_player (renamed from fh_fixed): Only Wizards can set * * this on players, but ordinary players can set it on other types * * of objects. */ bool fh_restrict_player ( dbref target, dbref player, FLAG flag, int fflags, bool reset ) { if ( isPlayer(target) && !Wizard(player)) { return false; } return (fh_any(target, player, flag, fflags, reset)); } /* --------------------------------------------------------------------------- * fh_privileged: You can set this flag on a non-player object, if you * yourself have this flag and are a player who owns themselves (i.e., * no robots). Only God can set this on a player. */ bool fh_privileged ( dbref target, dbref player, FLAG flag, int fflags, bool reset ) { if (!God(player)) { if ( !isPlayer(player) || player != Owner(player) || isPlayer(target) || (db[player].fs.word[fflags] & flag) == 0) { return false; } } return (fh_any(target, player, flag, fflags, reset)); } /* * --------------------------------------------------------------------------- * * fh_inherit: only players may set or clear this bit. */ bool fh_inherit(dbref target, dbref player, FLAG flag, int fflags, bool reset) { if (!Inherits(player)) { return false; } return (fh_any(target, player, flag, fflags, reset)); } /* * --------------------------------------------------------------------------- * * fh_dark_bit: manipulate the dark bit. Nonwizards may not set on players. */ bool fh_dark_bit(dbref target, dbref player, FLAG flag, int fflags, bool reset) { if ( !reset && isPlayer(target) && !( (target == player) && Can_Hide(player)) && !Wizard(player)) { return false; } return (fh_any(target, player, flag, fflags, reset)); } /* * --------------------------------------------------------------------------- * * fh_going_bit: manipulate the going bit. Non-gods may only clear. */ bool fh_going_bit(dbref target, dbref player, FLAG flag, int fflags, bool reset) { if ( Going(target) && reset && (Typeof(target) != TYPE_GARBAGE)) { notify(player, "Your object has been spared from destruction."); return (fh_any(target, player, flag, fflags, reset)); } if (!God(player)) { return false; } // Even God should not be allowed set protected dbrefs GOING. // if ( !reset && ( target == 0 || God(target) || target == mudconf.start_home || target == mudconf.start_room || target == mudconf.default_home || target == mudconf.master_room)) { return false; } return (fh_any(target, player, flag, fflags, reset)); } /* * --------------------------------------------------------------------------- * * fh_hear_bit: set or clear bits that affect hearing. */ bool fh_hear_bit(dbref target, dbref player, FLAG flag, int fflags, bool reset) { if (isPlayer(target) && (flag & MONITOR)) { if (Can_Monitor(player)) { return (fh_any(target, player, flag, fflags, reset)); } else { return false; } } bool could_hear = Hearer(target); bool result = fh_any(target, player, flag, fflags, reset); handle_ears(target, could_hear, Hearer(target)); return result; } /* --------------------------------------------------------------------------- * fh_player_bit: Can set and reset this on everything but players. */ bool fh_player_bit ( dbref target, dbref player, FLAG flag, int fflags, bool reset ) { if (isPlayer(target)) { return false; } return (fh_any(target, player, flag, fflags, reset)); } /* --------------------------------------------------------------------------- * fh_staff: only STAFF, WIZARDS, ROYALTY, (or GOD) may set or clear * the bit. */ bool fh_staff ( dbref target, dbref player, FLAG flag, int fflags, bool reset ) { if (!Staff(player) && !God(player)) { return false; } return (fh_any(target, player, flag, fflags, reset)); } static FLAGBITENT fbeAbode = { ABODE, 'A', FLAG_WORD2, 0, fh_any}; static FLAGBITENT fbeAnsi = { ANSI, 'X', FLAG_WORD2, 0, fh_any}; static FLAGBITENT fbeAudible = { HEARTHRU, 'a', FLAG_WORD1, 0, fh_hear_bit}; static FLAGBITENT fbeAuditorium = { AUDITORIUM, 'b', FLAG_WORD2, 0, fh_any}; static FLAGBITENT fbeBlind = { BLIND, 'B', FLAG_WORD2, 0, fh_wiz}; static FLAGBITENT fbeChownOk = { CHOWN_OK, 'C', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeConnected = { CONNECTED, 'c', FLAG_WORD2, CA_NO_DECOMP, fh_god}; static FLAGBITENT fbeDark = { DARK, 'D', FLAG_WORD1, 0, fh_dark_bit}; static FLAGBITENT fbeDestroyOk = { DESTROY_OK, 'd', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeEnterOk = { ENTER_OK, 'e', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeFixed = { FIXED, 'f', FLAG_WORD2, 0, fh_restrict_player}; static FLAGBITENT fbeFloating = { FLOATING, 'F', FLAG_WORD2, 0, fh_any}; static FLAGBITENT fbeGagged = { GAGGED, 'j', FLAG_WORD2, 0, fh_wiz}; static FLAGBITENT fbeGoing = { GOING, 'G', FLAG_WORD1, CA_NO_DECOMP, fh_going_bit}; static FLAGBITENT fbeHalted = { HALT, 'h', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeHasDaily = { HAS_DAILY, '*', FLAG_WORD2, CA_GOD|CA_NO_DECOMP, fh_god}; static FLAGBITENT fbeHasForwardList = { HAS_FWDLIST, '&', FLAG_WORD2, CA_GOD|CA_NO_DECOMP, fh_god}; static FLAGBITENT fbeHasListen = { HAS_LISTEN, '@', FLAG_WORD2, CA_GOD|CA_NO_DECOMP, fh_god}; static FLAGBITENT fbeHasStartup = { HAS_STARTUP, '+', FLAG_WORD1, CA_GOD|CA_NO_DECOMP, fh_god}; static FLAGBITENT fbeHaven = { HAVEN, 'H', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeHead = { HEAD_FLAG, '?', FLAG_WORD2, 0, fh_wiz}; static FLAGBITENT fbeHtml = { HTML, '(', FLAG_WORD2, 0, fh_any}; static FLAGBITENT fbeImmortal = { IMMORTAL, 'i', FLAG_WORD1, 0, fh_wiz}; static FLAGBITENT fbeInherit = { INHERIT, 'I', FLAG_WORD1, 0, fh_inherit}; static FLAGBITENT fbeJumpOk = { JUMP_OK, 'J', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeKeepAlive = { CKEEPALIVE, 'k', FLAG_WORD2, 0, fh_any}; static FLAGBITENT fbeKey = { KEY, 'K', FLAG_WORD2, 0, fh_any}; static FLAGBITENT fbeLight = { LIGHT, 'l', FLAG_WORD2, 0, fh_any}; static FLAGBITENT fbeLinkOk = { LINK_OK, 'L', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeMonitor = { MONITOR, 'M', FLAG_WORD1, 0, fh_hear_bit}; static FLAGBITENT fbeMyopic = { MYOPIC, 'm', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeNoCommand = { NO_COMMAND, 'n', FLAG_WORD2, 0, fh_any}; static FLAGBITENT fbeNoAccents = { NOACCENTS, '~', FLAG_WORD2, 0, fh_any}; static FLAGBITENT fbeNoBleed = { NOBLEED, '-', FLAG_WORD2, 0, fh_any}; static FLAGBITENT fbeNoSpoof = { NOSPOOF, 'N', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeOpaque = { TM_OPAQUE, 'O', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeOpenOk = { OPEN_OK, 'z', FLAG_WORD2, 0, fh_wiz}; static FLAGBITENT fbeParentOk = { PARENT_OK, 'Y', FLAG_WORD2, 0, fh_any}; static FLAGBITENT fbePlayerMails = { PLAYER_MAILS, ' ', FLAG_WORD2, CA_GOD|CA_NO_DECOMP, fh_god}; static FLAGBITENT fbePuppet = { PUPPET, 'p', FLAG_WORD1, 0, fh_hear_bit}; static FLAGBITENT fbeQuiet = { QUIET, 'Q', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeRobot = { ROBOT, 'r', FLAG_WORD1, 0, fh_player_bit}; static FLAGBITENT fbeRoyalty = { ROYALTY, 'Z', FLAG_WORD1, 0, fh_wiz}; static FLAGBITENT fbeSafe = { SAFE, 's', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeSlave = { SLAVE, 'x', FLAG_WORD2, CA_WIZARD, fh_wiz}; static FLAGBITENT fbeStaff = { STAFF, 'w', FLAG_WORD2, 0, fh_wiz}; static FLAGBITENT fbeSticky = { STICKY, 'S', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeSuspect = { SUSPECT, 'u', FLAG_WORD2, CA_WIZARD, fh_wiz}; static FLAGBITENT fbeTerse = { TERSE, 'q', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeTrace = { TRACE, 'T', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeTransparent = { SEETHRU, 't', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeUnfindable = { UNFINDABLE, 'U', FLAG_WORD2, 0, fh_any}; static FLAGBITENT fbeUninspected = { UNINSPECTED, 'g', FLAG_WORD2, 0, fh_wizroy}; static FLAGBITENT fbeVacation = { VACATION, '|', FLAG_WORD2, 0, fh_restrict_player}; static FLAGBITENT fbeVerbose = { VERBOSE, 'v', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeVisual = { VISUAL, 'V', FLAG_WORD1, 0, fh_any}; static FLAGBITENT fbeWizard = { WIZARD, 'W', FLAG_WORD1, 0, fh_god}; static FLAGBITENT fbeSitemon = { SITEMON, '$', FLAG_WORD3, 0, fh_wiz}; #ifdef WOD_REALMS static FLAGBITENT fbeFae = { FAE, '0', FLAG_WORD3, CA_STAFF, fh_wizroy}; static FLAGBITENT fbeChimera = { CHIMERA, '1', FLAG_WORD3, CA_STAFF, fh_wizroy}; static FLAGBITENT fbePeering = { PEERING, '2', FLAG_WORD3, CA_STAFF, fh_wizroy}; static FLAGBITENT fbeUmbra = { UMBRA, '3', FLAG_WORD3, CA_STAFF, fh_wizroy}; static FLAGBITENT fbeShroud = { SHROUD, '4', FLAG_WORD3, CA_STAFF, fh_wizroy}; static FLAGBITENT fbeMatrix = { MATRIX, '5', FLAG_WORD3, CA_STAFF, fh_wizroy}; static FLAGBITENT fbeObf = { OBF, '6', FLAG_WORD3, CA_STAFF, fh_wizroy}; static FLAGBITENT fbeHss = { HSS, '7', FLAG_WORD3, CA_STAFF, fh_wizroy}; static FLAGBITENT fbeMedium = { MEDIUM, '8', FLAG_WORD3, CA_STAFF, fh_wizroy}; static FLAGBITENT fbeDead = { DEAD, '9', FLAG_WORD3, CA_STAFF, fh_wizroy}; static FLAGBITENT fbeMarker0 = { MARK_0, ' ', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker1 = { MARK_1, ' ', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker2 = { MARK_2, ' ', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker3 = { MARK_3, ' ', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker4 = { MARK_4, ' ', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker5 = { MARK_5, ' ', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker6 = { MARK_6, ' ', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker7 = { MARK_7, ' ', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker8 = { MARK_8, ' ', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker9 = { MARK_9, ' ', FLAG_WORD3, 0, fh_god}; #else // WOD_REALMS static FLAGBITENT fbeMarker0 = { MARK_0, '0', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker1 = { MARK_1, '1', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker2 = { MARK_2, '2', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker3 = { MARK_3, '3', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker4 = { MARK_4, '4', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker5 = { MARK_5, '5', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker6 = { MARK_6, '6', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker7 = { MARK_7, '7', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker8 = { MARK_8, '8', FLAG_WORD3, 0, fh_god}; static FLAGBITENT fbeMarker9 = { MARK_9, '9', FLAG_WORD3, 0, fh_god}; #endif // WOD_REALMS FLAGNAMEENT gen_flag_names[] = { {"ABODE", true, &fbeAbode }, {"ACCENTS", false, &fbeNoAccents }, {"ANSI", true, &fbeAnsi }, {"AUDIBLE", true, &fbeAudible }, {"AUDITORIUM", true, &fbeAuditorium }, {"BLEED", false, &fbeNoBleed }, {"BLIND", true, &fbeBlind }, {"COMMANDS", false, &fbeNoCommand }, {"CHOWN_OK", true, &fbeChownOk }, {"CONNECTED", true, &fbeConnected }, {"DARK", true, &fbeDark }, {"DESTROY_OK", true, &fbeDestroyOk }, {"ENTER_OK", true, &fbeEnterOk }, {"FIXED", true, &fbeFixed }, {"FLOATING", true, &fbeFloating }, {"GAGGED", true, &fbeGagged }, {"GOING", true, &fbeGoing }, {"HALTED", true, &fbeHalted }, {"HAS_DAILY", true, &fbeHasDaily }, {"HAS_FORWARDLIST", true, &fbeHasForwardList }, {"HAS_LISTEN", true, &fbeHasListen }, {"HAS_STARTUP", true, &fbeHasStartup }, {"HAVEN", true, &fbeHaven }, {"HEAD", true, &fbeHead }, {"HTML", true, &fbeHtml }, {"IMMORTAL", true, &fbeImmortal }, {"INHERIT", true, &fbeInherit }, {"JUMP_OK", true, &fbeJumpOk }, {"KEEPALIVE", true, &fbeKeepAlive }, {"KEY", true, &fbeKey }, {"LIGHT", true, &fbeLight }, {"LINK_OK", true, &fbeLinkOk }, {"MARKER0", true, &fbeMarker0 }, {"MARKER1", true, &fbeMarker1 }, {"MARKER2", true, &fbeMarker2 }, {"MARKER3", true, &fbeMarker3 }, {"MARKER4", true, &fbeMarker4 }, {"MARKER5", true, &fbeMarker5 }, {"MARKER6", true, &fbeMarker6 }, {"MARKER7", true, &fbeMarker7 }, {"MARKER8", true, &fbeMarker8 }, {"MARKER9", true, &fbeMarker9 }, {"MONITOR", true, &fbeMonitor }, {"MYOPIC", true, &fbeMyopic }, {"NO_COMMAND", true, &fbeNoCommand }, {"NOACCENTS", true, &fbeNoAccents }, {"NOBLEED", true, &fbeNoBleed }, {"NOSPOOF", true, &fbeNoSpoof }, {"OPAQUE", true, &fbeOpaque }, {"OPEN_OK", true, &fbeOpenOk }, {"PARENT_OK", true, &fbeParentOk }, {"PLAYER_MAILS", true, &fbePlayerMails }, {"PUPPET", true, &fbePuppet }, {"QUIET", true, &fbeQuiet }, {"ROBOT", true, &fbeRobot }, {"ROYALTY", true, &fbeRoyalty }, {"SAFE", true, &fbeSafe }, {"SITEMON", true, &fbeSitemon }, {"SLAVE", true, &fbeSlave }, {"SPOOF", false, &fbeNoSpoof }, {"STAFF", true, &fbeStaff }, {"STICKY", true, &fbeSticky }, {"SUSPECT", true, &fbeSuspect }, {"TERSE", true, &fbeTerse }, {"TRACE", true, &fbeTrace }, {"TRANSPARENT", true, &fbeTransparent }, {"UNFINDABLE", true, &fbeUnfindable }, {"UNINSPECTED", true, &fbeUninspected }, {"VACATION", true, &fbeVacation }, {"VERBOSE", true, &fbeVerbose }, {"VISUAL", true, &fbeVisual }, {"WIZARD", true, &fbeWizard }, #ifdef WOD_REALMS {"FAE", true, &fbeFae }, {"CHIMERA", true, &fbeChimera }, {"PEERING", true, &fbePeering }, {"UMBRA", true, &fbeUmbra }, {"SHROUD", true, &fbeShroud }, {"MATRIX", true, &fbeMatrix }, {"OBF", true, &fbeObf }, {"HSS", true, &fbeHss }, {"MEDIUM", true, &fbeMedium }, {"DEAD", true, &fbeDead }, #endif // WOD_REALMS {NULL, false, NULL} }; OBJENT object_types[8] = { {"ROOM", 'R', CA_PUBLIC, OF_CONTENTS|OF_EXITS|OF_DROPTO|OF_HOME}, {"THING", ' ', CA_PUBLIC, OF_CONTENTS|OF_LOCATION|OF_EXITS|OF_HOME|OF_SIBLINGS}, {"EXIT", 'E', CA_PUBLIC, OF_SIBLINGS}, {"PLAYER", 'P', CA_PUBLIC, OF_CONTENTS|OF_LOCATION|OF_EXITS|OF_HOME|OF_OWNER|OF_SIBLINGS}, {"TYPE5", '+', CA_GOD, 0}, {"GARBAGE", '-', CA_PUBLIC, OF_CONTENTS|OF_LOCATION|OF_EXITS|OF_HOME|OF_SIBLINGS}, {"GARBAGE", '#', CA_GOD, 0} }; /* --------------------------------------------------------------------------- * init_flagtab: initialize flag hash tables. */ void init_flagtab(void) { char *nbuf = alloc_sbuf("init_flagtab"); for (FLAGNAMEENT *fp = gen_flag_names; fp->pOrigName; fp++) { fp->flagname = fp->pOrigName; strncpy(nbuf, fp->pOrigName, SBUF_SIZE); nbuf[SBUF_SIZE-1] = '\0'; mux_strlwr(nbuf); hashaddLEN(nbuf, strlen(nbuf), fp, &mudstate.flags_htab); } free_sbuf(nbuf); } /* --------------------------------------------------------------------------- * display_flags: display available flags. */ void display_flagtab(dbref player) { char *buf, *bp; FLAGNAMEENT *fp; bp = buf = alloc_lbuf("display_flagtab"); safe_str("Flags:", buf, &bp); for (fp = gen_flag_names; fp->flagname; fp++) { FLAGBITENT *fbe = fp->fbe; if ( ( (fbe->listperm & CA_WIZARD) && !Wizard(player)) || ( (fbe->listperm & CA_GOD) && !God(player))) { continue; } safe_chr(' ', buf, &bp); safe_str(fp->flagname, buf, &bp); if (fbe->flaglett != ' ') { safe_chr('(', buf, &bp); if (!fp->bPositive) { safe_chr('!', buf, &bp); } safe_chr(fbe->flaglett, buf, &bp); safe_chr(')', buf, &bp); } } *bp = '\0'; notify(player, buf); free_lbuf(buf); } char *MakeCanonicalFlagName ( const char *pName, int *pnName, bool *pbValid ) { static char buff[SBUF_SIZE]; char *p = buff; int nName = 0; while (*pName && nName < SBUF_SIZE) { *p = mux_tolower(*pName); p++; pName++; nName++; } *p = '\0'; if (nName < SBUF_SIZE) { *pnName = nName; *pbValid = true; return buff; } else { *pnName = 0; *pbValid = false; return NULL; } } FLAGNAMEENT *find_flag(char *flagname) { // Convert flagname to canonical lowercase format. // int nName; bool bValid; char *pName = MakeCanonicalFlagName(flagname, &nName, &bValid); FLAGNAMEENT *fe = NULL; if (bValid) { fe = (FLAGNAMEENT *)hashfindLEN(pName, nName, &mudstate.flags_htab); } return fe; } // --------------------------------------------------------------------------- // flag_set: Set or clear a specified flag on an object. // void flag_set(dbref target, dbref player, char *flag, int key) { bool bDone = false; do { // Trim spaces, and handle the negation character. // while (mux_isspace(*flag)) { flag++; } bool bNegate = false; if (*flag == '!') { bNegate = true; do { flag++; } while (mux_isspace(*flag)); } // Beginning of flag name is now 'flag'. // char *nflag = flag; while ( *nflag != '\0' && !mux_isspace(*nflag)) { nflag++; } if (*nflag == '\0') { bDone = true; } else { *nflag = '\0'; } // Make sure a flag name was specified. // if (*flag == '\0') { if (bNegate) { notify(player, "You must specify a flag to clear."); } else { notify(player, "You must specify a flag to set."); } } else { FLAGNAMEENT *fp = find_flag(flag); if (!fp) { notify(player, "I do not understand that flag."); } else { FLAGBITENT *fbe = fp->fbe; bool bClearSet = bNegate; if (!fp->bPositive) { bNegate = !bNegate; } // Invoke the flag handler, and print feedback. // if (!fbe->handler(target, player, fbe->flagvalue, fbe->flagflag, bNegate)) { notify(player, NOPERM_MESSAGE); } else if (!(key & SET_QUIET) && !Quiet(player)) { notify(player, (bClearSet ? "Cleared." : "Set.")); } } } flag = nflag + 1; } while (!bDone); } /* * --------------------------------------------------------------------------- * * decode_flags: converts a flags word into corresponding letters. */ char *decode_flags(dbref player, FLAGSET *fs) { char *buf, *bp; buf = bp = alloc_sbuf("decode_flags"); *bp = '\0'; if (!Good_obj(player)) { strcpy(buf, "#-2 ERROR"); return buf; } int flagtype = fs->word[FLAG_WORD1] & TYPE_MASK; bool bNeedColon = true; if (object_types[flagtype].lett != ' ') { safe_sb_chr(object_types[flagtype].lett, buf, &bp); bNeedColon = false; } FLAGNAMEENT *fp; for (fp = gen_flag_names; fp->flagname; fp++) { FLAGBITENT *fbe = fp->fbe; if ( !fp->bPositive || fbe->flaglett == ' ') { // Only look at positive-sense entries that have non-space flag // letters. // continue; } if (fs->word[fbe->flagflag] & fbe->flagvalue) { if ( ( (fbe->listperm & CA_STAFF) && !Staff(player)) || ( (fbe->listperm & CA_ADMIN) && !WizRoy(player)) || ( (fbe->listperm & CA_WIZARD) && !Wizard(player)) || ( (fbe->listperm & CA_GOD) && !God(player))) { continue; } // Don't show CONNECT on dark wizards to mortals // if ( flagtype == TYPE_PLAYER && fbe->flagflag == FLAG_WORD2 && fbe->flagvalue == CONNECTED && (fs->word[FLAG_WORD1] & (WIZARD | DARK)) == (WIZARD | DARK) && !See_Hidden(player)) { continue; } if ( bNeedColon && mux_isdigit(fbe->flaglett)) { // We can't allow numerical digits at the beginning. // safe_sb_chr(':', buf, &bp); } safe_sb_chr(fbe->flaglett, buf, &bp); bNeedColon = false; } } *bp = '\0'; return buf; } /* * --------------------------------------------------------------------------- * * has_flag: does object have flag visible to player? */ bool has_flag(dbref player, dbref it, char *flagname) { FLAGNAMEENT *fp = find_flag(flagname); if (!fp) { return false; } FLAGBITENT *fbe = fp->fbe; if ( ( fp->bPositive && (db[it].fs.word[fbe->flagflag] & fbe->flagvalue)) || ( !fp->bPositive && (db[it].fs.word[fbe->flagflag] & fbe->flagvalue) == 0)) { if ( ( (fbe->listperm & CA_STAFF) && !Staff(player)) || ( (fbe->listperm & CA_ADMIN) && !WizRoy(player)) || ( (fbe->listperm & CA_WIZARD) && !Wizard(player)) || ( (fbe->listperm & CA_GOD) && !God(player))) { return false; } // Don't show CONNECT on dark wizards to mortals // if ( isPlayer(it) && (fbe->flagvalue == CONNECTED) && (fbe->flagflag == FLAG_WORD2) && Hidden(it) && !See_Hidden(player)) { return false; } return true; } return false; } /* * --------------------------------------------------------------------------- * * flag_description: Return an mbuf containing the type and flags on thing. */ char *flag_description(dbref player, dbref target) { // Allocate the return buffer. // int otype = Typeof(target); char *buff = alloc_mbuf("flag_description"); char *bp = buff; // Store the header strings and object type. // safe_mb_str("Type: ", buff, &bp); safe_mb_str(object_types[otype].name, buff, &bp); safe_mb_str(" Flags:", buff, &bp); if (object_types[otype].perm != CA_PUBLIC) { *bp = '\0'; return buff; } // Store the type-invariant flags. // FLAGNAMEENT *fp; for (fp = gen_flag_names; fp->flagname; fp++) { if (!fp->bPositive) { continue; } FLAGBITENT *fbe = fp->fbe; if (db[target].fs.word[fbe->flagflag] & fbe->flagvalue) { if ( ( (fbe->listperm & CA_STAFF) && !Staff(player)) || ( (fbe->listperm & CA_ADMIN) && !WizRoy(player)) || ( (fbe->listperm & CA_WIZARD) && !Wizard(player)) || ( (fbe->listperm & CA_GOD) && !God(player))) { continue; } // Don't show CONNECT on dark wizards to mortals. // if ( isPlayer(target) && (fbe->flagvalue == CONNECTED) && (fbe->flagflag == FLAG_WORD2) && Hidden(target) && !See_Hidden(player)) { continue; } safe_mb_chr(' ', buff, &bp); safe_mb_str(fp->flagname, buff, &bp); } } // Terminate the string, and return the buffer to the caller. // *bp = '\0'; return buff; } /* * --------------------------------------------------------------------------- * * Return an lbuf containing the name and number of an object */ char *unparse_object_numonly(dbref target) { char *buf = alloc_lbuf("unparse_object_numonly"); if (target < 0) { strcpy(buf, aszSpecialDBRefNames[-target]); } else if (!Good_obj(target)) { sprintf(buf, "*ILLEGAL*(#%d)", target); } else { sprintf(buf, "%.200s(#%d)", Name(target), target); } return buf; } /* * --------------------------------------------------------------------------- * * Return an lbuf pointing to the object name and possibly the db# and flags */ char *unparse_object(dbref player, dbref target, bool obey_myopic) { char *buf = alloc_lbuf("unparse_object"); if (NOPERM <= target && target < 0) { strcpy(buf, aszSpecialDBRefNames[-target]); } else if (!Good_obj(target)) { sprintf(buf, "*ILLEGAL*(#%d)", target); } else { bool exam; if (obey_myopic) { exam = MyopicExam(player, target); } else { exam = Examinable(player, target); } if ( exam || (Flags(target) & (CHOWN_OK | JUMP_OK | LINK_OK | DESTROY_OK)) || (Flags2(target) & ABODE)) { // show everything // char *fp = decode_flags(player, &(db[target].fs)); sprintf(buf, "%.200s(#%d%s)", Moniker(target), target, fp); free_sbuf(fp); } else { // show only the name. // strcpy(buf, Moniker(target)); } } return buf; } /* --------------------------------------------------------------------------- * cf_flag_access: Modify who can set a flag. */ CF_HAND(cf_flag_access) { MUX_STRTOK_STATE tts; mux_strtok_src(&tts, str); mux_strtok_ctl(&tts, " \t=,"); char *fstr = mux_strtok_parse(&tts); char *permstr = mux_strtok_parse(&tts); if (!fstr || !*fstr) { return -1; } FLAGNAMEENT *fp; if ((fp = find_flag(fstr)) == NULL) { cf_log_notfound(player, cmd, "No such flag", fstr); return -1; } FLAGBITENT *fbe = fp->fbe; // Don't change the handlers on special things. // if ( (fbe->handler != fh_any) && (fbe->handler != fh_wizroy) && (fbe->handler != fh_wiz) && (fbe->handler != fh_god) && (fbe->handler != fh_restrict_player) && (fbe->handler != fh_privileged)) { STARTLOG(LOG_CONFIGMODS, "CFG", "PERM"); log_text("Cannot change access for flag: "); log_text(fp->flagname); ENDLOG; return -1; } if (!strcmp(permstr, "any")) { fbe->handler = fh_any; } else if (!strcmp(permstr, "royalty")) { fbe->handler = fh_wizroy; } else if (!strcmp(permstr, "wizard")) { fbe->handler = fh_wiz; } else if (!strcmp(permstr, "god")) { fbe->handler = fh_god; } else if (!strcmp(permstr, "restrict_player")) { fbe->handler = fh_restrict_player; } else if (!strcmp(permstr, "privileged")) { fbe->handler = fh_privileged; } else if (!strcmp(permstr, "staff")) { fbe->handler = fh_staff; } else { cf_log_notfound(player, cmd, "Flag access", permstr); return -1; } return 0; } /* * --------------------------------------------------------------------------- * * convert_flags: convert a list of flag letters into its bit pattern. * * Also set the type qualifier if specified and not already set. */ bool convert_flags(dbref player, char *flaglist, FLAGSET *fset, FLAG *p_type) { FLAG type = NOTYPE; FLAGSET flagmask; int i; for (i = FLAG_WORD1; i <= FLAG_WORD3; i++) { flagmask.word[i] = 0; } char *s; bool handled; for (s = flaglist; *s; s++) { handled = false; // Check for object type. // for (i = 0; i <= 7 && !handled; i++) { if ( object_types[i].lett == *s && !( ( (object_types[i].perm & CA_STAFF) && !Staff(player)) || ( (object_types[i].perm & CA_ADMIN) && !WizRoy(player)) || ( (object_types[i].perm & CA_WIZARD) && !Wizard(player)) || ( (object_types[i].perm & CA_GOD) && !God(player)))) { if ( type != NOTYPE && type != i) { char *p = tprintf("%c: Conflicting type specifications.", *s); notify(player, p); return false; } type = i; handled = true; } } // Check generic flags. // if (handled) { continue; } FLAGNAMEENT *fp; for (fp = gen_flag_names; fp->flagname && !handled; fp++) { FLAGBITENT *fbe = fp->fbe; if ( !fp->bPositive || fbe->flaglett == ' ') { continue; } if ( fbe->flaglett == *s && !( ( (fbe->listperm & CA_STAFF) && !Staff(player)) || ( (fbe->listperm & CA_ADMIN) && !WizRoy(player)) || ( (fbe->listperm & CA_WIZARD) && !Wizard(player)) || ( (fbe->listperm & CA_GOD) && !God(player)))) { flagmask.word[fbe->flagflag] |= fbe->flagvalue; handled = true; } } if (!handled) { notify(player, tprintf("%c: Flag unknown or not valid for specified object type", *s)); return false; } } // Return flags to search for and type. // *fset = flagmask; *p_type = type; return true; } /* * --------------------------------------------------------------------------- * * decompile_flags: Produce commands to set flags on target. */ void decompile_flags(dbref player, dbref thing, char *thingname) { // Report generic flags. // FLAGNAMEENT *fp; for (fp = gen_flag_names; fp->flagname; fp++) { FLAGBITENT *fbe = fp->fbe; // Only handle positive-sense entries. // Skip if we shouldn't decompile this flag. // Skip if this flag isn't set. // Skip if we can't see this flag. // if ( !fp->bPositive || (fbe->listperm & CA_NO_DECOMP) || (db[thing].fs.word[fbe->flagflag] & fbe->flagvalue) == 0 || !check_access(player, fbe->listperm)) { continue; } // Report this flag. // notify(player, tprintf("@set %s=%s", strip_ansi(thingname), fp->flagname)); } } // do_flag: Rename flags or remove flag aliases. // Based on RhostMUSH code. // bool flag_rename(char *alias, char *newname) { int nAlias; bool bValidAlias; char *pCheckedAlias = MakeCanonicalFlagName(alias, &nAlias, &bValidAlias); if (!bValidAlias) { return false; } char *pAlias = alloc_sbuf("flag_rename.old"); memcpy(pAlias, pCheckedAlias, nAlias+1); int nNewName; bool bValidNewName; char *pCheckedNewName = MakeCanonicalFlagName(newname, &nNewName, &bValidNewName); if (!bValidNewName) { free_sbuf(pAlias); return false; } char *pNewName = alloc_sbuf("flag_rename.new"); memcpy(pNewName, pCheckedNewName, nNewName+1); FLAGNAMEENT *flag1; flag1 = (FLAGNAMEENT *)hashfindLEN(pAlias, nAlias, &mudstate.flags_htab); if (flag1 != NULL) { FLAGNAMEENT *flag2; flag2 = (FLAGNAMEENT *)hashfindLEN(pNewName, nNewName, &mudstate.flags_htab); if (flag2 == NULL) { hashaddLEN(pNewName, nNewName, flag1, &mudstate.flags_htab); if (flag1->flagname != flag1->pOrigName) { MEMFREE(flag1->flagname); } flag1->flagname = StringCloneLen(pNewName, nNewName); mux_strupr(flag1->flagname); free_sbuf(pAlias); free_sbuf(pNewName); return true; } } free_sbuf(pAlias); free_sbuf(pNewName); return false; } void do_flag(dbref executor, dbref caller, dbref enactor, int key, int nargs, char *flag1, char *flag2) { if (key & FLAG_REMOVE) { if (nargs == 2) { notify(executor, "Extra argument ignored."); } int nAlias; bool bValidAlias; char *pCheckedAlias = MakeCanonicalFlagName(flag1, &nAlias, &bValidAlias); if (bValidAlias) { FLAGNAMEENT *lookup; lookup = (FLAGNAMEENT *)hashfindLEN(pCheckedAlias, nAlias, &mudstate.flags_htab); if (lookup) { if ( lookup->flagname != lookup->pOrigName && mux_stricmp(lookup->flagname, pCheckedAlias) == 0) { MEMFREE(lookup->flagname); lookup->flagname = lookup->pOrigName; hashdeleteLEN(pCheckedAlias, nAlias, &mudstate.flags_htab); notify(executor, tprintf("Flag name '%s' removed from the hash table.", pCheckedAlias)); } else { notify(executor, "Error: You can't remove the present flag name from the hash table."); } } } } else { if (nargs < 2) { notify(executor, "You must specify a flag and a name."); return; } if (flag_rename(flag1, flag2)) { notify(executor, "Flag name changed."); } else { notify(executor, "Error: Bad flagname given or flag not found."); } } } /* --------------------------------------------------------------------------- * cf_flag_name: Rename a flag. Counterpart to @flag. */ CF_HAND(cf_flag_name) { MUX_STRTOK_STATE tts; mux_strtok_src(&tts, str); mux_strtok_ctl(&tts, " \t=,"); char *flagstr = mux_strtok_parse(&tts); char *namestr = mux_strtok_parse(&tts); if ( !flagstr || !*flagstr || !namestr || !*namestr) { return -1; } if (flag_rename(flagstr, namestr)) { return 0; } else { return -1; } }