Eldhamud_2.5.83/clans/
Eldhamud_2.5.83/classes/
Eldhamud_2.5.83/doc/
Eldhamud_2.5.83/doc/DIKU/
Eldhamud_2.5.83/doc/MERC/
Eldhamud_2.5.83/doc/mudprogs/
Eldhamud_2.5.83/houses/
/****************************************************************************
 *			Eldhamud Codebase V2.2				    *
 * ------------------------------------------------------------------------ *
 *          EldhaMUD code (C) 2003-2008 by Robert Powell (Tommi)            *
 * ------------------------------------------------------------------------ *
 * Original SMAUG 1.4a written by Thoric (Derek Snider) with Altrag,        *
 * Blodkai, Haus, Narn, Scryn, Swordbearer, Tricops, Gorog, Rennard,        *
 * Grishnakh, Fireblade, and Nivek.                                         *
 *                                                                          *
 * Original MERC 2.1 code by Hatchet, Furey, and Kahn.                      *
 *                                                                          *
 * Original DikuMUD code by: Hans Staerfeldt, Katja Nyboe, Tom Madsen,      *
 * Michael Seifert, and Sebastian Hammer.                                   *
 * ------------------------------------------------------------------------ *
 *                            Ban module by Shaddai                         *
 ****************************************************************************/
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <time.h>
#include "./Headers/mud.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;

/*
 * Load all those nasty bans up :)
 * 	Shaddai
 */
void load_banlist( void )
{
   char buf[MAX_STRING_LENGTH];
   char *word;
   FILE *fp;
   bool fMatch = FALSE;
   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, BAN_SITE );
               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, int type )
{
   BAN_DATA *pban;
   int i = 0;
   CREATE( pban, BAN_DATA, 1 );
   pban->name = fread_string_nohash( 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_nohash( fp );
   pban->ban_time = fread_string_nohash( fp );
   pban->note = fread_string( fp );
   /*
    * Need to lookup the Class or race number if it is of that type 
    */
   if( type == BAN_SITE )
      for( i = 0; i < strlen( pban->name ); i++ )
      {
         if( pban->name[i] == '@' )
         {
            char *temp;
            char *temp2;
            temp = str_dup( pban->name );
            temp[i] = STRING_NULL;
            temp2 = &pban->name[i + 1];
            DISPOSE( pban->name );
            pban->name = str_dup( temp2 );
            DISPOSE( temp );
            break;
         }
      }
   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;
   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 %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 );
   }

   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
 */
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( "do_ban: no descriptor", 0 );
      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] != STRING_NULL && 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( "do_ban: illegal substate", 0 );
         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, "", "", 0, 0 );
         return;
   }
   if( arg1[0] == STRING_NULL )
      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] == STRING_NULL )
      {
         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] == STRING_NULL )
         goto syntax_message;
      if( !add_ban( ch, arg2, arg3, btime, BAN_SITE ) )
         return;
   }
   else if( !str_cmp( arg1, "show" ) )
   {
      /*
       * This will show the note attached to a ban 
       */
      if( arg2[0] == STRING_NULL || arg3[0] == STRING_NULL )
         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] = STRING_NULL;
      }
      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 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( "do_allow: no descriptor", 0 );
      return;
   }
   argument = one_argument( argument, arg1 );
   argument = one_argument( argument, arg2 );
   set_char_color( AT_IMMORT, ch );
   if( arg1[0] == STRING_NULL || arg2[0] == STRING_NULL )
      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] = STRING_NULL;
      }
      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
      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 );
   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( "do_warn: no descriptor", 0 );
      return;
   }
   argument = one_argument( argument, arg1 );
   argument = one_argument( argument, arg2 );
   if( arg1[0] == STRING_NULL || arg2[0] == STRING_NULL )
      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, "site" ) )
      type = BAN_SITE;
   else
      type = -1;
   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 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;
   /*
    * 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] == STRING_NULL || arg2[0] == STRING_NULL )
            return 0;
         if( is_number( arg2 ) )
         {
            level = atoi( arg2 );
            if( level < 0 || level > LEVEL_SUPREME )
            {
               ch_printf( ch, "Level range is from 0 to %d.\r\n", LEVEL_SUPREME );
               return 0;
            }
         }
         else if( !str_cmp( arg2, "all" ) )
            level = LEVEL_SUPREME;
         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_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 = str_dup( &arg[x + 1] );
                     arg[x] = STRING_NULL;
                     temp_user = str_dup( 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 )
                  {
                     DISPOSE( temp_host );
                     DISPOSE( 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] = STRING_NULL;
               }
               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 )
                        {
                           DISPOSE( temp_host );
                           DISPOSE( 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( &current_time ) );
                        temp->ban_time = str_dup( buf );
                        if( btime > 0 )
                        {
                           temp->duration = btime;
                           tms = localtime( &current_time );
                           tms->tm_mday += btime;
                           temp->unban_date = mktime( tms );
                        }
                        else
                        {
                           temp->duration = -1;
                           temp->unban_date = -1;
                        }
                        if( temp->ban_by )
                           DISPOSE( temp->ban_by );
                        if( user_name )
                        {
                           DISPOSE( temp_host );
                           DISPOSE( temp_user );
                        }
                        temp->ban_by = str_dup( ch->name );
                        send_to_char( "Updated entry.\r\n", 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 );
               pban->level = level;
               if( user_name )
               {
                  DISPOSE( temp_host );
                  DISPOSE( temp_user );
               }
               LINK( pban, first_ban, last_ban, next, prev );
               break;
            }
            default:
               bug( "Bad type in add_ban: %d.", type );
               return 0;
         }
         sprintf( buf, "%24.24s", ctime( &current_time ) );
         pban->ban_time = str_dup( buf );
         if( btime > 0 )
         {
            pban->duration = btime;
            tms = localtime( &current_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 );
         save_banlist(  );
         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;
      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] = STRING_NULL;
   for( pban = first_ban; pban; pban = pban->next )
   {
      if( pban->level != LEVEL_SUPREME )
         continue;
      if( pban->prefix && pban->suffix && strstr( pban->name, new_host ) )
      {
         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 )
{
   char buf[MAX_STRING_LENGTH];
   BAN_DATA *pban;
   char new_host[MAX_STRING_LENGTH];
   int i;
   bool fMatch = FALSE;
   switch ( type )
   {
      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] = STRING_NULL;
         break;
      default:
         bug( "Ban type in check_bans: %d.", type );
         return FALSE;
   }
   for( ; pban; pban = pban->next )
   {
      if( type == BAN_SITE )
      {
         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 )
         {
            if( check_expire( pban ) )
            {
               dispose_ban( pban, BAN_SITE );
               save_banlist(  );
               return FALSE;
            }
            if( ch->level > pban->level )
            {
               if( pban->warn )
               {
                  sprintf( buf, "%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[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, sysdata.log_level );
      return TRUE;
   }
   return FALSE;
}
void dispose_ban( BAN_DATA * pban, int type )
{
   if( !pban )
      return;
   if( type != BAN_SITE )
   {
      bug( "Dispose_ban: Unknown Ban Type %d.", type );
      return;
   }
   switch ( type )
   {
      case BAN_SITE:
         UNLINK( pban, first_ban, last_ban, next, prev );
         break;
   }
   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->note )
      STRFREE( pban->note );
   if( pban->ban_by )
      DISPOSE( pban->ban_by );
   if( pban->ban_time )
      DISPOSE( pban->ban_time );
   DISPOSE( pban );
}