/* * notify.c: a few handy routines to notify you when people enter and leave irc * * Written By Michael Sandrof * * Copyright (c) 1990 Michael Sandrof. * Copyright (c) 1991, 1992 Troy Rollo. * Copyright (c) 1992-2003 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. * * $Id: notify.c,v 1.14 2003/01/08 20:00:54 f Exp $ */ /* * * Revamped by lynX - Dec '91 */ #include "irc.h" #include "list.h" #include "notify.h" #include "ircaux.h" #include "whois.h" #include "hook.h" #include "server.h" #include "output.h" #include "vars.h" /**************************** PATCHED by Flier ******************************/ #include "myvars.h" extern void HandleNotifyOn _((char *, int)); extern void HandleNotifyOff _((char *, time_t)); extern void HandleNotifyOffUh _((char *, char *, char *, time_t, int)); extern void AddDelayNotify _((char *)); extern NickList *CheckJoiners _((char *, char *, int , ChannelList *)); extern void e_nick _((char *, char *, char *)); /* NotifyList has been moved to notify.h - Flier */ /****************************************************************************/ /**************************** PATCHED by Flier ******************************/ /*static NotifyList *notify_list = (NotifyList *) 0;*/ NotifyList *notify_list = (NotifyList *) 0; /****************************************************************************/ /* Rewritten, -lynx */ char * get_notify_list(which) int which; { char *list = (char *) 0; NotifyList *tmp; int first = 0; malloc_strcpy(&list, empty_string); for (tmp = notify_list; tmp; tmp = tmp->next) { if ((which & NOTIFY_LIST_ALL) == NOTIFY_LIST_ALL || ((which & NOTIFY_LIST_HERE) && tmp->flag) || ((which & NOTIFY_LIST_GONE) && !tmp->flag)) { if (first++) malloc_strcat(&list, " "); malloc_strcat(&list, tmp->nick); } } return list; } /* Rewritten, -lynx */ void show_notify_list(all) int all; { /**************************** Patched by Flier ******************************/ /*char *list; list = get_notify_list(NOTIFY_LIST_HERE); if (*list) say("Currently present: %s", list); if (all) { new_free(&list); list = get_notify_list(NOTIFY_LIST_GONE); if (*list) say("Currently absent: %s", list); } new_free(&list);*/ int i; char *list = (char *) 0; NotifyList *tmp, *tmp2; /* mark all as not printed */ for (tmp = notify_list; tmp; tmp = tmp->next) tmp->printed = 0; for (i = 0; i <= all; i++) { /* first print users by groups */ for (tmp = notify_list; tmp; tmp = tmp->next) { /* skip users not online */ if ((i == 0) && (tmp->flag != 1)) continue; /* skip online users */ if ((i == 1) && (tmp->flag == 1)) continue; /* skip already printed entries */ if (tmp->printed) continue; /* if a group is found print all entries in that group */ if (tmp->group) { for (tmp2 = tmp; tmp2; tmp2 = tmp2->next) { /* skip entry if group doesn't match */ if (!tmp2->group || strcmp(tmp->group, tmp2->group)) continue; if (strcmp(tmp->group, tmp2->group)) continue; /* skip users not online */ if ((i == 0) && (tmp2->flag != 1)) continue; /* skip online users */ if ((i == 1) && (tmp2->flag == 1)) continue; tmp2->printed = 1; if (list) malloc_strcat(&list, " "); malloc_strcat(&list, tmp2->nick); } say("Currently %s [%s]: %s", i ? "absent" : "present", tmp->group, list); new_free(&list); } } /* print the rest of list */ for (tmp = notify_list; tmp; tmp = tmp->next) { /* skip users not online */ if ((i == 0) && (tmp->flag != 1)) continue; /* skip online users */ if ((i == 1) && (tmp->flag == 1)) continue; /* skip already printed entries */ if (tmp->printed) continue; tmp->printed = 1; if (list) malloc_strcat(&list, " "); malloc_strcat(&list, tmp->nick); } if (list) { say("Currently %s: %s", i ? "absent" : "present", list); new_free(&list); } } /****************************************************************************/ } /* notify: the NOTIFY command. Does the whole ball-o-wax */ /*ARGSUSED*/ void notify(command, args, subargs) char *command, *args, *subargs; { char *nick, *list = (char *) 0, *ptr; int no_nicks = 1; int do_ison = 0; int old_server = from_server; NotifyList *new; /**************************** PATCHED by Flier ******************************/ char tmpbuf[mybufsize/2]; *tmpbuf='\0'; /****************************************************************************/ malloc_strcpy(&list, empty_string); while ((nick = next_arg(args, &args)) != NULL) { no_nicks = 0; while (nick) { if ((ptr = index(nick, ',')) != NULL) *ptr++ = '\0'; if (*nick == '-') { nick++; if (*nick) { if ((new = (NotifyList *) remove_from_list((List **) ¬ify_list, nick)) != NULL) { new_free(&(new->nick)); /**************************** PATCHED by Flier ******************************/ /*say("%s removed from notification list", nick);*/ new_free(&(new->userhost)); new_free(&(new->mask)); new_free(&(new->group)); if (inSZNotify!=1) say("%s removed from notification list",nick); /****************************************************************************/ new_free(&new); } else say("%s is not on the notification list", nick); } else { while ((new = notify_list)) { notify_list = new->next; new_free(&new->nick); /**************************** PATCHED by Flier ******************************/ new_free(&(new->userhost)); new_free(&(new->mask)); new_free(&(new->group)); /****************************************************************************/ new_free(&new); } /**************************** PATCHED by Flier ******************************/ /*say("Notify list cleared");*/ if (inSZNotify!=1) say("Notify list cleared"); /****************************************************************************/ } } else { /* compatibility */ if (*nick == '+') nick++; if (*nick) { /**************************** PATCHED by Flier ******************************/ char *mask; char *group; if ((mask=index(nick,'!'))) *mask++='\0'; if (mask && (group=index(mask,':'))) *group++='\0'; else if ((group=index(nick,':'))) *group++='\0'; /****************************************************************************/ do_ison = 1; if (index(nick, '*')) say("Wildcards not allowed in NOTIFY nicknames!"); else { if ((new = (NotifyList *) remove_from_list((List **) ¬ify_list, nick)) != NULL) { new_free(&(new->nick)); /**************************** PATCHED by Flier ******************************/ new_free(&(new->userhost)); new_free(&(new->mask)); new_free(&(new->group)); /****************************************************************************/ new_free(&new); } new = (NotifyList *) new_malloc(sizeof(NotifyList)); new->nick = (char *) 0; /**************************** PATCHED by Flier ******************************/ new->isfriend=0; new->userhost=(char *) 0; new->mask=(char *) 0; new->group=(char *) 0; if (mask) malloc_strcpy(&(new->mask),mask); if (group) malloc_strcpy(&(new->group),group); /****************************************************************************/ malloc_strcpy(&(new->nick), nick); new->flag = 0; add_to_list((List **) ¬ify_list, (List *) new); from_server = primary_server; if (get_server_2_6_2(from_server)) { malloc_strcat(&list, new->nick); malloc_strcat(&list, " "); } else add_to_whois_queue(new->nick, whois_notify, (char *) 0); /**************************** PATCHED by Flier ******************************/ /*say("%s added to the notification list", nick);*/ if (inSZNotify!=1) say("%s added to the notification list",nick); else new->flag=2; if (*tmpbuf) strmcat(tmpbuf," ",sizeof(tmpbuf)); strmcat(tmpbuf,new->nick,sizeof(tmpbuf)); new->server=from_server; /****************************************************************************/ from_server = old_server; } } else show_notify_list(0); } nick = ptr; } } /**************************** PATCHED by Flier ******************************/ /*if (do_ison) { from_server = primary_server; add_ison_to_whois(list, ison_notify); from_server = old_server; }*/ if (do_ison && inSZNotify==1 && *tmpbuf) AddDelayNotify(tmpbuf); else if (do_ison) { from_server = primary_server; add_ison_to_whois(list, ison_notify); from_server = old_server; } /****************************************************************************/ new_free(&list); if (no_nicks) show_notify_list(1); } /* * do_notify: This simply goes through the notify list, sending out a WHOIS * for each person on it. This uses the fancy whois stuff in whois.c to * figure things out. Look there for more details, if you can figure it out. * I wrote it and I can't figure it out. * * Thank you Michael... leaving me bugs to fix :) Well I fixed them! */ void do_notify() { static int location = 0; int count, c2, old_server = from_server; char buf[BIG_BUFFER_SIZE+1]; NotifyList *tmp; *buf = '\0'; from_server = primary_server; for (tmp = notify_list, c2 = count = 0; tmp; tmp = tmp->next, count++) { /**************************** PATCHED by Flier ******************************/ /*if (count >= location && count < location + 40)*/ if (tmp->flag!=2 && count >= location && count < location + 40) /****************************************************************************/ { c2++; /**************************** Patched by Flier ******************************/ /*strcat(buf, " "); strcat(buf, tmp->nick);*/ strmcat(buf, " ", sizeof(buf)); strmcat(buf, tmp->nick, sizeof(buf)); /****************************************************************************/ } } if (c2) add_ison_to_whois(buf, ison_notify); if ((location += 40) > count) location = 0; from_server = old_server; } /* * notify_mark: This marks a given person on the notify list as either on irc * (if flag is 1), or not on irc (if flag is 0). If the person's status has * changed since the last check, a message is displayed to that effect. If * the person is not on the notify list, this call is ignored * doit if passed as 0 means it comes from a join, or a msg, etc, not from * an ison reply. 1 is the other.. * we also bail out if the primary_server != from_server and the from-server * is valid. * * NOTE: this function should be called with no particular to_window or other * variables set that would affect what window it would be displayed in. * ideally, a message_from((char *) 0, LOG_CURRENT) should be the what is the * current window level. */ void notify_mark(nick, flag, doit) char *nick; int flag; int doit; { NotifyList *tmp; char *s = get_string_var(NOTIFY_HANDLER_VAR); /**************************** PATCHED by Flier ******************************/ char tmpbuf[mybufsize/4]; time_t timenow=time((time_t *) 0); /****************************************************************************/ if (from_server != primary_server && from_server != -1) return; /* if (!s || (!doit && 'O' == *s)) - this broke notify -gkm *//* old notify */ if (!doit && 'O' == *s) /* old notify */ return; if ('N' == *s) /* noisy notify */ doit = 1; if ((tmp = (NotifyList *) list_lookup((List **) ¬ify_list, nick, !USE_WILDCARDS, !REMOVE_FROM_LIST)) != NULL) { /**************************** PATCHED by Flier ******************************/ if (flag==3) { tmp->flag=0; return; } if (flag!=2 && tmp->flag==2) return; /****************************************************************************/ if (flag) { /**************************** PATCHED by Flier ******************************/ if (tmp->server!=parsing_server_index) { new_free(&(tmp->userhost)); tmp->flag=0; tmp->server=parsing_server_index; } /****************************************************************************/ if (tmp->flag != 1) { if (tmp->flag != -1 && doit #ifndef LITE && do_hook(NOTIFY_SIGNON_LIST, "%s", nick) #endif ) /**************************** PATCHED by Flier ******************************/ /*say("Signon by %s detected", nick);*/ if (flag!=2) HandleNotifyOn(nick,tmp->server); /****************************************************************************/ /* * copy the correct case of the nick * into our array ;) */ malloc_strcpy(&(tmp->nick), nick); malloc_strcpy((char **) &last_notify_nick, nick); tmp->flag = 1; } } else { /**************************** PATCHED by Flier ******************************/ /*if (tmp->flag == 1 && do_hook(NOTIFY_SIGNOFF_LIST, "%s", nick) && doit) say("Signoff by %s detected", nick);*/ char *host=NULL; if (tmp->userhost) { strmcpy(tmpbuf,tmp->userhost,sizeof(tmpbuf)); host=index(tmpbuf,'@'); if (host) host++; if (tmp->flag == 1 && host && tmpbuf[0] && doit #ifndef LITE && do_hook(NOTIFY_SIGNOFF_UH_LIST, "%s %s %s", nick,tmpbuf,host) #endif ) HandleNotifyOffUh(tmp->nick,tmp->userhost,tmp->mask, timenow,tmp->isfriend); } else if (tmp->flag == 1 && doit #ifndef LITE && do_hook(NOTIFY_SIGNOFF_LIST, "%s", nick) #endif ) HandleNotifyOff(tmp->nick,timenow); new_free(&tmp->userhost); /****************************************************************************/ tmp->flag = 0; } } } void save_notify(fp) FILE *fp; { NotifyList *tmp; if (notify_list) { fprintf(fp, "NOTIFY"); for (tmp = notify_list; tmp; tmp = tmp->next) fprintf(fp, " %s", tmp->nick); fprintf(fp, "\n"); } } /* I hate broken compilers -mrg */ static char *vals[] = { "NOISY", "QUIET", "OLD", (char *) 0 }; void set_notify_handler(value) char *value; { size_t len; int i; char *s; if (!value) value = empty_string; for (i = 0, len = strlen(value); (s = vals[i]); i++) if (0 == my_strnicmp(value, s, len)) break; set_string_var(NOTIFY_HANDLER_VAR, s); return; }