]>
Commit | Line | Data |
---|---|---|
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 | * 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. | |
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" | |
23 | #include "../../dbapi/dbapi.h" | |
24 | ||
25 | #include <string.h> | |
26 | #include <stdio.h> | |
27 | ||
28 | void csc_dorollbackchan_real(DBConn *dbconn, void *arg) { | |
29 | nick *np=getnickbynumeric((unsigned long)arg); | |
30 | reguser *rup, *crup1, *crup2; | |
31 | chanindex *cip = NULL; | |
32 | regchan *rcp=NULL; | |
33 | regchanuser *rcup; | |
34 | unsigned int userID, channelID, targetID; | |
35 | time_t changetime, authtime; | |
36 | flag_t oldflags, newflags; | |
37 | DBResult *pgres; | |
38 | int j, newuser; | |
39 | char fbuf[18]; | |
40 | ||
41 | if(!dbconn) | |
42 | return; | |
43 | ||
44 | pgres=dbgetresult(dbconn); | |
45 | ||
46 | if (!dbquerysuccessful(pgres)) { | |
47 | Error("chanserv", ERR_ERROR, "Error loading chanlev history data."); | |
48 | return; | |
49 | } | |
50 | ||
51 | if (dbnumfields(pgres) != 7) { | |
52 | Error("chanserv", ERR_ERROR, "Chanlev history data format error."); | |
53 | dbclear(pgres); | |
54 | return; | |
55 | } | |
56 | ||
57 | if (!np) { | |
58 | Error("chanserv", ERR_ERROR, "No nick pointer in rollback."); | |
59 | dbclear(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 | dbclear(pgres); | |
65 | return; | |
66 | } | |
67 | ||
68 | while(dbfetchrow(pgres)) { | |
69 | userID=strtoul(dbgetvalue(pgres, 0), NULL, 10); | |
70 | channelID=strtoul(dbgetvalue(pgres, 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 | dbclear(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(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); | |
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 | dbclear(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 chanserv.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 chanserv.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 | } |