ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/account.C
Revision: 1.1
Committed: Thu Jul 19 08:24:56 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Log Message:
initial import. the most important changes since Atheme are:
- fixed many memory leaks
- fixed many bugs
- converted to C++ and use more STL containers
- added a (not very enhanced yet) perl module
- greatly improved XML-RPC speed
- added a JSON-RPC module with code from json-cpp
- added a valgrind memcheck module to operserv
- added a more object oriented base64 implementation
- added a specialised unit test framework
- improved stability
- use gettimeofday() if available
- reworked adding/removing commands
- MemoServ IGNORE DEL can now remove indices

File Contents

# Content
1 /**
2 * account.C: Account management
3 * Rights to this code are documented in doc/LICENSE.
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/myuser.h>
12 #include <account/mynick.h>
13 #include <account/mychan.h>
14 #include <account/chanacs.h>
15 #include "uplink.h" /* XXX, for sendq_flush(curr_uplink->conn); */
16 #include "datastream.h"
17 #include "privs.h"
18
19 #if 0
20 static BlockHeap *myuser_heap; /* HEAP_USER */
21 static BlockHeap *mynick_heap; /* HEAP_USER */
22 static BlockHeap *mychan_heap; /* HEAP_CHANNEL */
23 static BlockHeap *chanacs_heap; /* HEAP_CHANACS */
24 static BlockHeap *metadata_heap; /* HEAP_CHANUSER */
25 #endif
26
27 /*
28 * init_accounts()
29 *
30 * Initializes the accounts DTree.
31 *
32 * Inputs:
33 * - none
34 *
35 * Outputs:
36 * - none
37 *
38 * Side Effects:
39 * - if the DTree initialization fails, services will abort.
40 */
41 void
42 init_accounts (void)
43 {
44 #if 0
45 myuser_heap = BlockHeapCreate (sizeof (myuser_t), HEAP_USER);
46 mynick_heap = BlockHeapCreate (sizeof (myuser_t), HEAP_USER);
47 mychan_heap = BlockHeapCreate (sizeof (mychan_t), HEAP_CHANNEL);
48 chanacs_heap = BlockHeapCreate (sizeof (chanacs_t), HEAP_CHANUSER);
49 metadata_heap = BlockHeapCreate (sizeof (metadata_t), HEAP_CHANUSER);
50
51 if (myuser_heap == NULL || mynick_heap == NULL || mychan_heap == NULL || chanacs_heap == NULL || metadata_heap == NULL)
52 {
53 slog (LG_ERROR, "init_accounts(): block allocator failure.");
54 exit (EXIT_FAILURE);
55 }
56 #endif
57
58 mulist = dictionary_create ("myuser", HASH_USER, irccasecmp);
59 nicklist = dictionary_create ("mynick", HASH_USER, irccasecmp);
60 mclist = dictionary_create ("mychan", HASH_CHANNEL, irccasecmp);
61 }
62
63 static int
64 expire_myuser_cb (dictionary_elem_t *delem, void *unused)
65 {
66 myuser_t *mu = static_cast<myuser_t *> (delem->node.data);
67
68 /* If they're logged in, update lastlogin time.
69 * To decrease db traffic, may want to only do
70 * this if the account would otherwise be
71 * deleted. -- jilles
72 */
73 if (!mu->logins.empty ())
74 {
75 mu->lastlogin = NOW;
76 return 0;
77 }
78
79 if (MU_HOLD & mu->flags)
80 return 0;
81
82 if (((NOW - mu->lastlogin) >= nicksvs.expiry) || ((mu->flags & MU_WAITAUTH) && (NOW - mu->registered >= 86400)))
83 {
84 /* Don't expire accounts with privs on them in atheme.conf,
85 * otherwise someone can reregister
86 * them and take the privs -- jilles */
87 if (is_conf_soper (mu))
88 return 0;
89
90 snoop (_("EXPIRE: \2%s\2 from \2%s\2 "), mu->name, mu->email);
91 slog (LG_REGISTER, "expire_check(): expiring account %s (unused %ds, email %s, nicks %d, chanacs %d)", mu->name, (int) (NOW - mu->lastlogin), mu->email, LIST_LENGTH (&mu->nicks), LIST_LENGTH (&mu->chanacs));
92 mu->refcnt_dec ();
93 }
94
95 return 0;
96 }
97
98 void
99 expire_check (void *arg)
100 {
101 mynick_t *mn;
102 mychan_t *mc;
103 user_t *u;
104 dictionary_iteration_state_t state;
105
106 /* Let them know about this and the likely subsequent db_save()
107 * right away -- jilles */
108 sendq_flush (curr_uplink->conn);
109
110 if (nicksvs.expiry != 0)
111 {
112 dictionary_foreach (mulist, expire_myuser_cb, NULL);
113
114 DICTIONARY_FOREACH (mn, mynick_t, &state, nicklist)
115 {
116 if ((NOW - mn->lastseen) >= nicksvs.expiry)
117 {
118 if (MU_HOLD & mn->owner->flags)
119 continue;
120
121 /* do not drop main nick like this */
122 if (!irccasecmp (mn->nick, mn->owner->name))
123 continue;
124
125 u = user_find_named (mn->nick);
126 if (u != NULL && u->myuser == mn->owner)
127 {
128 /* still logged in, bleh */
129 mn->lastseen = NOW;
130 mn->owner->lastlogin = NOW;
131 continue;
132 }
133
134 snoop (_("EXPIRE: \2%s\2 from \2%s\2"), mn->nick, mn->owner->name);
135 slog (LG_REGISTER, "expire_check(): expiring nick %s (unused %ds, account %s)", mn->nick, NOW - mn->lastseen, mn->owner->name);
136 object_unref (mn);
137 }
138 }
139 }
140
141 if (chansvs.expiry != 0)
142 {
143 DICTIONARY_FOREACH (mc, mychan_t, &state, mclist)
144 {
145 if ((NOW - mc->used) >= 86400 - 3660)
146 {
147 /* keep last used time accurate to
148 * within a day, making sure an active
149 * channel will never get "Last used"
150 * in /cs info -- jilles */
151 if (mychan_isused (mc))
152 {
153 mc->used = NOW;
154 slog (LG_DEBUG, "expire_check(): updating last used time on %s because it appears to be still in use", mc->name);
155 continue;
156 }
157 }
158
159 if ((NOW - mc->used) >= chansvs.expiry)
160 {
161 if (MU_HOLD & mc->founder->flags)
162 continue;
163
164 if (MC_HOLD & mc->flags)
165 continue;
166
167 snoop (_("EXPIRE: \2%s\2 from \2%s\2"), mc->name, mc->founder->name);
168 slog (LG_REGISTER, "expire_check(): expiring channel %s (unused %ds, founder %s, chanacs %d)", mc->name, NOW - mc->used, mc->founder->name, LIST_LENGTH (&mc->chanacs));
169
170 hook_call_event ("channel_drop", mc);
171 if ((config_options.chan && irccasecmp (mc->name, config_options.chan)) || !config_options.chan)
172 part (mc->name, chansvs.nick);
173
174 mc->refcnt_dec ();
175 }
176 }
177 }
178 }
179
180 static int
181 check_myuser_cb (dictionary_elem_t *delem, void *unused)
182 {
183 myuser_t *mu = static_cast<myuser_t *> (delem->node.data);
184 mynick_t *mn;
185
186 if (MU_OLD_ALIAS & mu->flags)
187 {
188 slog (LG_REGISTER, "db_check(): converting previously linked nick %s to a standalone nick", mu->name);
189 mu->flags &= ~MU_OLD_ALIAS;
190 mu->del_metadata ("private:alias:parent");
191 }
192
193 if (!nicksvs.no_nick_ownership)
194 {
195 mn = mynick_find (mu->name);
196 if (mn == NULL)
197 {
198 slog (LG_REGISTER, "db_check(): adding missing nick %s", mu->name);
199 mn = mynick_add (mu, mu->name);
200 mn->registered = mu->registered;
201 mn->lastseen = mu->lastlogin;
202 }
203 else if (mn->owner != mu)
204 {
205 slog (LG_REGISTER, "db_check(): replacing nick %s owned by %s with %s", mn->nick, mn->owner->name, mu->name);
206 object_unref (mn);
207 mn = mynick_add (mu, mu->name);
208 mn->registered = mu->registered;
209 mn->lastseen = mu->lastlogin;
210 }
211 }
212
213 return 0;
214 }
215
216 void
217 db_check ()
218 {
219 mychan_t *mc;
220 dictionary_iteration_state_t state;
221
222 dictionary_foreach (mulist, check_myuser_cb, NULL);
223
224 DICTIONARY_FOREACH (mc, mychan_t, &state, mclist)
225 {
226 if (!chanacs_find (mc, mc->founder, CA_FLAGS))
227 {
228 slog (LG_REGISTER, "db_check(): adding access for founder on channel %s", mc->name);
229 chanacs_change_simple (mc, mc->founder, NULL, CA_FOUNDER_0, 0);
230 }
231 }
232 }