ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/users.C
Revision: 1.7
Committed: Sat Sep 22 14:27:30 2007 UTC (16 years, 7 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +13 -11 lines
Log Message:
split up ermyth into ermyth-modules, libermyth (currently just ermyth-util) and ermyth-core

File Contents

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