]>
Commit | Line | Data |
---|---|---|
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" | |
6b2ca929 | 23 | #include "../../pqsql/pqsql.h" |
24 | ||
25 | #include <libpq-fe.h> | |
183b8e2f P |
26 | #include <string.h> |
27 | #include <stdio.h> | |
28 | ||
6b2ca929 | 29 | void csc_dorollbackchan_real(PGconn *dbconn, void *arg) { |
c54295ef | 30 | nick *np=getnickbynumeric((unsigned long)arg); |
6b2ca929 | 31 | reguser *rup, *crup1, *crup2; |
32 | chanindex *cip; | |
33 | regchan *rcp=NULL; | |
34 | regchanuser *rcup; | |
35 | unsigned int userID, channelID, targetID; | |
36 | time_t changetime, authtime; | |
37 | flag_t oldflags, newflags; | |
38 | PGresult *pgres; | |
39 | int i, j, num, newuser; | |
40 | char fbuf[18]; | |
41 | ||
b3565978 CP |
42 | if(!dbconn) |
43 | return; | |
44 | ||
6b2ca929 | 45 | pgres=PQgetResult(dbconn); |
46 | ||
47 | if (PQresultStatus(pgres) != PGRES_TUPLES_OK) { | |
48 | Error("chanserv", ERR_ERROR, "Error loading chanlev history data."); | |
49 | return; | |
50 | } | |
51 | ||
52 | if (PQnfields(pgres) != 7) { | |
53 | Error("chanserv", ERR_ERROR, "Chanlev history data format error."); | |
c34af51f | 54 | PQclear(pgres); |
6b2ca929 | 55 | return; |
56 | } | |
57 | ||
58 | num=PQntuples(pgres); | |
59 | ||
60 | if (!np) { | |
61 | Error("chanserv", ERR_ERROR, "No nick pointer in rollback."); | |
62 | PQclear(pgres); | |
63 | return; | |
64 | } | |
65 | if (!(rup=getreguserfromnick(np)) || !UHasOperPriv(rup)) { | |
66 | Error("chanserv", ERR_ERROR, "No reguser pointer or oper privs in rollback."); | |
67 | PQclear(pgres); | |
68 | return; | |
69 | } | |
70 | ||
71 | for (i=0; i<num; i++) { | |
72 | userID=strtoul(PQgetvalue(pgres, i, 0), NULL, 10); | |
73 | channelID=strtoul(PQgetvalue(pgres, i, 1), NULL, 10); | |
74 | ||
75 | if (!rcp) { | |
76 | for (j=0; j<CHANNELHASHSIZE && !rcp; j++) { | |
77 | for (cip=chantable[j]; cip && !rcp; cip=cip->next) { | |
78 | if (!cip->exts[chanservext]) | |
79 | continue; | |
80 | ||
81 | if (((regchan*)cip->exts[chanservext])->ID == channelID) | |
82 | rcp=(regchan*)cip->exts[chanservext]; | |
83 | } | |
84 | } | |
85 | ||
86 | if (!rcp) { | |
87 | Error("chanserv", ERR_ERROR, "No regchan pointer or oper privs in rollback."); | |
88 | PQclear(pgres); | |
89 | return; | |
90 | } | |
91 | ||
92 | cip=rcp->index; | |
93 | ||
94 | chanservsendmessage(np, "Attempting to roll back %s:", cip->name->content); | |
95 | } | |
96 | targetID=strtoul(PQgetvalue(pgres, i, 2), NULL, 10); | |
97 | changetime=strtoul(PQgetvalue(pgres, i, 3), NULL, 10); | |
98 | authtime=strtoul(PQgetvalue(pgres, i, 4), NULL, 10); | |
99 | oldflags=strtoul(PQgetvalue(pgres, i, 5), NULL, 10); | |
100 | newflags=strtoul(PQgetvalue(pgres, i, 6), NULL, 10); | |
101 | strncpy(fbuf, printflags(newflags, rcuflags), 17); | |
102 | fbuf[17]='\0'; | |
103 | crup1=findreguserbyID(userID); | |
104 | crup2=findreguserbyID(targetID); | |
105 | ||
106 | if (!crup2) { | |
107 | chanservsendmessage(np, "Affected user (ID: %d) is no longer in database, continuing...", targetID); | |
108 | continue; | |
109 | } | |
110 | ||
111 | if (!(rcup=findreguseronchannel(rcp, crup2))) { | |
112 | rcup=getregchanuser(); | |
113 | rcup->user=crup2; | |
114 | rcup->chan=rcp; | |
115 | rcup->flags=0; | |
116 | rcup->changetime=time(NULL); | |
117 | rcup->usetime=0; | |
118 | rcup->info=NULL; | |
119 | newuser=1; | |
120 | } | |
121 | else | |
122 | newuser=0; | |
123 | csdb_chanlevhistory_insert(rcp, np, rcup->user, rcup->flags, oldflags); | |
124 | rcup->flags=oldflags; | |
125 | chanservsendmessage(np, "%s user flags for %s (%s -> %s)", newflags?oldflags?"Restoring":"Deleting":"Readding", | |
126 | crup2->username, fbuf, printflags(oldflags, rcuflags)); | |
127 | ||
128 | if (rcup->flags) { | |
129 | if (newuser) { | |
130 | addregusertochannel(rcup); | |
131 | csdb_createchanuser(rcup); | |
132 | } | |
133 | else | |
134 | csdb_updatechanuser(rcup); | |
135 | } | |
136 | else { | |
137 | if (!newuser) { | |
138 | csdb_deletechanuser(rcup); | |
139 | delreguserfromchannel(rcp, crup2); | |
140 | } | |
141 | ||
142 | freesstring(rcup->info); | |
143 | freeregchanuser(rcup); | |
144 | rcup=NULL; | |
145 | ||
146 | for (j=0; j<REGCHANUSERHASHSIZE; j++) | |
147 | if (rcp->regusers[j]) | |
148 | break; | |
149 | ||
20600a07 | 150 | if (j==REGCHANUSERHASHSIZE) { |
6b2ca929 | 151 | cs_log(np, "DELCHAN %s (Cleared chanlev from rollback)", cip->name->content); |
152 | chanservsendmessage(np, "Rollback cleared chanlev list, channel deleted."); | |
153 | rcp=NULL; | |
154 | } | |
155 | } | |
156 | } | |
157 | chanservstdmessage(np, QM_DONE); | |
158 | ||
159 | PQclear(pgres); | |
160 | } | |
161 | ||
162 | void csdb_rollbackchanlevhistory(nick *np, regchan *rcp, reguser* rup, time_t starttime) { | |
163 | if (rup) | |
b3565978 | 164 | q9c_asyncquery(csc_dorollbackchan_real, (void *)np->numeric, |
522e2b8c | 165 | "SELECT userID, channelID, targetID, changetime, authtime, oldflags, newflags from chanserv.chanlevhistory where " |
6b2ca929 | 166 | "userID=%u and channelID=%u and changetime>%lu order by changetime desc limit 1000", rup->ID, rcp->ID, starttime); |
167 | else | |
b3565978 | 168 | q9c_asyncquery(csc_dorollbackchan_real, (void *)np->numeric, |
522e2b8c | 169 | "SELECT userID, channelID, targetID, changetime, authtime, oldflags, newflags from chanserv.chanlevhistory where " |
6b2ca929 | 170 | "channelID=%u and changetime>%lu order by changetime desc limit 1000", rcp->ID, starttime); |
171 | } | |
172 | ||
183b8e2f P |
173 | int csc_dorollbackchan(void *source, int cargc, char **cargv) { |
174 | nick *sender=source; | |
175 | chanindex *cip; | |
176 | reguser *rup, *trup=NULL; | |
177 | regchan *rcp; | |
178 | time_t starttime=getnettime(); | |
179 | long duration; | |
180 | ||
181 | if (!(rup=getreguserfromnick(sender))) | |
182 | return CMD_ERROR; | |
183 | ||
184 | if (cargc < 2) { | |
185 | chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "rollbackchan"); | |
186 | return CMD_ERROR; | |
187 | } | |
188 | ||
189 | if (!(cip=cs_checkaccess(sender, cargv[0], 0, NULL, NULL, 0, 0))) | |
190 | return CMD_ERROR; | |
191 | ||
192 | rcp=(regchan*)cip->exts[chanservext]; | |
193 | ||
194 | if (cargc > 2) { | |
195 | duration=durationtolong(cargv[2]); | |
196 | if (!(trup=findreguser(sender, cargv[1]))) | |
197 | return CMD_ERROR; | |
198 | } | |
199 | else | |
200 | duration=durationtolong(cargv[1]); | |
201 | ||
202 | if (!duration) { | |
203 | chanservsendmessage(sender, "Invalid duration."); | |
204 | return CMD_ERROR; | |
205 | } | |
206 | starttime-=duration; | |
207 | ||
208 | cs_log(sender,"ROLLBACKCHAN %s #%s %s", cip->name->content, rup->username, cargv[1]); | |
209 | ||
210 | csdb_rollbackchanlevhistory(sender, rcp, trup, starttime); | |
211 | ||
212 | return CMD_OK; | |
213 | } |