/* * 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-2000 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("@(#)$Id: ignore.c,v 1.22 2000/07/18 17:12: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 void ignore_list _((u_char *)); 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 **) &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 **) &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 **) &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_strcpy(buffer, msg); if (type & IGNORE_MSGS) my_strcat(buffer, " MSGS"); if (type & IGNORE_PUBLIC) my_strcat(buffer, " PUBLIC"); if (type & IGNORE_WALLS) my_strcat(buffer, " WALLS"); if (type & IGNORE_WALLOPS) my_strcat(buffer, " WALLOPS"); if (type & IGNORE_INVITES) my_strcat(buffer, " INVITES"); if (type & IGNORE_NOTICES) my_strcat(buffer, " NOTICES"); if (type & IGNORE_NOTES) my_strcat(buffer, " NOTES"); if (type & IGNORE_CTCPS) my_strcat(buffer, " CTCPS"); if (type & IGNORE_CRAP) my_strcat(buffer, " CRAP"); 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 **) &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 **) &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 void ignore_list(nick) u_char *nick; { Ignore *tmp; size_t len = 0; u_char buffer[BIG_BUFFER_SIZE]; if (ignored_nicks) { say("Ignorance List:"); if (nick) { len = my_strlen(nick); upper(nick); } for (tmp = ignored_nicks; tmp; tmp = tmp->next) { char s[BIG_BUFFER_SIZE]; if (nick) { if (my_strncmp(nick, tmp->nick, len)) continue; } *buffer = (u_char) 0; if (tmp->type == IGNORE_ALL) my_strmcat(buffer," ALL", BIG_BUFFER_SIZE); else if (tmp->high == IGNORE_ALL) { sprintf(s, " %cALL%c", highlight_char, highlight_char); my_strmcat(buffer, s, BIG_BUFFER_SIZE); } else if (tmp->dont == IGNORE_ALL) my_strmcat(buffer," DONT-ALL", BIG_BUFFER_SIZE); else { if (tmp->type & IGNORE_PUBLIC) my_strmcat(buffer, " PUBLIC", BIG_BUFFER_SIZE); else if (tmp->high & IGNORE_PUBLIC) { sprintf(s, " %cPUBLIC%c", highlight_char, highlight_char); my_strmcat(buffer, s, BIG_BUFFER_SIZE); } else if (tmp->dont & IGNORE_PUBLIC) my_strmcat(buffer, " DONT-PUBLIC", BIG_BUFFER_SIZE); if (tmp->type & IGNORE_MSGS) my_strmcat(buffer, " MSGS", BIG_BUFFER_SIZE); else if (tmp->high & IGNORE_MSGS) { sprintf(s, " %cMSGS%c", highlight_char, highlight_char); my_strmcat(buffer, s, BIG_BUFFER_SIZE); } else if (tmp->dont & IGNORE_MSGS) my_strmcat(buffer, " DONT-MSGS", BIG_BUFFER_SIZE); if (tmp->type & IGNORE_WALLS) my_strmcat(buffer, " WALLS", BIG_BUFFER_SIZE); else if (tmp->high & IGNORE_WALLS) { sprintf(s, " %cWALLS%c", highlight_char, highlight_char); my_strmcat(buffer, s, BIG_BUFFER_SIZE); } else if (tmp->dont & IGNORE_WALLS) my_strmcat(buffer, " DONT-WALLS", BIG_BUFFER_SIZE); if (tmp->type & IGNORE_WALLOPS) my_strmcat(buffer, " WALLOPS", BIG_BUFFER_SIZE); else if (tmp->high & IGNORE_WALLOPS) { sprintf(s, " %cWALLOPS%c", highlight_char, highlight_char); my_strmcat(buffer, s, BIG_BUFFER_SIZE); } else if (tmp->dont & IGNORE_WALLOPS) my_strmcat(buffer, " DONT-WALLOPS", BIG_BUFFER_SIZE); if (tmp->type & IGNORE_INVITES) my_strmcat(buffer, " INVITES", BIG_BUFFER_SIZE); else if (tmp->high & IGNORE_INVITES) { sprintf(s, " %cINVITES%c", highlight_char, highlight_char); my_strmcat(buffer, s, BIG_BUFFER_SIZE); } else if (tmp->dont & IGNORE_INVITES) my_strmcat(buffer, " DONT-INVITES", BIG_BUFFER_SIZE); if (tmp->type & IGNORE_NOTICES) my_strmcat(buffer, " NOTICES", BIG_BUFFER_SIZE); else if (tmp->high & IGNORE_NOTICES) { sprintf(s, " %cNOTICES%c", highlight_char, highlight_char); my_strmcat(buffer, s, BIG_BUFFER_SIZE); } else if (tmp->dont & IGNORE_NOTICES) my_strmcat(buffer, " DONT-NOTICES", BIG_BUFFER_SIZE); if (tmp->type & IGNORE_NOTES) my_strmcat(buffer, " NOTES", BIG_BUFFER_SIZE); else if (tmp->high & IGNORE_NOTES) { sprintf(s, " %cNOTES%c", highlight_char, highlight_char); my_strmcat(buffer, s, BIG_BUFFER_SIZE); } else if (tmp->dont & IGNORE_NOTES) my_strmcat(buffer, " DONT-NOTES", BIG_BUFFER_SIZE); if (tmp->type & IGNORE_CTCPS) my_strmcat(buffer, " CTCPS", BIG_BUFFER_SIZE); else if (tmp->high & IGNORE_CTCPS) { sprintf(s, " %cCTCPS%c", highlight_char, highlight_char); my_strmcat(buffer, s, BIG_BUFFER_SIZE); } else if (tmp->dont & IGNORE_CTCPS) my_strmcat(buffer, " DONT-CTCPS", BIG_BUFFER_SIZE); if (tmp->type & IGNORE_CRAP) my_strmcat(buffer, " CRAP", BIG_BUFFER_SIZE); else if (tmp->high & IGNORE_CRAP) { sprintf(s, " %cCRAP%c", highlight_char, highlight_char); my_strmcat(buffer, s, BIG_BUFFER_SIZE); } else if (tmp->dont & IGNORE_CRAP) my_strmcat(buffer, " DONT-CRAP", BIG_BUFFER_SIZE); } say("\t%s:\t%s", tmp->nick, buffer); } } else say("There is nothing on the ignorance list."); } /* * 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; size_t len; int flag, no_flags; 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; } if ((len = my_strlen(type)) == 0) { say("You must specify one of the following:"); say("\tALL MSGS PUBLIC WALLS WALLOPS INVITES \ NOTICES NOTES NONE"); return; } if (my_strncmp(type, "ALL", len) == 0) ignore_nickname(nick, IGNORE_ALL, flag); else if (my_strncmp(type, "MSGS", len) == 0) ignore_nickname(nick, IGNORE_MSGS, flag); else if (my_strncmp(type, "PUBLIC", len) == 0) ignore_nickname(nick, IGNORE_PUBLIC, flag); else if (my_strncmp(type, "WALLS", len) == 0) ignore_nickname(nick, IGNORE_WALLS, flag); else if (my_strncmp(type, "WALLOPS", len) == 0) ignore_nickname(nick, IGNORE_WALLOPS, flag); else if (my_strncmp(type, "INVITES", len) == 0) ignore_nickname(nick, IGNORE_INVITES, flag); else if (my_strncmp(type, "NOTICES", len) == 0) ignore_nickname(nick, IGNORE_NOTICES, flag); else if (my_strncmp(type, "NOTES", len) == 0) ignore_nickname(nick, IGNORE_NOTES, flag); else if (my_strncmp(type, "CTCPS", len) == 0) ignore_nickname(nick, IGNORE_CTCPS, flag); else if (my_strncmp(type, "CRAP", len) == 0) ignore_nickname(nick, IGNORE_CRAP, flag); else if (my_strncmp(type, "NONE", len) == 0) { 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); } else ignore_list((u_char *) 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)); } .