deltamud/deltamud/
deltamud/deltamud/bin/
deltamud/deltamud/cnf/
deltamud/deltamud/lib/
deltamud/deltamud/lib/etc/
deltamud/deltamud/lib/misc/
deltamud/deltamud/lib/plrobjs/
deltamud/deltamud/lib/text/
deltamud/deltamud/lib/text/help/
deltamud/deltamud/lib/world/
deltamud/deltamud/lib/world/trg/
/* ************************************************************************
   *   File: ban.c                                         Part of CircleMUD *
   *  Usage: banning/unbanning/checking sites and player names               *
   *                                                                         *
   *  All rights reserved.  See license.doc for complete information.        *
   *                                                                         *
   *  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
   *  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
   ************************************************************************ */

#include "conf.h"
#include "sysdep.h"

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"

struct ban_list_element *ban_list = NULL;


char *ban_types[] =
{
  "no",
  "new",
  "select",
  "all",
  "ERROR"
};

/*
   Wildmatch by Storm
   To give us flexibility with bans (not everyone has a static ip :)).
*/

int wildmatch(char *mask, char *string) {
  int mpos=0, spos=0;
  while(1) {
    if (strlen(string)-spos-1==0 || strlen(mask)-mpos-1==0) {
      if ((mask[mpos]=='*' && strlen(mask)-mpos-1==0) || (strlen(mask)-mpos-1==0 && strlen(string)-spos-1==0))
        return 1;
      else {
        return 0;
      }
    }
    switch(mask[mpos]) {
      case '?':
        spos++;
        mpos++;
        break;
      case '*':
        while (mask[mpos+1]=='*') mpos++;
        if (mask[mpos+1]==string[spos] || mask[mpos+1]=='?')
          mpos+=2;
        spos++;
        break;
      default:
        if (mask[mpos]!=string[spos])  {
          return 0;
        }
        mpos++;
        spos++;
        break;
    }
  }
}


void
load_banned (void)
{
  FILE *fl;
  int i, date;
  char site_name[BANNED_SITE_LENGTH + 1], ban_type[100];
  char name[MAX_NAME_LENGTH + 1];
  struct ban_list_element *next_node;

  ban_list = 0;

  if (!(fl = fopen (BAN_FILE, "r")))
    {
      perror ("SYSERR: Unable to open banfile");
      return;
    }
  while (fscanf (fl, " %s %s %d %s ", ban_type, site_name, &date, name) == 4)
    {
      CREATE (next_node, struct ban_list_element, 1);
      strncpy (next_node->site, site_name, BANNED_SITE_LENGTH);
      next_node->site[BANNED_SITE_LENGTH] = '\0';
      strncpy (next_node->name, name, MAX_NAME_LENGTH);
      next_node->name[MAX_NAME_LENGTH] = '\0';
      next_node->date = date;

      for (i = BAN_NOT; i <= BAN_ALL; i++)
	if (!strcmp (ban_type, ban_types[i]))
	  next_node->type = i;

      next_node->next = ban_list;
      ban_list = next_node;
    }

  fclose (fl);
}


int
isbanned (char *hostname)
{
  int i;
  struct ban_list_element *banned_node;
  char *nextchar;

  if (!hostname || !*hostname)
    return (0);

  i = 0;
  for (nextchar = hostname; *nextchar; nextchar++)
    *nextchar = LOWER (*nextchar);

  for (banned_node = ban_list; banned_node; banned_node = banned_node->next)
    if (wildmatch(banned_node->site, hostname))	/* if hostname is a substring */
      i = MAX (i, banned_node->type);

  return i;
}


void
_write_one_node (FILE * fp, struct ban_list_element *node)
{
  if (node)
    {
      _write_one_node (fp, node->next);
      fprintf (fp, "%s %s %ld %s\n", ban_types[node->type],
	       node->site, (long) node->date, node->name);
    }
}



void
write_ban_list (void)
{
  FILE *fl;

  if (!(fl = fopen (BAN_FILE, "w")))
    {
      perror ("SYSERR: write_ban_list");
      return;
    }
  _write_one_node (fl, ban_list);	/* recursively write from end to start */
  fclose (fl);
  return;
}


ACMD (do_ban)
{
  char flag[MAX_INPUT_LENGTH], site[MAX_INPUT_LENGTH], format[MAX_INPUT_LENGTH],
   *nextchar, *timestr;
  int i;
  struct ban_list_element *ban_node;

  *buf = '\0';

  if (!*argument)
    {
      if (!ban_list)
	{
	  send_to_char ("No sites are banned.\r\n", ch);
	  return;
	}
      strcpy (format, "%-25.25s  %-8.8s  %-10.10s  %-16.16s\r\n");
      sprintf (buf, format,
	       "Banned Site Name",
	       "Ban Type",
	       "Banned On",
	       "Banned By");
      send_to_char (buf, ch);
      sprintf (buf, format,
	       "---------------------------------",
	       "---------------------------------",
	       "---------------------------------",
	       "---------------------------------");
      send_to_char (buf, ch);

      for (ban_node = ban_list; ban_node; ban_node = ban_node->next)
	{
	  if (ban_node->date)
	    {
	      timestr = asctime (localtime (&(ban_node->date)));
	      *(timestr + 10) = 0;
	      strcpy (site, timestr);
	    }
	  else
	    strcpy (site, "Unknown");
	  sprintf (buf, format, ban_node->site, ban_types[ban_node->type], site,
		   ban_node->name);
	  send_to_char (buf, ch);
	}
      return;
    }
  two_arguments (argument, flag, site);
  if (!*site || !*flag)
    {
      send_to_char ("Usage: ban {all | select | new} site_name\r\n", ch);
      return;
    }
  if (!(!str_cmp (flag, "select") || !str_cmp (flag, "all") || !str_cmp (flag, "new")))
    {
      send_to_char ("Flag must be ALL, SELECT, or NEW.\r\n", ch);
      return;
    }
  for (ban_node = ban_list; ban_node; ban_node = ban_node->next)
    {
      if (!str_cmp (ban_node->site, site))
	{
	  send_to_char ("That site has already been banned -- unban it to change the ban type.\r\n", ch);
	  return;
	}
    }

  CREATE (ban_node, struct ban_list_element, 1);
  strncpy (ban_node->site, site, BANNED_SITE_LENGTH);
  for (nextchar = ban_node->site; *nextchar; nextchar++)
    *nextchar = LOWER (*nextchar);
  ban_node->site[BANNED_SITE_LENGTH] = '\0';
  strncpy (ban_node->name, GET_NAME (ch), MAX_NAME_LENGTH);
  ban_node->name[MAX_NAME_LENGTH] = '\0';
  ban_node->date = time (0);

  for (i = BAN_NEW; i <= BAN_ALL; i++)
    if (!str_cmp (flag, ban_types[i]))
      ban_node->type = i;

  ban_node->next = ban_list;
  ban_list = ban_node;

  sprintf (buf, "%s has banned %s for %s players.", GET_NAME (ch), site,
	   ban_types[ban_node->type]);
  mudlog (buf, NRM, MAX (LVL_GOD, GET_INVIS_LEV (ch)), TRUE);
  send_to_char ("Site banned.\r\n", ch);
  write_ban_list ();
}


ACMD (do_unban)
{
  char site[80];
  struct ban_list_element *ban_node, *temp;
  int found = 0;

  one_argument (argument, site);
  if (!*site)
    {
      send_to_char ("A site to unban might help.\r\n", ch);
      return;
    }
  ban_node = ban_list;
  while (ban_node && !found)
    {
      if (!str_cmp (ban_node->site, site))
	found = 1;
      else
	ban_node = ban_node->next;
    }

  if (!found)
    {
      send_to_char ("That site is not currently banned.\r\n", ch);
      return;
    }
  REMOVE_FROM_LIST (ban_node, ban_list, next);
  send_to_char ("Site unbanned.\r\n", ch);
  sprintf (buf, "%s removed the %s-player ban on %s.",
	   GET_NAME (ch), ban_types[ban_node->type], ban_node->site);
  mudlog (buf, NRM, MAX (LVL_GOD, GET_INVIS_LEV (ch)), TRUE);

  free (ban_node);
  write_ban_list ();
}


/**************************************************************************
 *  Code to check for invalid names (i.e., profanity, etc.)		  *
 *  Written by Sharon P. Goza						  *
 **************************************************************************/

#define MAX_INVALID_NAMES	200
extern int top_of_mobt;
extern struct char_data *mob_proto;

char *invalid_list[MAX_INVALID_NAMES];
int num_invalid = 0;

int
Valid_Name (char *newname)
{
  int i;

  char tempname[MAX_INPUT_LENGTH];

  /* return valid if list doesn't exist */
  if (!invalid_list || num_invalid < 1)
    return 1;

  /* change to lowercase */
  strcpy (tempname, newname);
  for (i = 0; tempname[i]; i++)
    tempname[i] = LOWER (tempname[i]);

  /* Does the desired name contain a string in the invalid list? */
  for (i = 0; i < num_invalid; i++)
    if (strstr (tempname, invalid_list[i]))
      return 0;

  /* Is the desired name already taken by a mob in the game? */
  for (i = 0; i < top_of_mobt; i++) {
    if (is_name(tempname, mob_proto[i].player.name))
      return 0;
  }

  return 1;
}


void
Read_Invalid_List (void)
{
  FILE *fp;
  char temp[256];

  if (!(fp = fopen (XNAME_FILE, "r")))
    {
      perror ("SYSERR: Unable to open invalid name file");
      return;
    }

  num_invalid = 0;
  while (get_line (fp, temp) && num_invalid < MAX_INVALID_NAMES)
    invalid_list[num_invalid++] = str_dup (temp);

  if (num_invalid >= MAX_INVALID_NAMES)
    {
      fprintf (stderr, "SYSERR: Too many invalid names; change MAX_INVALID_NAMES in ban.c\n");
      exit (1);
    }

  fclose (fp);
}