1 /*
2 * Copyright (C) 2007 Colin DIDIER
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 #include <string.h>
19
20 #include "module.h"
21 #include "signals.h"
22
23 #include "rosters.h"
24 #include "muc-nicklist.h"
25
26 const char *xmpp_nicklist_affiliation[] = {
27 "none",
28 "owner",
29 "admin",
30 "member",
31 "outcast",
32 NULL
33 };
34
35 const char *xmpp_nicklist_role[] = {
36 "none",
37 "moderator",
38 "participant",
39 "visitor",
40 NULL
41 };
42
43 XMPP_NICK_REC *
xmpp_nicklist_insert(MUC_REC * channel,const char * nickname,const char * full_jid)44 xmpp_nicklist_insert(MUC_REC *channel, const char *nickname,
45 const char *full_jid)
46 {
47 XMPP_NICK_REC *rec;
48
49 g_return_val_if_fail(IS_MUC(channel), NULL);
50 g_return_val_if_fail(nickname != NULL, NULL);
51 rec = g_new0(XMPP_NICK_REC, 1);
52 rec->nick = g_strdup(nickname);
53 rec->host = (full_jid != NULL) ?
54 g_strdup(full_jid) : g_strconcat(channel->name, "/", rec->nick, (void *)NULL);
55 rec->show = XMPP_PRESENCE_AVAILABLE;
56 rec->status = NULL;
57 rec->affiliation = XMPP_NICKLIST_AFFILIATION_NONE;
58 rec->role = XMPP_NICKLIST_ROLE_NONE;
59 nicklist_insert(CHANNEL(channel), (NICK_REC *)rec);
60 return rec;
61 }
62
63 static void
nick_hash_add(CHANNEL_REC * channel,NICK_REC * nick)64 nick_hash_add(CHANNEL_REC *channel, NICK_REC *nick)
65 {
66 NICK_REC *list;
67
68 nick->next = NULL;
69 list = g_hash_table_lookup(channel->nicks, nick->nick);
70 if (list == NULL)
71 g_hash_table_insert(channel->nicks, nick->nick, nick);
72 else {
73 /* multiple nicks with same name */
74 while (list->next != NULL)
75 list = list->next;
76 list->next = nick;
77 }
78 /* move our own nick to beginning of the nick list.. */
79 if (nick == channel->ownnick)
80 nicklist_set_own(channel, nick);
81 }
82
83 static void
nick_hash_remove(CHANNEL_REC * channel,NICK_REC * nick)84 nick_hash_remove(CHANNEL_REC *channel, NICK_REC *nick)
85 {
86 NICK_REC *list;
87
88 list = g_hash_table_lookup(channel->nicks, nick->nick);
89 if (list == NULL)
90 return;
91 if (list == nick || list->next == NULL) {
92 g_hash_table_remove(channel->nicks, nick->nick);
93 if (list->next != NULL)
94 g_hash_table_insert(channel->nicks, nick->next->nick,
95 nick->next);
96 } else {
97 while (list->next != nick)
98 list = list->next;
99 list->next = nick->next;
100 }
101 }
102
103 void
xmpp_nicklist_rename(MUC_REC * channel,XMPP_NICK_REC * nick,const char * oldnick,const char * newnick)104 xmpp_nicklist_rename(MUC_REC *channel, XMPP_NICK_REC *nick,
105 const char *oldnick, const char *newnick)
106 {
107
108 g_return_if_fail(IS_MUC(channel));
109 g_return_if_fail(IS_XMPP_NICK(nick));
110 g_return_if_fail(oldnick != NULL);
111 g_return_if_fail(newnick != NULL);
112 /* remove old nick from hash table */
113 nick_hash_remove(CHANNEL(channel), NICK(nick));
114 g_free(nick->nick);
115 nick->nick = g_strdup(newnick);
116 /* add new nick to hash table */
117 nick_hash_add(CHANNEL(channel), NICK(nick));
118 signal_emit("nicklist changed", 3, channel, nick, oldnick);
119 if (strcmp(oldnick, channel->nick) == 0) {
120 nicklist_set_own(CHANNEL(channel), NICK(nick));
121 g_free(channel->nick);
122 channel->nick = g_strdup(newnick);
123 }
124 }
125
126 int
xmpp_nicklist_get_affiliation(const char * affiliation)127 xmpp_nicklist_get_affiliation(const char *affiliation)
128 {
129 if (affiliation != NULL) {
130 if (g_ascii_strcasecmp(affiliation,
131 xmpp_nicklist_affiliation[XMPP_NICKLIST_AFFILIATION_OWNER]) == 0)
132 return XMPP_NICKLIST_AFFILIATION_OWNER;
133 else if (g_ascii_strcasecmp(affiliation,
134 xmpp_nicklist_affiliation[XMPP_NICKLIST_AFFILIATION_ADMIN]) == 0)
135 return XMPP_NICKLIST_AFFILIATION_ADMIN;
136 else if (g_ascii_strcasecmp(affiliation,
137 xmpp_nicklist_affiliation[XMPP_NICKLIST_AFFILIATION_MEMBER]) == 0)
138 return XMPP_NICKLIST_AFFILIATION_MEMBER;
139 else if (g_ascii_strcasecmp(affiliation,
140 xmpp_nicklist_affiliation[XMPP_NICKLIST_AFFILIATION_OUTCAST]) == 0)
141 return XMPP_NICKLIST_AFFILIATION_OUTCAST;
142 }
143 return XMPP_NICKLIST_AFFILIATION_NONE;
144 }
145
146 int
xmpp_nicklist_get_role(const char * role)147 xmpp_nicklist_get_role(const char *role)
148 {
149 if (role != NULL) {
150 if (g_ascii_strcasecmp(role,
151 xmpp_nicklist_role[XMPP_NICKLIST_ROLE_MODERATOR]) == 0)
152 return XMPP_NICKLIST_ROLE_MODERATOR;
153 else if (g_ascii_strcasecmp(role,
154 xmpp_nicklist_role[XMPP_NICKLIST_ROLE_PARTICIPANT]) == 0)
155 return XMPP_NICKLIST_ROLE_PARTICIPANT;
156 else if (g_ascii_strcasecmp(role,
157 xmpp_nicklist_role[XMPP_NICKLIST_ROLE_VISITOR]) == 0)
158 return XMPP_NICKLIST_ROLE_VISITOR;
159 }
160 return XMPP_NICKLIST_ROLE_NONE;
161 }
162
163 gboolean
xmpp_nicklist_modes_changed(XMPP_NICK_REC * nick,int affiliation,int role)164 xmpp_nicklist_modes_changed(XMPP_NICK_REC *nick, int affiliation, int role)
165 {
166 g_return_val_if_fail(IS_XMPP_NICK(nick), FALSE);
167 return nick->affiliation != affiliation || nick->role != role;
168 }
169
170 void
xmpp_nicklist_set_modes(XMPP_NICK_REC * nick,int affiliation,int role)171 xmpp_nicklist_set_modes(XMPP_NICK_REC *nick, int affiliation, int role)
172 {
173 g_return_if_fail(IS_XMPP_NICK(nick));
174
175 nick->affiliation = affiliation;
176 nick->role = role;
177 switch (affiliation) {
178 case XMPP_NICKLIST_AFFILIATION_OWNER:
179 nick->prefixes[0] = '&';
180 nick->prefixes[1] = '\0';
181 nick->op = TRUE;
182 break;
183 case XMPP_NICKLIST_AFFILIATION_ADMIN:
184 nick->prefixes[0] = '\0';
185 nick->op = TRUE;
186 break;
187 default:
188 nick->prefixes[0] = '\0';
189 nick->op = FALSE;
190 }
191 switch (role) {
192 case XMPP_NICKLIST_ROLE_MODERATOR:
193 nick->voice = TRUE;
194 nick->halfop = TRUE;
195 break;
196 case XMPP_NICKLIST_ROLE_PARTICIPANT:
197 nick->halfop = FALSE;
198 nick->voice = TRUE;
199 break;
200 default:
201 nick->halfop = FALSE;
202 nick->voice = FALSE;
203 }
204 }
205
206 void
xmpp_nicklist_set_presence(XMPP_NICK_REC * nick,int show,const char * status)207 xmpp_nicklist_set_presence(XMPP_NICK_REC *nick, int show, const char *status)
208 {
209 g_return_if_fail(IS_XMPP_NICK(nick));
210 nick->show = show;
211 g_free(nick->status);
212 nick->status = g_strdup(status);
213 }
214
215 static void
sig_nicklist_remove(MUC_REC * channel,XMPP_NICK_REC * nick)216 sig_nicklist_remove(MUC_REC *channel, XMPP_NICK_REC *nick)
217 {
218 if (!IS_MUC(channel) || !IS_XMPP_NICK(nick))
219 return;
220 g_free(nick->status);
221 }
222
223 void
muc_nicklist_init(void)224 muc_nicklist_init(void)
225 {
226 signal_add("nicklist remove", sig_nicklist_remove);
227 }
228
229 void
muc_nicklist_deinit(void)230 muc_nicklist_deinit(void)
231 {
232 signal_remove("nicklist remove", sig_nicklist_remove);
233 }
234