1 /********************************************************************\
2 * BitlBee -- An IRC to other IM-networks gateway *
4 * Copyright 2002-2004 Wilmer van der Gaast and others *
5 \********************************************************************/
7 /* Stuff to handle, save and search IRC buddies */
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License with
21 the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22 if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23 Suite 330, Boston, MA 02111-1307 USA
29 irc_user_t
*irc_user_new( irc_t
*irc
, const char *nick
)
31 irc_user_t
*iu
= g_new0( irc_user_t
, 1 );
34 iu
->nick
= g_strdup( nick
);
35 iu
->user
= iu
->host
= iu
->fullname
= iu
->nick
;
37 iu
->key
= g_strdup( nick
);
39 /* Using the hash table for speed and irc->users for easy iteration
40 through the list (since the GLib API doesn't have anything sane
42 g_hash_table_insert( irc
->nick_user_hash
, iu
->key
, iu
);
43 irc
->users
= g_slist_insert_sorted( irc
->users
, iu
, irc_user_cmp
);
48 int irc_user_free( irc_t
*irc
, irc_user_t
*iu
)
50 static struct im_connection
*last_ic
;
57 ( iu
->bu
->ic
->flags
& OPT_LOGGING_OUT
) &&
58 iu
->bu
->ic
!= last_ic
)
60 char host_prefix
[] = "bitlbee.";
63 /* Irssi recognises netsplits by quitmsgs with two
64 hostnames, where a hostname is a "word" with one
65 of more dots. Mangle no-dot hostnames a bit. */
66 if( strchr( irc
->root
->host
, '.' ) )
71 if( !set_getbool( &irc
->b
->set
, "simulate_netsplit" ) )
72 msg
= g_strdup( "Account off-line" );
73 else if( ( s
= strchr( iu
->bu
->ic
->acc
->user
, '@' ) ) )
74 msg
= g_strdup_printf( "%s%s %s", host_prefix
,
75 irc
->root
->host
, s
+ 1 );
77 msg
= g_strdup_printf( "%s%s %s.%s",
78 host_prefix
, irc
->root
->host
,
79 iu
->bu
->ic
->acc
->prpl
->name
, irc
->root
->host
);
81 else if( !iu
->bu
|| !( iu
->bu
->ic
->flags
& OPT_LOGGING_OUT
) )
84 msg
= g_strdup( "Removed" );
87 irc_user_quit( iu
, msg
);
89 irc
->users
= g_slist_remove( irc
->users
, iu
);
90 g_hash_table_remove( irc
->nick_user_hash
, iu
->key
);
93 if( iu
->nick
!= iu
->user
) g_free( iu
->user
);
94 if( iu
->nick
!= iu
->host
) g_free( iu
->host
);
95 if( iu
->nick
!= iu
->fullname
) g_free( iu
->fullname
);
96 g_free( iu
->pastebuf
);
97 if( iu
->pastebuf_timer
) b_event_remove( iu
->pastebuf_timer
);
104 irc_user_t
*irc_user_by_name( irc_t
*irc
, const char *nick
)
106 char key
[strlen(nick
)+1];
110 return g_hash_table_lookup( irc
->nick_user_hash
, key
);
115 int irc_user_set_nick( irc_user_t
*iu
, const char *new )
117 irc_t
*irc
= iu
->irc
;
119 char key
[strlen(new)+1];
123 if( iu
== NULL
|| !nick_lc( key
) ||
124 ( ( new_iu
= irc_user_by_name( irc
, new ) ) && new_iu
!= iu
) )
127 for( cl
= irc
->channels
; cl
; cl
= cl
->next
)
129 irc_channel_t
*ic
= cl
->data
;
131 /* Send a NICK update if we're renaming our user, or someone
132 who's in the same channel like our user. */
133 if( iu
== irc
->user
||
134 ( ( ic
->flags
& IRC_CHANNEL_JOINED
) &&
135 irc_channel_has_user( ic
, iu
) ) )
137 irc_send_nick( iu
, new );
142 irc
->users
= g_slist_remove( irc
->users
, iu
);
143 g_hash_table_remove( irc
->nick_user_hash
, iu
->key
);
145 if( iu
->nick
== iu
->user
) iu
->user
= NULL
;
146 if( iu
->nick
== iu
->host
) iu
->host
= NULL
;
147 if( iu
->nick
== iu
->fullname
) iu
->fullname
= NULL
;
149 iu
->nick
= g_strdup( new );
150 if( iu
->user
== NULL
) iu
->user
= g_strdup( iu
->nick
);
151 if( iu
->host
== NULL
) iu
->host
= g_strdup( iu
->nick
);
152 if( iu
->fullname
== NULL
) iu
->fullname
= g_strdup( iu
->nick
);
155 iu
->key
= g_strdup( key
);
156 g_hash_table_insert( irc
->nick_user_hash
, iu
->key
, iu
);
157 irc
->users
= g_slist_insert_sorted( irc
->users
, iu
, irc_user_cmp
);
159 if( iu
== irc
->user
)
160 ipc_to_master_str( "NICK :%s\r\n", new );
165 gint
irc_user_cmp( gconstpointer a_
, gconstpointer b_
)
167 const irc_user_t
*a
= a_
, *b
= b_
;
169 return strcmp( a
->key
, b
->key
);
172 const char *irc_user_get_away( irc_user_t
*iu
)
174 irc_t
*irc
= iu
->irc
;
175 bee_user_t
*bu
= iu
->bu
;
177 if( iu
== irc
->user
)
178 return set_getstr( &irc
->b
->set
, "away" );
181 if( !bu
->flags
& BEE_USER_ONLINE
)
183 else if( bu
->flags
& BEE_USER_AWAY
)
187 static char ret
[MAX_STRING
];
188 g_snprintf( ret
, MAX_STRING
- 1, "%s (%s)",
189 bu
->status
? : "Away", bu
->status_msg
);
193 return bu
->status
? : "Away";
200 void irc_user_quit( irc_user_t
*iu
, const char *msg
)
203 gboolean send_quit
= FALSE
;
208 for( l
= iu
->irc
->channels
; l
; l
= l
->next
)
210 irc_channel_t
*ic
= l
->data
;
211 send_quit
|= irc_channel_del_user( ic
, iu
, IRC_CDU_SILENT
, NULL
) &&
212 ( ic
->flags
& IRC_CHANNEL_JOINED
);
216 irc_send_quit( iu
, msg
);
219 /* User-type dependent functions, for root/NickServ: */
220 static gboolean
root_privmsg( irc_user_t
*iu
, const char *msg
)
222 char cmd
[strlen(msg
)+1];
225 root_command_string( iu
->irc
, cmd
);
230 static gboolean
root_ctcp( irc_user_t
*iu
, char * const *ctcp
)
232 if( g_strcasecmp( ctcp
[0], "VERSION" ) == 0 )
234 irc_send_msg_f( iu
, "NOTICE", iu
->irc
->user
->nick
, "\001%s %s\001",
235 ctcp
[0], "BitlBee " BITLBEE_VERSION
" " ARCH
"/" CPU
);
237 else if( g_strcasecmp( ctcp
[0], "PING" ) == 0 )
239 irc_send_msg_f( iu
, "NOTICE", iu
->irc
->user
->nick
, "\001%s %s\001",
240 ctcp
[0], ctcp
[1] ? : "" );
246 const struct irc_user_funcs irc_user_root_funcs
= {
251 /* Echo to yourself: */
252 static gboolean
self_privmsg( irc_user_t
*iu
, const char *msg
)
254 irc_send_msg( iu
, "PRIVMSG", iu
->nick
, msg
, NULL
);
259 const struct irc_user_funcs irc_user_self_funcs
= {