/**************************************************************************
* 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;
}