/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// *
* -----------------------------------------------------------| (0...0) *
* SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( *
* -----------------------------------------------------------| {o o} *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~*
* Tricops and Fireblade | *
* ------------------------------------------------------------------------ *
* Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* ------------------------------------------------------------------------ *
* Ban module by Shaddai *
****************************************************************************/
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <time.h>
#include "h/mud.h"
#include "h/ban.h"
#include "h/files.h"
/* Local functions */
void fread_ban args((FILE * fp, int type));
bool check_expire args((BAN_DATA *ban));
void dispose_ban args((BAN_DATA *ban, int type));
void free_ban args((BAN_DATA *pban));
/* Global Variables */
BAN_DATA *first_ban;
BAN_DATA *last_ban;
BAN_DATA *first_ban_class;
BAN_DATA *last_ban_class;
BAN_DATA *first_ban_race;
BAN_DATA *last_ban_race;
/*
* Load all those nasty bans up :)
* Shaddai
*/
void load_banlist(void)
{
const char *word;
FILE *fp;
bool fMatch = FALSE;
if(!(fp = FileOpen(SYSTEM_DIR BAN_LIST, "r")))
{
bug("load_banlist: Cannot open %s", BAN_LIST);
perror(BAN_LIST);
return;
}
for(;;)
{
word = feof(fp) ? "END" : fread_word(fp);
fMatch = FALSE;
switch (UPPER(word[0]))
{
case 'C':
if(!str_cmp(word, "CLASS"))
{
fread_ban(fp, BAN_CLASS);
fMatch = TRUE;
}
break;
case 'E':
if(!str_cmp(word, "END"))
{ /* File should always contain END */
FileClose(fp);
log_string("Done.");
return;
}
case 'R':
if(!str_cmp(word, "RACE"))
{
fread_ban(fp, BAN_RACE);
fMatch = TRUE;
}
break;
case 'S':
if(!str_cmp(word, "SITE"))
{
fread_ban(fp, BAN_SITE);
fMatch = TRUE;
}
break;
}
if(!fMatch)
{
bug("Load_banlist: no match: %s", word);
fread_to_eol(fp);
} /* End of switch statement */
} /* End of for loop */
}
/*
* Load up one class or one race ban structure.
*/
void fread_ban(FILE * fp, int type)
{
BAN_DATA *pban;
unsigned int i = 0;
bool fMatch = FALSE;
CREATE(pban, BAN_DATA, 1);
pban->name = fread_string(fp);
pban->level = fread_number(fp);
pban->duration = fread_number(fp);
pban->unban_date = fread_number(fp);
if(type == BAN_SITE)
{ /* Sites have 2 extra numbers written out */
pban->prefix = fread_number(fp);
pban->suffix = fread_number(fp);
}
pban->warn = fread_number(fp);
pban->ban_by = fread_string(fp);
pban->ban_time = fread_string(fp);
pban->note = fread_string(fp);
/*
* Need to lookup the class or race number if it is of that type
*/
if(type == BAN_CLASS)
for(i = 0; i < MAX_CLASS; i++)
{
if(!str_cmp(class_table[i]->who_name, pban->name))
{
fMatch = TRUE;
break;
}
}
else if(type == BAN_RACE)
for(i = 0; i < MAX_RACE; i++)
{
if(!str_cmp(race_table[i]->race_name, pban->name))
{
fMatch = TRUE;
break;
}
}
else if(type == BAN_SITE)
for(i = 0; i < strlen(pban->name); i++)
{
if(pban->name[i] == '@')
{
char *temp;
char *temp2;
temp = STRALLOC(pban->name);
temp[i] = '\0';
temp2 = &pban->name[i + 1];
STRFREE(pban->name);
pban->name = STRALLOC(temp2);
DISPOSE(temp);
break;
}
}
if(type == BAN_RACE || type == BAN_CLASS)
{
if(fMatch)
pban->flag = i;
else
{ /* The file is corupted throw out * * * * this ban structure */
bug("Bad class structure %d.\r\n", i);
free_ban(pban);
return;
}
}
if(type == BAN_CLASS)
LINK(pban, first_ban_class, last_ban_class, next, prev);
else if(type == BAN_RACE)
LINK(pban, first_ban_race, last_ban_race, next, prev);
else if(type == BAN_SITE)
LINK(pban, first_ban, last_ban, next, prev);
else
{ /* Bad type throw out the ban * * * * structure */
bug("Fread_ban: Bad type %d", type);
free_ban(pban);
}
return;
}
/*
* Saves all bans, for sites, classes and races.
* Shaddai
*/
void save_banlist(void)
{
BAN_DATA *pban;
FILE *fp;
if(!(fp = FileOpen(SYSTEM_DIR BAN_LIST, "w")))
{
bug("Save_banlist: Cannot open %s", BAN_LIST);
perror(BAN_LIST);
return;
}
/*
* Print out all the site bans
*/
for(pban = first_ban; pban; pban = pban->next)
{
fprintf(fp, "SITE\n");
fprintf(fp, "%s~\n", pban->name);
fprintf(fp, "%d %d %d %d %d %d\n", pban->level, pban->duration, pban->unban_date, pban->prefix, pban->suffix, pban->warn);
fprintf(fp, "%s~\n%s~\n%s~\n", pban->ban_by, pban->ban_time, pban->note);
}
/*
* Print out all the race bans
*/
for(pban = first_ban_race; pban; pban = pban->next)
{
fprintf(fp, "RACE\n");
fprintf(fp, "%s~\n", pban->name);
fprintf(fp, "%d %d %d %d\n", pban->level, pban->duration, pban->unban_date, pban->warn);
fprintf(fp, "%s~\n%s~\n%s~\n", pban->ban_by, pban->ban_time, pban->note);
}
/*
* Print out all the class bans
*/
for(pban = first_ban_class; pban; pban = pban->next)
{
fprintf(fp, "CLASS\n");
fprintf(fp, "%s~\n", pban->name);
fprintf(fp, "%d %d %d %d\n", pban->level, pban->duration, pban->unban_date, pban->warn);
fprintf(fp, "%s~\n%s~\n%s~\n", pban->ban_by, pban->ban_time, pban->note);
}
fprintf(fp, "END\n"); /* File must have an END even if * empty */
FileClose(fp);
return;
}
/*
* The main command for ban, lots of arguments so be carefull what you
* change here. Shaddai
*/
void do_ban(CHAR_DATA *ch, char *argument)
{
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
char arg3[MAX_INPUT_LENGTH];
char arg4[MAX_INPUT_LENGTH];
char *temp;
BAN_DATA *pban;
int value = 0, btime;
if(IS_NPC(ch))
{ /* Don't want mobs banning sites * ;) */
send_to_char("Monsters are too dumb to do that!\r\n", ch);
return;
}
if(!ch->desc)
{ /* No desc means no go :) */
bug("%s", "do_ban: no descriptor");
return;
}
set_char_color(AT_IMMORT, ch);
argument = one_argument(argument, arg1);
argument = one_argument(argument, arg2);
argument = one_argument(argument, arg3);
argument = one_argument(argument, arg4);
/*
* Do we have a time duration for the ban?
*/
if(arg4[0] != '\0' && is_number(arg4))
btime = atoi(arg4);
else
btime = -1;
/*
* -1 is default, but no reason the time should be greater than 1000
* * or less than 1, after all if it is greater than 1000 you are talking
* * around 3 years.
*/
if(btime != -1 && (btime < 1 || btime > 1000))
{
send_to_char("Time value is -1 (forever) or from 1 to 1000.\r\n", ch);
return;
}
/*
* Need to be carefull with sub-states or everything will get messed up.
*/
switch (ch->substate)
{
default:
bug("%s", "do_ban: illegal substate");
return;
case SUB_RESTRICTED:
send_to_char("You cannot use this command from within another command.\r\n", ch);
return;
case SUB_NONE:
ch->tempnum = SUB_NONE;
break;
/*
* Returning to end the editing of the note
*/
case SUB_BAN_DESC:
add_ban(ch, (char *)"", (char *)"", 0, 0);
return;
}
if(arg1[0] == '\0')
goto syntax_message;
/*
* If no args are sent after the class/site/race, show the current banned
* * items. Shaddai
*/
if(!str_cmp(arg1, "site"))
{
if(arg2[0] == '\0')
{
show_bans(ch, BAN_SITE);
return;
}
/*
* Are they high enough to ban sites?
*/
if(get_trust(ch) < sysdata.ban_site_level)
{
ch_printf(ch, "You must be %d level to add bans.\r\n", sysdata.ban_site_level);
return;
}
if(arg3[0] == '\0')
goto syntax_message;
if(!add_ban(ch, arg2, arg3, btime, BAN_SITE))
return;
}
else if(!str_cmp(arg1, "race"))
{
if(arg2[0] == '\0')
{
show_bans(ch, BAN_RACE);
return;
}
/*
* Are they high enough level to ban races?
*/
if(get_trust(ch) < sysdata.ban_race_level)
{
ch_printf(ch, "You must be %d level to add bans.\r\n", sysdata.ban_race_level);
return;
}
if(arg3[0] == '\0')
goto syntax_message;
if(!add_ban(ch, arg2, arg3, btime, BAN_RACE))
return;
}
else if(!str_cmp(arg1, "class"))
{
if(arg2[0] == '\0')
{
show_bans(ch, BAN_CLASS);
return;
}
/*
* Are they high enough to ban classes?
*/
if(get_trust(ch) < sysdata.ban_class_level)
{
ch_printf(ch, "You must be %d level to add bans.\r\n", sysdata.ban_class_level);
return;
}
if(arg3[0] == '\0')
goto syntax_message;
if(!add_ban(ch, arg2, arg3, btime, BAN_CLASS))
return;
}
else if(!str_cmp(arg1, "show"))
{
/*
* This will show the note attached to a ban
*/
if(arg2[0] == '\0' || arg3[0] == '\0')
goto syntax_message;
temp = arg3;
if(arg3[0] == '#')
{ /* Use #1 to show the first ban */
temp = arg3;
temp++;
if(!is_number(temp))
{
send_to_char("Which ban # to show?\r\n", ch);
return;
}
value = atoi(temp);
if(value < 1)
{
send_to_char("You must specify a number greater than 0.\r\n", ch);
return;
}
}
if(!str_cmp(arg2, "site"))
{
pban = first_ban;
if(temp[0] == '*')
temp++;
if(temp[strlen(temp) - 1] == '*')
temp[strlen(temp) - 1] = '\0';
}
else if(!str_cmp(arg2, "class"))
pban = first_ban_class;
else if(!str_cmp(arg2, "race"))
pban = first_ban_race;
else
goto syntax_message;
for(; pban; pban = pban->next)
if(value == 1 || !str_cmp(pban->name, temp))
break;
else if(value > 1)
value--;
if(!pban)
{
send_to_char("No such ban.\r\n", ch);
return;
}
ch_printf(ch, "Banned by: %s\r\n", pban->ban_by);
send_to_char(pban->note, ch);
return;
}
else
goto syntax_message;
return;
/* Catch all syntax message, make sure that return stays above this or you
* will get the syntax message everytime you issue the command even if it
* is a valid one. Shaddai
*/
syntax_message:
send_to_char("Syntax: ban site <address> <type> <duration>\r\n", ch);
send_to_char("Syntax: ban race <race> <type> <duration>\r\n", ch);
send_to_char("Syntax: ban class <class> <type> <duration>\r\n", ch);
send_to_char("Syntax: ban show <field> <number>\r\n", ch);
send_to_char("Ban site lists current bans.\r\n", ch);
send_to_char("Duration is the length of the ban in days.\r\n", ch);
send_to_char("Type can be: newbie, mortal, all, warn or level.\r\n", ch);
send_to_char("In ban show, the <field> is site, race or class,", ch);
send_to_char(" and the <number> is the ban number.\r\n", ch);
return;
}
/*
* Allow a already banned site/class or race. Shaddai
*/
void do_allow(CHAR_DATA *ch, char *argument)
{
BAN_DATA *pban;
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
char *temp = NULL;
bool fMatch = FALSE;
int value = 0;
if(IS_NPC(ch))
{ /* No mobs allowing sites */
send_to_char("Monsters are too dumb to do that!\r\n", ch);
return;
}
if(!ch->desc)
{ /* No desc is a bad thing */
bug("%s", "do_allow: no descriptor");
return;
}
argument = one_argument(argument, arg1);
argument = one_argument(argument, arg2);
set_char_color(AT_IMMORT, ch);
if(arg1[0] == '\0' || arg2[0] == '\0')
goto syntax_message;
if(arg2[0] == '#')
{ /* Use #1 to ban the first ban in * the list specified */
temp = arg2;
temp++;
if(!is_number(temp))
{
send_to_char("Which ban # to allow?\r\n", ch);
return;
}
value = atoi(temp);
}
if(!str_cmp(arg1, "site"))
{
if(!value)
{
if(strlen(arg2) < 2)
{
send_to_char("You have to have at least 2 chars for a ban\r\n", ch);
send_to_char("If you are trying to allow by number use #\r\n", ch);
return;
}
temp = arg2;
if(arg2[0] == '*')
temp++;
if(temp[strlen(temp) - 1] == '*')
temp[strlen(temp) - 1] = '\0';
}
for(pban = first_ban; pban; pban = pban->next)
{
/*
* Need to make sure we dispose properly of the ban_data
* * Or memory problems will be created.
* * Shaddai
*/
if(value == 1 || !str_cmp(pban->name, temp))
{
fMatch = TRUE;
dispose_ban(pban, BAN_SITE);
break;
}
if(value > 1)
value--;
}
}
else if(!str_cmp(arg1, "race"))
{
arg2[0] = toupper(arg2[0]);
for(pban = first_ban_race; pban; pban = pban->next)
{
/*
* Need to make sure we dispose properly of the ban_data
* * Or memory problems will be created.
* * Shaddai
*/
if(value == 1 || !str_cmp(pban->name, arg2))
{
fMatch = TRUE;
dispose_ban(pban, BAN_RACE);
break;
}
if(value > 1)
value--;
}
}
else if(!str_cmp(arg1, "class"))
{
arg2[0] = toupper(arg2[0]);
for(pban = first_ban_class; pban; pban = pban->next)
{
/*
* Need to make sure we dispose properly of the ban_data
* * Or memory problems will be created.
* * Shaddai
*/
if(value == 1 || !str_cmp(pban->name, arg2))
{
fMatch = TRUE;
dispose_ban(pban, BAN_CLASS);
break;
}
if(value > 1)
value--;
}
}
else
goto syntax_message;
if(fMatch)
{
save_banlist();
ch_printf(ch, "%s is now allowed.\r\n", arg2);
}
else
ch_printf(ch, "%s was not banned.\r\n", arg2);
return;
/*
* Make sure that return above stays in!
*/
syntax_message:
send_to_char("Syntax: allow site <address>\r\n", ch);
send_to_char("Syntax: allow race <race>\r\n", ch);
send_to_char("Syntax: allow class <class>\r\n", ch);
return;
}
/*
* Sets the warn flag on bans.
*/
void do_warn(CHAR_DATA *ch, char *argument)
{
char arg1[MAX_STRING_LENGTH];
char arg2[MAX_STRING_LENGTH];
char *name;
int count = -1, type;
BAN_DATA *pban, *start, *end;
/*
* Don't want mobs or link-deads doing this.
*/
if(IS_NPC(ch))
{
send_to_char("Monsters are too dumb to do that!\r\n", ch);
return;
}
if(!ch->desc)
{
bug("%s", "do_warn: no descriptor");
return;
}
argument = one_argument(argument, arg1);
argument = one_argument(argument, arg2);
if(arg1[0] == '\0' || arg2[0] == '\0')
goto syntax_message;
if(arg2[0] == '#')
{
name = arg2;
name++;
if(!is_number(name))
goto syntax_message;
count = atoi(name);
if(count < 1)
{
send_to_char("The number has to be above 0.\r\n", ch);
return;
}
}
/*
* We simply set up which ban list we will be looking at here.
*/
if(!str_cmp(arg1, "class"))
type = BAN_CLASS;
else if(!str_cmp(arg1, "race"))
type = BAN_RACE;
else if(!str_cmp(arg1, "site"))
type = BAN_SITE;
else
type = -1;
if(type == BAN_CLASS)
{
pban = first_ban_class;
start = first_ban_class;
end = last_ban_class;
arg2[0] = toupper(arg2[0]);
}
else if(type == BAN_RACE)
{
pban = first_ban_race;
start = first_ban_race;
end = last_ban_race;
arg2[0] = toupper(arg2[0]);
}
else if(type == BAN_SITE)
{
pban = first_ban;
start = first_ban;
end = last_ban;
}
else
goto syntax_message;
for(; pban && count != 0; count--, pban = pban->next)
if(count == -1 && !str_cmp(pban->name, arg2))
break;
if(pban)
{
/*
* If it is just a warn delete it, otherwise remove the warn flag.
*/
if(pban->warn)
{
if(pban->level == BAN_WARN)
{
dispose_ban(pban, type);
send_to_char("Warn has been deleted.\r\n", ch);
}
else
{
pban->warn = FALSE;
send_to_char("Warn turned off.\r\n", ch);
}
}
else
{
pban->warn = TRUE;
send_to_char("Warn turned on.\r\n", ch);
}
save_banlist();
}
else
{
ch_printf(ch, "%s was not found in the ban list.\r\n", arg2);
return;
}
return;
/*
* The above return has to stay in!
*/
syntax_message:
send_to_char("Syntax: warn class <field>\r\n", ch);
send_to_char("Syntax: warn race <field>\r\n", ch);
send_to_char("Syntax: warn site <field>\r\n", ch);
send_to_char("Field is either #(ban_number) or the site/class/race.\r\n", ch);
send_to_char("Example: warn class #1\r\n", ch);
return;
}
/*
* This actually puts the new ban into the proper linked list and
* initializes its data. Shaddai
*/
int add_ban(CHAR_DATA *ch, char *arg1, char *arg2, int btime, int type)
{
char arg[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
BAN_DATA *pban, *temp;
struct tm *tms;
char *name;
int level, i, value;
/*
* Should we check to see if they have dropped link sometime in between
* * writing the note and now? Not sure but for right now we won't since
* * do_ban checks for that. Shaddai
*/
switch (ch->substate)
{
default:
bug("%s", "add_ban: illegal substate");
return 0;
case SUB_RESTRICTED:
send_to_char("You cannot use this command from within another command.\r\n", ch);
return 0;
case SUB_NONE:
{
one_argument(arg1, arg);
smash_tilde(arg); /* Make sure the immortals don't * put a ~ in it. */
if(arg[0] == '\0' || arg2[0] == '\0')
return 0;
if(is_number(arg2))
{
level = atoi(arg2);
if(level < 0 || level > LEVEL_AJ_GENERAL)
{
ch_printf(ch, "Level range is from 0 to %d.\r\n", LEVEL_AJ_GENERAL);
return 0;
}
}
else if(!str_cmp(arg2, "all"))
level = LEVEL_AJ_GENERAL;
else if(!str_cmp(arg2, "newbie"))
level = 1;
else if(!str_cmp(arg2, "mortal"))
level = LEVEL_AVATAR;
else if(!str_cmp(arg2, "warn"))
level = BAN_WARN;
else
{
bug("%s", "Bad string for flag in add_ban.");
return 0;
}
switch (type)
{
case BAN_CLASS:
if(arg[0] == '\0')
return 0;
if(is_number(arg))
value = atoi(arg);
else
{
for(i = 0; i < MAX_CLASS; i++)
if(!str_cmp(class_table[i]->who_name, arg))
break;
value = i;
}
if(value < 0 || value >= MAX_CLASS)
{
send_to_char("Unknown class.\r\n", ch);
return 0;
}
for(temp = first_ban_class; temp; temp = temp->next)
{
if(temp->flag == value)
{
if(temp->level == level)
{
send_to_char("That entry already exists.\r\n", ch);
return 0;
}
else
{
temp->level = level;
if(temp->level == BAN_WARN)
temp->warn = TRUE;
sprintf(buf, "%24.24s", ctime(¤t_time));
temp->ban_time = STRALLOC(buf);
if(btime > 0)
{
temp->duration = btime;
tms = localtime(¤t_time);
tms->tm_mday += btime;
temp->unban_date = mktime(tms);
}
else
{
temp->duration = -1;
temp->unban_date = -1;
}
if(temp->ban_by)
STRFREE(temp->ban_by);
temp->ban_by = STRALLOC(ch->name);
send_to_char("Updated entry.\r\n", ch);
return 1;
}
}
}
CREATE(pban, BAN_DATA, 1);
pban->name = STRALLOC(class_table[value]->who_name);
pban->flag = value;
pban->level = level;
pban->ban_by = STRALLOC(ch->name);
LINK(pban, first_ban_class, last_ban_class, next, prev);
break;
case BAN_RACE:
if(is_number(arg))
value = atoi(arg);
else
{
for(i = 0; i < MAX_RACE; i++)
if(!str_cmp(race_table[i]->race_name, arg))
break;
value = i;
}
if(value < 0 || value >= MAX_RACE)
{
send_to_char("Unknown race.\r\n", ch);
return 0;
}
for(temp = first_ban_race; temp; temp = temp->next)
{
if(temp->flag == value)
{
if(temp->level == level)
{
send_to_char("That entry already exists.\r\n", ch);
return 0;
}
else
{
temp->level = level;
if(temp->level == BAN_WARN)
temp->warn = TRUE;
sprintf(buf, "%24.24s", ctime(¤t_time));
temp->ban_time = STRALLOC(buf);
if(btime > 0)
{
temp->duration = btime;
tms = localtime(¤t_time);
tms->tm_mday += btime;
temp->unban_date = mktime(tms);
}
else
{
temp->duration = -1;
temp->unban_date = -1;
}
if(temp->ban_by)
STRFREE(temp->ban_by);
temp->ban_by = STRALLOC(ch->name);
send_to_char("Updated entry.\r\n", ch);
return 1;
}
}
}
CREATE(pban, BAN_DATA, 1);
pban->name = STRALLOC(race_table[value]->race_name);
pban->flag = value;
pban->level = level;
pban->ban_by = STRALLOC(ch->name);
LINK(pban, first_ban_race, last_ban_race, next, prev);
break;
case BAN_SITE:
{
bool prefix = FALSE, suffix = FALSE, user_name = FALSE;
char *temp_host = NULL, *temp_user = NULL;
int x;
for(x = 0; x < strlen(arg); x++)
{
if(arg[x] == '@')
{
user_name = TRUE;
temp_host = STRALLOC(&arg[x + 1]);
arg[x] = '\0';
temp_user = STRALLOC(arg);
break;
}
}
if(!user_name)
name = arg;
else
name = temp_host;
if(!name)
{ /* Double check to make sure name * isnt null */
/*
* Free this stuff if its there
*/
if(user_name)
{
STRFREE(temp_host);
STRFREE(temp_user);
}
send_to_char("Name was null.\r\n", ch);
return 0;
}
if(name[0] == '*')
{
prefix = TRUE;
name++;
}
if(name[strlen(name) - 1] == '*')
{
suffix = TRUE;
name[strlen(name) - 1] = '\0';
}
for(temp = first_ban; temp; temp = temp->next)
{
if(!str_cmp(temp->name, name))
{
if(temp->level == level && (prefix && temp->prefix) && (suffix && temp->suffix))
{
/*
* Free this stuff if its there
*/
if(user_name)
{
STRFREE(temp_host);
STRFREE(temp_user);
}
send_to_char("That entry already exists.\r\n", ch);
return 0;
}
else
{
temp->suffix = suffix;
temp->prefix = prefix;
if(temp->level == BAN_WARN)
temp->warn = TRUE;
temp->level = level;
sprintf(buf, "%24.24s", ctime(¤t_time));
temp->ban_time = STRALLOC(buf);
if(btime > 0)
{
temp->duration = btime;
tms = localtime(¤t_time);
tms->tm_mday += btime;
temp->unban_date = mktime(tms);
}
else
{
temp->duration = -1;
temp->unban_date = -1;
}
if(temp->ban_by)
STRFREE(temp->ban_by);
if(user_name)
{
STRFREE(temp_host);
STRFREE(temp_user);
}
temp->ban_by = STRALLOC(ch->name);
send_to_char("Updated entry.\r\n", ch);
return 1;
}
}
}
CREATE(pban, BAN_DATA, 1);
pban->ban_by = STRALLOC(ch->name);
pban->suffix = suffix;
pban->prefix = prefix;
pban->name = STRALLOC(name);
pban->level = level;
LINK(pban, first_ban, last_ban, next, prev);
if(user_name)
{
STRFREE(temp_host);
STRFREE(temp_user);
}
break;
}
default:
bug("Bad type in add_ban: %d.", type);
return 0;
}
sprintf(buf, "%24.24s", ctime(¤t_time));
pban->ban_time = STRALLOC(buf);
if(btime > 0)
{
pban->duration = btime;
tms = localtime(¤t_time);
tms->tm_mday += btime;
pban->unban_date = mktime(tms);
}
else
{
pban->duration = -1;
pban->unban_date = -1;
}
if(pban->level == BAN_WARN)
pban->warn = TRUE;
ch->substate = SUB_BAN_DESC;
ch->dest_buf = pban;
if(!pban->note)
pban->note = STRALLOC("");;
start_editing(ch, pban->note);
return 1;
}
case SUB_BAN_DESC:
pban = (BAN_DATA *)ch->dest_buf;
if(!pban)
{
bug("%s", "do_ban: sub_ban_desc: NULL ch->dest_buf");
ch->substate = SUB_NONE;
return 0;
}
if(pban->note)
STRFREE(pban->note);
pban->note = copy_buffer(ch);
stop_editing(ch);
ch->substate = ch->tempnum;
save_banlist();
if(pban->duration > 0)
{
ch_printf(ch, "%s banned for %d days.\r\n", pban->name, pban->duration);
}
else
{
ch_printf(ch, "%s banned forever.\r\n", pban->name);
}
return 1;
}
return 1;
}
/*
* Print the bans out to the screen. Shaddai
*/
void show_bans(CHAR_DATA *ch, int type)
{
BAN_DATA *pban;
int bnum;
set_pager_color(AT_IMMORT, ch);
switch (type)
{
case BAN_SITE:
send_to_pager("Banned sites:\r\n", ch);
send_to_pager("[ #] Warn (Lv) Time By For Site\r\n", ch);
send_to_pager("---- ---- ---- ------------------------ --------------- ---- ---------------\r\n", ch);
pban = first_ban;
set_pager_color(AT_PLAIN, ch);
for(bnum = 1; pban; pban = pban->next, bnum++)
{
pager_printf(ch, "[%2d] %-4s (%2d) %-24s %-15s %4d %c%s%c\r\n",
bnum, (pban->warn) ? "YES" : "no", pban->level, pban->ban_time, pban->ban_by, pban->duration, (pban->prefix) ? '*' : ' ', pban->name, (pban->suffix) ? '*' : ' ');
}
return;
case BAN_RACE:
send_to_pager("Banned races:\r\n", ch);
send_to_pager("[ #] Warn (Lv) Time By For Race\r\n", ch);
pban = first_ban_race;
break;
case BAN_CLASS:
send_to_pager("Banned classes:\r\n", ch);
send_to_pager("[ #] Warn (Lv) Time By For Class\r\n", ch);
pban = first_ban_class;
break;
default:
bug("Bad type in show_bans: %d", type);
return;
}
send_to_pager("---- ---- ---- ------------------------ --------------- ---- ---------------\r\n", ch);
set_pager_color(AT_PLAIN, ch);
for(bnum = 1; pban; pban = pban->next, bnum++)
pager_printf(ch, "[%2d] %-4s (%2d) %-24s %-15s %4d %s\r\n", bnum, (pban->warn) ? "YES" : "no", pban->level, pban->ban_time, pban->ban_by, pban->duration, pban->name);
return;
}
/*
* Check for totally banned sites. Need this because we don't have a
* char struct yet. Shaddai
*/
bool check_total_bans(DESCRIPTOR_DATA *d)
{
BAN_DATA *pban;
char new_host[MAX_STRING_LENGTH];
int i;
for(i = 0; i < (int)strlen(d->host); i++)
new_host[i] = LOWER(d->host[i]);
new_host[i] = '\0';
for(pban = first_ban; pban; pban = pban->next)
{
if(pban->level != LEVEL_AJ_GENERAL)
continue;
if(pban->prefix && pban->suffix && strstr(new_host, pban->name))
{
if(check_expire(pban))
{
dispose_ban(pban, BAN_SITE);
save_banlist();
return FALSE;
}
else
return TRUE;
}
/*
* Bug of switched checks noticed by Cronel
*/
if(pban->suffix && !str_prefix(pban->name, new_host))
{
if(check_expire(pban))
{
dispose_ban(pban, BAN_SITE);
save_banlist();
return FALSE;
}
else
return TRUE;
}
if(pban->prefix && !str_suffix(pban->name, new_host))
{
if(check_expire(pban))
{
dispose_ban(pban, BAN_SITE);
save_banlist();
return FALSE;
}
else
return TRUE;
}
if(!str_cmp(pban->name, new_host))
{
if(check_expire(pban))
{
dispose_ban(pban, BAN_SITE);
save_banlist();
return FALSE;
}
else
return TRUE;
}
}
return FALSE;
}
/*
* The workhose, checks for bans on sites/classes and races. Shaddai
*/
bool check_bans(CHAR_DATA *ch, int type)
{
BAN_DATA *pban;
char new_host[MAX_STRING_LENGTH];
int i;
bool fMatch = FALSE;
char buf[MSL];
switch (type)
{
case BAN_RACE:
pban = first_ban_race;
break;
case BAN_CLASS:
pban = first_ban_class;
break;
case BAN_SITE:
pban = first_ban;
for(i = 0; i < (int)(strlen(ch->desc->host)); i++)
new_host[i] = LOWER(ch->desc->host[i]);
new_host[i] = '\0';
break;
default:
bug("Ban type in check_bans: %d.", type);
return FALSE;
}
for(; pban; pban = pban->next)
{
if(type == BAN_CLASS && pban->flag == ch->Class)
{
if(check_expire(pban))
{
dispose_ban(pban, BAN_CLASS);
save_banlist();
return FALSE;
}
if(ch->level > pban->level)
{
if(pban->warn)
{
snprintf(buf, MSL, "%s class logging in from %s.", pban->name, ch->desc->host);
log_string_plus(buf, LOG_WARN, sysdata.log_level);
}
return FALSE;
}
else
return TRUE;
}
if(type == BAN_RACE && pban->flag == ch->race)
{
if(check_expire(pban))
{
dispose_ban(pban, BAN_RACE);
save_banlist();
return FALSE;
}
if(ch->level > pban->level)
{
if(pban->warn)
{
snprintf(buf, MSL, "%s race logging in from %s.", pban->name, ch->desc->host);
log_string_plus(buf, LOG_WARN, sysdata.log_level);
}
return FALSE;
}
else
return TRUE;
}
if(type == BAN_SITE)
{
if(pban->prefix && pban->suffix && strstr(new_host, pban->name))
fMatch = TRUE;
else if(pban->prefix && !str_suffix(pban->name, new_host))
fMatch = TRUE;
else if(pban->suffix && !str_prefix(pban->name, new_host))
fMatch = TRUE;
else if(!str_cmp(pban->name, new_host))
fMatch = TRUE;
if(fMatch)
{
if(check_expire(pban))
{
dispose_ban(pban, BAN_SITE);
save_banlist();
return FALSE;
}
if(ch->level > pban->level)
{
if(pban->warn)
{
snprintf(buf, MSL, "%s logging in from site %s.", ch->name, ch->desc->host);
log_string_plus(buf, LOG_WARN, sysdata.log_level);
}
return FALSE;
}
else
return TRUE;
}
}
}
return FALSE;
}
bool check_expire(BAN_DATA *pban)
{
char buf[MSL];
if(pban->unban_date < 0)
return FALSE;
if(pban->unban_date <= current_time)
{
snprintf(buf, MSL, "%s ban has expired.", pban->name);
log_string_plus(buf, LOG_WARN, sysdata.log_level);
return TRUE;
}
return FALSE;
}
void dispose_ban(BAN_DATA *pban, int type)
{
if(!pban)
return;
if(type != BAN_SITE && type != BAN_CLASS && type != BAN_RACE)
{
bug("dispose_ban: Unknown Ban Type %d.", type);
return;
}
switch (type)
{
case BAN_SITE:
UNLINK(pban, first_ban, last_ban, next, prev);
break;
case BAN_CLASS:
UNLINK(pban, first_ban_class, last_ban_class, next, prev);
break;
case BAN_RACE:
UNLINK(pban, first_ban_race, last_ban_race, next, prev);
break;
}
free_ban(pban);
}
void free_ban(BAN_DATA *pban)
{
STRFREE(pban->name);
STRFREE(pban->ban_time);
STRFREE(pban->note);
STRFREE(pban->ban_by);
DISPOSE(pban);
}
void free_bans(void)
{
BAN_DATA *ban, *ban_next;
for(ban = first_ban; ban; ban = ban_next)
{
ban_next = ban->next;
dispose_ban(ban, BAN_SITE);
}
for(ban = first_ban_race; ban; ban = ban_next)
{
ban_next = ban->next;
dispose_ban(ban, BAN_RACE);
}
for(ban = first_ban_class; ban; ban = ban_next)
{
ban_next = ban->next;
dispose_ban(ban, BAN_CLASS);
}
return;
}