/****************************************************************************
* [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 "mud.h"
/* Local functions */
void fread_ban args ( ( FILE *fp ) );
bool check_expire args ( ( BAN_DATA *ban ) );
void dispose_ban args ( ( BAN_DATA *ban ) );
void free_ban args ( ( BAN_DATA *pban ) );
/* Global Variables */
BAN_DATA *first_ban;
BAN_DATA *last_ban;
/*
* Load all those nasty bans up :)
* Shaddai
* Nasty is right <shudder>
* Ban code stripped down and made cleaner -Keolah Aug 20 2001
*/
void load_banlist ( void ) {
char buf[MAX_STRING_LENGTH];
char *word;
FILE *fp;
bool fMatch;
if (!(fp = fopen (SYSTEM_DIR BAN_LIST, "r")))
{
bug ("Save_banlist: Cannot open " BAN_LIST, 0);
perror (BAN_LIST);
return;
}
for ( ; ; )
{
word = feof (fp) ? "END" : fread_word ( fp );
fMatch = FALSE;
switch ( UPPER ( word[0] ) )
{
case 'E':
if ( !str_cmp ( word, "END"))/*File should always contain END*/
{
fclose ( fp );
log_string ( "Done." );
return;
}
case 'S':
if ( !str_cmp ( word, "SITE" ) )
{
fread_ban ( fp );
fMatch = TRUE;
}
break;
}
if ( !fMatch )
{
sprintf ( buf, "Load_banlist: no match: %s", word );
bug ( buf, 0 );
} /* End of switch statement */
} /* End of for loop */
}
/*
* Load up one class or one race ban structure.
*/
void fread_ban ( FILE *fp ) {
BAN_DATA *pban;
int i = 0;
CREATE ( pban, BAN_DATA, 1 );
pban->name = fread_string_nohash ( fp );
pban->user = NULL;
/* was level */ fread_number( fp );
pban->duration = fread_number( fp );
pban->unban_date = fread_number( fp );
pban->prefix = fread_number( fp );
pban->suffix = fread_number( fp );
pban->ban_by = fread_string_nohash( fp );
pban->ban_time = fread_string_nohash( fp );
for ( i = 0; i < strlen( pban->name); i ++ ) {
if ( pban->name[i] == '@' )
{
char *temp;
char *temp2;
temp = str_dup( pban->name );
temp[i] = '\0';
temp2 = &pban->name[i+1];
DISPOSE( pban->name );
pban->name = str_dup( temp2 );
pban->user = str_dup( temp );
DISPOSE( temp );
}
}
LINK( pban, first_ban, last_ban, next, prev );
return;
}
void save_banlist ( void ) {
BAN_DATA *pban;
FILE *fp;
fclose (fpReserve);
if (!(fp = fopen (SYSTEM_DIR BAN_LIST, "w")))
{
bug ("Save_banlist: Cannot open " BAN_LIST, 0);
perror (BAN_LIST);
fpReserve = fopen (NULL_FILE, "r");
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\n", pban->duration,
pban->unban_date, pban->prefix, pban->suffix, pban->warn );
fprintf (fp, "%s~\n%s~\n", pban->ban_by, pban->ban_time );
}
fprintf (fp, "END\n"); /* File must have an END even if empty */
fclose (fp);
fpReserve = fopen (NULL_FILE, "r");
return;
}
/*
* The main command for ban, lots of arguments so be carefull what you
* change here. Shaddai
* Not anymore ;) -keo
*/
void do_ban ( CHAR_DATA *ch, char *argument ) {
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
int time;
if (IS_NPC (ch)) /* Don't want mobs banning sites ;) */
{
send_to_char ("Monsters are too dumb to do that!\n\r", ch);
return;
}
if (!ch->desc) /* No desc means no go :) */
{
bug ("do_ban: no descriptor", 0);
return;
}
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
if (!str_cmp(arg1, "list")) {
show_bans(ch);
return;
}
if (!str_cmp(arg1, "clear")) {
return;
}
/* Do we have a time duration for the ban? */
if ( arg2[0] != '\0' && is_number( arg2 ) )
time = atoi( arg2 );
else
time = -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 ( time != -1 && ( time < 1 || time > 1000 ) )
{
send_to_char("Time value is -1 (forever) or from 1 to 1000.\n\r", ch);
return;
}
add_ban(ch, arg1, time);
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, int time )
{
char arg[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
BAN_DATA *pban, *temp;
struct tm *tms;
char *name;
bool prefix = FALSE, suffix = FALSE;
one_argument( arg1, arg );
smash_tilde ( arg ); /* Make sure the immortals don't put a ~ in it. */
if ( arg[0] == '\0')
return 0;
name = arg;
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 ( (prefix && temp->prefix)
&& ( suffix && temp->suffix ))
{
send_to_char ("That entry already exists.\n\r",ch);
return 0;
}
else
{
temp->suffix = suffix;
temp->prefix = prefix;
temp->warn = TRUE;
sprintf (buf, "%24.24s", ctime (¤t_time));
temp->ban_time = str_dup (buf);
if ( temp->ban_by )
DISPOSE( temp->ban_by );
temp->ban_by = str_dup ( ch->name );
send_to_char("Updated entry.\n\r", ch);
return 1;
}
}
}
CREATE( pban, BAN_DATA, 1 );
pban->ban_by = str_dup ( ch->name );
pban->suffix = suffix;
pban->prefix = prefix;
pban->name = str_dup( name );
LINK( pban, first_ban, last_ban, next, prev );
sprintf (buf, "%24.24s", ctime (¤t_time));
pban->ban_time = str_dup (buf);
if ( time > 0 ) {
pban->duration = time;
tms = localtime(¤t_time);
tms->tm_mday += time;
pban->unban_date = mktime(tms);
}
else {
pban->duration = -1;
pban->unban_date = -1;
}
save_banlist( );
if ( pban->duration > 0 )
{
if ( !pban->user )
ch_printf (ch, "%s banned for %d days.\n\r", pban->name, pban->duration );
else
ch_printf (ch, "%s@%s banned for %d days.\n\r", pban->user, pban->name, pban->duration );
}
else
{
if ( !pban->user )
ch_printf (ch, "%s banned forever.\n\r", pban->name );
else
ch_printf (ch, "%s@%s banned forever.\n\r", pban->user, pban->name );
}
return 1;
}
/*
* Print the bans out to the screen. Shaddai
*/
void show_bans ( CHAR_DATA *ch) {
BAN_DATA *pban;
int bnum;
set_pager_color (AT_IMMORT, ch);
send_to_pager("Banned sites:\n\r", ch);
send_to_pager("[ #] Time By For Site\n\r",ch);
send_to_pager("---- ------------------------ --------------- ---- ---------------\n\r", ch);
pban = first_ban;
set_pager_color( AT_PLAIN, ch );
for ( bnum=1; pban; pban=pban->next, bnum++)
{
pager_printf (ch, "[%2d] %-24s %-15s %4d %c%s%c\n\r",
bnum,
pban->ban_time, pban->ban_by, pban->duration,
(pban->prefix)?'*':' ',
pban->name, (pban->suffix)?'*':' ');
}
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->user && str_cmp( d->user, pban->user ) )
continue;
if ( pban->prefix && pban->suffix &&
strstr( pban->name, new_host ) )
{
if ( check_expire( pban ) )
{
dispose_ban( pban );
save_banlist( );
return FALSE;
}
else
return TRUE;
}
if ( pban->suffix && !str_suffix( pban->name, new_host ) )
{
if ( check_expire( pban ) )
{
dispose_ban( pban );
save_banlist( );
return FALSE;
}
else
return TRUE;
}
if ( pban->prefix && !str_prefix( pban->name, new_host ) )
{
if ( check_expire( pban ) )
{
dispose_ban( pban );
save_banlist( );
return FALSE;
}
else
return TRUE;
}
if ( !str_cmp( pban->name, new_host ) )
{
if ( check_expire( pban ) )
{
dispose_ban( pban );
save_banlist( );
return FALSE;
}
else
return TRUE;
}
}
return FALSE;
}
/* Check player logging in for multiplaying. Exclude imms and players with
a PLR_MULTI flag. -- Scion */
bool check_multi(CHAR_DATA *ch) {
DESCRIPTOR_DATA *d;
int chars=1;
for (d=first_descriptor; d; d=d->next) {
if (d->character && d->character != ch
&& d->host == ch->desc->host
&& !d->character->pcdata->permissions
&& !xIS_SET(d->character->act, PLR_MULTI))
chars++;
}
if (chars > sysdata.morts_allowed)
return TRUE;
return FALSE;
}
/*
* The workhose, checks for bans on sites/classes and races. Shaddai
*/
bool check_bans( CHAR_DATA *ch ) {
char buf[MAX_STRING_LENGTH];
BAN_DATA *pban;
char new_host[MAX_STRING_LENGTH];
int i;
bool fMatch = FALSE;
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';
for ( ; pban; pban = pban->next ) {
if ( pban->prefix && pban->suffix &&
strstr( pban->name, new_host ) )
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 && pban->user &&
str_cmp(pban->user, ch->desc->user) )
fMatch = FALSE;
if ( fMatch )
{
if ( check_expire( pban ) )
{
dispose_ban( pban );
save_banlist( );
return FALSE;
}
sprintf( buf, "%s logging in from site %s.",
ch->name, ch->desc->host );
log_string_plus( buf, LOG_WARN, 0 );
return FALSE;
}
}
return FALSE;
}
bool check_expire( BAN_DATA *pban )
{
char buf[MAX_STRING_LENGTH];
if ( pban->unban_date < 0 )
return FALSE;
if ( pban->unban_date <= current_time )
{
sprintf( buf, "%s ban has expired.", pban->name );
log_string_plus( buf, LOG_WARN, 0 );
return TRUE;
}
return FALSE;
}
void dispose_ban ( BAN_DATA *pban)
{
if ( !pban )
return;
UNLINK( pban, first_ban, last_ban, next, prev );
free_ban( pban );
return;
}
void free_ban( BAN_DATA *pban )
{
if ( pban->name )
DISPOSE( pban->name );
if ( pban->ban_time )
DISPOSE( pban->ban_time );
if ( pban->user )
DISPOSE( pban->user );
if ( pban->ban_by )
DISPOSE( pban->ban_by );
if ( pban->ban_time )
DISPOSE( pban->ban_time );
DISPOSE( pban );
}