2 * Copyright (C) 1998 Peter Zelezny.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
22 #include <sys/types.h>
38 GSList
*notify_list
= 0;
43 despacify_dup (char *str
)
45 char *p
, *res
= malloc (strlen (str
) + 1);
62 notify_netcmp (char *str
, void *serv
)
64 char *net
= despacify_dup (server_get_network (serv
, TRUE
));
66 if (rfc_casecmp (str
, net
) == 0)
69 return 0; /* finish & return FALSE from token_foreach() */
73 return 1; /* keep going... */
76 /* monitor this nick on this particular network? */
79 notify_do_network (struct notify
*notify
, server
*serv
)
81 if (!notify
->networks
) /* ALL networks for this nick */
84 if (token_foreach (notify
->networks
, ',', notify_netcmp
, serv
))
85 return FALSE
; /* network list doesn't contain this one */
90 struct notify_per_server
*
91 notify_find_server_entry (struct notify
*notify
, struct server
*serv
)
93 GSList
*list
= notify
->server_list
;
94 struct notify_per_server
*servnot
;
98 servnot
= (struct notify_per_server
*) list
->data
;
99 if (servnot
->server
== serv
)
104 /* not found, should we add it, or is this not a network where
105 we're monitoring this nick? */
106 if (!notify_do_network (notify
, serv
))
109 servnot
= malloc (sizeof (struct notify_per_server
));
112 memset (servnot
, 0, sizeof (struct notify_per_server
));
113 servnot
->server
= serv
;
114 servnot
->notify
= notify
;
115 notify
->server_list
= g_slist_prepend (notify
->server_list
, servnot
);
124 struct notify
*notify
;
125 GSList
*list
= notify_list
;
127 fh
= xchat_open_file ("notify.conf", O_TRUNC
| O_WRONLY
| O_CREAT
, 0600, XOF_DOMODE
);
132 notify
= (struct notify
*) list
->data
;
133 write (fh
, notify
->name
, strlen (notify
->name
));
134 if (notify
->networks
)
137 write (fh
, notify
->networks
, strlen (notify
->networks
));
153 fh
= xchat_open_file ("notify.conf", O_RDONLY
, 0, 0);
156 while (waitline (fh
, buf
, sizeof buf
, FALSE
) != -1)
158 if (buf
[0] != '#' && buf
[0] != 0)
160 sep
= strchr (buf
, ' ');
164 notify_adduser (buf
, sep
+ 1);
167 notify_adduser (buf
, NULL
);
174 static struct notify_per_server
*
175 notify_find (server
*serv
, char *nick
)
177 GSList
*list
= notify_list
;
178 struct notify_per_server
*servnot
;
179 struct notify
*notify
;
183 notify
= (struct notify
*) list
->data
;
185 servnot
= notify_find_server_entry (notify
, serv
);
192 if (!serv
->p_cmp (notify
->name
, nick
))
202 notify_announce_offline (server
* serv
, struct notify_per_server
*servnot
,
203 char *nick
, int quiet
)
207 sess
= serv
->front_session
;
209 servnot
->ison
= FALSE
;
210 servnot
->lastoff
= time (0);
212 EMIT_SIGNAL (XP_TE_NOTIFYOFFLINE
, sess
, nick
, serv
->servername
,
213 server_get_network (serv
, TRUE
), NULL
, 0);
214 fe_notify_update (nick
);
215 fe_notify_update (0);
219 notify_announce_online (server
* serv
, struct notify_per_server
*servnot
,
224 sess
= serv
->front_session
;
226 servnot
->lastseen
= time (0);
230 servnot
->ison
= TRUE
;
231 servnot
->laston
= time (0);
232 EMIT_SIGNAL (XP_TE_NOTIFYONLINE
, sess
, nick
, serv
->servername
,
233 server_get_network (serv
, TRUE
), NULL
, 0);
234 fe_notify_update (nick
);
235 fe_notify_update (0);
237 if (prefs
.whois_on_notifyonline
)
240 /* Let's do whois with idle time (like in /quote WHOIS %s %s) */
242 char *wii_str
= malloc (strlen (nick
) * 2 + 2);
243 sprintf (wii_str
, "%s %s", nick
, nick
);
244 serv
->p_whois (serv
, wii_str
);
249 /* handles numeric 601 */
252 notify_set_offline (server
* serv
, char *nick
, int quiet
)
254 struct notify_per_server
*servnot
;
256 servnot
= notify_find (serv
, nick
);
260 notify_announce_offline (serv
, servnot
, nick
, quiet
);
263 /* handles numeric 604 and 600 */
266 notify_set_online (server
* serv
, char *nick
)
268 struct notify_per_server
*servnot
;
270 servnot
= notify_find (serv
, nick
);
274 notify_announce_online (serv
, servnot
, nick
);
278 notify_watch (server
* serv
, char *nick
, int add
)
286 if (serv
->supports_monitor
)
287 snprintf (tbuf
, sizeof (tbuf
), "MONITOR %c %s", addchar
, nick
);
288 else if (serv
->supports_watch
)
289 snprintf (tbuf
, sizeof (tbuf
), "WATCH %c%s", addchar
, nick
);
293 serv
->p_raw (serv
, tbuf
);
297 notify_watch_all (struct notify
*notify
, int add
)
300 GSList
*list
= serv_list
;
304 if (serv
->connected
&& serv
->end_of_motd
&& notify_do_network (notify
, serv
))
305 notify_watch (serv
, notify
->name
, add
);
311 notify_flush_watches (server
* serv
, GSList
*from
, GSList
*end
)
315 struct notify
*notify
;
317 serv
->supports_monitor
? strcpy (tbuf
, "MONITOR + ") : strcpy (tbuf
, "WATCH");
323 serv
->supports_monitor
? strcat (tbuf
, ",") : strcat (tbuf
, " +");
324 strcat (tbuf
, notify
->name
);
327 serv
->p_raw (serv
, tbuf
);
330 /* called when logging in. e.g. when End of motd. */
333 notify_send_watches (server
* serv
)
335 struct notify
*notify
;
341 point
= list
= notify_list
;
346 if (notify_do_network (notify
, serv
))
348 len
+= strlen (notify
->name
) + serv
->supports_monitor
? 1 : 2; /* just , for monitor or + and space for watch */;
351 notify_flush_watches (serv
, point
, list
);
352 len
= strlen (notify
->name
) + serv
->supports_monitor
? 1 : 2;
361 notify_flush_watches (serv
, point
, NULL
);
364 /* called when receiving a ISON 303 - should this func go? */
367 notify_markonline (server
*serv
, char *word
[])
369 struct notify
*notify
;
370 struct notify_per_server
*servnot
;
371 GSList
*list
= notify_list
;
376 notify
= (struct notify
*) list
->data
;
377 servnot
= notify_find_server_entry (notify
, serv
);
387 if (!serv
->p_cmp (notify
->name
, word
[i
]))
390 notify_announce_online (serv
, servnot
, notify
->name
);
394 /* FIXME: word[] is only a 32 element array, limits notify list to
396 if (i
> PDIWORDS
- 5)
398 /*fprintf (stderr, _("*** XCHAT WARNING: notify list too large.\n"));*/
402 if (!seen
&& servnot
->ison
)
404 notify_announce_offline (serv
, servnot
, notify
->name
, FALSE
);
408 fe_notify_update (0);
411 /* yuck! Old routine for ISON notify */
414 notify_checklist_for_server (server
*serv
)
417 struct notify
*notify
;
418 GSList
*list
= notify_list
;
421 strcpy (outbuf
, "ISON ");
425 if (notify_do_network (notify
, serv
))
428 strcat (outbuf
, notify
->name
);
429 strcat (outbuf
, " ");
430 if (strlen (outbuf
) > 460)
432 /* LAME: we can't send more than 512 bytes to the server, but *
433 * if we split it in two packets, our offline detection wouldn't *
435 /*fprintf (stderr, _("*** XCHAT WARNING: notify list too large.\n"));*/
443 serv
->p_raw (serv
, outbuf
);
447 notify_checklist (void) /* check ISON list */
450 GSList
*list
= serv_list
;
455 if (serv
->connected
&& serv
->end_of_motd
&& !serv
->supports_watch
&& !serv
->supports_monitor
)
457 notify_checklist_for_server (serv
);
465 notify_showlist (struct session
*sess
)
468 struct notify
*notify
;
469 GSList
*list
= notify_list
;
470 struct notify_per_server
*servnot
;
473 EMIT_SIGNAL (XP_TE_NOTIFYHEAD
, sess
, NULL
, NULL
, NULL
, NULL
, 0);
477 notify
= (struct notify
*) list
->data
;
478 servnot
= notify_find_server_entry (notify
, sess
->server
);
479 if (servnot
&& servnot
->ison
)
480 snprintf (outbuf
, sizeof (outbuf
), _(" %-20s online\n"), notify
->name
);
482 snprintf (outbuf
, sizeof (outbuf
), _(" %-20s offline\n"), notify
->name
);
483 PrintText (sess
, outbuf
);
488 sprintf (outbuf
, "%d", i
);
489 EMIT_SIGNAL (XP_TE_NOTIFYNUMBER
, sess
, outbuf
, NULL
, NULL
, NULL
, 0);
491 EMIT_SIGNAL (XP_TE_NOTIFYEMPTY
, sess
, NULL
, NULL
, NULL
, NULL
, 0);
495 notify_deluser (char *name
)
497 struct notify
*notify
;
498 struct notify_per_server
*servnot
;
499 GSList
*list
= notify_list
;
503 notify
= (struct notify
*) list
->data
;
504 if (!rfc_casecmp (notify
->name
, name
))
506 fe_notify_update (notify
->name
);
507 /* Remove the records for each server */
508 while (notify
->server_list
)
510 servnot
= (struct notify_per_server
*) notify
->server_list
->data
;
511 notify
->server_list
=
512 g_slist_remove (notify
->server_list
, servnot
);
515 notify_list
= g_slist_remove (notify_list
, notify
);
516 notify_watch_all (notify
, FALSE
);
517 if (notify
->networks
)
518 free (notify
->networks
);
521 fe_notify_update (0);
530 notify_adduser (char *name
, char *networks
)
532 struct notify
*notify
= malloc (sizeof (struct notify
));
535 memset (notify
, 0, sizeof (struct notify
));
536 if (strlen (name
) >= NICKLEN
)
538 notify
->name
= malloc (NICKLEN
);
539 safe_strcpy (notify
->name
, name
, NICKLEN
);
542 notify
->name
= strdup (name
);
545 notify
->networks
= despacify_dup (networks
);
546 notify
->server_list
= 0;
547 notify_list
= g_slist_prepend (notify_list
, notify
);
549 fe_notify_update (notify
->name
);
550 fe_notify_update (0);
551 notify_watch_all (notify
, TRUE
);
556 notify_is_in_list (server
*serv
, char *name
)
558 struct notify
*notify
;
559 GSList
*list
= notify_list
;
563 notify
= (struct notify
*) list
->data
;
564 if (!serv
->p_cmp (notify
->name
, name
))
573 notify_isnotify (struct session
*sess
, char *name
)
575 struct notify
*notify
;
576 struct notify_per_server
*servnot
;
577 GSList
*list
= notify_list
;
581 notify
= (struct notify
*) list
->data
;
582 if (!sess
->server
->p_cmp (notify
->name
, name
))
584 servnot
= notify_find_server_entry (notify
, sess
->server
);
585 if (servnot
&& servnot
->ison
)
597 GSList
*list
= notify_list
;
598 GSList
*nslist
, *srvlist
;
599 struct notify
*notify
;
600 struct notify_per_server
*servnot
;
606 /* Traverse the list of notify structures */
607 notify
= (struct notify
*) list
->data
;
608 nslist
= notify
->server_list
;
611 /* Look at each per-server structure */
612 servnot
= (struct notify_per_server
*) nslist
->data
;
614 /* Check the server is valid */
619 serv
= (struct server
*) srvlist
->data
;
620 if (servnot
->server
== serv
)
622 valid
= serv
->connected
; /* Only valid if server is too */
625 srvlist
= srvlist
->next
;
629 notify
->server_list
=
630 g_slist_remove (notify
->server_list
, servnot
);
632 nslist
= notify
->server_list
;
635 nslist
= nslist
->next
;
640 fe_notify_update (0);