/* ************************************************************************
* file: ban.c , site banning module Part of CircleMUD *
* Usage : banning/unbanning/checking sites and names(asshole control) *
* Ban code written by Jeremy "Ras" Elson *
* Invalid name code written by Sharon P. Goza (Aramina) *
* Copyright (C) 1992, 1993 The Trustees of the Johns Hopkins University *
************************************************************************* */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.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 = 0;
/* external vars */
typedef char namestring[MAX_NAME_LENGTH];
extern char *ban_types[];
namestring *invalid_list = NULL;
int num_invalid = 0;
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("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 = tolower(*nextchar);
for (banned_node = ban_list; banned_node; banned_node = banned_node->next)
if (strstr(hostname, banned_node->site)) /* 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 %d %s\n", ban_types[node->type],
node->site, node->date, node->name);
}
}
void write_ban_list(void)
{
FILE * fl;
if (!(fl = fopen(BAN_FILE, "w"))) {
perror("write_ban_list");
return;
}
_write_one_node(fl, ban_list); /* recursively write from end to start */
fclose(fl);
return;
}
ACMD(do_ban)
{
char flag[80], site[80], format[50], *nextchar, *timestr;
int i;
struct ban_list_element *ban_node;
if (IS_NPC(ch)) {
send_to_char("You Beast!!\n\r", ch);
return;
}
strcpy(buf, "");
if (!*argument) {
if (!ban_list) {
send_to_char("No sites are banned.\n\r", ch);
return;
}
strcpy(format, "%-25.25s %-8.8s %-10.10s %-16.16s\n\r");
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;
}
half_chop(argument, flag, site);
if (!*site || !*flag) {
send_to_char("Usage: ban {all | select | new} site_name\n\r", 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.\n\r", 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.\n\r", 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 = tolower(*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]);
syslog(buf, NRM, MAX(LEVEL_GOD, GET_INVIS_LEV(ch)), TRUE);
send_to_char("Site banned.\n\r", ch);
write_ban_list();
}
ACMD(do_unban)
{
char site[80];
struct ban_list_element *ban_node, *prev_node;
int found = 0;
if (IS_NPC(ch)) {
send_to_char("You are not godly enough for that!\n\r", ch);
}
one_argument(argument, site);
if (!*site) {
send_to_char("A site to unban might help.\n\r", 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.\n\r", ch);
return;
}
/* first element in list */
if (ban_node == ban_list)
ban_list = ban_list->next;
else {
for (prev_node = ban_list; prev_node->next != ban_node;
prev_node = prev_node->next)
;
prev_node->next = ban_node->next;
}
send_to_char("Site unbanned.\n\r", ch);
sprintf(buf, "%s removed the %s-player ban on %s.",
GET_NAME(ch), ban_types[ban_node->type], ban_node->site);
syslog(buf, NRM, MAX(LEVEL_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 *
**************************************************************************/
int Valid_Name(char *newname)
{
int i;
char *cptr;
char tempname[MAX_NAME_LENGTH];
/* Made the list of invalid names and words a file to avoid a
recompile when an immortal gets promoted or we think of differnt
permutations, all names in the list should be in caps */
/* IF THE LIST COULDN'T BE READ IN FOR A REASON, RETURN VALID */
if (!invalid_list)
return(1);
/* CHANGE THE INPUT STRING TO BE LOWERCASE SO WE ONLY HAVE TO COMPARE ONCE */
for (i = 0, cptr = newname; *cptr && i < MAX_NAME_LENGTH; )
tempname[i++] = tolower(*cptr++);
tempname[i] = 0;
/* Loop through the invalid list and see if the string occurs
in the desired name */
for (i = 0; i < num_invalid; i++)
if (strstr(tempname, invalid_list[i]))
return(0);
return(1);
}
void Read_Invalid_List(void)
{
FILE * fp;
int i = 0;
char string[80];
if (!(fp = fopen(XNAME_FILE, "r"))) {
perror("Unable to open invalid name file");
return;
}
/* count how many records */
while (!feof(fp)) {
fscanf(fp, "%s", string);
num_invalid++;
}
rewind(fp);
CREATE(invalid_list, namestring, num_invalid);
while (!feof(fp)) {
fscanf(fp, "%s", invalid_list[i++]);
}
/* make sure there are no nulls in there */
for (i = 0; i < num_invalid && *invalid_list[i]; i++)
num_invalid = i-i;
fclose(fp);
}