/ circle3.1 / src / ban.c
ban.c
  1  /* ************************************************************************
  2  *   File: ban.c                                         Part of CircleMUD *
  3  *  Usage: banning/unbanning/checking sites and player names               *
  4  *                                                                         *
  5  *  All rights reserved.  See license.doc for complete information.        *
  6  *                                                                         *
  7  *  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
  8  *  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
  9  ************************************************************************ */
 10  
 11  #include "conf.h"
 12  #include "sysdep.h"
 13  
 14  
 15  #include "structs.h"
 16  #include "utils.h"
 17  #include "comm.h"
 18  #include "interpreter.h"
 19  #include "handler.h"
 20  #include "db.h"
 21  
 22  /* local globals */
 23  struct ban_list_element *ban_list = NULL;
 24  
 25  /* local functions */
 26  void load_banned(void);
 27  int isbanned(char *hostname);
 28  void _write_one_node(FILE *fp, struct ban_list_element *node);
 29  void write_ban_list(void);
 30  ACMD(do_ban);
 31  ACMD(do_unban);
 32  int Valid_Name(char *newname);
 33  void Read_Invalid_List(void);
 34  void Free_Invalid_List(void);
 35  
 36  
 37  const char *ban_types[] = {
 38    "no",
 39    "new",
 40    "select",
 41    "all",
 42    "ERROR"
 43  };
 44  
 45  
 46  void load_banned(void)
 47  {
 48    FILE *fl;
 49    int i, date;
 50    char site_name[BANNED_SITE_LENGTH + 1], ban_type[100];
 51    char name[MAX_NAME_LENGTH + 1];
 52    struct ban_list_element *next_node;
 53  
 54    ban_list = 0;
 55  
 56    if (!(fl = fopen(BAN_FILE, "r"))) {
 57      if (errno != ENOENT) {
 58        log("SYSERR: Unable to open banfile '%s': %s", BAN_FILE, strerror(errno));
 59      } else
 60        log("   Ban file '%s' doesn't exist.", BAN_FILE);
 61      return;
 62    }
 63    while (fscanf(fl, " %s %s %d %s ", ban_type, site_name, &date, name) == 4) {
 64      CREATE(next_node, struct ban_list_element, 1);
 65      strncpy(next_node->site, site_name, BANNED_SITE_LENGTH);	/* strncpy: OK (n_n->site:BANNED_SITE_LENGTH+1) */
 66      next_node->site[BANNED_SITE_LENGTH] = '\0';
 67      strncpy(next_node->name, name, MAX_NAME_LENGTH);	/* strncpy: OK (n_n->name:MAX_NAME_LENGTH+1) */
 68      next_node->name[MAX_NAME_LENGTH] = '\0';
 69      next_node->date = date;
 70  
 71      for (i = BAN_NOT; i <= BAN_ALL; i++)
 72        if (!strcmp(ban_type, ban_types[i]))
 73  	next_node->type = i;
 74  
 75      next_node->next = ban_list;
 76      ban_list = next_node;
 77    }
 78  
 79    fclose(fl);
 80  }
 81  
 82  
 83  int isbanned(char *hostname)
 84  {
 85    int i;
 86    struct ban_list_element *banned_node;
 87    char *nextchar;
 88  
 89    if (!hostname || !*hostname)
 90      return (0);
 91  
 92    i = 0;
 93    for (nextchar = hostname; *nextchar; nextchar++)
 94      *nextchar = LOWER(*nextchar);
 95  
 96    for (banned_node = ban_list; banned_node; banned_node = banned_node->next)
 97      if (strstr(hostname, banned_node->site))	/* if hostname is a substring */
 98        i = MAX(i, banned_node->type);
 99  
100    return (i);
101  }
102  
103  
104  void _write_one_node(FILE *fp, struct ban_list_element *node)
105  {
106    if (node) {
107      _write_one_node(fp, node->next);
108      fprintf(fp, "%s %s %ld %s\n", ban_types[node->type],
109  	    node->site, (long) node->date, node->name);
110    }
111  }
112  
113  
114  
115  void write_ban_list(void)
116  {
117    FILE *fl;
118  
119    if (!(fl = fopen(BAN_FILE, "w"))) {
120      perror("SYSERR: Unable to open '" BAN_FILE "' for writing");
121      return;
122    }
123    _write_one_node(fl, ban_list);/* recursively write from end to start */
124    fclose(fl);
125    return;
126  }
127  
128  
129  #define BAN_LIST_FORMAT "%-25.25s  %-8.8s  %-10.10s  %-16.16s\r\n"
130  ACMD(do_ban)
131  {
132    char flag[MAX_INPUT_LENGTH], site[MAX_INPUT_LENGTH], *nextchar;
133    char timestr[16];
134    int i;
135    struct ban_list_element *ban_node;
136  
137    if (!*argument) {
138      if (!ban_list) {
139        send_to_char(ch, "No sites are banned.\r\n");
140        return;
141      }
142      send_to_char(ch, BAN_LIST_FORMAT,
143  	    "Banned Site Name",
144  	    "Ban Type",
145  	    "Banned On",
146  	    "Banned By");
147      send_to_char(ch, BAN_LIST_FORMAT,
148  	    "---------------------------------",
149  	    "---------------------------------",
150  	    "---------------------------------",
151  	    "---------------------------------");
152  
153      for (ban_node = ban_list; ban_node; ban_node = ban_node->next) {
154        if (ban_node->date) {
155  	strlcpy(timestr, asctime(localtime(&(ban_node->date))), 10);
156  	timestr[10] = '\0';
157        } else
158  	strcpy(timestr, "Unknown");	/* strcpy: OK (strlen("Unknown") < 16) */
159  
160        send_to_char(ch, BAN_LIST_FORMAT, ban_node->site, ban_types[ban_node->type], timestr, ban_node->name);
161      }
162      return;
163    }
164  
165    two_arguments(argument, flag, site);
166    if (!*site || !*flag) {
167      send_to_char(ch, "Usage: ban {all | select | new} site_name\r\n");
168      return;
169    }
170    if (!(!str_cmp(flag, "select") || !str_cmp(flag, "all") || !str_cmp(flag, "new"))) {
171      send_to_char(ch, "Flag must be ALL, SELECT, or NEW.\r\n");
172      return;
173    }
174    for (ban_node = ban_list; ban_node; ban_node = ban_node->next) {
175      if (!str_cmp(ban_node->site, site)) {
176        send_to_char(ch, "That site has already been banned -- unban it to change the ban type.\r\n");
177        return;
178      }
179    }
180  
181    CREATE(ban_node, struct ban_list_element, 1);
182    strncpy(ban_node->site, site, BANNED_SITE_LENGTH);	/* strncpy: OK (b_n->site:BANNED_SITE_LENGTH+1) */
183    for (nextchar = ban_node->site; *nextchar; nextchar++)
184      *nextchar = LOWER(*nextchar);
185    ban_node->site[BANNED_SITE_LENGTH] = '\0';
186    strncpy(ban_node->name, GET_NAME(ch), MAX_NAME_LENGTH);	/* strncpy: OK (b_n->size:MAX_NAME_LENGTH+1) */
187    ban_node->name[MAX_NAME_LENGTH] = '\0';
188    ban_node->date = time(0);
189  
190    for (i = BAN_NEW; i <= BAN_ALL; i++)
191      if (!str_cmp(flag, ban_types[i]))
192        ban_node->type = i;
193  
194    ban_node->next = ban_list;
195    ban_list = ban_node;
196  
197    mudlog(NRM, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "%s has banned %s for %s players.",
198  	GET_NAME(ch), site, ban_types[ban_node->type]);
199    send_to_char(ch, "Site banned.\r\n");
200    write_ban_list();
201  }
202  #undef BAN_LIST_FORMAT
203  
204  
205  ACMD(do_unban)
206  {
207    char site[MAX_INPUT_LENGTH];
208    struct ban_list_element *ban_node, *temp;
209    int found = 0;
210  
211    one_argument(argument, site);
212    if (!*site) {
213      send_to_char(ch, "A site to unban might help.\r\n");
214      return;
215    }
216    ban_node = ban_list;
217    while (ban_node && !found) {
218      if (!str_cmp(ban_node->site, site))
219        found = 1;
220      else
221        ban_node = ban_node->next;
222    }
223  
224    if (!found) {
225      send_to_char(ch, "That site is not currently banned.\r\n");
226      return;
227    }
228    REMOVE_FROM_LIST(ban_node, ban_list, next);
229    send_to_char(ch, "Site unbanned.\r\n");
230    mudlog(NRM, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "%s removed the %s-player ban on %s.",
231  	GET_NAME(ch), ban_types[ban_node->type], ban_node->site);
232  
233    free(ban_node);
234    write_ban_list();
235  }
236  
237  
238  /**************************************************************************
239   *  Code to check for invalid names (i.e., profanity, etc.)		  *
240   *  Written by Sharon P. Goza						  *
241   **************************************************************************/
242  
243  #define MAX_INVALID_NAMES	200
244  
245  char *invalid_list[MAX_INVALID_NAMES];
246  int num_invalid = 0;
247  
248  int Valid_Name(char *newname)
249  {
250    int i;
251    struct descriptor_data *dt;
252    char tempname[MAX_INPUT_LENGTH];
253  
254    /*
255     * Make sure someone isn't trying to create this same name.  We want to
256     * do a 'str_cmp' so people can't do 'Bob' and 'BoB'.  The creating login
257     * will not have a character name yet and other people sitting at the
258     * prompt won't have characters yet.
259     */
260    for (dt = descriptor_list; dt; dt = dt->next)
261      if (dt->character && GET_NAME(dt->character) && !str_cmp(GET_NAME(dt->character), newname))
262        return (STATE(dt) == CON_PLAYING);
263  
264    /* return valid if list doesn't exist */
265    if (!invalid_list || num_invalid < 1)
266      return (1);
267  
268    /* change to lowercase */
269    strlcpy(tempname, newname, sizeof(tempname));
270    for (i = 0; tempname[i]; i++)
271      tempname[i] = LOWER(tempname[i]);
272  
273    /* Does the desired name contain a string in the invalid list? */
274    for (i = 0; i < num_invalid; i++)
275      if (strstr(tempname, invalid_list[i]))
276        return (0);
277  
278    return (1);
279  }
280  
281  
282  /* What's with the wacky capitalization in here? */
283  void Free_Invalid_List(void)
284  {
285    int invl;
286  
287    for (invl = 0; invl < num_invalid; invl++)
288      free(invalid_list[invl]);
289  
290    num_invalid = 0;
291  }
292  
293  
294  void Read_Invalid_List(void)
295  {
296    FILE *fp;
297    char temp[256];
298  
299    if (!(fp = fopen(XNAME_FILE, "r"))) {
300      perror("SYSERR: Unable to open '" XNAME_FILE "' for reading");
301      return;
302    }
303  
304    num_invalid = 0;
305    while (get_line(fp, temp) && num_invalid < MAX_INVALID_NAMES)
306      invalid_list[num_invalid++] = strdup(temp);
307  
308    if (num_invalid >= MAX_INVALID_NAMES) {
309      log("SYSERR: Too many invalid names; change MAX_INVALID_NAMES in ban.c");
310      exit(1);
311    }
312  
313    fclose(fp);
314  }