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, 8 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

# User Rev Content
1 pippijn 1.1 /*
2     * users.C: User management.
3 pippijn 1.6 *
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 pippijn 1.2 * Rights to this code are documented in doc/pod/license.pod.
10 pippijn 1.4 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
11 pippijn 1.1 */
12    
13 pippijn 1.7 static char const rcsid[] = "$Id: users.C,v 1.6 2007-09-16 18:54:45 pippijn Exp $";
14 pippijn 1.1
15     #include "atheme.h"
16 pippijn 1.7 #include <libermyth.h>
17 pippijn 1.5 #include "servers.h"
18 pippijn 1.1 #include <account/mynick.h>
19     #include <account/myuser.h>
20 pippijn 1.7 #include <util/predicates.h>
21 pippijn 1.1
22 pippijn 1.7 user_t::map_type user_t::map;
23 pippijn 1.4 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 pippijn 1.1
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 pippijn 1.4 #if 0
45 pippijn 1.1 user_heap = BlockHeapCreate (sizeof (user_t), HEAP_USER);
46 pippijn 1.4 #endif
47 pippijn 1.1 }
48    
49     /*
50 pippijn 1.4 * 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 pippijn 1.1 *
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 pippijn 1.4 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 pippijn 1.1 {
79     user_t *u;
80    
81     slog (LG_DEBUG, "user_add(): %s (%s@%s) -> %s", nick, user, host, server->name);
82    
83 pippijn 1.4 u = new user_t;
84 pippijn 1.1
85     if (uid != NULL)
86     {
87     strlcpy (u->uid, uid, IDLEN);
88 pippijn 1.4 uidlist[u->uid] = u;
89 pippijn 1.1 }
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 pippijn 1.7 user_t::map[u->nick] = u;
114 pippijn 1.1
115     cnt.user++;
116    
117 pippijn 1.4 u->callback.add (u);
118 pippijn 1.1
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 pippijn 1.4 u->callback.remove (u);
152 pippijn 1.1
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 pippijn 1.7 user_t::map.erase (u->nick);
168 pippijn 1.1
169     if (*u->uid)
170 pippijn 1.4 uidlist.erase (u->uid);
171 pippijn 1.1
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 pippijn 1.5 if ((mn = mynick_t::find (u->nick)) != NULL && mn->owner == u->myuser)
181 pippijn 1.1 mn->lastseen = NOW;
182     u->myuser = NULL;
183     }
184    
185 pippijn 1.4 delete u;
186 pippijn 1.1
187     cnt.user--;
188     }
189    
190     /*
191 pippijn 1.4 * user_find(char const * const nick)
192 pippijn 1.1 *
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 pippijn 1.4 user_find (char const * const nick)
207 pippijn 1.1 {
208 pippijn 1.7 user_t::map_type::iterator it;
209 pippijn 1.4 uid_map::iterator idit;
210 pippijn 1.1
211     if (nick == NULL)
212     return NULL;
213    
214     if (ircd->uses_uid == true)
215     {
216 pippijn 1.4 idit = uidlist.find (nick);
217 pippijn 1.1
218 pippijn 1.4 if (idit != uidlist.end ())
219     return idit->second;
220 pippijn 1.1 }
221    
222 pippijn 1.7 it = user_t::map.find (nick);
223 pippijn 1.1
224 pippijn 1.7 if (it != user_t::map.end ())
225 pippijn 1.1 {
226     if (ircd->uses_p10)
227     wallops (_("user_find(): found user %s by nick!"), nick);
228 pippijn 1.4 return it->second;
229 pippijn 1.1 }
230    
231     return NULL;
232     }
233    
234     /*
235 pippijn 1.4 * user_find_named(char const * const nick)
236 pippijn 1.1 *
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 pippijn 1.4 user_find_named (char const * const nick)
251 pippijn 1.1 {
252 pippijn 1.7 user_t::map_type::iterator it = user_t::map.find (nick);
253 pippijn 1.4
254 pippijn 1.7 if (it != user_t::map.end ())
255 pippijn 1.4 return it->second;
256    
257     return NULL;
258 pippijn 1.1 }
259    
260     /*
261 pippijn 1.4 * user_changeuid(user_t *u, char const * const uid)
262 pippijn 1.1 *
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 pippijn 1.4 user_changeuid (user_t *u, char const * const uid)
277 pippijn 1.1 {
278     if (*u->uid)
279 pippijn 1.4 uidlist.erase (u->uid);
280 pippijn 1.1
281     strlcpy (u->uid, uid ? uid : "", IDLEN);
282    
283     if (*u->uid)
284 pippijn 1.4 uidlist[u->uid] = u;
285 pippijn 1.1 }
286    
287     /*
288 pippijn 1.4 * user_changenick(user_t *u, char const * const uid)
289 pippijn 1.1 *
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 pippijn 1.4 user_changenick (user_t *u, char const * const nick, time_t ts)
305 pippijn 1.1 {
306     mynick_t *mn;
307    
308 pippijn 1.5 if (u->myuser != NULL && (mn = mynick_t::find (u->nick)) != NULL && mn->owner == u->myuser)
309 pippijn 1.1 mn->lastseen = NOW;
310 pippijn 1.7 user_t::map.erase (u->nick);
311 pippijn 1.1
312     strlcpy (u->nick, nick, NICKLEN);
313     u->ts = ts;
314    
315 pippijn 1.7 user_t::map[u->nick] = u;
316 pippijn 1.1 }
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 pippijn 1.4 user_mode (user_t *u, char const * const modes)
338 pippijn 1.1 {
339     int dir = MTYPE_ADD;
340 pippijn 1.4 char const *modestring = modes;
341 pippijn 1.1
342 pippijn 1.4 if (!u)
343 pippijn 1.1 {
344     slog (LG_DEBUG, "user_mode(): called for nonexistant user");
345     return;
346     }
347    
348 pippijn 1.4 while (*modestring != '\0')
349 pippijn 1.1 {
350 pippijn 1.4 switch (*modestring)
351 pippijn 1.1 {
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 pippijn 1.4 if (!(u->flags & UF_INVIS))
362     u->server->invis++;
363     u->flags |= UF_INVIS;
364 pippijn 1.1 }
365     else if ((dir = MTYPE_DEL))
366     {
367 pippijn 1.4 if (u->flags & UF_INVIS)
368     u->server->invis--;
369     u->flags &= ~UF_INVIS;
370 pippijn 1.1 }
371     break;
372     case 'o':
373     if (dir == MTYPE_ADD)
374     {
375 pippijn 1.4 if (!is_ircop (u))
376 pippijn 1.1 {
377 pippijn 1.4 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 pippijn 1.1 }
383     }
384     else if ((dir = MTYPE_DEL))
385     {
386 pippijn 1.4 if (is_ircop (u))
387 pippijn 1.1 {
388 pippijn 1.4 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 pippijn 1.1 }
394     }
395     default:
396     break;
397     }
398 pippijn 1.4 modestring++;
399 pippijn 1.1 }
400     }