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