2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation; either version 2 of the License, or
5 (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 * New global lists code
21 * Added by Shaney, 29 May 1995 :)
27 static struct List *firstGlobalList = NULL;
29 static ListTable ListArray[] =
31 {P_GOD, "removedcom"},
37 {P_ADMIN, "c1muzzle"}, /* possible FICS trouble spots */
38 {P_ADMIN, "c24muzzle"}, /* would prefer two param addlist - DAV */
39 {P_ADMIN, "c46muzzle"}, /* is a temp solution */
40 {P_ADMIN, "c49muzzle"},
41 {P_ADMIN, "c50muzzle"},
42 {P_ADMIN, "c51muzzle"},
49 {P_PUBLIC, "computer"},
51 {P_PERSONAL, "censor"},
52 {P_PERSONAL, "gnotify"},
53 {P_PERSONAL, "noplay"},
54 {P_PERSONAL, "notify"},
55 {P_PERSONAL, "channel"},
56 {P_PERSONAL, "follow"},
57 {P_PERSONAL, "remote"},
60 /* free up memory used by lists */
61 void lists_close(void)
65 for (l=firstGlobalList; l; ) {
66 struct List *next = l->next;
68 for (i=0;i<l->numMembers;i++) {
77 firstGlobalList = NULL;
81 /* find a list. does not load from disk */
82 static struct List *list_find1(int p, enum ListWhich l)
84 struct player *pp = &player_globals.parray[p];
85 struct List *prev, *tempList, **starter;
88 personal = ListArray[l].rights == P_PERSONAL;
89 starter = personal ? &(pp->lists) : &firstGlobalList;
91 for (prev = NULL, tempList = *starter; tempList != NULL; tempList = tempList->next) {
92 if (l == tempList->which) {
94 prev->next = tempList->next;
95 tempList->next = *starter;
100 if (tempList->which >= L_LASTLIST) {
101 /* THIS SHOULD NEVER HAPPEN! But has been in personal list: bugs! */
102 d_printf( "fics: ERROR!! in lists code\n");
111 /* find a list. loads from disk if not in memory. */
112 static struct List *list_find(int p, enum ListWhich l)
116 char listmember[100];
119 lst = list_find1(p, l);
124 /* create the base list */
125 list_add(p, l, NULL);
127 if (ListArray[l].rights == P_PERSONAL) {
131 fp = fopen_p("%s/%s", "r", LISTS_DIR, ListArray[l].name);
136 if (fgets(listmember, sizeof(listmember), fp) != NULL) {
137 if (list_add(p, l, listmember) == 0) {
144 /* we've added some, retry */
146 return list_find1(p, l);
153 /* add item to list */
154 int list_add(int p, enum ListWhich l, const char *s)
156 struct player *pp = &player_globals.parray[p];
157 struct List *gl = list_find1(p, l);
160 gl = calloc(1, sizeof(*gl));
162 if (ListArray[l].rights == P_PERSONAL) {
163 gl->next = pp->lists;
166 gl->next = firstGlobalList;
167 firstGlobalList = gl;
173 if (ListArray[l].rights == P_PERSONAL &&
174 gl->numMembers >= config_get_int("MAX_USER_LIST_SIZE", DEFAULT_MAX_USER_LIST_SIZE)) {
178 while (isspace(*s)) s++;
180 gl->m_member = (char **)realloc(gl->m_member, sizeof(char *) * (gl->numMembers+1));
181 gl->m_member[gl->numMembers] = strndup(s, strcspn(s, " \t\r\n"));
187 /* remove item from list */
188 static int list_sub(int p, enum ListWhich l, char *s)
190 struct List *gl = list_find(p, l);
196 for (i = 0; i < gl->numMembers; i++) {
197 if (!strcasecmp(s, gl->m_member[i])) {
201 if (i == gl->numMembers) {
205 FREE(gl->m_member[i]);
207 for (; i < (gl->numMembers - 1); i++) {
208 gl->m_member[i] = gl->m_member[i+1];
212 gl->m_member = (char **)realloc(gl->m_member, sizeof(char *) * gl->numMembers);
216 /* find list by name, doesn't have to be the whole name */
217 struct List *list_findpartial(int p, char *which, int gonnado)
219 struct player *pp = &player_globals.parray[p];
221 int i, foundit, slen;
223 slen = strlen(which);
224 for (i = 0, foundit = -1; ListArray[i].name != NULL; i++) {
225 if (!strncasecmp(ListArray[i].name, which, slen)) {
229 return NULL; /* ambiguous */
234 int rights = ListArray[foundit].rights;
237 switch (rights) { /* check rights */
239 if (gonnado && !player_ishead(p))
243 if ((gonnado && (pp->adminLevel < ADMIN_GOD)) ||
244 (!gonnado && (pp->adminLevel < ADMIN_ADMIN)))
248 if (pp->adminLevel < ADMIN_ADMIN)
252 if (gonnado && (pp->adminLevel < ADMIN_ADMIN))
257 pprintf(p, "\"%s\" is not an appropriate list name or you have insufficient rights.\n", which);
260 gl = list_find(p, foundit);
262 pprintf(p, "\"%s\" does not match any list name.\n", which);
268 /* see if something is in a list */
269 int in_list(int p, enum ListWhich which, char *member)
273 int filterList = (which == L_FILTER);
275 gl = list_find(p, which);
276 if ((gl == NULL) || (member == NULL))
278 for (i = 0; i < gl->numMembers; i++) {
280 if (!strncasecmp(member, gl->m_member[i], strlen(gl->m_member[i])))
283 if (!strcasecmp(member, gl->m_member[i]))
290 /* add or subtract something to/from a list */
291 int list_addsub(int p, char* list, char* who, int addsub)
293 struct player *pp = &player_globals.parray[p];
294 int p1, connected, loadme, personal, ch;
295 char *listname, *member, junkChar;
297 char *yourthe, *addrem;
299 gl = list_findpartial(p, list, addsub);
303 personal = ListArray[gl->which].rights == P_PERSONAL;
304 loadme = (gl->which != L_FILTER) && (gl->which != L_REMOVEDCOM) && (gl->which != L_CHANNEL);
305 listname = ListArray[gl->which].name;
306 yourthe = personal ? "your" : "the";
307 addrem = (addsub == 1) ? "added to" : "removed from";
310 if (!FindPlayer(p, who, &p1, &connected)) {
313 member = who; /* allow sub removed/renamed player */
316 member = player_globals.parray[p1].name;
321 if (addsub == 1) { /* add to list */
323 if (gl->which == L_CHANNEL) {
325 if (sscanf (who,"%d%c",&ch, &junkChar) == 1 && ch >= 0 && ch < 255) {
326 if ((ch == 0) && (!in_list(p,L_ADMIN,pp->name))) {
327 pprintf(p, "Only admins may join channel 0.\n");
331 pprintf (p,"The channel to add must be a number between 0 and %d.\n",MAX_CHANNELS - 1);
335 if (in_list(p, gl->which, member)) {
336 pprintf(p, "[%s] is already on %s %s list.\n", member, yourthe, listname);
337 if (loadme && !connected)
341 if (list_add(p, gl->which, member)) {
342 pprintf(p, "Sorry, %s %s list is full.\n", yourthe, listname);
343 if (loadme && !connected)
347 } else if (addsub == 2) { /* subtract from list */
348 if (!in_list(p, gl->which, member)) {
349 pprintf(p, "[%s] is not in %s %s list.\n", member, yourthe, listname);
350 if (loadme && !connected)
354 list_sub(p, gl->which, member);
356 pprintf(p, "[%s] %s %s %s list.\n", member, addrem, yourthe, listname);
360 char filename[MAX_FILENAME_SIZE];
373 pprintf(p, "Please leave a comment to explain why %s was %s the %s list.\n", member, addrem, listname);
374 pcommand(p, "addcomment %s %s %s list.\n", member, addrem, listname);
377 if (player_globals.parray[p1].b_stats.rating > 0)
378 UpdateRank(TYPE_BLITZ, member, &player_globals.parray[p1].b_stats, member);
379 if (player_globals.parray[p1].s_stats.rating > 0)
380 UpdateRank(TYPE_STAND, member, &player_globals.parray[p1].s_stats, member);
381 if (player_globals.parray[p1].w_stats.rating > 0)
382 UpdateRank(TYPE_WILD, member, &player_globals.parray[p1].w_stats, member);
385 if (addsub == 1) { /* adding to list */
386 player_globals.parray[p1].adminLevel = 10;
387 pprintf(p, "%s has been given an admin level of 10 - change with asetadmin.\n", member);
389 player_globals.parray[p1].adminLevel = 0;
398 if (loadme && connected)
399 pprintf_prompt(p1, "You have been %s the %s list by %s.\n",
400 addrem, listname, pp->name);
402 sprintf(filename, "%s/%s", LISTS_DIR, listname);
403 fp = fopen_s(filename, "w");
405 d_printf( "Couldn't save %s list.\n", listname);
408 for (i = 0; i < gl->numMembers; i++)
409 fprintf(fp, "%s\n", gl->m_member[i]);
413 if (loadme || (gl->which == L_ADMIN)) {
416 if (loadme && !connected) {
422 int com_addlist(int p, param_list param)
424 return list_addsub(p, param[0].val.word, param[1].val.word, 1);
427 int com_sublist(int p,param_list param)
429 return list_addsub(p, param[0].val.word, param[1].val.word, 2);
432 /* toggle being in a list */
433 int com_togglelist(int p,param_list param)
435 char *list = param[0].val.word;
436 char *val = param[1].val.word;
437 struct List *gl = list_findpartial(p, list, 0);
439 pprintf(p, "'%s' does not match any list name.\n", list);
442 if (in_list(p, gl->which, val)) {
443 return com_sublist(p, param);
445 return com_addlist(p, param);
448 int com_showlist(int p, param_list param)
450 struct player *pp = &player_globals.parray[p];
454 char *rightnames[] = {"EDIT HEAD, READ ADMINS", "EDIT GODS, READ ADMINS", "READ/WRITE ADMINS", "PUBLIC", "PERSONAL"};
456 if (param[0].type == 0) { /* Show all lists */
457 pprintf(p, "Lists:\n\n");
458 for (i = 0; ListArray[i].name != NULL; i++) {
459 rights = ListArray[i].rights;
460 if ((rights > P_ADMIN) || (pp->adminLevel >= ADMIN_ADMIN))
461 pprintf(p, "%-20s is %s\n", ListArray[i].name, rightnames[rights]);
463 } else { /* find match in index */
464 gl = list_findpartial(p, param[0].val.word, 0);
468 rights = ListArray[gl->which].rights;
469 /* display the list */
471 multicol *m = multicol_start(gl->numMembers);
473 pprintf(p, "-- %s list: %d %s --", ListArray[gl->which].name,
475 ((!(strcmp(ListArray[gl->which].name,"filter"))) ? "ips" : (!(strcmp(ListArray[gl->which].name,"removedcom"))) ? "commands" : (!(strcmp(ListArray[gl->which].name,"channel"))) ? "channels" : "names"));
476 for (i = 0; i < gl->numMembers; i++)
477 multicol_store_sorted(m, gl->m_member[i]);
478 multicol_pprint(m, p, pp->d_width, 2);
485 int list_channels(int p,int p1)
487 struct player *pp = &player_globals.parray[p];
491 gl = list_findpartial(p1, "channel", 0);
495 rights = ListArray[gl->which].rights;
496 /* display the list */
497 if (gl->numMembers == 0)
500 multicol *m = multicol_start(gl->numMembers);
502 for (i = 0; i < gl->numMembers; i++)
503 multicol_store_sorted(m, gl->m_member[i]);
504 multicol_pprint(m, p, pp->d_width, 1);
510 /* free the memory used by a list */
511 void list_free(struct List * gl)
517 for (i = 0; i < gl->numMembers; i++) {
518 FREE(gl->m_member[i]);
527 /* check lists for validity - pure paranoia */
528 void lists_validate(int p)
530 struct player *pp = &player_globals.parray[p];
533 for (gl=pp->lists; gl; gl=gl->next) {
534 if (gl->numMembers && !gl->m_member) {
541 int titled_player(int p,char* name)
543 if ((in_list(p, L_FM, name)) ||
544 (in_list(p, L_IM, name)) ||
545 (in_list(p, L_GM, name)) ||
546 (in_list(p, L_WGM, name))) {