ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/users.C
Revision: 1.3
Committed: Sat Jul 21 13:23:22 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.2: +1 -1 lines
Log Message:
- added rcsid to some files
- more documentation tweaks
- made most protocol commands local to phandler.C
- added ircd metadata (inspircd only for now)
- added inspircd swhois support

File Contents

# User Rev Content
1 pippijn 1.1 /*
2     * users.C: User management.
3 pippijn 1.2 * Rights to this code are documented in doc/pod/license.pod.
4 pippijn 1.1 *
5     * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
6     */
7    
8 pippijn 1.3 static char const rcsid[] = "$Id$";
9 pippijn 1.1
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     }