/** * account.C: Account management * Rights to this code are documented in doc/pod/license.pod. * * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team * Copyright © 2005-2007 Atheme Project (http://www.atheme.org) */ static char const rcsid[] = "$Id: account.C,v 1.5 2007/08/30 19:56:24 pippijn Exp $"; #include #include "atheme.h" #include #include #include #include #include "uplink.h" /* XXX, for sendq_flush(curr_uplink->conn); */ #include "datastream.h" #include "privs.h" /* * init_accounts() * * Initializes the accounts DTree. * * Inputs: * - none * * Outputs: * - none * * Side Effects: * - if the DTree initialization fails, services will abort. */ void init_accounts (void) { #if 0 myuser_heap = BlockHeapCreate (sizeof (myuser_t), HEAP_USER); mynick_heap = BlockHeapCreate (sizeof (myuser_t), HEAP_USER); mychan_heap = BlockHeapCreate (sizeof (mychan_t), HEAP_CHANNEL); chanacs_heap = BlockHeapCreate (sizeof (chanacs_t), HEAP_CHANUSER); metadata_heap = BlockHeapCreate (sizeof (metadata_t), HEAP_CHANUSER); #endif } static int expire_myuser_cb (myuser_pair &mup) { myuser_t *mu = mup.second; /* If they're logged in, update lastlogin time. * To decrease db traffic, may want to only do * this if the account would otherwise be * deleted. -- jilles */ if (!mu->logins.empty ()) { mu->lastlogin = NOW; return 0; } if (MU_HOLD & mu->flags) return 0; if (((NOW - mu->lastlogin) >= nicksvs.expiry) || ((mu->flags & MU_WAITAUTH) && (NOW - mu->registered >= 86400))) { /* Don't expire accounts with privs on them in atheme.conf, * otherwise someone can reregister * them and take the privs -- jilles */ if (is_conf_soper (mu)) return 0; snoop (_("EXPIRE: \2%s\2 from \2%s\2 "), mu->name, mu->email); 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)); mu->refcnt_dec (); } return 0; } void expire_check (void *arg) { mynick_t *mn; mychan_t *mc; user_t *u; /* Let them know about this and the likely subsequent db_save() * right away -- jilles */ sendq_flush (curr_uplink->conn); if (nicksvs.expiry != 0) { std::for_each (mulist.begin (), mulist.end (), expire_myuser_cb); foreach (mynick_pair &mnp, nicklist) { mn = mnp.second; if ((NOW - mn->lastseen) >= nicksvs.expiry) { if (MU_HOLD & mn->owner->flags) continue; /* do not drop main nick like this */ if (!irccasecmp (mn->nick, mn->owner->name)) continue; u = user_find_named (mn->nick); if (u != NULL && u->myuser == mn->owner) { /* still logged in, bleh */ mn->lastseen = NOW; mn->owner->lastlogin = NOW; continue; } snoop (_("EXPIRE: \2%s\2 from \2%s\2"), mn->nick, mn->owner->name); slog (LG_REGISTER, "expire_check(): expiring nick %s (unused %ds, account %s)", mn->nick, NOW - mn->lastseen, mn->owner->name); object_unref (mn); } } } if (chansvs.expiry != 0) { foreach (mychan_pair &mp, mclist) { mc = mp.second; if ((NOW - mc->used) >= 86400 - 3660) { /* keep last used time accurate to * within a day, making sure an active * channel will never get "Last used" * in /cs info -- jilles */ if (mc->isused ()) { mc->used = NOW; slog (LG_DEBUG, "expire_check(): updating last used time on %s because it appears to be still in use", mc->name); continue; } } if ((NOW - mc->used) >= chansvs.expiry) { if (MC_HOLD & mc->flags) continue; snoop (_("EXPIRE: \2%s\2 from \2%s\2"), mc->name, mc->founder_names ()); slog (LG_REGISTER, "expire_check(): expiring channel %s (unused %ds, founder %s, chanacs %d)", mc->name, NOW - mc->used, mc->founder_names (), LIST_LENGTH (&mc->chanacs)); mc->callback.drop (mc); if ((config_options.chan && irccasecmp (mc->name, config_options.chan)) || !config_options.chan) part (mc->name, chansvs.nick); mc->refcnt_dec (); } } } } static int check_myuser_cb (myuser_pair &mup) { myuser_t *mu = mup.second; mynick_t *mn; if (MU_OLD_ALIAS & mu->flags) { slog (LG_REGISTER, "db_check(): converting previously linked nick %s to a standalone nick", mu->name); mu->flags &= ~MU_OLD_ALIAS; mu->del_metadata ("private:alias:parent"); } if (!nicksvs.no_nick_ownership) { mn = mynick_find (mu->name); if (mn == NULL) { slog (LG_REGISTER, "db_check(): adding missing nick %s", mu->name); mn = mynick_add (mu, mu->name); mn->registered = mu->registered; mn->lastseen = mu->lastlogin; } else if (mn->owner != mu) { slog (LG_REGISTER, "db_check(): replacing nick %s owned by %s with %s", mn->nick, mn->owner->name, mu->name); object_unref (mn); mn = mynick_add (mu, mu->name); mn->registered = mu->registered; mn->lastseen = mu->lastlogin; } } return 0; } void db_check () { std::for_each (mulist.begin (), mulist.end (), check_myuser_cb); }