]>
Commit | Line | Data |
---|---|---|
7ac9dbae P |
1 | /* Automatically generated by refactor.pl. |
2 | * | |
3 | * | |
4 | * CMDNAME: cleanupdb | |
85174237 | 5 | * CMDLEVEL: QCMD_DEV |
7ac9dbae | 6 | * CMDARGS: 0 |
85174237 | 7 | * CMDDESC: Clean up database. |
7ac9dbae P |
8 | * CMDFUNC: csu_docleanupdb |
9 | * CMDPROTO: int csu_docleanupdb(void *source, int cargc, char **cargv); | |
85174237 | 10 | * CMDHELP: Usage: cleanupdb |
a6f1f6b6 | 11 | * CMDHELP: Cleans up inactive accounts, unused accounts and inactive channels. |
7ac9dbae P |
12 | */ |
13 | ||
14 | #include "../chanserv.h" | |
15 | #include "../../lib/irc_string.h" | |
16 | #include <stdio.h> | |
17 | #include <string.h> | |
18 | ||
511881d6 | 19 | unsigned int cleanupdb_active; |
20 | ||
21 | void csu_docleanupdb_real(DBConn *dbconn, void *arg) { | |
22 | nick *sender=getnickbynumeric((unsigned long)arg); | |
a6f1f6b6 | 23 | reguser *vrup, *srup, *founder; |
e9484491 | 24 | regchanuser *rcup, *nrcup; |
23b85e10 | 25 | authname *anp; |
e9484491 | 26 | int i,j; |
86a73ca1 | 27 | time_t t, to_age, unused_age, maxchan_age, authhistory_age; |
a6f1f6b6 CP |
28 | int expired = 0, unauthed = 0, chansvaped = 0; |
29 | chanindex *cip, *ncip; | |
30 | regchan *rcp; | |
511881d6 | 31 | DBResult *pgres; |
32 | unsigned int themarker; | |
33 | unsigned int id; | |
34 | ||
cf50e022 | 35 | t = time(NULL); |
a6f1f6b6 CP |
36 | to_age = t - (CLEANUP_ACCOUNT_INACTIVE * 3600 * 24); |
37 | unused_age = t - (CLEANUP_ACCOUNT_UNUSED * 3600 * 24); | |
38 | maxchan_age = t - (CLEANUP_CHANNEL_INACTIVE * 3600 * 24); | |
86a73ca1 | 39 | authhistory_age = t - (CLEANUP_AUTHHISTORY * 3600 * 24); |
7ac9dbae | 40 | |
511881d6 | 41 | themarker=nextauthnamemarker(); |
42 | ||
43 | if (!dbconn) { | |
44 | if (sender) | |
45 | chanservsendmessage(sender, "No DB connection, aborting cleanup."); | |
46 | goto out; | |
47 | } | |
48 | ||
49 | pgres=dbgetresult(dbconn); | |
50 | ||
51 | if (!dbquerysuccessful(pgres)) { | |
52 | Error("chanserv", ERR_ERROR, "Error loading cleanupdb data."); | |
53 | if (sender) | |
54 | chanservsendmessage(sender, "DB error, aborting cleanup."); | |
55 | goto out; | |
56 | } | |
57 | ||
58 | while (dbfetchrow(pgres)) { | |
59 | id=strtoul(dbgetvalue(pgres, 0), NULL, 10); | |
60 | anp=findauthname(id); | |
61 | if (anp) | |
62 | anp->marker=themarker; | |
63 | } | |
64 | ||
65 | dbclear(pgres); | |
66 | ||
a6f1f6b6 CP |
67 | cs_log(sender, "CLEANUPDB started"); |
68 | ||
511881d6 | 69 | if (sender) |
70 | chanservsendmessage(sender, "Scanning regusers..."); | |
7ac9dbae P |
71 | for (i=0;i<REGUSERHASHSIZE;i++) { |
72 | for (vrup=regusernicktable[i]; vrup; vrup=srup) { | |
73 | srup=vrup->nextbyname; | |
23b85e10 | 74 | if (!(anp=findauthname(vrup->ID))) |
75 | continue; /* should maybe raise hell instead */ | |
a6f1f6b6 | 76 | |
511881d6 | 77 | /* If this user has the right marker, this means the authtracker data |
78 | * indicates that they have been active recently */ | |
79 | if (anp->marker == themarker) | |
80 | continue; | |
81 | ||
372e4f1d | 82 | if(!anp->nicks && !UHasStaffPriv(vrup) && !UIsCleanupExempt(vrup)) { |
cf50e022 CP |
83 | if(vrup->lastauth && (vrup->lastauth < to_age)) { |
84 | expired++; | |
fc40d46b | 85 | cs_log(sender, "CLEANUPDB inactive user %s %u", vrup->username, vrup->ID); |
cf50e022 CP |
86 | } else if(!vrup->lastauth && (vrup->created < unused_age)) { |
87 | unauthed++; | |
fc40d46b | 88 | cs_log(sender, "CLEANUPDB unused user %s %u", vrup->username, vrup->ID); |
cf50e022 CP |
89 | } else { |
90 | continue; | |
91 | } | |
92 | ||
7ac9dbae | 93 | cs_removeuser(vrup); |
7ac9dbae P |
94 | } |
95 | } | |
96 | } | |
a6f1f6b6 | 97 | |
511881d6 | 98 | if (sender) |
99 | chanservsendmessage(sender, "Scanning chanindicies..."); | |
100 | ||
a6f1f6b6 CP |
101 | for (i=0;i<CHANNELHASHSIZE;i++) { |
102 | for (cip=chantable[i];cip;cip=ncip) { | |
103 | ncip=cip->next; | |
104 | if (!(rcp=cip->exts[chanservext])) | |
105 | continue; | |
106 | ||
bbdc40a1 CP |
107 | /* there's a bug here... if no joins or modes are done within the threshold |
108 | * and someone leaves just before the cleanup then the channel will be nuked. | |
109 | */ | |
110 | ||
111 | /* this is one possible soln but relies on cleanupdb being run more frequently than | |
112 | * the threshold: | |
113 | */ | |
114 | if(cip->channel && cs_ischannelactive(cip->channel, rcp)) { | |
115 | rcp->lastactive = t; | |
116 | if (rcp->lastcountersync < (t - COUNTERSYNCINTERVAL)) { | |
117 | csdb_updatechannelcounters(rcp); | |
118 | rcp->lastcountersync=t; | |
119 | } | |
120 | } | |
121 | ||
a6f1f6b6 CP |
122 | if(rcp->lastactive < maxchan_age) { |
123 | /* don't remove channels with the original founder as an oper */ | |
124 | founder=findreguserbyID(rcp->founder); | |
125 | if(founder && UHasOperPriv(founder)) | |
126 | continue; | |
127 | ||
128 | cs_log(sender, "CLEANUPDB inactive channel %s", cip->name?cip->name->content:"??"); | |
41938c9d | 129 | cs_removechannel(rcp, "Channel deleted due to lack of activity."); |
a6f1f6b6 CP |
130 | chansvaped++; |
131 | } | |
374a30be | 132 | |
133 | /* Get rid of any dead chanlev entries */ | |
134 | for (j=0;j<REGCHANUSERHASHSIZE;j++) { | |
e9484491 | 135 | for (rcup=rcp->regusers[j];rcup;rcup=nrcup) { |
374a30be | 136 | nrcup=rcup->nextbychan; |
137 | ||
138 | if (!rcup->flags) { | |
511881d6 | 139 | if (sender) |
140 | chanservsendmessage(sender, "Removing user %s from channel %s (no flags)",rcup->user->username,rcp->index->name->content); | |
374a30be | 141 | csdb_deletechanuser(rcup); |
142 | delreguserfromchannel(rcp, rcup->user); | |
374a30be | 143 | } |
144 | } | |
145 | } | |
a6f1f6b6 CP |
146 | } |
147 | } | |
7ac9dbae | 148 | |
511881d6 | 149 | if (sender) |
150 | chanservsendmessage(sender, "Starting history database cleanup (will run in background)."); | |
151 | ||
86a73ca1 | 152 | csdb_cleanuphistories(authhistory_age); |
153 | ||
a6f1f6b6 | 154 | cs_log(sender, "CLEANUPDB complete %d inactive accounts %d unused accounts %d channels", expired, unauthed, chansvaped); |
511881d6 | 155 | if (sender) |
156 | chanservsendmessage(sender, "Cleanup complete, %d accounts inactive for %d days, %d accounts weren't used within %d days, %d channels were inactive for %d days.", expired, CLEANUP_ACCOUNT_INACTIVE, unauthed, CLEANUP_ACCOUNT_UNUSED, chansvaped, CLEANUP_CHANNEL_INACTIVE); | |
157 | ||
158 | out: | |
159 | cleanupdb_active=0; | |
160 | } | |
161 | ||
162 | int csu_docleanupdb(void *source, int cargc, char **cargv) { | |
163 | nick *sender=source; | |
164 | unsigned int to_age; | |
165 | ||
166 | to_age = time(NULL) - (CLEANUP_ACCOUNT_INACTIVE * 3600 * 24); | |
167 | ||
168 | if (cleanupdb_active) { | |
169 | chanservsendmessage(sender, "Cleanup already in progress.\n"); | |
170 | return CMD_ERROR; | |
171 | } | |
172 | ||
173 | /* This query returns a single column containing the userids of all users | |
174 | * who have active sessions now, or sessions which ended in the last | |
175 | * CLEANUP_ACCOUNT_INACTIVE days. */ | |
176 | q9u_asyncquery(csu_docleanupdb_real, (void *)sender->numeric, | |
177 | "SELECT userID from chanserv.authhistory WHERE disconnecttime=0 OR disconnecttime > %d GROUP BY userID", to_age); | |
178 | ||
179 | chanservsendmessage(sender, "Retrieving auth history data, cleanup will proceed when done."); | |
180 | ||
181 | cleanupdb_active=1; | |
182 | ||
80d2de64 | 183 | return CMD_OK; |
7ac9dbae | 184 | } |
511881d6 | 185 |