source: irc_user.c @ 8bae78d

Last change on this file since 8bae78d was 9767d03, checked in by dequis <dx@…>, at 2018-07-31T04:41:55Z

Modify server-time implementation to not change API

The new functions with the different paramters are flagged as internal,
so it doesn't even add new symbols.

abi-compliance checker says it's 100% compatible, yay.

  • Property mode set to 100644
File size: 6.4 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., 51 Franklin St.,
23  Fifth Floor, Boston, MA  02110-1301  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(irc, iu->key);
39        g_hash_table_insert(irc->nick_user_hash, iu->key, iu);
40
41        return iu;
42}
43
44int irc_user_free(irc_t *irc, irc_user_t *iu)
45{
46        static struct im_connection *last_ic;
47        static char *msg;
48
49        if (!iu) {
50                return 0;
51        }
52
53        if (iu->bu &&
54            (iu->bu->ic->flags & OPT_LOGGING_OUT) &&
55            iu->bu->ic != last_ic) {
56                char host_prefix[] = "bitlbee.";
57                char *s;
58
59                /* Irssi recognises netsplits by quitmsgs with two
60                   hostnames, where a hostname is a "word" with one
61                   of more dots. Mangle no-dot hostnames a bit. */
62                if (strchr(irc->root->host, '.')) {
63                        *host_prefix = '\0';
64                }
65
66                last_ic = iu->bu->ic;
67                g_free(msg);
68                if (!set_getbool(&irc->b->set, "simulate_netsplit")) {
69                        msg = g_strdup("Account off-line");
70                } else if ((s = strchr(iu->bu->ic->acc->user, '@'))) {
71                        msg = g_strdup_printf("%s%s %s", host_prefix,
72                                              irc->root->host, s + 1);
73                } else {
74                        msg = g_strdup_printf("%s%s %s.%s",
75                                              host_prefix, irc->root->host,
76                                              iu->bu->ic->acc->prpl->name, irc->root->host);
77                }
78        } else if (!iu->bu || !(iu->bu->ic->flags & OPT_LOGGING_OUT)) {
79                g_free(msg);
80                msg = g_strdup("Removed");
81                last_ic = NULL;
82        }
83        irc_user_quit(iu, msg);
84
85        g_hash_table_remove(irc->nick_user_hash, iu->key);
86
87        g_free(iu->nick);
88        if (iu->nick != iu->user) {
89                g_free(iu->user);
90        }
91        if (iu->nick != iu->host) {
92                g_free(iu->host);
93        }
94        if (iu->nick != iu->fullname) {
95                g_free(iu->fullname);
96        }
97        g_free(iu->pastebuf);
98        if (iu->pastebuf_timer) {
99                b_event_remove(iu->pastebuf_timer);
100        }
101        g_free(iu->key);
102        g_free(iu);
103
104        return 1;
105}
106
107irc_user_t *irc_user_by_name(irc_t *irc, const char *nick)
108{
109        char key[strlen(nick) + 1];
110
111        strcpy(key, nick);
112        if (nick_lc(irc, key)) {
113                return g_hash_table_lookup(irc->nick_user_hash, key);
114        } else {
115                return NULL;
116        }
117}
118
119int irc_user_set_nick(irc_user_t *iu, const char *new)
120{
121        irc_t *irc = iu->irc;
122        irc_user_t *new_iu;
123        char key[strlen(new) + 1];
124        GSList *cl;
125
126        strcpy(key, new);
127        if (iu == NULL || !nick_lc(irc, key) ||
128            ((new_iu = irc_user_by_name(irc, new)) && new_iu != iu)) {
129                return 0;
130        }
131
132        for (cl = irc->channels; cl; cl = cl->next) {
133                irc_channel_t *ic = cl->data;
134
135                /* Send a NICK update if we're renaming our user, or someone
136                   who's in the same channel like our user. */
137                if (iu == irc->user ||
138                    ((ic->flags & IRC_CHANNEL_JOINED) &&
139                     irc_channel_has_user(ic, iu))) {
140                        irc_send_nick(iu, new);
141                        break;
142                }
143        }
144
145        g_hash_table_remove(irc->nick_user_hash, iu->key);
146
147        if (iu->nick == iu->user) {
148                iu->user = NULL;
149        }
150        if (iu->nick == iu->host) {
151                iu->host = NULL;
152        }
153        if (iu->nick == iu->fullname) {
154                iu->fullname = NULL;
155        }
156        g_free(iu->nick);
157        iu->nick = g_strdup(new);
158        if (iu->user == NULL) {
159                iu->user = g_strdup(iu->nick);
160        }
161        if (iu->host == NULL) {
162                iu->host = g_strdup(iu->nick);
163        }
164        if (iu->fullname == NULL) {
165                iu->fullname = g_strdup(iu->nick);
166        }
167
168        g_free(iu->key);
169        iu->key = g_strdup(key);
170        g_hash_table_insert(irc->nick_user_hash, iu->key, iu);
171
172        if (iu == irc->user) {
173                ipc_to_master_str("NICK :%s\r\n", new);
174        }
175
176        return 1;
177}
178
179gint irc_user_cmp(gconstpointer a_, gconstpointer b_)
180{
181        const irc_user_t *a = a_, *b = b_;
182
183        return strcmp(a->key, b->key);
184}
185
186const char *irc_user_get_away(irc_user_t *iu)
187{
188        irc_t *irc = iu->irc;
189        bee_user_t *bu = iu->bu;
190
191        if (iu == irc->user) {
192                return set_getstr(&irc->b->set, "away");
193        } else if (bu) {
194                if (!bu->flags & BEE_USER_ONLINE) {
195                        return "Offline";
196                } else if (bu->flags & BEE_USER_AWAY) {
197                        if (bu->status_msg) {
198                                static char ret[MAX_STRING];
199                                g_snprintf(ret, MAX_STRING - 1, "%s (%s)",
200                                           bu->status ? : "Away", bu->status_msg);
201                                return ret;
202                        } else {
203                                return bu->status ? : "Away";
204                        }
205                }
206        }
207
208        return NULL;
209}
210
211void irc_user_quit(irc_user_t *iu, const char *msg)
212{
213        GSList *l;
214        gboolean send_quit = FALSE;
215
216        if (!iu) {
217                return;
218        }
219
220        for (l = iu->irc->channels; l; l = l->next) {
221                irc_channel_t *ic = l->data;
222                send_quit |= irc_channel_del_user(ic, iu, IRC_CDU_SILENT, NULL) &&
223                             (ic->flags & IRC_CHANNEL_JOINED);
224        }
225
226        if (send_quit) {
227                irc_send_quit(iu, msg);
228        }
229}
230
231/* User-type dependent functions, for root/NickServ: */
232static gboolean root_privmsg(irc_user_t *iu, const char *msg)
233{
234        char cmd[strlen(msg) + 1];
235
236        strcpy(cmd, msg);
237        root_command_string(iu->irc, cmd);
238
239        return TRUE;
240}
241
242static gboolean root_ctcp(irc_user_t *iu, char * const *ctcp)
243{
244        if (g_strcasecmp(ctcp[0], "VERSION") == 0) {
245                irc_send_msg_f(iu, "NOTICE", iu->irc->user->nick, "\001%s %s\001",
246                               ctcp[0], PACKAGE " " BITLBEE_VERSION);
247        } else if (g_strcasecmp(ctcp[0], "PING") == 0) {
248                irc_send_msg_f(iu, "NOTICE", iu->irc->user->nick, "\001%s %s\001",
249                               ctcp[0], ctcp[1] ? : "");
250        }
251
252        return TRUE;
253}
254
255const struct irc_user_funcs irc_user_root_funcs = {
256        root_privmsg,
257        root_ctcp,
258};
259
260/* Echo to yourself: */
261static gboolean self_privmsg(irc_user_t *iu, const char *msg)
262{
263        irc_send_msg(iu, "PRIVMSG", iu->nick, msg, NULL);
264
265        return TRUE;
266}
267
268const struct irc_user_funcs irc_user_self_funcs = {
269        self_privmsg,
270};
Note: See TracBrowser for help on using the repository browser.