ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/account.C
Revision: 1.2
Committed: Sat Jul 21 01:29:10 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
- moved to new documentation system
- fixed small build error

File Contents

# User Rev Content
1 pippijn 1.1 /**
2     * account.C: Account 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     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     }