315 lines
8.3 KiB
C
315 lines
8.3 KiB
C
|
/* ************************************************************************
|
||
|
* 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"
|
||
|
|
||
|
/* local globals */
|
||
|
struct ban_list_element *ban_list = NULL;
|
||
|
|
||
|
/* local functions */
|
||
|
void load_banned(void);
|
||
|
int isbanned(char *hostname);
|
||
|
void _write_one_node(FILE *fp, struct ban_list_element *node);
|
||
|
void write_ban_list(void);
|
||
|
ACMD(do_ban);
|
||
|
ACMD(do_unban);
|
||
|
int Valid_Name(char *newname);
|
||
|
void Read_Invalid_List(void);
|
||
|
void Free_Invalid_List(void);
|
||
|
|
||
|
|
||
|
const char *ban_types[] = {
|
||
|
"no",
|
||
|
"new",
|
||
|
"select",
|
||
|
"all",
|
||
|
"ERROR"
|
||
|
};
|
||
|
|
||
|
|
||
|
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"))) {
|
||
|
if (errno != ENOENT) {
|
||
|
log("SYSERR: Unable to open banfile '%s': %s", BAN_FILE, strerror(errno));
|
||
|
} else
|
||
|
log(" Ban file '%s' doesn't exist.", BAN_FILE);
|
||
|
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); /* strncpy: OK (n_n->site:BANNED_SITE_LENGTH+1) */
|
||
|
next_node->site[BANNED_SITE_LENGTH] = '\0';
|
||
|
strncpy(next_node->name, name, MAX_NAME_LENGTH); /* strncpy: OK (n_n->name:MAX_NAME_LENGTH+1) */
|
||
|
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 (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 %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: Unable to open '" BAN_FILE "' for writing");
|
||
|
return;
|
||
|
}
|
||
|
_write_one_node(fl, ban_list);/* recursively write from end to start */
|
||
|
fclose(fl);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
#define BAN_LIST_FORMAT "%-25.25s %-8.8s %-10.10s %-16.16s\r\n"
|
||
|
ACMD(do_ban)
|
||
|
{
|
||
|
char flag[MAX_INPUT_LENGTH], site[MAX_INPUT_LENGTH], *nextchar;
|
||
|
char timestr[16];
|
||
|
int i;
|
||
|
struct ban_list_element *ban_node;
|
||
|
|
||
|
if (!*argument) {
|
||
|
if (!ban_list) {
|
||
|
send_to_char(ch, "No sites are banned.\r\n");
|
||
|
return;
|
||
|
}
|
||
|
send_to_char(ch, BAN_LIST_FORMAT,
|
||
|
"Banned Site Name",
|
||
|
"Ban Type",
|
||
|
"Banned On",
|
||
|
"Banned By");
|
||
|
send_to_char(ch, BAN_LIST_FORMAT,
|
||
|
"---------------------------------",
|
||
|
"---------------------------------",
|
||
|
"---------------------------------",
|
||
|
"---------------------------------");
|
||
|
|
||
|
for (ban_node = ban_list; ban_node; ban_node = ban_node->next) {
|
||
|
if (ban_node->date) {
|
||
|
strlcpy(timestr, asctime(localtime(&(ban_node->date))), 10);
|
||
|
timestr[10] = '\0';
|
||
|
} else
|
||
|
strcpy(timestr, "Unknown"); /* strcpy: OK (strlen("Unknown") < 16) */
|
||
|
|
||
|
send_to_char(ch, BAN_LIST_FORMAT, ban_node->site, ban_types[ban_node->type], timestr, ban_node->name);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
two_arguments(argument, flag, site);
|
||
|
if (!*site || !*flag) {
|
||
|
send_to_char(ch, "Usage: ban {all | select | new} site_name\r\n");
|
||
|
return;
|
||
|
}
|
||
|
if (!(!str_cmp(flag, "select") || !str_cmp(flag, "all") || !str_cmp(flag, "new"))) {
|
||
|
send_to_char(ch, "Flag must be ALL, SELECT, or NEW.\r\n");
|
||
|
return;
|
||
|
}
|
||
|
for (ban_node = ban_list; ban_node; ban_node = ban_node->next) {
|
||
|
if (!str_cmp(ban_node->site, site)) {
|
||
|
send_to_char(ch, "That site has already been banned -- unban it to change the ban type.\r\n");
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CREATE(ban_node, struct ban_list_element, 1);
|
||
|
strncpy(ban_node->site, site, BANNED_SITE_LENGTH); /* strncpy: OK (b_n->site:BANNED_SITE_LENGTH+1) */
|
||
|
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); /* strncpy: OK (b_n->size:MAX_NAME_LENGTH+1) */
|
||
|
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;
|
||
|
|
||
|
mudlog(NRM, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "%s has banned %s for %s players.",
|
||
|
GET_NAME(ch), site, ban_types[ban_node->type]);
|
||
|
send_to_char(ch, "Site banned.\r\n");
|
||
|
write_ban_list();
|
||
|
}
|
||
|
#undef BAN_LIST_FORMAT
|
||
|
|
||
|
|
||
|
ACMD(do_unban)
|
||
|
{
|
||
|
char site[MAX_INPUT_LENGTH];
|
||
|
struct ban_list_element *ban_node, *temp;
|
||
|
int found = 0;
|
||
|
|
||
|
one_argument(argument, site);
|
||
|
if (!*site) {
|
||
|
send_to_char(ch, "A site to unban might help.\r\n");
|
||
|
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(ch, "That site is not currently banned.\r\n");
|
||
|
return;
|
||
|
}
|
||
|
REMOVE_FROM_LIST(ban_node, ban_list, next);
|
||
|
send_to_char(ch, "Site unbanned.\r\n");
|
||
|
mudlog(NRM, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "%s removed the %s-player ban on %s.",
|
||
|
GET_NAME(ch), ban_types[ban_node->type], ban_node->site);
|
||
|
|
||
|
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
|
||
|
|
||
|
char *invalid_list[MAX_INVALID_NAMES];
|
||
|
int num_invalid = 0;
|
||
|
|
||
|
int Valid_Name(char *newname)
|
||
|
{
|
||
|
int i;
|
||
|
struct descriptor_data *dt;
|
||
|
char tempname[MAX_INPUT_LENGTH];
|
||
|
|
||
|
/*
|
||
|
* Make sure someone isn't trying to create this same name. We want to
|
||
|
* do a 'str_cmp' so people can't do 'Bob' and 'BoB'. The creating login
|
||
|
* will not have a character name yet and other people sitting at the
|
||
|
* prompt won't have characters yet.
|
||
|
*/
|
||
|
for (dt = descriptor_list; dt; dt = dt->next)
|
||
|
if (dt->character && GET_NAME(dt->character) && !str_cmp(GET_NAME(dt->character), newname))
|
||
|
return (STATE(dt) == CON_PLAYING);
|
||
|
|
||
|
/* return valid if list doesn't exist */
|
||
|
if (!invalid_list || num_invalid < 1)
|
||
|
return (1);
|
||
|
|
||
|
/* change to lowercase */
|
||
|
strlcpy(tempname, newname, sizeof(tempname));
|
||
|
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);
|
||
|
|
||
|
return (1);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* What's with the wacky capitalization in here? */
|
||
|
void Free_Invalid_List(void)
|
||
|
{
|
||
|
int invl;
|
||
|
|
||
|
for (invl = 0; invl < num_invalid; invl++)
|
||
|
free(invalid_list[invl]);
|
||
|
|
||
|
num_invalid = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Read_Invalid_List(void)
|
||
|
{
|
||
|
FILE *fp;
|
||
|
char temp[256];
|
||
|
|
||
|
if (!(fp = fopen(XNAME_FILE, "r"))) {
|
||
|
perror("SYSERR: Unable to open '" XNAME_FILE "' for reading");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
num_invalid = 0;
|
||
|
while (get_line(fp, temp) && num_invalid < MAX_INVALID_NAMES)
|
||
|
invalid_list[num_invalid++] = strdup(temp);
|
||
|
|
||
|
if (num_invalid >= MAX_INVALID_NAMES) {
|
||
|
log("SYSERR: Too many invalid names; change MAX_INVALID_NAMES in ban.c");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
fclose(fp);
|
||
|
}
|