ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/users.C
Revision: 1.4
Committed: Tue Aug 28 17:08:12 2007 UTC (16 years, 9 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.3: +69 -69 lines
Log Message:
- changed name
- updated the example config to the new system
- added more documentation
- enhanced documentation generators
- added a link to the pdf to the website
- added an RSS feed generator
- transitioned hooks to c++ callbacks
- did various merges with upstream along the way
- added const where appropriate
- removed the old block allocator
- fixed most memory leaks
- transitioned some dictionaries to std::map
- transitioned some lists to std::vector
- made some free functions members where appropriate
- renamed string to dynstr and added a static string ststr
- use NOW instead of time (NULL) if possible
- completely reworked database backends, crypto handlers and protocol handlers
  to use an object factory
- removed the old module system. ermyth does not do any dynamic loading anymore
- fixed most of the build system
- reworked how protocol commands work

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