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 }