ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/account.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: +45 -68 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

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