1 |
/* |
2 |
* users.C: User management. |
3 |
* |
4 |
* Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team |
5 |
* Rights to this code are as documented in COPYING. |
6 |
* |
7 |
* |
8 |
* Portions of this file were derived from sources bearing the following license: |
9 |
* Rights to this code are documented in doc/pod/license.pod. |
10 |
* Copyright © 2005-2007 Atheme Project (http://www.atheme.org) |
11 |
*/ |
12 |
|
13 |
static char const rcsid[] = "$Id: users.C,v 1.5 2007-09-09 20:05:53 pippijn Exp $"; |
14 |
|
15 |
#include "atheme.h" |
16 |
#include "servers.h" |
17 |
#include <account/mynick.h> |
18 |
#include <account/myuser.h> |
19 |
|
20 |
user_map userlist; |
21 |
typedef std::map<char const * const, user_t *, str_lt> uid_map; |
22 |
static uid_map uidlist; |
23 |
user_t::callbacks user_t::callback; |
24 |
|
25 |
/* |
26 |
* init_users() |
27 |
* |
28 |
* Initializes the users heap and DTree. |
29 |
* |
30 |
* Inputs: |
31 |
* - none |
32 |
* |
33 |
* Outputs: |
34 |
* - none |
35 |
* |
36 |
* Side Effects: |
37 |
* - the users heap and DTree are initialized. |
38 |
*/ |
39 |
void |
40 |
init_users (void) |
41 |
{ |
42 |
#if 0 |
43 |
user_heap = BlockHeapCreate (sizeof (user_t), HEAP_USER); |
44 |
#endif |
45 |
} |
46 |
|
47 |
/* |
48 |
* user_add(char const * const nick, char const * const user, char const * const host, char const * const vhost, char const * const ip, |
49 |
* char const * const uid, char const * const gecos, server_t *server, time_t ts); |
50 |
* |
51 |
* User object factory. |
52 |
* |
53 |
* Inputs: |
54 |
* - nickname of new user |
55 |
* - username of new user |
56 |
* - hostname of new user |
57 |
* - virtual hostname of new user if applicable otherwise NULL |
58 |
* - ip of user if applicable otherwise NULL |
59 |
* - unique identifier (UID) of user if appliable otherwise NULL |
60 |
* - gecos of new user |
61 |
* - pointer to server new user is on |
62 |
* - user's timestamp |
63 |
* |
64 |
* Outputs: |
65 |
* - on success, a new user |
66 |
* - on failure, NULL |
67 |
* |
68 |
* Side Effects: |
69 |
* - if successful, a user is created and added to the users DTree. |
70 |
* |
71 |
* Bugs: |
72 |
* - this function does not check if a user object by this name already exists |
73 |
*/ |
74 |
user_t * |
75 |
user_add (char const * const nick, char const * const user, char const * const host, char const * const vhost, char const * const ip, char const * const uid, char const * const gecos, server_t *server, time_t ts) |
76 |
{ |
77 |
user_t *u; |
78 |
|
79 |
slog (LG_DEBUG, "user_add(): %s (%s@%s) -> %s", nick, user, host, server->name); |
80 |
|
81 |
u = new user_t; |
82 |
|
83 |
if (uid != NULL) |
84 |
{ |
85 |
strlcpy (u->uid, uid, IDLEN); |
86 |
uidlist[u->uid] = u; |
87 |
} |
88 |
|
89 |
strlcpy (u->nick, nick, NICKLEN); |
90 |
strlcpy (u->user, user, USERLEN); |
91 |
strlcpy (u->host, host, HOSTLEN); |
92 |
strlcpy (u->gecos, gecos, GECOSLEN); |
93 |
|
94 |
if (vhost) |
95 |
strlcpy (u->vhost, vhost, HOSTLEN); |
96 |
else |
97 |
strlcpy (u->vhost, host, HOSTLEN); |
98 |
|
99 |
if (ip && strcmp (ip, "0") && strcmp (ip, "0.0.0.0") && strcmp (ip, "255.255.255.255")) |
100 |
strlcpy (u->ip, ip, HOSTIPLEN); |
101 |
|
102 |
u->server = server; |
103 |
u->server->users++; |
104 |
node_add (u, node_create (), &u->server->userlist); |
105 |
|
106 |
if (ts) |
107 |
u->ts = ts; |
108 |
else |
109 |
u->ts = NOW; |
110 |
|
111 |
userlist[u->nick] = u; |
112 |
|
113 |
cnt.user++; |
114 |
|
115 |
u->callback.add (u); |
116 |
|
117 |
return u; |
118 |
} |
119 |
|
120 |
/* |
121 |
* user_delete(user_t *u) |
122 |
* |
123 |
* Destroys a user object and deletes the object from the users DTree. |
124 |
* |
125 |
* Inputs: |
126 |
* - user object to delete |
127 |
* |
128 |
* Outputs: |
129 |
* - nothing |
130 |
* |
131 |
* Side Effects: |
132 |
* - on success, a user is deleted from the users DTree. |
133 |
*/ |
134 |
void |
135 |
user_delete (user_t *u) |
136 |
{ |
137 |
node_t *n, *tn; |
138 |
chanuser_t *cu; |
139 |
mynick_t *mn; |
140 |
|
141 |
if (!u) |
142 |
{ |
143 |
slog (LG_DEBUG, "user_delete(): called for NULL user"); |
144 |
return; |
145 |
} |
146 |
|
147 |
slog (LG_DEBUG, "user_delete(): removing user: %s -> %s", u->nick, u->server->name); |
148 |
|
149 |
u->callback.remove (u); |
150 |
|
151 |
u->server->users--; |
152 |
if (is_ircop (u)) |
153 |
u->server->opers--; |
154 |
if (u->flags & UF_INVIS) |
155 |
u->server->invis--; |
156 |
|
157 |
/* remove the user from each channel */ |
158 |
LIST_FOREACH_SAFE (n, tn, u->channels.head) |
159 |
{ |
160 |
cu = (chanuser_t *) n->data; |
161 |
|
162 |
chanuser_delete (cu->chan, u); |
163 |
} |
164 |
|
165 |
userlist.erase (u->nick); |
166 |
|
167 |
if (*u->uid) |
168 |
uidlist.erase (u->uid); |
169 |
|
170 |
n = node_find (u, &u->server->userlist); |
171 |
node_del (n, &u->server->userlist); |
172 |
node_free (n); |
173 |
|
174 |
if (u->myuser) |
175 |
{ |
176 |
u->myuser->logins.erase (u); |
177 |
u->myuser->lastlogin = NOW; |
178 |
if ((mn = mynick_t::find (u->nick)) != NULL && mn->owner == u->myuser) |
179 |
mn->lastseen = NOW; |
180 |
u->myuser = NULL; |
181 |
} |
182 |
|
183 |
delete u; |
184 |
|
185 |
cnt.user--; |
186 |
} |
187 |
|
188 |
/* |
189 |
* user_find(char const * const nick) |
190 |
* |
191 |
* Finds a user by UID or nickname. |
192 |
* |
193 |
* Inputs: |
194 |
* - nickname or UID to look up |
195 |
* |
196 |
* Outputs: |
197 |
* - on success, the user object that was requested |
198 |
* - on failure, NULL |
199 |
* |
200 |
* Side Effects: |
201 |
* - none |
202 |
*/ |
203 |
user_t * |
204 |
user_find (char const * const nick) |
205 |
{ |
206 |
user_map::iterator it; |
207 |
uid_map::iterator idit; |
208 |
|
209 |
if (nick == NULL) |
210 |
return NULL; |
211 |
|
212 |
if (ircd->uses_uid == true) |
213 |
{ |
214 |
idit = uidlist.find (nick); |
215 |
|
216 |
if (idit != uidlist.end ()) |
217 |
return idit->second; |
218 |
} |
219 |
|
220 |
it = userlist.find (nick); |
221 |
|
222 |
if (it != userlist.end ()) |
223 |
{ |
224 |
if (ircd->uses_p10) |
225 |
wallops (_("user_find(): found user %s by nick!"), nick); |
226 |
return it->second; |
227 |
} |
228 |
|
229 |
return NULL; |
230 |
} |
231 |
|
232 |
/* |
233 |
* user_find_named(char const * const nick) |
234 |
* |
235 |
* Finds a user by nickname. Prevents chasing users by their UID. |
236 |
* |
237 |
* Inputs: |
238 |
* - nickname to look up |
239 |
* |
240 |
* Outputs: |
241 |
* - on success, the user object that was requested |
242 |
* - on failure, NULL |
243 |
* |
244 |
* Side Effects: |
245 |
* - none |
246 |
*/ |
247 |
user_t * |
248 |
user_find_named (char const * const nick) |
249 |
{ |
250 |
user_map::iterator it = userlist.find (nick); |
251 |
|
252 |
if (it != userlist.end ()) |
253 |
return it->second; |
254 |
|
255 |
return NULL; |
256 |
} |
257 |
|
258 |
/* |
259 |
* user_changeuid(user_t *u, char const * const uid) |
260 |
* |
261 |
* Changes a user object's UID. |
262 |
* |
263 |
* Inputs: |
264 |
* - user object to change UID |
265 |
* - new UID |
266 |
* |
267 |
* Outputs: |
268 |
* - nothing |
269 |
* |
270 |
* Side Effects: |
271 |
* - a user object's UID is changed. |
272 |
*/ |
273 |
void |
274 |
user_changeuid (user_t *u, char const * const uid) |
275 |
{ |
276 |
if (*u->uid) |
277 |
uidlist.erase (u->uid); |
278 |
|
279 |
strlcpy (u->uid, uid ? uid : "", IDLEN); |
280 |
|
281 |
if (*u->uid) |
282 |
uidlist[u->uid] = u; |
283 |
} |
284 |
|
285 |
/* |
286 |
* user_changenick(user_t *u, char const * const uid) |
287 |
* |
288 |
* Changes a user object's nick and TS. |
289 |
* |
290 |
* Inputs: |
291 |
* - user object to change |
292 |
* - new nick |
293 |
* - new TS |
294 |
* |
295 |
* Outputs: |
296 |
* - nothing |
297 |
* |
298 |
* Side Effects: |
299 |
* - a user object's nick and TS is changed. |
300 |
*/ |
301 |
void |
302 |
user_changenick (user_t *u, char const * const nick, time_t ts) |
303 |
{ |
304 |
mynick_t *mn; |
305 |
|
306 |
if (u->myuser != NULL && (mn = mynick_t::find (u->nick)) != NULL && mn->owner == u->myuser) |
307 |
mn->lastseen = NOW; |
308 |
userlist.erase (u->nick); |
309 |
|
310 |
strlcpy (u->nick, nick, NICKLEN); |
311 |
u->ts = ts; |
312 |
|
313 |
userlist[u->nick] = u; |
314 |
} |
315 |
|
316 |
/* |
317 |
* user_mode(user_t *user, char *modes) |
318 |
* |
319 |
* Changes a user object's modes. |
320 |
* |
321 |
* Inputs: |
322 |
* - user object to change modes on |
323 |
* - modestring describing the usermode change |
324 |
* |
325 |
* Outputs: |
326 |
* - nothing |
327 |
* |
328 |
* Side Effects: |
329 |
* - on success, a user's modes are adjusted. |
330 |
* |
331 |
* Bugs: |
332 |
* - this routine only tracks +i and +o usermode changes. |
333 |
*/ |
334 |
void |
335 |
user_mode (user_t *u, char const * const modes) |
336 |
{ |
337 |
int dir = MTYPE_ADD; |
338 |
char const *modestring = modes; |
339 |
|
340 |
if (!u) |
341 |
{ |
342 |
slog (LG_DEBUG, "user_mode(): called for nonexistant user"); |
343 |
return; |
344 |
} |
345 |
|
346 |
while (*modestring != '\0') |
347 |
{ |
348 |
switch (*modestring) |
349 |
{ |
350 |
case '+': |
351 |
dir = MTYPE_ADD; |
352 |
break; |
353 |
case '-': |
354 |
dir = MTYPE_DEL; |
355 |
break; |
356 |
case 'i': |
357 |
if (dir == MTYPE_ADD) |
358 |
{ |
359 |
if (!(u->flags & UF_INVIS)) |
360 |
u->server->invis++; |
361 |
u->flags |= UF_INVIS; |
362 |
} |
363 |
else if ((dir = MTYPE_DEL)) |
364 |
{ |
365 |
if (u->flags & UF_INVIS) |
366 |
u->server->invis--; |
367 |
u->flags &= ~UF_INVIS; |
368 |
} |
369 |
break; |
370 |
case 'o': |
371 |
if (dir == MTYPE_ADD) |
372 |
{ |
373 |
if (!is_ircop (u)) |
374 |
{ |
375 |
u->flags |= UF_IRCOP; |
376 |
slog (LG_DEBUG, "user_mode(): %s is now an IRCop", u->nick); |
377 |
snoop ("OPER: %s (%s)", u->nick, u->server->name); |
378 |
u->server->opers++; |
379 |
u->callback.oper (u); |
380 |
} |
381 |
} |
382 |
else if ((dir = MTYPE_DEL)) |
383 |
{ |
384 |
if (is_ircop (u)) |
385 |
{ |
386 |
u->flags &= ~UF_IRCOP; |
387 |
slog (LG_DEBUG, "user_mode(): %s is no longer an IRCop", u->nick); |
388 |
snoop ("DEOPER: %s (%s)", u->nick, u->server->name); |
389 |
u->server->opers--; |
390 |
u->callback.deoper (u); |
391 |
} |
392 |
} |
393 |
default: |
394 |
break; |
395 |
} |
396 |
modestring++; |
397 |
} |
398 |
} |