/************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefiting. We hope that you share your changes too. What goes * * around, comes around. * *************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * *************************************************************************** * 1stMUD ROM Derivative (c) 2001-2003 by Ryan Jennings * * http://1stmud.dlmud.com/ <r-jenn@shaw.ca> * ***************************************************************************/ #include "merc.h" #include "recycle.h" #include "interp.h" #include "tablesave.h" /* The quoting character -- what overrides wildcards (do not undef) */ #define QUOTE '\\' /* The "matches ANYTHING" wildcard (do not undef) */ #define WILDS '*' /* The "matches ANY NUMBER OF NON-SPACE CHARS" wildcard (do not undef) */ #define WILDP '%' /* The "matches EXACTLY ONE CHARACTER" wildcard (do not undef) */ #define WILDQ '?' /* Changing these is probably counter-productive :) */ #define MATCH (match+saved+sofar) #define NOMATCH 0 int wild_match(register unsigned char *m, register unsigned char *n) { unsigned char *ma = m, *lsm = 0, *lsn = 0, *lpm = 0, *lpn = 0; int match = 1, saved = 0; register unsigned int sofar = 0; /* take care of null strings (should never match) */ if ((m == 0) || (n == 0) || (!*n)) return NOMATCH; /* (!*m) test used to be here, too, but I got rid of it. After all, If (!*n) was FALSE, there must be a character in the name (the second string), so if the mask is empty it is a non-match. Since the algorithm handles this correctly without testing for it here and this shouldn't be called with null masks anyway, it should be a bit faster this way */ while (*n) { /* Used to test for (!*m) here, but this scheme seems to work better */ switch (*m) { case 0: do m--; /* Search backwards */ while ((m > ma) && (*m == '?')); /* For first non-? char */ if ((m > ma) ? ((*m == '*') && (m[-1] != QUOTE)) : (*m == '*')) return MATCH; /* nonquoted * = match */ break; case WILDP: while (*(++m) == WILDP); /* Zap redundant %s */ if (*m != WILDS) { /* Don't both if next=* */ if (*n != ' ') { /* WILDS can't match ' ' */ lpm = m; lpn = n; /* Save % fallback spot */ saved += sofar; sofar = 0; /* And save tally count */ } continue; /* Done with % */ } /* FALL THROUGH */ case WILDS: do m++; /* Zap redundant wilds */ while ((*m == WILDS) || (*m == WILDP)); lsm = m; lsn = n; lpm = 0; /* Save * fallback spot */ match += (saved + sofar); /* Save tally count */ saved = sofar = 0; continue; /* Done with * */ case WILDQ: m++; n++; continue; /* Match one char */ case QUOTE: m++; /* Handle quoting */ } if (tolower(*m) == tolower(*n)) { /* If matching */ m++; n++; sofar++; continue; /* Tally the match */ } if (lpm) { /* Try to fallback on % */ n = ++lpn; m = lpm; sofar = 0; /* Restore position */ if ((*n | 32) == 32) lpm = 0; /* Can't match 0 or ' ' */ continue; /* Next char, please */ } if (lsm) { /* Try to fallback on * */ n = ++lsn; m = lsm; /* Restore position */ /* Used to test for (!*n) here but it wasn't necessary so it's gone */ saved = sofar = 0; continue; /* Next char, please */ } return NOMATCH; /* No fallbacks=No match */ } while ((*m == WILDS) || (*m == WILDP)) m++; /* Zap leftover %s & *s */ return (*m) ? NOMATCH : MATCH; /* End of both = match */ } BAN_DATA ban; const struct savetable_type bansavetable[] = { {"name", FIELD_STRING, (void *) &ban.name, NULL, NULL}, {"level", FIELD_INT, (void *) &ban.level, NULL, NULL}, {"flags", FIELD_FLAGVECTOR, (void *) &ban.ban_flags, NULL, NULL}, {NULL, 0, NULL, NULL, NULL} }; TABLESAVE(rw_bans) { rw_list(type, BAN_FILE, BAN_DATA, ban_first, ban_last, next, prev, new_ban, "BAN", ban, bansavetable); } bool check_ban(const char *site, int type) { BAN_DATA *pban; char host[MAX_STRING_LENGTH]; strcpy(host, capitalize(site)); host[0] = LOWER(host[0]); for (pban = ban_first; pban != NULL; pban = pban->next) { if (!IS_SET(pban->ban_flags, type)) continue; if (wild_match((unsigned char *) pban->name, (unsigned char *) host)) return TRUE; } return FALSE; } void ban_site(CHAR_DATA * ch, const char *argument) { char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH]; BUFFER *buffer; BAN_DATA *pban, *prev; int type; argument = one_argument(argument, arg1); argument = one_argument(argument, arg2); if (IS_NULLSTR(arg1)) { if (ban_first == NULL) { chprintln(ch, "No sites banned at this time."); return; } buffer = new_buf(); bprintln(buffer, "Banned sites level type"); for (pban = ban_first; pban != NULL; pban = pban->next) { bprintlnf(buffer, "%-12s %-3d %s", pban->name, pban->level, IS_SET(pban->ban_flags, BAN_NEWBIES) ? "newbies" : IS_SET(pban->ban_flags, BAN_PERMIT) ? "permit" : IS_SET(pban->ban_flags, BAN_ALL) ? "all" : ""); } sendpage(ch, buf_string(buffer)); free_buf(buffer); return; } /* find out what type of ban */ if (IS_NULLSTR(arg2) || !str_prefix(arg2, "all")) type = BAN_ALL; else if (!str_prefix(arg2, "newbies")) type = BAN_NEWBIES; else if (!str_prefix(arg2, "permit")) type = BAN_PERMIT; else { chprintln(ch, "Acceptable ban types are all, newbies, and permit."); return; } if (strlen(arg1) == 0) { chprintln(ch, "You have to ban SOMETHING."); return; } prev = NULL; for (pban = ban_first; pban != NULL; pban = prev) { prev = pban->next; if (!str_cmp(arg1, pban->name)) { if (pban->level > get_trust(ch)) { chprintln(ch, "That ban was set by a higher power."); return; } else { UNLINK(pban, ban_first, ban_last, next, prev); free_ban(pban); } } } pban = new_ban(); pban->name = str_dup(arg1); pban->level = get_trust(ch); /* set ban type */ pban->ban_flags = type; LINK(pban, ban_first, ban_last, next, prev); rw_bans(action_write); chprintlnf(ch, "%s has been banned.", pban->name); return; } CH_CMD(do_ban) { ban_site(ch, argument); } CH_CMD(do_allow) { char arg[MAX_INPUT_LENGTH]; BAN_DATA *prev; BAN_DATA *curr; one_argument(argument, arg); if (IS_NULLSTR(arg)) { chprintln(ch, "Remove which site from the ban list?"); return; } prev = NULL; for (curr = ban_first; curr != NULL; curr = prev) { prev = curr->next; if (!str_cmp(arg, curr->name)) { if (curr->level > get_trust(ch)) { chprintln(ch, "You are not powerful enough to lift that ban."); return; } UNLINK(curr, ban_first, ban_last, next, prev); free_ban(curr); chprintlnf(ch, "Ban on %s lifted.", arg); rw_bans(action_write); return; } } chprintln(ch, "Site is not banned."); return; }