/* * ignore.c: handles the ingore command for irc * * Written By Michael Sandrof * * Copyright (c) 1990 Michael Sandrof. * Copyright (c) 1991, 1992 Troy Rollo. * Copyright (c) 1992-2004 Matthew R. Green. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "irc.h" IRCII_RCSID("@(#)$eterna: ignore.c,v 1.34 2005/09/21 22:19:20 mrg Exp $"); #include "ignore.h" #include "ircaux.h" #include "list.h" #include "vars.h" #include "output.h" #define NUMBER_OF_IGNORE_LEVELS 9 #define IGNORE_REMOVE 1 #define IGNORE_DONT 2 #define IGNORE_HIGH -1 int ignore_usernames = 0; u_char highlight_char = '\0'; static int ignore_usernames_sums[NUMBER_OF_IGNORE_LEVELS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static int remove_ignore(u_char *); static u_char *ignore_list(u_char *, int); static int ignore_usernames_mask(int, int); static void ignore_nickname(u_char *, int, int); /* * Ignore: the ignore list structure, consists of the nickname, and the type * of ignorance which is to take place */ typedef struct IgnoreStru { struct IgnoreStru *next; u_char *nick; int type; int dont; int high; } Ignore; /* ignored_nicks: pointer to the head of the ignore list */ static Ignore *ignored_nicks = NULL; static int ignore_usernames_mask(mask, thing) int mask; int thing; { int i; int p; for (i = 0, p = 1; i < NUMBER_OF_IGNORE_LEVELS; i++, p *= 2) if (mask & p) ignore_usernames_sums[i] += thing; mask = 0; for (i = 0, p = 1; i < NUMBER_OF_IGNORE_LEVELS; i++, p *= 2) if (ignore_usernames_sums[i]) mask += p; return (mask); } /* * ignore_nickname: adds nick to the ignore list, using type as the type of * ignorance to take place. */ static void ignore_nickname(nick, type, flag) u_char *nick; int type; int flag; { Ignore *new; char *msg; u_char *ptr; u_char buffer[BIG_BUFFER_SIZE]; while (nick) { if ((ptr = my_index(nick, ',')) != NULL) *ptr = '\0'; if (my_index(nick, '@')) ignore_usernames = ignore_usernames_mask(type, 1); if (*nick) { if (!(new = (Ignore *) list_lookup((List **)(void *)&ignored_nicks, nick, !USE_WILDCARDS, !REMOVE_FROM_LIST))) { if (flag == IGNORE_REMOVE) { say("%s is not on the ignorance list", nick); if (ptr) *(ptr++) = ','; nick = ptr; continue; } else { if ((new = (Ignore *) remove_from_list((List **)(void *)&ignored_nicks, nick)) != NULL) { new_free(&(new->nick)); new_free(&new); } new = (Ignore *) new_malloc(sizeof(Ignore)); new->nick = (u_char *) 0; new->type = 0; new->dont = 0; new->high = 0; malloc_strcpy(&(new->nick), nick); upper(new->nick); add_to_list((List **)(void *)&ignored_nicks, (List *) new); } } switch (flag) { case IGNORE_REMOVE: new->type &= (~type); new->high &= (~type); new->dont &= (~type); msg = "Not ignoring"; break; case IGNORE_DONT: new->dont |= type; new->type &= (~type); new->high &= (~type); msg = "Never ignoring"; break; case IGNORE_HIGH: new->high |= type; new->type &= (~type); new->dont &= (~type); msg = "Highlighting"; break; default: new->type |= type; new->high &= (~type); new->dont &= (~type); msg = "Ignoring"; break; } if (type == IGNORE_ALL) { switch (flag) { case IGNORE_REMOVE: say("%s removed from ignorance list", new->nick); remove_ignore(new->nick); break; case IGNORE_HIGH: say("Highlighting ALL messages from %s", new->nick); break; case IGNORE_DONT: say("Never ignoring messages from %s", new->nick); break; default: say("Ignoring ALL messages from %s", new->nick); break; } return; } else if (type) { my_strmcpy(buffer, msg, sizeof buffer); if (type & IGNORE_MSGS) my_strmcat(buffer, " MSGS", sizeof buffer); if (type & IGNORE_PUBLIC) my_strmcat(buffer, " PUBLIC", sizeof buffer); if (type & IGNORE_WALLS) my_strmcat(buffer, " WALLS", sizeof buffer); if (type & IGNORE_WALLOPS) my_strmcat(buffer, " WALLOPS", sizeof buffer); if (type & IGNORE_INVITES) my_strmcat(buffer, " INVITES", sizeof buffer); if (type & IGNORE_NOTICES) my_strmcat(buffer, " NOTICES", sizeof buffer); if (type & IGNORE_NOTES) my_strmcat(buffer, " NOTES", sizeof buffer); if (type & IGNORE_CTCPS) my_strmcat(buffer, " CTCPS", sizeof buffer); if (type & IGNORE_CRAP) my_strmcat(buffer, " CRAP", sizeof buffer); say("%s from %s", buffer, new->nick); } if ((new->type == 0) && (new->high == 0)) remove_ignore(new->nick); } if (ptr) *(ptr++) = ','; nick = ptr; } } /* * remove_ignore: removes the given nick from the ignore list and returns 0. * If the nick wasn't in the ignore list to begin with, 1 is returned. */ static int remove_ignore(nick) u_char *nick; { Ignore *tmp; if ((tmp = (Ignore *) list_lookup((List **)(void *)&ignored_nicks, nick, !USE_WILDCARDS, REMOVE_FROM_LIST)) != NULL) { if (my_index(nick, '@')) ignore_usernames = ignore_usernames_mask(tmp->type, -1); new_free(&(tmp->nick)); new_free(&tmp); return (0); } return (1); } /* * is_ignored: checks to see if nick is being ignored (poor nick). Checks * against type to see if ignorance is to take place. If nick is marked as * IGNORE_ALL or ignorace types match, 1 is returned, otherwise 0 is * returned. */ int is_ignored(nick, type) u_char *nick; int type; { Ignore *tmp; if (ignored_nicks) { if ((tmp = (Ignore *) list_lookup((List **)(void *)&ignored_nicks, nick, USE_WILDCARDS, !REMOVE_FROM_LIST)) != NULL) { if (tmp->dont & type) return (DONT_IGNORE); if (tmp->type & type) return (IGNORED); if (tmp->high & type) return (HIGHLIGHTED); } } return (0); } /* ignore_list: shows the entired ignorance list */ static u_char * ignore_list(nick, simple_string) u_char *nick; int simple_string; { Ignore *tmp; u_char buffer[BIG_BUFFER_SIZE], *rv = (u_char *) 0; if (ignored_nicks) { if (!simple_string) say("Ignorance List:"); if (nick) upper(nick); for (tmp = ignored_nicks; tmp; tmp = tmp->next) { char s[BIG_BUFFER_SIZE], highlight_string[2]; /* * ignore if we're searching for a specific nick and * this isn't the one. */ if (nick && my_strcmp(nick, tmp->nick)) continue; if (simple_string) { if (!nick) { malloc_strncat(&rv, tmp->nick, 1); my_strcat(rv, " "); continue; } highlight_string[0] = 0; } else { highlight_string[0] = highlight_char; highlight_string[1] = 0; } *buffer = (u_char) 0; if (tmp->type == IGNORE_ALL) my_strmcat(buffer," ALL", sizeof buffer); else if (tmp->high == IGNORE_ALL) { snprintf(s, sizeof s, " %sALL%s", highlight_string, highlight_string); my_strmcat(buffer, s, sizeof buffer); } else if (tmp->dont == IGNORE_ALL) my_strmcat(buffer," DONT-ALL", sizeof buffer); else { if (tmp->type & IGNORE_PUBLIC) my_strmcat(buffer, " PUBLIC", sizeof buffer); else if (tmp->high & IGNORE_PUBLIC) { snprintf(s, sizeof s, " %sPUBLIC%s", highlight_string, highlight_string); my_strmcat(buffer, s, sizeof buffer); } else if (tmp->dont & IGNORE_PUBLIC) my_strmcat(buffer, " DONT-PUBLIC", sizeof buffer); if (tmp->type & IGNORE_MSGS) my_strmcat(buffer, " MSGS", sizeof buffer); else if (tmp->high & IGNORE_MSGS) { snprintf(s, sizeof s, " %sMSGS%s", highlight_string, highlight_string); my_strmcat(buffer, s, sizeof buffer); } else if (tmp->dont & IGNORE_MSGS) my_strmcat(buffer, " DONT-MSGS", sizeof buffer); if (tmp->type & IGNORE_WALLS) my_strmcat(buffer, " WALLS", sizeof buffer); else if (tmp->high & IGNORE_WALLS) { snprintf(s, sizeof s, " %sWALLS%s", highlight_string, highlight_string); my_strmcat(buffer, s, sizeof buffer); } else if (tmp->dont & IGNORE_WALLS) my_strmcat(buffer, " DONT-WALLS", sizeof buffer); if (tmp->type & IGNORE_WALLOPS) my_strmcat(buffer, " WALLOPS", sizeof buffer); else if (tmp->high & IGNORE_WALLOPS) { snprintf(s, sizeof s, " %sWALLOPS%s", highlight_string, highlight_string); my_strmcat(buffer, s, sizeof buffer); } else if (tmp->dont & IGNORE_WALLOPS) my_strmcat(buffer, " DONT-WALLOPS", sizeof buffer); if (tmp->type & IGNORE_INVITES) my_strmcat(buffer, " INVITES", sizeof buffer); else if (tmp->high & IGNORE_INVITES) { snprintf(s, sizeof s, " %sINVITES%s", highlight_string, highlight_string); my_strmcat(buffer, s, sizeof buffer); } else if (tmp->dont & IGNORE_INVITES) my_strmcat(buffer, " DONT-INVITES", sizeof buffer); if (tmp->type & IGNORE_NOTICES) my_strmcat(buffer, " NOTICES", sizeof buffer); else if (tmp->high & IGNORE_NOTICES) { snprintf(s, sizeof s, " %sNOTICES%s", highlight_string, highlight_string); my_strmcat(buffer, s, sizeof buffer); } else if (tmp->dont & IGNORE_NOTICES) my_strmcat(buffer, " DONT-NOTICES", sizeof buffer); if (tmp->type & IGNORE_NOTES) my_strmcat(buffer, " NOTES", sizeof buffer); else if (tmp->high & IGNORE_NOTES) { snprintf(s, sizeof s, " %sNOTES%s", highlight_string, highlight_string); my_strmcat(buffer, s, sizeof buffer); } else if (tmp->dont & IGNORE_NOTES) my_strmcat(buffer, " DONT-NOTES", sizeof buffer); if (tmp->type & IGNORE_CTCPS) my_strmcat(buffer, " CTCPS", sizeof buffer); else if (tmp->high & IGNORE_CTCPS) { snprintf(s, sizeof s, " %sCTCPS%s", highlight_string, highlight_string); my_strmcat(buffer, s, sizeof buffer); } else if (tmp->dont & IGNORE_CTCPS) my_strmcat(buffer, " DONT-CTCPS", sizeof buffer); if (tmp->type & IGNORE_CRAP) my_strmcat(buffer, " CRAP", sizeof buffer); else if (tmp->high & IGNORE_CRAP) { snprintf(s, sizeof s, " %sCRAP%s", highlight_string, highlight_string); my_strmcat(buffer, s, sizeof buffer); } else if (tmp->dont & IGNORE_CRAP) my_strmcat(buffer, " DONT-CRAP", sizeof buffer); } if (simple_string) { malloc_strcpy(&rv, buffer+1); break; } say("\t%s:\t%s", tmp->nick, buffer); } } else { say("There is nothing on the ignorance list."); } return rv; } u_char * ignore_list_string(nick) u_char *nick; { return ignore_list(nick, 1); } /* * ignore: does the /IGNORE command. Figures out what type of ignoring the * user wants to do and calls the proper ignorance command to do it. */ /*ARGSUSED*/ void ignore(command, args, subargs) u_char *command, *args, *subargs; { u_char *nick, *type; int flag, no_flags, ignore_type; if ((nick = next_arg(args, &args)) != NULL) { no_flags = 1; while ((type = next_arg(args, &args)) != NULL) { no_flags = 0; upper(type); switch (*type) { case '^': flag = IGNORE_DONT; type++; break; case '-': flag = IGNORE_REMOVE; type++; break; case '+': flag = IGNORE_HIGH; type++; break; default: flag = 0; break; } ignore_type = get_ignore_type(type); if (ignore_type != -1) ignore_nickname(nick, ignore_type, flag); else if (ignore_type == -1) { u_char *ptr; while (nick) { if ((ptr = my_index(nick, ',')) != NULL) *ptr = (u_char) 0; if (*nick) { if (remove_ignore(nick)) say("%s is not in the ignorance list!", nick); else say("%s removed from ignorance list", nick); } if (ptr) *(ptr++) = ','; nick = ptr; } } else { say("You must specify one of the following:"); say("\tALL MSGS PUBLIC WALLS WALLOPS INVITES \ NOTICES NOTES CTCPS CRAP NONE"); } } if (no_flags) ignore_list(nick, 0); } else ignore_list((u_char *) 0, 0); } /* * set_highlight_char: what the name says.. the character to use * for highlighting.. either BOLD, INVERSE, or UNDERLINE.. */ void set_highlight_char(s) u_char *s; { size_t len; len = my_strlen(s); upper(s); if (!my_strncmp(s, "BOLD", len)) { set_string_var(HIGHLIGHT_CHAR_VAR, UP("BOLD")); highlight_char = BOLD_TOG; } else if (!my_strncmp(s, "INVERSE", len)) { set_string_var(HIGHLIGHT_CHAR_VAR, UP("INVERSE")); highlight_char = REV_TOG; } else if (!my_strncmp(s, "UNDERLINE", len)) { set_string_var(HIGHLIGHT_CHAR_VAR, UP("UNDERLINE")); highlight_char = UND_TOG; } else say("HIGHLIGHT_CHAR must be one of BOLD, INVERSE, or \ UNDERLINE"); } int ignore_combo(flag1, flag2) int flag1; int flag2; { if (flag1 == DONT_IGNORE || flag2 == DONT_IGNORE) return DONT_IGNORE; if (flag1 == IGNORED || flag2 == IGNORED) return IGNORED; if (flag1 == HIGHLIGHTED || flag2 == HIGHLIGHTED) return HIGHLIGHTED; return 0; } /* * double_ignore - makes live simpiler when using doing ignore code * added, april 1993, phone. */ int double_ignore(nick, userhost, type) u_char *nick, *userhost; int type; { if (userhost) return (ignore_combo(is_ignored(nick, type), is_ignored(userhost, type))); else return (is_ignored(nick, type)); } int get_ignore_type(type) u_char *type; { size_t len = my_strlen(type); int rv; if (len == 0) rv = 0; if (my_strnicmp(type, UP("ALL"), len) == 0) rv = IGNORE_ALL; else if (my_strnicmp(type, UP("MSGS"), len) == 0) rv = IGNORE_MSGS; else if (my_strnicmp(type, UP("PUBLIC"), len) == 0) rv = IGNORE_PUBLIC; else if (my_strnicmp(type, UP("WALLS"), len) == 0) rv = IGNORE_WALLS; else if (my_strnicmp(type, UP("WALLOPS"), len) == 0) rv = IGNORE_WALLOPS; else if (my_strnicmp(type, UP("INVITES"), len) == 0) rv = IGNORE_INVITES; else if (my_strnicmp(type, UP("NOTICES"), len) == 0) rv = IGNORE_NOTICES; else if (my_strnicmp(type, UP("NOTES"), len) == 0) rv = IGNORE_NOTES; else if (my_strnicmp(type, UP("CTCPS"), len) == 0) rv = IGNORE_CTCPS; else if (my_strnicmp(type, UP("CRAP"), len) == 0) rv = IGNORE_CRAP; else if (my_strnicmp(type, UP("NONE"), len) == 0) rv = -1; else rv = 0; return (rv); }