source: irc_user.c @ 420ddc00

Last change on this file since 420ddc00 was 0e788f5, checked in by Wilmer van der Gaast <wilmer@…>, at 2013-02-21T19:15:59Z

I'm still bored on a long flight. Wrote a script to automatically update
my copyright mentions since some were getting pretty stale. Left files not
touched since before 2012 alone so that this change doesn't touch almost
EVERY source file.

  • Property mode set to 100644
File size: 6.8 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2012 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Stuff to handle, save and search IRC buddies                         */
8
9/*
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.
14
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.
19
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
24*/
25
26#include "bitlbee.h"
27#include "ipc.h"
28
29irc_user_t *irc_user_new( irc_t *irc, const char *nick )
30{
31        irc_user_t *iu = g_new0( irc_user_t, 1 );
32       
33        iu->irc = irc;
34        iu->nick = g_strdup( nick );
35        iu->user = iu->host = iu->fullname = iu->nick;
36       
37        iu->key = g_strdup( nick );
38        nick_lc( iu->key );
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
41           for that.) */
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 );
44       
45        return iu;
46}
47
48int irc_user_free( irc_t *irc, irc_user_t *iu )
49{
50        static struct im_connection *last_ic;
51        static char *msg;
52       
53        if( !iu )
54                return 0;
55       
56        if( iu->bu &&
57            ( iu->bu->ic->flags & OPT_LOGGING_OUT ) &&
58            iu->bu->ic != last_ic )
59        {
60                char host_prefix[] = "bitlbee.";
61                char *s;
62               
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, '.' ) )
67                        *host_prefix = '\0';
68               
69                last_ic = iu->bu->ic;
70                g_free( msg );
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 );
76                else
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 );
80        }
81        else if( !iu->bu || !( iu->bu->ic->flags & OPT_LOGGING_OUT ) )
82        {
83                g_free( msg );
84                msg = g_strdup( "Removed" );
85                last_ic = NULL;
86        }
87        irc_user_quit( iu, msg );
88       
89        irc->users = g_slist_remove( irc->users, iu );
90        g_hash_table_remove( irc->nick_user_hash, iu->key );
91       
92        g_free( iu->nick );
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 );
98        g_free( iu->key );
99        g_free( iu );
100       
101        return 1;
102}
103
104irc_user_t *irc_user_by_name( irc_t *irc, const char *nick )
105{
106        char key[strlen(nick)+1];
107       
108        strcpy( key, nick );
109        if( nick_lc( key ) )
110                return g_hash_table_lookup( irc->nick_user_hash, key );
111        else
112                return NULL;
113}
114
115int irc_user_set_nick( irc_user_t *iu, const char *new )
116{
117        irc_t *irc = iu->irc;
118        irc_user_t *new_iu;
119        char key[strlen(new)+1];
120        GSList *cl;
121       
122        strcpy( key, new );
123        if( iu == NULL || !nick_lc( key ) ||
124            ( ( new_iu = irc_user_by_name( irc, new ) ) && new_iu != iu ) )
125                return 0;
126       
127        for( cl = irc->channels; cl; cl = cl->next )
128        {
129                irc_channel_t *ic = cl->data;
130               
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 ) ) )
136                {
137                        irc_send_nick( iu, new );
138                        break;
139                }
140        }
141       
142        irc->users = g_slist_remove( irc->users, iu );
143        g_hash_table_remove( irc->nick_user_hash, iu->key );
144       
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;
148        g_free( iu->nick );
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 );
153       
154        g_free( iu->key );
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 );
158       
159        if( iu == irc->user )
160                ipc_to_master_str( "NICK :%s\r\n", new );
161       
162        return 1;
163}
164
165gint irc_user_cmp( gconstpointer a_, gconstpointer b_ )
166{
167        const irc_user_t *a = a_, *b = b_;
168       
169        return strcmp( a->key, b->key );
170}
171
172const char *irc_user_get_away( irc_user_t *iu )
173{
174        irc_t *irc = iu->irc;
175        bee_user_t *bu = iu->bu;
176       
177        if( iu == irc->user )
178                return set_getstr( &irc->b->set, "away" );
179        else if( bu )
180        {
181                if( !bu->flags & BEE_USER_ONLINE )
182                        return "Offline";
183                else if( bu->flags & BEE_USER_AWAY )
184                {
185                        if( bu->status_msg )
186                        {
187                                static char ret[MAX_STRING];
188                                g_snprintf( ret, MAX_STRING - 1, "%s (%s)",
189                                            bu->status ? : "Away", bu->status_msg );
190                                return ret;
191                        }
192                        else
193                                return bu->status ? : "Away";
194                }
195        }
196       
197        return NULL;
198}
199
200void irc_user_quit( irc_user_t *iu, const char *msg )
201{
202        GSList *l;
203        gboolean send_quit = FALSE;
204       
205        if( !iu )
206                return;
207       
208        for( l = iu->irc->channels; l; l = l->next )
209        {
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 );
213        }
214       
215        if( send_quit )
216                irc_send_quit( iu, msg );
217}
218
219/* User-type dependent functions, for root/NickServ: */
220static gboolean root_privmsg( irc_user_t *iu, const char *msg )
221{
222        char cmd[strlen(msg)+1];
223       
224        strcpy( cmd, msg );
225        root_command_string( iu->irc, cmd );
226       
227        return TRUE;
228}
229
230static gboolean root_ctcp( irc_user_t *iu, char * const *ctcp )
231{
232        if( g_strcasecmp( ctcp[0], "VERSION" ) == 0 )
233        {
234                irc_send_msg_f( iu, "NOTICE", iu->irc->user->nick, "\001%s %s\001",
235                                ctcp[0], PACKAGE " " BITLBEE_VERSION " " ARCH "/" CPU );
236        }
237        else if( g_strcasecmp( ctcp[0], "PING" ) == 0 )
238        {
239                irc_send_msg_f( iu, "NOTICE", iu->irc->user->nick, "\001%s %s\001",
240                                ctcp[0], ctcp[1] ? : "" );
241        }
242       
243        return TRUE;
244}
245
246const struct irc_user_funcs irc_user_root_funcs = {
247        root_privmsg,
248        root_ctcp,
249};
250
251/* Echo to yourself: */
252static gboolean self_privmsg( irc_user_t *iu, const char *msg )
253{
254        irc_send_msg( iu, "PRIVMSG", iu->nick, msg, NULL );
255       
256        return TRUE;
257}
258
259const struct irc_user_funcs irc_user_self_funcs = {
260        self_privmsg,
261};
Note: See TracBrowser for help on using the repository browser.