ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/users.C
Revision: 1.2
Committed: Sat Jul 21 01:29:13 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
- moved to new documentation system
- fixed small build error

File Contents

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