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
23 #include <sys/types.h>
48 clear_channel (session
*sess
)
51 strcpy (sess
->waitchannel
, sess
->channel
);
53 sess
->doing_who
= FALSE
;
54 sess
->done_away_check
= FALSE
;
58 if (sess
->current_modes
)
60 free (sess
->current_modes
);
61 sess
->current_modes
= NULL
;
64 if (sess
->mode_timeout_tag
)
66 fe_timeout_remove (sess
->mode_timeout_tag
);
67 sess
->mode_timeout_tag
= 0;
70 fe_clear_channel (sess
);
71 userlist_clear (sess
);
72 fe_set_nonchannel (sess
, FALSE
);
77 set_topic (session
*sess
, char *topic
, char *stripped_topic
)
81 sess
->topic
= strdup (stripped_topic
);
82 fe_set_topic (sess
, topic
, stripped_topic
);
86 find_session_from_nick (char *nick
, server
*serv
)
89 GSList
*list
= sess_list
;
91 sess
= find_dialog (serv
, nick
);
95 if (serv
->front_session
)
97 if (userlist_find (serv
->front_session
, nick
))
98 return serv
->front_session
;
101 if (current_sess
&& current_sess
->server
== serv
)
103 if (userlist_find (current_sess
, nick
))
110 if (sess
->server
== serv
)
112 if (userlist_find (sess
, nick
))
121 inbound_open_dialog (server
*serv
, char *from
)
125 sess
= new_ircwindow (serv
, from
, SESS_DIALOG
, 0);
126 /* for playing sounds */
127 EMIT_SIGNAL (XP_TE_OPENDIALOG
, sess
, NULL
, NULL
, NULL
, NULL
, 0);
133 inbound_make_idtext (server
*serv
, char *idtext
, int max
, int id
)
136 if (serv
->have_idmsg
|| serv
->have_accnotify
)
140 safe_strcpy (idtext
, prefs
.irc_id_ytext
, max
);
143 safe_strcpy (idtext
, prefs
.irc_id_ntext
, max
);
145 /* convert codes like %C,%U to the proper ones */
146 check_special_chars (idtext
, TRUE
);
151 inbound_privmsg (server
*serv
, char *from
, char *ip
, char *text
, int id
)
156 gboolean nodiag
= FALSE
;
158 sess
= find_dialog (serv
, from
);
160 if (sess
|| prefs
.autodialog
)
162 /*0=ctcp 1=priv will set autodialog=0 here is flud detected */
165 if (flood_check (from
, ip
, serv
, current_sess
, 1))
166 /* Create a dialog session */
167 sess
= inbound_open_dialog (serv
, from
);
169 sess
= serv
->server_session
;
176 if (prefs
.logging
&& sess
->logfd
!= -1 &&
177 (!sess
->topic
|| strcmp(sess
->topic
, ip
)))
180 snprintf (tbuf
, sizeof (tbuf
), "[%s has address %s]\n", from
, ip
);
181 write (sess
->logfd
, tbuf
, strlen (tbuf
));
183 set_topic (sess
, ip
, ip
);
185 inbound_chanmsg (serv
, NULL
, NULL
, from
, text
, FALSE
, id
);
189 sess
= find_session_from_nick (from
, serv
);
192 sess
= serv
->front_session
;
193 nodiag
= TRUE
; /* We don't want it to look like a normal message in front sess */
196 user
= userlist_find (sess
, from
);
199 user
->lasttalk
= time (0);
204 inbound_make_idtext (serv
, idtext
, sizeof (idtext
), id
);
206 if (sess
->type
== SESS_DIALOG
&& !nodiag
)
207 EMIT_SIGNAL (XP_TE_DPRIVMSG
, sess
, from
, text
, idtext
, NULL
, 0);
209 EMIT_SIGNAL (XP_TE_PRIVMSG
, sess
, from
, text
, idtext
, NULL
, 0);
212 /* used for Alerts section. Masks can be separated by commas and spaces. */
215 alert_match_word (char *word
, char *masks
)
226 /* if it's a 0, space or comma, the word has ended. */
227 if (*p
== 0 || *p
== ' ' || *p
== ',')
231 res
= match (masks
, word
);
235 return TRUE
; /* yes, matched! */
246 alert_match_text (char *text
, char *masks
)
248 unsigned char *p
= text
;
249 unsigned char endchar
;
257 if (*p
>= '0' && *p
<= '9')
263 /* if it's RFC1459 <special>, it can be inside a word */
266 case '-': case '[': case ']': case '\\':
267 case '`': case '^': case '{': case '}':
273 /* if it's a 0, space or comma, the word has ended. */
274 if (*p
== 0 || *p
== ' ' || *p
== ',' ||
275 /* if it's anything BUT a letter, the word has ended. */
276 (!g_unichar_isalpha (g_utf8_get_char (p
))))
280 res
= alert_match_word (text
, masks
);
284 return TRUE
; /* yes, matched! */
286 text
= p
+ g_utf8_skip
[p
[0]];
291 p
+= g_utf8_skip
[p
[0]];
296 is_hilight (char *from
, char *text
, session
*sess
, server
*serv
)
298 if (alert_match_word (from
, prefs
.irc_no_hilight
))
301 text
= strip_color (text
, -1, STRIP_ALL
);
303 if (alert_match_text (text
, serv
->nick
) ||
304 alert_match_text (text
, prefs
.irc_extra_hilight
) ||
305 alert_match_word (from
, prefs
.irc_nick_hilight
))
308 if (sess
!= current_tab
)
309 sess
->nick_said
= TRUE
;
310 fe_set_hilight (sess
);
319 inbound_action (session
*sess
, char *chan
, char *from
, char *ip
, char *text
, int fromme
, int id
)
322 server
*serv
= sess
->server
;
324 char nickchar
[2] = "\000";
326 int privaction
= FALSE
;
330 if (is_channel (serv
, chan
))
332 sess
= find_channel (serv
, chan
);
335 /* it's a private action! */
337 /* find a dialog tab for it */
338 sess
= find_dialog (serv
, from
);
339 /* if non found, open a new one */
340 if (!sess
&& prefs
.autodialog
)
342 /* but only if it wouldn't flood */
343 if (flood_check (from
, ip
, serv
, current_sess
, 1))
344 sess
= inbound_open_dialog (serv
, from
);
346 sess
= serv
->server_session
;
350 sess
= find_session_from_nick (from
, serv
);
351 /* still not good? */
353 sess
= serv
->front_session
;
361 if (sess
!= current_tab
)
365 sess
->msg_said
= FALSE
;
366 sess
->new_data
= TRUE
;
369 sess
->msg_said
= TRUE
;
370 sess
->new_data
= FALSE
;
374 user
= userlist_find (sess
, from
);
377 nickchar
[0] = user
->prefix
[0];
378 user
->lasttalk
= time (0);
383 inbound_make_idtext (serv
, idtext
, sizeof (idtext
), id
);
385 if (!fromme
&& !privaction
)
387 if (is_hilight (from
, text
, sess
, serv
))
389 EMIT_SIGNAL (XP_TE_HCHANACTION
, sess
, from
, text
, nickchar
, idtext
, 0);
395 EMIT_SIGNAL (XP_TE_UACTION
, sess
, from
, text
, nickchar
, idtext
, 0);
396 else if (!privaction
)
397 EMIT_SIGNAL (XP_TE_CHANACTION
, sess
, from
, text
, nickchar
, idtext
, 0);
398 else if (sess
->type
== SESS_DIALOG
)
399 EMIT_SIGNAL (XP_TE_DPRIVACTION
, sess
, from
, text
, idtext
, NULL
, 0);
401 EMIT_SIGNAL (XP_TE_PRIVACTION
, sess
, from
, text
, idtext
, NULL
, 0);
405 inbound_chanmsg (server
*serv
, session
*sess
, char *chan
, char *from
, char *text
, char fromme
, int id
)
409 char nickchar
[2] = "\000";
416 sess
= find_channel (serv
, chan
);
417 if (!sess
&& !is_channel (serv
, chan
))
418 sess
= find_dialog (serv
, chan
);
421 sess
= find_dialog (serv
, from
);
427 if (sess
!= current_tab
)
429 sess
->msg_said
= TRUE
;
430 sess
->new_data
= FALSE
;
433 user
= userlist_find (sess
, from
);
438 nickchar
[0] = user
->prefix
[0];
439 user
->lasttalk
= time (0);
444 if (prefs
.auto_unmark_away
&& serv
->is_away
)
445 sess
->server
->p_set_back (sess
->server
);
446 EMIT_SIGNAL (XP_TE_UCHANMSG
, sess
, from
, text
, nickchar
, NULL
, 0);
450 inbound_make_idtext (serv
, idtext
, sizeof (idtext
), id
);
452 if (is_hilight (from
, text
, sess
, serv
))
455 if (sess
->type
== SESS_DIALOG
)
456 EMIT_SIGNAL (XP_TE_DPRIVMSG
, sess
, from
, text
, idtext
, NULL
, 0);
458 EMIT_SIGNAL (XP_TE_HCHANMSG
, sess
, from
, text
, nickchar
, idtext
, 0);
460 EMIT_SIGNAL (XP_TE_CHANMSG
, sess
, from
, text
, nickchar
, idtext
, 0);
464 inbound_newnick (server
*serv
, char *nick
, char *newnick
, int quiet
)
468 GSList
*list
= sess_list
;
470 if (!serv
->p_cmp (nick
, serv
->nick
))
473 safe_strcpy (serv
->nick
, newnick
, NICKLEN
);
479 if (sess
->server
== serv
)
481 if (userlist_change (sess
, nick
, newnick
) || (me
&& sess
->type
== SESS_SERVER
))
486 EMIT_SIGNAL (XP_TE_UCHANGENICK
, sess
, nick
, newnick
, NULL
,
489 EMIT_SIGNAL (XP_TE_CHANGENICK
, sess
, nick
, newnick
, NULL
,
493 if (sess
->type
== SESS_DIALOG
&& !serv
->p_cmp (sess
->channel
, nick
))
495 safe_strcpy (sess
->channel
, newnick
, CHANLEN
);
496 fe_set_channel (sess
);
503 dcc_change_nick (serv
, nick
, newnick
);
506 fe_set_nick (serv
, newnick
);
509 /* find a "<none>" tab */
511 find_unused_session (server
*serv
)
514 GSList
*list
= sess_list
;
517 sess
= (session
*) list
->data
;
518 if (sess
->type
== SESS_CHANNEL
&& sess
->channel
[0] == 0 &&
519 sess
->server
== serv
)
521 if (sess
->waitchannel
[0] == 0)
530 find_session_from_waitchannel (char *chan
, struct server
*serv
)
533 GSList
*list
= sess_list
;
536 sess
= (session
*) list
->data
;
537 if (sess
->server
== serv
&& sess
->channel
[0] == 0 && sess
->type
== SESS_CHANNEL
)
539 if (!serv
->p_cmp (chan
, sess
->waitchannel
))
548 inbound_ujoin (server
*serv
, char *chan
, char *nick
, char *ip
)
552 /* already joined? probably a bnc */
553 sess
= find_channel (serv
, chan
);
556 /* see if a window is waiting to join this channel */
557 sess
= find_session_from_waitchannel (chan
, serv
);
560 /* find a "<none>" tab and use that */
561 sess
= find_unused_session (serv
);
563 /* last resort, open a new tab/window */
564 sess
= new_ircwindow (serv
, chan
, SESS_CHANNEL
, 1);
568 safe_strcpy (sess
->channel
, chan
, CHANLEN
);
570 fe_set_channel (sess
);
572 fe_set_nonchannel (sess
, TRUE
);
573 userlist_clear (sess
);
575 log_open_or_close (sess
);
577 sess
->waitchannel
[0] = 0;
578 sess
->ignore_date
= TRUE
;
579 sess
->ignore_mode
= TRUE
;
580 sess
->ignore_names
= TRUE
;
581 sess
->end_of_names
= FALSE
;
584 serv
->p_join_info (sess
->server
, chan
);
586 EMIT_SIGNAL (XP_TE_UJOIN
, sess
, nick
, chan
, ip
, NULL
, 0);
590 /* sends WHO #channel */
591 serv
->p_user_list (sess
->server
, chan
);
592 sess
->doing_who
= TRUE
;
597 inbound_ukick (server
*serv
, char *chan
, char *kicker
, char *reason
)
599 session
*sess
= find_channel (serv
, chan
);
602 EMIT_SIGNAL (XP_TE_UKICK
, sess
, serv
->nick
, chan
, kicker
, reason
, 0);
603 clear_channel (sess
);
604 if (prefs
.autorejoin
)
606 serv
->p_join (serv
, chan
, sess
->channelkey
);
607 safe_strcpy (sess
->waitchannel
, chan
, CHANLEN
);
613 inbound_upart (server
*serv
, char *chan
, char *ip
, char *reason
)
615 session
*sess
= find_channel (serv
, chan
);
619 EMIT_SIGNAL (XP_TE_UPARTREASON
, sess
, serv
->nick
, ip
, chan
, reason
,
622 EMIT_SIGNAL (XP_TE_UPART
, sess
, serv
->nick
, ip
, chan
, NULL
, 0);
623 clear_channel (sess
);
628 inbound_nameslist (server
*serv
, char *chan
, char *names
)
634 sess
= find_channel (serv
, chan
);
637 EMIT_SIGNAL (XP_TE_USERSONCHAN
, serv
->server_session
, chan
, names
, NULL
,
641 if (!sess
->ignore_names
)
642 EMIT_SIGNAL (XP_TE_USERSONCHAN
, sess
, chan
, names
, NULL
, NULL
, 0);
644 if (sess
->end_of_names
)
646 sess
->end_of_names
= FALSE
;
647 userlist_clear (sess
);
657 userlist_add (sess
, name
, 0, NULL
, NULL
);
662 userlist_add (sess
, name
, 0, NULL
, NULL
);
666 if (pos
< (NICKLEN
-1))
674 inbound_topic (server
*serv
, char *chan
, char *topic_text
)
676 session
*sess
= find_channel (serv
, chan
);
677 char *stripped_topic
;
681 stripped_topic
= strip_color (topic_text
, -1, STRIP_ALL
);
682 set_topic (sess
, topic_text
, stripped_topic
);
683 g_free (stripped_topic
);
685 sess
= serv
->server_session
;
687 EMIT_SIGNAL (XP_TE_TOPIC
, sess
, chan
, topic_text
, NULL
, NULL
, 0);
691 inbound_topicnew (server
*serv
, char *nick
, char *chan
, char *topic
)
694 char *stripped_topic
;
696 sess
= find_channel (serv
, chan
);
699 EMIT_SIGNAL (XP_TE_NEWTOPIC
, sess
, nick
, topic
, chan
, NULL
, 0);
700 stripped_topic
= strip_color (topic
, -1, STRIP_ALL
);
701 set_topic (sess
, topic
, stripped_topic
);
702 g_free (stripped_topic
);
707 inbound_join (server
*serv
, char *chan
, char *user
, char *ip
, char *account
, char *realname
)
709 session
*sess
= find_channel (serv
, chan
);
712 EMIT_SIGNAL (XP_TE_JOIN
, sess
, user
, chan
, ip
, NULL
, 0);
713 userlist_add (sess
, user
, ip
, account
, realname
);
718 inbound_kick (server
*serv
, char *chan
, char *user
, char *kicker
, char *reason
)
720 session
*sess
= find_channel (serv
, chan
);
723 EMIT_SIGNAL (XP_TE_KICK
, sess
, kicker
, user
, chan
, reason
, 0);
724 userlist_remove (sess
, user
);
729 inbound_part (server
*serv
, char *chan
, char *user
, char *ip
, char *reason
)
731 session
*sess
= find_channel (serv
, chan
);
735 EMIT_SIGNAL (XP_TE_PARTREASON
, sess
, user
, ip
, chan
, reason
, 0);
737 EMIT_SIGNAL (XP_TE_PART
, sess
, user
, ip
, chan
, NULL
, 0);
738 userlist_remove (sess
, user
);
743 inbound_topictime (server
*serv
, char *chan
, char *nick
, time_t stamp
)
745 char *tim
= ctime (&stamp
);
746 session
*sess
= find_channel (serv
, chan
);
749 sess
= serv
->server_session
;
751 tim
[24] = 0; /* get rid of the \n */
752 EMIT_SIGNAL (XP_TE_TOPICDATE
, sess
, chan
, nick
, tim
, NULL
, 0);
756 inbound_quit (server
*serv
, char *nick
, char *ip
, char *reason
)
758 GSList
*list
= sess_list
;
761 int was_on_front_session
= FALSE
;
765 sess
= (session
*) list
->data
;
766 if (sess
->server
== serv
)
768 if (sess
== current_sess
)
769 was_on_front_session
= TRUE
;
770 if (user
= userlist_find (sess
, nick
))
772 EMIT_SIGNAL (XP_TE_QUIT
, sess
, nick
, reason
, ip
, NULL
, 0);
773 userlist_remove_user (sess
, user
);
774 } else if (sess
->type
== SESS_DIALOG
&& !serv
->p_cmp (sess
->channel
, nick
))
776 EMIT_SIGNAL (XP_TE_QUIT
, sess
, nick
, reason
, ip
, NULL
, 0);
782 notify_set_offline (serv
, nick
, was_on_front_session
);
786 inbound_account (server
*serv
, char *nick
, char *account
)
788 session
*sess
= NULL
;
795 if (sess
->server
== serv
)
796 userlist_set_account (sess
, nick
, account
);
802 inbound_ping_reply (session
*sess
, char *timestring
, char *from
)
804 unsigned long tim
, nowtim
, dif
;
808 if (strncmp (timestring
, "LAG", 3) == 0)
814 tim
= strtoul (timestring
, NULL
, 10);
815 nowtim
= make_ping_time ();
818 sess
->server
->ping_recv
= time (0);
822 sess
->server
->lag_sent
= 0;
823 sess
->server
->lag
= dif
/ 1000;
824 fe_set_lag (sess
->server
, dif
/ 100000);
828 if (atol (timestring
) == 0)
830 if (sess
->server
->lag_sent
)
831 sess
->server
->lag_sent
= 0;
833 EMIT_SIGNAL (XP_TE_PINGREP
, sess
, from
, "?", NULL
, NULL
, 0);
836 snprintf (outbuf
, sizeof (outbuf
), "%ld.%ld%ld", dif
/ 1000000, (dif
/ 100000) % 10, dif
% 10);
837 EMIT_SIGNAL (XP_TE_PINGREP
, sess
, from
, outbuf
, NULL
, NULL
, 0);
842 find_session_from_type (int type
, server
*serv
)
845 GSList
*list
= sess_list
;
849 if (sess
->type
== type
&& serv
== sess
->server
)
857 inbound_notice (server
*serv
, char *to
, char *nick
, char *msg
, char *ip
, int id
)
861 int server_notice
= FALSE
;
863 if (is_channel (serv
, ptr
))
864 sess
= find_channel (serv
, ptr
);
866 if (!sess
&& ptr
[0] == '@')
869 sess
= find_channel (serv
, ptr
);
872 if (!sess
&& ptr
[0] == '%')
875 sess
= find_channel (serv
, ptr
);
878 if (!sess
&& ptr
[0] == '+')
881 sess
= find_channel (serv
, ptr
);
884 if (strcmp (nick
, ip
) == 0)
885 server_notice
= TRUE
;
890 if (prefs
.notices_tabs
)
892 int stype
= server_notice
? SESS_SNOTICES
: SESS_NOTICES
;
893 sess
= find_session_from_type (stype
, serv
);
896 if (stype
== SESS_NOTICES
)
897 sess
= new_ircwindow (serv
, "(notices)", SESS_NOTICES
, 0);
899 sess
= new_ircwindow (serv
, "(snotices)", SESS_SNOTICES
, 0);
900 fe_set_channel (sess
);
902 fe_set_nonchannel (sess
, FALSE
);
903 userlist_clear (sess
);
904 log_open_or_close (sess
);
906 /* Avoid redundancy with some Undernet notices */
907 if (!strncmp (msg
, "*** Notice -- ", 14))
912 if (msg
[0] == '[' && (!serv
->have_idmsg
|| id
))
914 /* guess where chanserv meant to post this -sigh- */
915 if (!strcasecmp (nick
, "ChanServ") && !find_dialog (serv
, nick
))
917 char *dest
= strdup (msg
+ 1);
918 char *end
= strchr (dest
, ']');
922 sess
= find_channel (serv
, dest
);
928 sess
= find_session_from_nick (nick
, serv
);
933 sess
= serv
->server_session
;
935 sess
= serv
->front_session
;
942 if (!strncmp (msg
, "PING", 4))
944 inbound_ping_reply (sess
, msg
+ 5, nick
);
948 po
= strchr (msg
, '\001');
953 EMIT_SIGNAL (XP_TE_SERVNOTICE
, sess
, msg
, nick
, NULL
, NULL
, 0);
955 EMIT_SIGNAL (XP_TE_CHANNOTICE
, sess
, nick
, to
, msg
, NULL
, 0);
957 EMIT_SIGNAL (XP_TE_NOTICE
, sess
, nick
, msg
, NULL
, NULL
, 0);
961 inbound_away (server
*serv
, char *nick
, char *msg
)
963 struct away_msg
*away
= server_away_find_message (serv
, nick
);
964 session
*sess
= NULL
;
967 if (away
&& !strcmp (msg
, away
->message
)) /* Seen the msg before? */
969 if (prefs
.show_away_once
&& !serv
->inside_whois
)
973 server_away_save_message (serv
, nick
, msg
);
976 if (prefs
.irc_whois_front
)
977 sess
= serv
->front_session
;
980 if (!serv
->inside_whois
)
981 sess
= find_session_from_nick (nick
, serv
);
983 sess
= serv
->server_session
;
986 /* possibly hide the output */
987 if (!serv
->inside_whois
|| !serv
->skip_next_whois
)
988 EMIT_SIGNAL (XP_TE_WHOIS5
, sess
, nick
, msg
, NULL
, NULL
, 0);
994 if (sess
->server
== serv
)
995 userlist_set_away (sess
, nick
, TRUE
);
1001 inbound_away_notify (server
*serv
, char *nick
, char *reason
)
1003 session
*sess
= NULL
;
1010 if (sess
->server
== serv
)
1011 userlist_set_away (sess
, nick
, reason
? TRUE
: FALSE
);
1017 inbound_nameslist_end (server
*serv
, char *chan
)
1022 if (!strcmp (chan
, "*"))
1028 if (sess
->server
== serv
)
1030 sess
->end_of_names
= TRUE
;
1031 sess
->ignore_names
= FALSE
;
1037 sess
= find_channel (serv
, chan
);
1040 sess
->end_of_names
= TRUE
;
1041 sess
->ignore_names
= FALSE
;
1048 check_autojoin_channels (server
*serv
)
1052 GSList
*list
= sess_list
;
1054 GSList
*channels
, *keys
;
1056 /* shouldnt really happen, the io tag is destroyed in server.c */
1057 if (!is_server (serv
))
1060 /* send auto join list */
1063 joinlist_split (serv
->autojoin
, &channels
, &keys
);
1064 serv
->p_join_list (serv
, channels
, keys
);
1065 joinlist_free (channels
, keys
);
1067 free (serv
->autojoin
);
1068 serv
->autojoin
= NULL
;
1071 /* this is really only for re-connects when you
1072 * join channels not in the auto-join list. */
1078 if (sess
->server
== serv
)
1080 if (sess
->willjoinchannel
[0] != 0)
1082 strcpy (sess
->waitchannel
, sess
->willjoinchannel
);
1083 sess
->willjoinchannel
[0] = 0;
1085 po
= strchr (sess
->waitchannel
, ',');
1088 po
= strchr (sess
->waitchannel
, ' ');
1092 channels
= g_slist_append (channels
, g_strdup (sess
->waitchannel
));
1093 keys
= g_slist_append (keys
, g_strdup (sess
->channelkey
));
1102 serv
->p_join_list (serv
, channels
, keys
);
1103 joinlist_free (channels
, keys
);
1106 serv
->joindelay_tag
= 0;
1107 fe_server_event (serv
, FE_SE_LOGGEDIN
, i
);
1112 inbound_next_nick (session
*sess
, char *nick
)
1115 server
*serv
= sess
->server
;
1120 switch (serv
->nickcount
)
1123 newnick
= prefs
.nick2
;
1124 net
= serv
->network
;
1125 /* use network specific "Second choice"? */
1126 if (net
&& !(net
->flags
& FLAG_USE_GLOBAL
) && net
->nick2
)
1127 newnick
= net
->nick2
;
1128 serv
->p_change_nick (serv
, newnick
);
1129 EMIT_SIGNAL (XP_TE_NICKCLASH
, sess
, nick
, newnick
, NULL
, NULL
, 0);
1133 serv
->p_change_nick (serv
, prefs
.nick3
);
1134 EMIT_SIGNAL (XP_TE_NICKCLASH
, sess
, nick
, prefs
.nick3
, NULL
, NULL
, 0);
1138 EMIT_SIGNAL (XP_TE_NICKFAIL
, sess
, NULL
, NULL
, NULL
, NULL
, 0);
1143 do_dns (session
*sess
, char *nick
, char *host
)
1148 po
= strrchr (host
, '@');
1151 EMIT_SIGNAL (XP_TE_RESOLVINGUSER
, sess
, nick
, host
, NULL
, NULL
, 0);
1152 snprintf (tbuf
, sizeof (tbuf
), "exec -d %s %s", prefs
.dnsprogram
, host
);
1153 handle_command (sess
, tbuf
, FALSE
);
1157 set_default_modes (server
*serv
)
1165 strcat (modes
, "w");
1166 if (prefs
.servernotice
)
1167 strcat (modes
, "s");
1168 if (prefs
.invisible
)
1169 strcat (modes
, "i");
1171 if (modes
[1] != '\0')
1173 serv
->p_mode (serv
, serv
->nick
, modes
);
1178 inbound_login_start (session
*sess
, char *nick
, char *servname
)
1180 inbound_newnick (sess
->server
, sess
->server
->nick
, nick
, TRUE
);
1181 server_set_name (sess
->server
, servname
);
1182 if (sess
->type
== SESS_SERVER
)
1183 log_open_or_close (sess
);
1184 /* reset our away status */
1185 if (sess
->server
->reconnect_away
)
1187 handle_command (sess
->server
->server_session
, "away", FALSE
);
1188 sess
->server
->reconnect_away
= FALSE
;
1193 inbound_set_all_away_status (server
*serv
, char *nick
, unsigned int status
)
1202 if (sess
->server
== serv
)
1203 userlist_set_away (sess
, nick
, status
);
1209 inbound_uaway (server
*serv
)
1211 serv
->is_away
= TRUE
;
1212 serv
->away_time
= time (NULL
);
1215 inbound_set_all_away_status (serv
, serv
->nick
, 1);
1219 inbound_uback (server
*serv
)
1221 serv
->is_away
= FALSE
;
1222 serv
->reconnect_away
= FALSE
;
1225 inbound_set_all_away_status (serv
, serv
->nick
, 0);
1229 inbound_foundip (session
*sess
, char *ip
)
1231 struct hostent
*HostAddr
;
1233 HostAddr
= gethostbyname (ip
);
1236 prefs
.dcc_ip
= ((struct in_addr
*) HostAddr
->h_addr
)->s_addr
;
1237 EMIT_SIGNAL (XP_TE_FOUNDIP
, sess
,
1238 inet_ntoa (*((struct in_addr
*) HostAddr
->h_addr
)),
1239 NULL
, NULL
, NULL
, 0);
1244 inbound_user_info_start (session
*sess
, char *nick
)
1246 /* set away to FALSE now, 301 may turn it back on */
1247 inbound_set_all_away_status (sess
->server
, nick
, 0);
1250 /* reporting new information found about this user. chan may be NULL.
1251 * away may be 0xff to indicate UNKNOWN. */
1254 inbound_user_info (session
*sess
, char *chan
, char *user
, char *host
,
1255 char *servname
, char *nick
, char *realname
,
1256 char *account
, unsigned int away
)
1258 server
*serv
= sess
->server
;
1265 uhost
= g_malloc (strlen (user
) + strlen (host
) + 2);
1266 sprintf (uhost
, "%s@%s", user
, host
);
1271 who_sess
= find_channel (serv
, chan
);
1273 userlist_add_hostname (who_sess
, nick
, uhost
, realname
, servname
, account
, away
);
1276 if (serv
->doing_dns
&& nick
&& host
)
1277 do_dns (sess
, nick
, host
);
1282 /* came from WHOIS, not channel specific */
1283 for (list
= sess_list
; list
; list
= list
->next
)
1286 if (sess
->type
== SESS_CHANNEL
&& sess
->server
== serv
)
1288 userlist_add_hostname (sess
, nick
, uhost
, realname
, servname
, account
, away
);
1297 inbound_banlist (session
*sess
, time_t stamp
, char *chan
, char *mask
, char *banner
, int is_exemption
)
1299 char *time_str
= ctime (&stamp
);
1300 server
*serv
= sess
->server
;
1302 time_str
[19] = 0; /* get rid of the \n */
1306 sess
= find_channel (serv
, chan
);
1309 sess
= serv
->front_session
;
1313 if (!fe_is_banwindow (sess
))
1316 /* let proto-irc.c do the 'goto def' for exemptions */
1320 EMIT_SIGNAL (XP_TE_BANLIST
, sess
, chan
, mask
, banner
, time_str
, 0);
1324 fe_add_ban_list (sess
, mask
, banner
, time_str
, is_exemption
);
1328 /* execute 1 end-of-motd command */
1331 inbound_exec_eom_cmd (char *str
, void *sess
)
1333 handle_command (sess
, (str
[0] == '/') ? str
+ 1 : str
, TRUE
);
1338 inbound_nickserv_login (server
*serv
)
1340 /* this could grow ugly, but let's hope there won't be new NickServ types */
1341 switch (serv
->loginmethod
)
1343 case LOGIN_MSG_NICKSERV
:
1344 case LOGIN_NICKSERV
:
1345 case LOGIN_CHALLENGEAUTH
:
1358 inbound_login_end (session
*sess
, char *text
)
1360 server
*serv
= sess
->server
;
1362 if (!serv
->end_of_motd
)
1364 if (prefs
.ip_from_server
&& serv
->use_who
)
1366 serv
->skip_next_userhost
= TRUE
;
1367 serv
->p_get_ip_uh (serv
, serv
->nick
); /* sends USERHOST mynick */
1369 set_default_modes (serv
);
1373 /* there may be more than 1, separated by \n */
1374 if (((ircnet
*)serv
->network
)->command
)
1376 token_foreach (((ircnet
*)serv
->network
)->command
, '\n', inbound_exec_eom_cmd
, sess
);
1379 /* send nickserv password */
1380 if (((ircnet
*)serv
->network
)->pass
&& inbound_nickserv_login (serv
))
1382 serv
->p_ns_identify (serv
, ((ircnet
*)serv
->network
)->pass
);
1386 /* send JOIN now or wait? */
1387 if (serv
->network
&& ((ircnet
*)serv
->network
)->pass
&& prefs
.irc_join_delay
&& inbound_nickserv_login (serv
))
1389 serv
->joindelay_tag
= fe_timeout_add (prefs
.irc_join_delay
* 1000, check_autojoin_channels
, serv
);
1393 check_autojoin_channels (serv
);
1396 if (serv
->supports_watch
|| serv
->supports_monitor
)
1398 notify_send_watches (serv
);
1401 serv
->end_of_motd
= TRUE
;
1404 if (prefs
.skipmotd
&& !serv
->motd_skipped
)
1406 serv
->motd_skipped
= TRUE
;
1407 EMIT_SIGNAL (XP_TE_MOTDSKIP
, serv
->server_session
, NULL
, NULL
, NULL
, NULL
, 0);
1411 EMIT_SIGNAL (XP_TE_MOTD
, serv
->server_session
, text
, NULL
, NULL
, NULL
, 0);
1415 inbound_identified (server
*serv
) /* 'MODE +e MYSELF' on freenode */
1417 if (serv
->joindelay_tag
)
1419 /* stop waiting, just auto JOIN now */
1420 fe_timeout_remove (serv
->joindelay_tag
);
1421 serv
->joindelay_tag
= 0;
1422 check_autojoin_channels (serv
);
1427 inbound_cap_ack (server
*serv
, char *nick
, char *extensions
)
1429 char *pass
; /* buffer for SASL password */
1431 EMIT_SIGNAL (XP_TE_CAPACK
, serv
->server_session
, nick
, extensions
,
1434 if (strstr (extensions
, "identify-msg") != 0)
1436 serv
->have_idmsg
= TRUE
;
1439 if (strstr (extensions
, "multi-prefix") != 0)
1441 serv
->have_namesx
= TRUE
;
1444 if (strstr (extensions
, "away-notify") != 0)
1446 serv
->have_awaynotify
= TRUE
;
1449 if (strstr (extensions
, "account-notify") != 0)
1451 serv
->have_accnotify
= TRUE
;
1454 if (strstr (extensions
, "extended-join") != 0)
1456 serv
->have_extjoin
= TRUE
;
1459 if (strstr (extensions
, "sasl") != 0)
1463 serv
->have_sasl
= TRUE
;
1465 user
= (((ircnet
*)serv
->network
)->user
)
1466 ? (((ircnet
*)serv
->network
)->user
) : prefs
.username
;
1468 EMIT_SIGNAL (XP_TE_SASLAUTH
, serv
->server_session
, user
, NULL
,
1470 tcp_send_len (serv
, "AUTHENTICATE PLAIN\r\n", 20);
1472 pass
= encode_sasl_pass (user
, serv
->password
);
1473 tcp_sendf (serv
, "AUTHENTICATE %s\r\n", pass
);
1479 inbound_cap_ls (server
*serv
, char *nick
, char *extensions_str
)
1481 char buffer
[256]; /* buffer for requesting capabilities and emitting the signal */
1482 guint32 want_cap
; /* format the CAP REQ string based on previous capabilities being requested or not */
1483 guint32 want_sasl
; /* CAP END shouldn't be sent when SASL is requested, it needs further responses */
1487 EMIT_SIGNAL (XP_TE_CAPLIST
, serv
->server_session
, nick
, extensions_str
,
1492 extensions
= g_strsplit (extensions_str
, " ", 0);
1494 strcpy (buffer
, "CAP REQ :");
1496 for (i
=0; extensions
[i
]; i
++)
1498 const char *extension
= extensions
[i
];
1500 if (!strcmp (extension
, "identify-msg"))
1502 strcat (buffer
, "identify-msg ");
1505 if (!strcmp (extension
, "multi-prefix"))
1507 strcat (buffer
, "multi-prefix ");
1510 if (!strcmp (extension
, "away-notify"))
1512 strcat (buffer
, "away-notify ");
1515 if (!strcmp (extension
, "account-notify"))
1517 strcat (buffer
, "account-notify ");
1520 if (!strcmp (extension
, "extended-join"))
1522 strcat (buffer
, "extended-join ");
1526 /* bouncers can prefix a name space to the extension so we should use.
1527 * znc uses "znc.in/server-time".
1529 if (!strcmp (extension
, "znc.in/server-time"))
1531 strcat (buffer
, "znc.in/server-time");
1532 strcat (buffer
, " ");
1534 else if (!strcmp (extension
, "server-time"))
1536 /* ignore. it is best to have server-time explicitly enabled or have
1537 * a option in the preferences (or per server).
1542 /* if the SASL password is set AND auth mode is set to SASL, request SASL auth */
1543 if (serv
->loginmethod
== LOGIN_SASL
1544 && strcmp (extension
, "sasl") != 0
1545 && strlen (serv
->password
) != 0)
1547 strcat (buffer
, "sasl ");
1553 g_strfreev (extensions
);
1557 /* buffer + 9 = emit buffer without "CAP REQ :" */
1558 EMIT_SIGNAL (XP_TE_CAPREQ
, serv
->server_session
,
1559 buffer
+ 9, NULL
, NULL
, NULL
, 0);
1560 tcp_sendf (serv
, "%s\r\n", buffer
);
1564 /* if we use SASL, CAP END is dealt via raw numerics */
1565 tcp_send_len (serv
, "CAP END\r\n", 9);
1570 inbound_cap_nak (server
*serv
)
1572 tcp_send_len (serv
, "CAP END\r\n", 9);
1576 inbound_cap_list (server
*serv
, char *nick
, char *extensions
)
1578 EMIT_SIGNAL (XP_TE_CAPACK
, serv
->server_session
, nick
, extensions
,