atd/area/
atd/build/
atd/clans/
atd/log/
atd/player/store/
atd/site/
atd/src/bin/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include "merc.h"
#include "leader.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 :)
 *
 */
void load_bans ( )
{
    char buf[MAX_STRING_LENGTH];
    char *word;
    FILE *fp;
    bool fMatch = FALSE;

    if (!(fp = fopen(DATA_DIR BAN_LIST, "r")))
    {
        bug ("load_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 '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*/
            {
                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 );
            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;
    int i = 0;
    bool fMatch = FALSE;

    pban = alloc_mem(sizeof( BAN_DATA ) );

    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 )
    {
        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; class_table[i].class_name[0] != '\0'; i++ )
        {
            if ( !str_cmp( class_table[i].class_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 = str_dup( pban->name );
                temp[i] = '\0';
                temp2 = &pban->name[i+1];
                free_string( pban->name );
		pban->name = str_dup( temp2 );
                break;
            }
        }

    if ( type == BAN_CLASS )
    {
        if ( fMatch )
            pban->flag = i;
        else /* The file is corupted throw out this ban structure */
        {
            bug("Bad class structure %d.\n\r", i );
            free_ban( pban );
            return;
        }
    }
    if ( type == BAN_CLASS )
        LINK( pban, first_ban_class, last_ban_class, 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
 */

void save_banlist ( void )
{
    BAN_DATA *pban;
    FILE *fp;

    fclose (fpReserve);
    if (!(fp = fopen (DATA_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 );
    }

    /* 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 */
    fclose (fp);
    fpReserve = fopen (NULL_FILE, "r");
    return;
}

/*
 * The main command for ban, lots of arguments so be carefull what you
 * change here.
 */

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, 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 );
    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 ) )
        time = atoi( arg4 );
    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;
    }

    if ( arg1[0] == '\0' )
    {
        send_to_char("Syntax: ban site  <address> <type> <duration>\n\r", ch );
        send_to_char("Syntax: ban class <class>   <type> <duration>\n\r", ch );
        send_to_char("Syntax: ban show  <field>   <number>\n\r", ch );
        send_to_char("Ban site lists current bans.\n\r", ch );
        send_to_char("Duration is the length of the ban in days.\n\r", ch );
        send_to_char("Type can be:  newbie, mortal, all, warn or level.\n\r", 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.\n\r", ch );
        return;
    }

    if ( !str_cmp ( arg1, "site" ) )
    {
        if ( arg2[0] == '\0' )
        {
            show_bans( ch, BAN_SITE );
            return;
        }

        if ( get_trust(ch) < sysdata.ban_site_level )
        {
            ch_printf(ch,"You must be %d level to add bans.\n\r",
                      sysdata.ban_site_level);
            return;
        }
        if ( arg3[0] == '\0' )
        {
            do_ban(ch,"");
            return;
        }
        if ( !add_ban ( ch, arg2, arg3, time, BAN_SITE ) )
            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.\n\r",sysdata.ban_class_level);
            return;
        }
        if ( arg3[0] == '\0' )
        {
            do_ban(ch,"");
            return;
        }
        if ( !add_ban(ch, arg2, arg3, time, BAN_CLASS ) )
            return;
    }
    else if ( !str_cmp ( arg1, "show" ) )
    {
        if ( arg2[0] == '\0' || arg3[0] == '\0' )
        {
            do_ban(ch,"");
            return;
        }
        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?\n\r", ch);
                return;
            }
            value = atoi(temp);
            if ( value < 1 )
            {
                send_to_char ("You must specify a number greater than 0.\n\r",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
        {
            do_ban(ch,"");
            return;
        }
        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.\n\r", ch);
            return;
        }
        ch_printf(ch, "Banned by: %s\n\r", pban->ban_by );
        send_to_char ( pban->note, ch );
        return;
    }
    do_ban(ch,"");
    return;
}

/*
 * Allow a already banned site/class
 */
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!\n\r", 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 );


    if ( arg1[0] == '\0' || arg2[0] == '\0')
    {
	send_to_char ("Syntax: allow site  <address>\n\r", ch );
        send_to_char ("Syntax: allow class <class>\n\r", ch );
        return;
    }

    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?\n\r", 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\n\r", ch);
                send_to_char("If you are trying to allow by number use #\n\r",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 )
        {
            if ( value == 1 || !str_cmp ( pban->name, temp ) )
            {
                fMatch = TRUE;
                wiznetf( ch, WIZ_MISC, get_trust( ch ),
                         "%s allowing site %s.",
                        ch->name, pban->name );
                dispose_ban( pban, BAN_SITE );
                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 )
        {
            if ( value == 1 || !str_cmp ( pban->name, arg2 ) )
            {
                fMatch = TRUE;
                wiznetf( ch, WIZ_MISC, get_trust( ch ),
                         "%s allowing class %s.",
                        ch->name, pban->name );
                dispose_ban( pban, BAN_CLASS );
                break;
            }
            if ( value > 1 )
                value--;
        }
    }
    else
    {
        do_allow(ch,"");
        return;
    }
    
    if ( fMatch )
    {
        save_banlist();
        ch_printf(ch, "%s is now allowed.\n\r", arg2 );
    }
    else
        ch_printf(ch, "%s was not banned.\n\r", arg2 );
    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;


    if (IS_NPC (ch))
    {
        send_to_char ("Monsters are too dumb to do that!\n\r", 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] == '\0' || arg2[0] == '\0' )
    {
	send_to_char ("Syntax: warn class <field>\n\r", ch );
        send_to_char ("Syntax: warn site  <field>\n\r", ch );
        send_to_char ("Field is either #(ban_number) or the site/class/race.\n\r", ch);
        send_to_char ("Example:  warn class #1\n\r", ch );
        return;
    }

    if ( arg2[0] == '#' )
    {
        name = arg2;
        name++;
        if ( !is_number( name ) )
        {
            do_warn(ch,"");
            return;
        }
        count = atoi( name );
        if ( count < 1 )
        {
            send_to_char("The number has to be above 0.\n\r", ch );
            return;
        }
    }

    if ( !str_cmp( arg1, "class") )
        type = BAN_CLASS;
    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_SITE )
    {
        pban = first_ban;
        start = first_ban;
        end = last_ban;
    }
    else
    {
        do_warn(ch,"");
        return;
    }
    for ( ; pban && count != 0; count--, pban = pban->next )
        if ( count == -1 && !str_cmp(pban->name, arg2 ) )
            break;
    if ( pban )
    {
        if ( pban->warn )
        {
            if ( pban->level == BAN_WARN )
            {
                dispose_ban( pban, type );
                send_to_char("Warn has been deleted.\n\r", ch );
            }
            else
            {
                pban->warn = FALSE;
                send_to_char("Warn turned off.\n\r", ch);
            }
        }
        else
        {
            pban->warn = TRUE;
            send_to_char("Warn turned on.\n\r", ch );
        }
        save_banlist( );
    }
    else
    {
        ch_printf(ch, "%s was not found in the ban list.\n\r", arg2 );
        return;
    }
    return;
}

/*
 *  This actually puts the new ban into the proper linked list and
 *  initializes its data.
 */
int add_ban( CHAR_DATA *ch, char *arg1, char *arg2, int time, int type )
{
    char arg[MAX_STRING_LENGTH];
    char buf[MAX_STRING_LENGTH];
    BAN_DATA *pban, *temp;
    struct tm *tms;
    char *name;
    int level, 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.
     */

    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_IMPLEMENTOR )
        {
            ch_printf(ch,"Level range is from 0 to %d.\n\r", LEVEL_IMPLEMENTOR );
            return 0;
        }
    }
    else if ( !str_cmp( arg2, "all" ) )
        level = LEVEL_IMPLEMENTOR;
    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("Bad string for flag in add_ban.", 0 );
        return 0;
    }

    switch ( type )
    {
    case BAN_CLASS:
        if ( arg[0] == '\0' )
            return 0;
        if ( is_number( arg ) )
            value = atoi( arg );
        else
            value = class_lookupn(arg);
        if (value < 0 || value >= MAX_CLASS)
        {
            send_to_char("Unknown class.\n\r", 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.\n\r",ch);
                    return 0;
                }
                else
                {
                    temp->level = level;
                    if ( temp->level == BAN_WARN )
                        temp->warn = TRUE;
                    sprintf (buf, "%24.24s", ctime (&current_time));
                    temp->ban_time = str_dup (buf);
                    if ( temp->ban_by )
                        free_string( temp->ban_by );
                    temp->ban_by = str_dup ( ch->name );
                    send_to_char("Updated entry.\n\r", ch);
                    return 1;
                }
            }
        }
        pban = alloc_mem( sizeof( BAN_DATA) );
        pban->name = str_dup ( class_table[value].class_name );
        pban->flag = value;
        pban->level = level;
        pban->ban_by = str_dup ( ch->name );
        LINK( pban, first_ban_class, last_ban_class, next, prev );
        wiznetf( ch, WIZ_MISC,
                 get_trust( ch ), "%s setting class ban on %s",
                 ch->name, pban->name );
        break;
    case BAN_SITE:
        {
            bool prefix = FALSE, suffix = FALSE;

            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 ( temp->level == level && (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;
                        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 ( temp->ban_by )
                            free_string( temp->ban_by );
                        temp->ban_by = str_dup ( ch->name );
                        send_to_char("Updated entry.\n\r", ch);
                        return 1;
                    }
                }
            }
            pban = alloc_mem( sizeof( BAN_DATA ) );
            pban->ban_by = str_dup ( ch->name );
            pban->suffix = suffix;
            pban->prefix = prefix;
            pban->name = str_dup( name );
            pban->level = level;
            LINK( pban, first_ban, last_ban, next, prev );
        wiznetf( ch, WIZ_MISC,
                 get_trust( ch ), "%s setting class ban on %s",
                 ch->name, pban->name );
            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 ( time > 0 ) {
        pban->duration = time;
        tms = localtime(&current_time);
        tms->tm_mday += time;
        pban->unban_date = mktime(tms);
    }
    else {
        pban->duration = -1;
        pban->unban_date = -1;
    }
    if ( pban->level == BAN_WARN )
        pban->warn = TRUE;

    string_append( ch, &pban->note );

    save_banlist( );
    if ( pban->duration > 0 )
    {
        ch_printf (ch, "%s banned for %d days.\n\r", pban->name, pban->duration );
    }
    else
    {
        ch_printf (ch, "%s banned forever.\n\r", pban->name );
    }
    return 1;
}

/*
 * Print the bans out to the screen
 */
void show_bans ( CHAR_DATA *ch, int type )
{
    BAN_DATA *pban;
    int bnum;

    switch ( type )
    {
    case BAN_SITE:
        page_to_char("Banned sites:\n\r", ch);
        page_to_char("[ ##] Warn (Lv) Time                     By              For   Site\n\r",ch);
        page_to_char("---- ---- ---- ------------------------ --------------- ----  ---------------\n\r", ch);
        pban = first_ban;
        for ( bnum=1; pban; pban=pban->next, bnum++)
        {
                pager_printf (ch, "[%2d] %-4s (%2d) %-24s %-15s %4d  %c%s%c\n\r",
                              bnum, (pban->warn)?"YES":"no", pban->level,
                              pban->ban_time, pban->ban_by, pban->duration,
                              (pban->prefix)?'*':' ',
                              pban->name, (pban->suffix)?'*':' ');
        }
        return;
    case BAN_CLASS:
        page_to_char("Banned classes:\n\r", ch);
        page_to_char("[ #] Warn (Lv) Time                     By              For   Class\n\r",ch);
        pban = first_ban_class;
        break;
    default:
        bug ("Bad type in show_bans: %d", type );
        return;
    }
    page_to_char("---- ---- ---- ------------------------ --------------- ----  ---------------\n\r", ch);
    for ( bnum=1; pban; pban=pban->next, bnum++)
        pager_printf (ch, "[%2d] %-4s (%2d) %-24s %-15s %4d  %s\n\r", 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
 */

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_IMPLEMENTOR )
            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
 */
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_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 ) {
                    sprintf( buf, "%s class logging in from %s.",
                             pban->name, ch->desc->host );
                    log_string( buf );
                }
                return FALSE;
            }
            else
                return TRUE;
        }
        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( buf );
                    }
                    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( buf );
        return TRUE;
    }
    return FALSE;
}

void dispose_ban ( BAN_DATA *pban , int type)
{
    if ( !pban )
        return;

    if ( type != BAN_SITE && type != BAN_CLASS )
    {
        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;
    }
    free_ban( pban );
    return;
}

void free_ban( BAN_DATA *pban )
{
    if ( pban->name )
        free_string( pban->name );
    if ( pban->ban_time )
        free_string( pban->ban_time );
    if ( pban->note )
        free_string( pban->note );
    if ( pban->ban_by )
        free_string( pban->ban_by );
    if ( pban->ban_time )
        free_string( pban->ban_time );
    free_mem( pban, sizeof( *pban ) );
}