]> jfr.im git - irc/quakenet/newserv.git/blame - chanserv/disabledcmds/rollbackchan.c
TRUSTS: require sqlite
[irc/quakenet/newserv.git] / chanserv / disabledcmds / rollbackchan.c
CommitLineData
183b8e2f
P
1/* Automatically generated by refactor.pl.
2 *
3 *
4 * CMDNAME: rollbackchan
5 * CMDLEVEL: QCMD_OPER
6 * CMDARGS: 3
7 * CMDDESC: Roll back access changes on a channel.
8 * CMDFUNC: csc_dorollbackchan
9 * CMDPROTO: int csc_dorollbackchan(void *source, int cargc, char **cargv);
94e4d2f4
CP
10 * CMDHELP: Usage: rollbackchan <channel> [<username>] <duration>
11 * CMDHELP: Reverts a channel's user access entries to a point in the past.
12 * CMDHELP: If username is specified only changes to that user will be made.
183b8e2f
P
13 */
14
15#include "../chanserv.h"
16#include "../../nick/nick.h"
17#include "../../lib/flags.h"
18#include "../../lib/irc_string.h"
19#include "../../channel/channel.h"
20#include "../../parser/parser.h"
21#include "../../irc/irc.h"
22#include "../../localuser/localuserchannel.h"
ee8cd7d0 23#include "../../dbapi/dbapi.h"
6b2ca929 24
183b8e2f
P
25#include <string.h>
26#include <stdio.h>
27
ee8cd7d0 28void csc_dorollbackchan_real(DBConn *dbconn, void *arg) {
c54295ef 29 nick *np=getnickbynumeric((unsigned long)arg);
6b2ca929 30 reguser *rup, *crup1, *crup2;
09cb349b 31 chanindex *cip = NULL;
6b2ca929 32 regchan *rcp=NULL;
33 regchanuser *rcup;
34 unsigned int userID, channelID, targetID;
35 time_t changetime, authtime;
36 flag_t oldflags, newflags;
ee8cd7d0
CP
37 DBResult *pgres;
38 int j, newuser;
6b2ca929 39 char fbuf[18];
40
b3565978
CP
41 if(!dbconn)
42 return;
43
ee8cd7d0 44 pgres=dbgetresult(dbconn);
6b2ca929 45
ee8cd7d0 46 if (!dbquerysuccessful(pgres)) {
6b2ca929 47 Error("chanserv", ERR_ERROR, "Error loading chanlev history data.");
48 return;
49 }
50
ee8cd7d0 51 if (dbnumfields(pgres) != 7) {
6b2ca929 52 Error("chanserv", ERR_ERROR, "Chanlev history data format error.");
ee8cd7d0 53 dbclear(pgres);
6b2ca929 54 return;
55 }
56
6b2ca929 57 if (!np) {
58 Error("chanserv", ERR_ERROR, "No nick pointer in rollback.");
ee8cd7d0 59 dbclear(pgres);
6b2ca929 60 return;
61 }
62 if (!(rup=getreguserfromnick(np)) || !UHasOperPriv(rup)) {
63 Error("chanserv", ERR_ERROR, "No reguser pointer or oper privs in rollback.");
ee8cd7d0 64 dbclear(pgres);
6b2ca929 65 return;
66 }
67
ee8cd7d0
CP
68 while(dbfetchrow(pgres)) {
69 userID=strtoul(dbgetvalue(pgres, 0), NULL, 10);
70 channelID=strtoul(dbgetvalue(pgres, 1), NULL, 10);
6b2ca929 71
72 if (!rcp) {
73 for (j=0; j<CHANNELHASHSIZE && !rcp; j++) {
74 for (cip=chantable[j]; cip && !rcp; cip=cip->next) {
75 if (!cip->exts[chanservext])
76 continue;
77
78 if (((regchan*)cip->exts[chanservext])->ID == channelID)
79 rcp=(regchan*)cip->exts[chanservext];
80 }
81 }
82
83 if (!rcp) {
84 Error("chanserv", ERR_ERROR, "No regchan pointer or oper privs in rollback.");
ee8cd7d0 85 dbclear(pgres);
6b2ca929 86 return;
87 }
88
89 cip=rcp->index;
90
91 chanservsendmessage(np, "Attempting to roll back %s:", cip->name->content);
92 }
ee8cd7d0
CP
93 targetID=strtoul(dbgetvalue(pgres, 2), NULL, 10);
94 changetime=strtoul(dbgetvalue(pgres, 3), NULL, 10);
95 authtime=strtoul(dbgetvalue(pgres, 4), NULL, 10);
96 oldflags=strtoul(dbgetvalue(pgres, 5), NULL, 10);
97 newflags=strtoul(dbgetvalue(pgres, 6), NULL, 10);
6b2ca929 98 strncpy(fbuf, printflags(newflags, rcuflags), 17);
99 fbuf[17]='\0';
100 crup1=findreguserbyID(userID);
101 crup2=findreguserbyID(targetID);
102
103 if (!crup2) {
104 chanservsendmessage(np, "Affected user (ID: %d) is no longer in database, continuing...", targetID);
105 continue;
106 }
107
108 if (!(rcup=findreguseronchannel(rcp, crup2))) {
109 rcup=getregchanuser();
110 rcup->user=crup2;
111 rcup->chan=rcp;
112 rcup->flags=0;
113 rcup->changetime=time(NULL);
114 rcup->usetime=0;
115 rcup->info=NULL;
116 newuser=1;
117 }
118 else
119 newuser=0;
120 csdb_chanlevhistory_insert(rcp, np, rcup->user, rcup->flags, oldflags);
121 rcup->flags=oldflags;
122 chanservsendmessage(np, "%s user flags for %s (%s -> %s)", newflags?oldflags?"Restoring":"Deleting":"Readding",
123 crup2->username, fbuf, printflags(oldflags, rcuflags));
124
125 if (rcup->flags) {
126 if (newuser) {
127 addregusertochannel(rcup);
128 csdb_createchanuser(rcup);
129 }
130 else
131 csdb_updatechanuser(rcup);
132 }
133 else {
134 if (!newuser) {
135 csdb_deletechanuser(rcup);
136 delreguserfromchannel(rcp, crup2);
137 }
138
139 freesstring(rcup->info);
140 freeregchanuser(rcup);
141 rcup=NULL;
142
143 for (j=0; j<REGCHANUSERHASHSIZE; j++)
144 if (rcp->regusers[j])
145 break;
146
20600a07 147 if (j==REGCHANUSERHASHSIZE) {
6b2ca929 148 cs_log(np, "DELCHAN %s (Cleared chanlev from rollback)", cip->name->content);
149 chanservsendmessage(np, "Rollback cleared chanlev list, channel deleted.");
150 rcp=NULL;
151 }
152 }
153 }
154 chanservstdmessage(np, QM_DONE);
155
ee8cd7d0 156 dbclear(pgres);
6b2ca929 157}
158
159void csdb_rollbackchanlevhistory(nick *np, regchan *rcp, reguser* rup, time_t starttime) {
160 if (rup)
b3565978 161 q9c_asyncquery(csc_dorollbackchan_real, (void *)np->numeric,
522e2b8c 162 "SELECT userID, channelID, targetID, changetime, authtime, oldflags, newflags from chanserv.chanlevhistory where "
6b2ca929 163 "userID=%u and channelID=%u and changetime>%lu order by changetime desc limit 1000", rup->ID, rcp->ID, starttime);
164 else
b3565978 165 q9c_asyncquery(csc_dorollbackchan_real, (void *)np->numeric,
522e2b8c 166 "SELECT userID, channelID, targetID, changetime, authtime, oldflags, newflags from chanserv.chanlevhistory where "
6b2ca929 167 "channelID=%u and changetime>%lu order by changetime desc limit 1000", rcp->ID, starttime);
168}
169
183b8e2f
P
170int csc_dorollbackchan(void *source, int cargc, char **cargv) {
171 nick *sender=source;
172 chanindex *cip;
173 reguser *rup, *trup=NULL;
174 regchan *rcp;
175 time_t starttime=getnettime();
176 long duration;
177
178 if (!(rup=getreguserfromnick(sender)))
179 return CMD_ERROR;
180
181 if (cargc < 2) {
182 chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "rollbackchan");
183 return CMD_ERROR;
184 }
185
186 if (!(cip=cs_checkaccess(sender, cargv[0], 0, NULL, NULL, 0, 0)))
187 return CMD_ERROR;
188
189 rcp=(regchan*)cip->exts[chanservext];
190
191 if (cargc > 2) {
192 duration=durationtolong(cargv[2]);
193 if (!(trup=findreguser(sender, cargv[1])))
194 return CMD_ERROR;
195 }
196 else
197 duration=durationtolong(cargv[1]);
198
199 if (!duration) {
200 chanservsendmessage(sender, "Invalid duration.");
201 return CMD_ERROR;
202 }
203 starttime-=duration;
204
205 cs_log(sender,"ROLLBACKCHAN %s #%s %s", cip->name->content, rup->username, cargv[1]);
206
207 csdb_rollbackchanlevhistory(sender, rcp, trup, starttime);
208
209 return CMD_OK;
210}