]> jfr.im git - irc/quakenet/newserv.git/blob - chanserv/chancmds/rollbackchan.c
Attempt to import clean unloading wrt. pqsql into Q9.
[irc/quakenet/newserv.git] / chanserv / chancmds / rollbackchan.c
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);
10 */
11
12 #include "../chanserv.h"
13 #include "../../nick/nick.h"
14 #include "../../lib/flags.h"
15 #include "../../lib/irc_string.h"
16 #include "../../channel/channel.h"
17 #include "../../parser/parser.h"
18 #include "../../irc/irc.h"
19 #include "../../localuser/localuserchannel.h"
20 #include "../../pqsql/pqsql.h"
21
22 #include <libpq-fe.h>
23 #include <string.h>
24 #include <stdio.h>
25
26 void csc_dorollbackchan_real(PGconn *dbconn, void *arg) {
27 nick *np=getnickbynumeric((unsigned long)arg);
28 reguser *rup, *crup1, *crup2;
29 chanindex *cip;
30 regchan *rcp=NULL;
31 regchanuser *rcup;
32 unsigned int userID, channelID, targetID;
33 time_t changetime, authtime;
34 flag_t oldflags, newflags;
35 PGresult *pgres;
36 int i, j, num, newuser;
37 char fbuf[18];
38
39 if(!dbconn)
40 return;
41
42 pgres=PQgetResult(dbconn);
43
44 if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
45 Error("chanserv", ERR_ERROR, "Error loading chanlev history data.");
46 return;
47 }
48
49 if (PQnfields(pgres) != 7) {
50 Error("chanserv", ERR_ERROR, "Chanlev history data format error.");
51 PQclear(pgres);
52 return;
53 }
54
55 num=PQntuples(pgres);
56
57 if (!np) {
58 Error("chanserv", ERR_ERROR, "No nick pointer in rollback.");
59 PQclear(pgres);
60 return;
61 }
62 if (!(rup=getreguserfromnick(np)) || !UHasOperPriv(rup)) {
63 Error("chanserv", ERR_ERROR, "No reguser pointer or oper privs in rollback.");
64 PQclear(pgres);
65 return;
66 }
67
68 for (i=0; i<num; i++) {
69 userID=strtoul(PQgetvalue(pgres, i, 0), NULL, 10);
70 channelID=strtoul(PQgetvalue(pgres, i, 1), NULL, 10);
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.");
85 PQclear(pgres);
86 return;
87 }
88
89 cip=rcp->index;
90
91 chanservsendmessage(np, "Attempting to roll back %s:", cip->name->content);
92 }
93 targetID=strtoul(PQgetvalue(pgres, i, 2), NULL, 10);
94 changetime=strtoul(PQgetvalue(pgres, i, 3), NULL, 10);
95 authtime=strtoul(PQgetvalue(pgres, i, 4), NULL, 10);
96 oldflags=strtoul(PQgetvalue(pgres, i, 5), NULL, 10);
97 newflags=strtoul(PQgetvalue(pgres, i, 6), NULL, 10);
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
147 if (j==REGCHANUSERHASHSIZE) {
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
156 PQclear(pgres);
157 }
158
159 void csdb_rollbackchanlevhistory(nick *np, regchan *rcp, reguser* rup, time_t starttime) {
160 if (rup)
161 q9c_asyncquery(csc_dorollbackchan_real, (void *)np->numeric,
162 "SELECT userID, channelID, targetID, changetime, authtime, oldflags, newflags from chanlevhistory where "
163 "userID=%u and channelID=%u and changetime>%lu order by changetime desc limit 1000", rup->ID, rcp->ID, starttime);
164 else
165 q9c_asyncquery(csc_dorollbackchan_real, (void *)np->numeric,
166 "SELECT userID, channelID, targetID, changetime, authtime, oldflags, newflags from chanlevhistory where "
167 "channelID=%u and changetime>%lu order by changetime desc limit 1000", rcp->ID, starttime);
168 }
169
170 int 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 }