]>
jfr.im git - irc/quakenet/newserv.git/blob - chanserv/chancmds/chanlev.c
1 /* Automatically generated by refactor.pl.
5 * CMDLEVEL: QCMD_AUTHED
7 * CMDDESC: Shows or modifies user access on a channel.
8 * CMDFUNC: csc_dochanlev
9 * CMDPROTO: int csc_dochanlev(void *source, int cargc, char **cargv);
10 * CMDHELP: Usage: CHANLEV <channel> [<user> [<change>]]
11 * CMDHELP: Displays or alters the access of known users on a channel, where:
12 * CMDHELP: channel - the channel to use
13 * CMDHELP: user - the user to list or modify. user can be specified as either an active
14 * CMDHELP: nickname on the network or #accountname. If user is not specified then
15 * CMDHELP: all known users are listed.
16 * CMDHELP: change - lists the flags to add or remove, with + to add or - to remove. For
17 * CMDHELP: example, +ao to add a and o flags, or -gv to remove g and v flags. This
18 * CMDHELP: can be used to add or remove users from the channel. If change is not
19 * CMDHELP: specified then the current access of the named user is displayed.
20 * CMDHELP: Displaying known user information requires you to be known (+k) on the named channel.
21 * CMDHELP: Adjusting flags for other users requires master (+m) access on the named channel.
22 * CMDHELP: Adding or removing the +m flag for other users requires owner (+n) access on the
23 * CMDHELP: named channel.
24 * CMDHELP: You may always remove your own flags, except +qdb flags (which are not visible to you).
25 * CMDHELP: Adding or removing personal flags requires you to be known (+k) on the named channel.
26 * CMDHELP: Note that channel owners (+n) can grant +n to channel masters but they must use
27 * CMDHELP: the GIVEOWNER command for this.
28 * CMDHELP: The access level flags determine which commands a user is allowed to use on a channel.
29 * CMDHELP: Holding an access flag also grants access to any action requiring a lesser flag (e.g.
30 * CMDHELP: +m users can perform actions requiring operator (+o) status even if they do not
31 * CMDHELP: actually have +o set). The access flags are listed in descending order.
32 * CMDHELP: Valid flags are:
33 * CMDHELP: Access level flags - these control the user's overall privilege level on the channel:
34 * CMDHELP: +n OWNER Can add or remove masters and all other flags (except personal flags)
35 * CMDHELP: +m MASTER Can add or remove all access except master or owner
36 * CMDHELP: +o OP Can get ops on the channel
37 * CMDHELP: +v VOICE Can get voice on the channel
38 * CMDHELP: +k KNOWN Known on the channel - can get invites to the channel via INVITE
39 * CMDHELP: Punishment flags - these restrict the user on the channel in some way:
40 * CMDHELP: +q DEVOICE Not allowed to be voiced on the channel
41 * CMDHELP: +d DEOP Not allowed to be opped on the channel
42 * CMDHELP: +b BANNED Banned from the channel
43 * CMDHELP: Extra flags - these control specific behaviour on the channel:
44 * CMDHELP: +a AUTOOP Ops the user automatically when they join the channel (the user
45 * CMDHELP: must also hold +o in order to have this flag)
46 * CMDHELP: +g AUTOVOICE Voices the user automatically when they join the channel (the
47 * CMDHELP: user must also hold +v in order to have this flag)
48 * CMDHELP: +p PROTECT If the user has +o or +v, this makes sure they will always have
49 * CMDHELP: that status, they will be reopped/voiced if deopped/voiced
50 * CMDHELP: +t TOPIC Can use SETTOPIC to alter the topic on the channel
51 * CMDHELP: Personal flags - these control user personal preferences and can only be changed
52 * CMDHELP: by the user concerned. They are not visible to other users.
53 * CMDHELP: +w NOWELCOME Prevents the welcome message being sent when you join the channel.
54 * CMDHELP: +j AUTOINV Invites you to the channel automatically when you authenticate.
55 * CMDHELP: Note that non-sensible combinations of flags are not allowed. After making a
56 * CMDHELP: change the current status of the named user on the channel will be confirmed.
59 #include "../chanserv.h"
60 #include "../../nick/nick.h"
61 #include "../../lib/flags.h"
62 #include "../../lib/irc_string.h"
63 #include "../../channel/channel.h"
64 #include "../../parser/parser.h"
65 #include "../../irc/irc.h"
66 #include "../../localuser/localuserchannel.h"
70 int compareflags(const void *u1
, const void *u2
) {
71 const regchanuser
*r1
=*(void **)u1
, *r2
=*(void **)u2
;
74 for (f1
=QCUFLAG_OWNER
;f1
;f1
>>=1)
78 for (f2
=QCUFLAG_OWNER
;f2
;f2
>>=1)
83 return ircd_strcmp(r1
->user
->username
, r2
->user
->username
);
89 int csc_dochanlev(void *source
, int cargc
, char **cargv
) {
93 regchanuser
*rcup
, *rcuplist
;
95 reguser
*rup
=getreguserfromnick(sender
), *target
;
96 char time1
[15],time2
[15];
99 flag_t flagmask
, changemask
, flags
, oldflags
;
107 chanservstdmessage(sender
, QM_NOTENOUGHPARAMS
, "chanlev");
111 if (!(cip
=cs_checkaccess(sender
, cargv
[0], CA_KNOWN
,
112 NULL
, "chanlev", QPRIV_VIEWFULLCHANLEV
, 0)))
115 rcp
=cip
->exts
[chanservext
];
116 rcup
=findreguseronchannel(rcp
, rup
);
118 /* Set flagmask for +v/+o users (can't see bans etc.) */
119 flagmask
= (QCUFLAG_OWNER
| QCUFLAG_MASTER
| QCUFLAG_OP
| QCUFLAG_VOICE
| QCUFLAG_AUTOVOICE
|
120 QCUFLAG_AUTOOP
| QCUFLAG_TOPIC
| QCUFLAG_PROTECT
| QCUFLAG_KNOWN
);
122 /* masters and above can see everything except personal flags */
123 if (rcup
&& CUHasMasterPriv(rcup
)) {
124 flagmask
= QCUFLAG_ALL
& ~QCUFLAGS_PERSONAL
;
128 /* Staff access, show everything */
129 if (cs_privcheck(QPRIV_VIEWFULLCHANLEV
, sender
)) {
130 flagmask
= QCUFLAG_ALL
;
135 /* One arg: list chanlev */
136 int ncnt
=0,mcnt
=0,ocnt
=0,vcnt
=0,kcnt
=0,bcnt
=0;
138 if (cs_privcheck(QPRIV_VIEWFULLCHANLEV
, sender
)) {
139 reguser
*founder
=NULL
, *addedby
=NULL
;
140 addedby
=findreguserbyID(rcp
->addedby
);
141 chanservstdmessage(sender
, QM_ADDEDBY
, addedby
? addedby
->username
: "(unknown)");
142 founder
=findreguserbyID(rcp
->founder
);
143 chanservstdmessage(sender
, QM_FOUNDER
, founder
? founder
->username
: "(unknown)");
145 chanservstdmessage(sender
, QM_CHANTYPE
, chantypes
[rcp
->chantype
]->content
);
149 if (CIsSuspended(rcp
) && cs_privcheck(QPRIV_VIEWCHANSUSPENSION
, sender
)) {
152 if(cs_privcheck(QPRIV_VIEWSUSPENDEDBY
, sender
)) {
153 reguser
*trup
= findreguserbyID(rcp
->suspendby
);
155 bywhom
= trup
->username
;
157 bywhom
= "(unknown)";
163 chanservstdmessage(sender
, QM_CHANLEV_SUSPENDREASON
, rcp
->suspendreason
?rcp
->suspendreason
->content
:"(no reason)");
164 chanservstdmessage(sender
, QM_CHANLEV_SUSPENDBY
, bywhom
);
165 chanservstdmessage(sender
, QM_CHANLEV_SUSPENDSINCE
, rcp
->suspendtime
);
168 if (rcp
->comment
&& (cs_privcheck(QPRIV_VIEWCOMMENTS
, sender
)))
169 chanservstdmessage(sender
, QM_SHORT_COMMENT
, rcp
->comment
->content
);
172 for (i
=0,usercount
=0;i
<REGCHANUSERHASHSIZE
;i
++)
173 for (rcuplist
=rcp
->regusers
[i
];rcuplist
;rcuplist
=rcuplist
->nextbychan
)
177 rusers
=(regchanuser
**)malloc(usercount
* sizeof(regchanuser
*));
180 for (j
=i
=0;i
<REGCHANUSERHASHSIZE
;i
++) {
181 for (rcuplist
=rcp
->regusers
[i
];rcuplist
;rcuplist
=rcuplist
->nextbychan
) {
182 if (!(flags
=rcuplist
->flags
& flagmask
))
185 rusers
[j
++]=rcuplist
;
190 qsort(rusers
, j
, sizeof(regchanuser
*), compareflags
);
196 if (!(flags
=rcuplist
->flags
& flagmask
))
199 /* If you're listing yourself, we should show personal flags too */
200 if (rcuplist
==rcup
) {
201 flags
=rcuplist
->flags
& (flagmask
| QCUFLAGS_PERSONAL
);
204 /* Do the count here; note that +n's aren't counted as +m (and so on). We're not
205 * using the IsX() macros because the displayed count needs to match up with
206 * the displayed flags... */
207 if (flags
& QCUFLAG_OWNER
) ncnt
++; else
208 if (flags
& QCUFLAG_MASTER
) mcnt
++; else
209 if (flags
& QCUFLAG_OP
) ocnt
++; else
210 if (flags
& QCUFLAG_VOICE
) vcnt
++; else
211 if (flags
& QCUFLAG_KNOWN
) kcnt
++;
212 if (flags
& QCUFLAG_BANNED
) bcnt
++;
215 chanservstdmessage(sender
, QM_CHANLEVHEADER
, cip
->name
->content
);
217 chanservstdmessage(sender
, QM_CHANLEVCOLFULL
);
219 chanservstdmessage(sender
, QM_CHANLEVCOLSHORT
);
224 if (!rcuplist
->usetime
) {
225 strcpy(time1
,"Never");
227 tmp
=gmtime(&(rcuplist
->usetime
));
228 strftime(time1
,sizeof(time1
),Q9_FORMAT_TIME
,tmp
);
230 if (!rcuplist
->changetime
) {
231 strcpy(time2
, "Unknown");
233 tmp
=gmtime(&(rcuplist
->changetime
));
234 strftime(time2
,sizeof(time2
),Q9_FORMAT_TIME
,tmp
);
236 chanservsendmessage(sender
, " %-15s %-13s %-14s %-14s %s", rcuplist
->user
->username
,
237 printflags(flags
, rcuflags
), time1
, time2
, rcuplist
->info
?rcuplist
->info
->content
:"");
239 chanservsendmessage(sender
, " %-15s %s", rcuplist
->user
->username
, printflags(flags
, rcuflags
));
243 chanservstdmessage(sender
, QM_ENDOFLIST
);
244 chanservstdmessage(sender
, QM_CHANLEVSUMMARY
, j
, ncnt
, mcnt
, ocnt
, vcnt
, kcnt
, bcnt
);
246 chanservstdmessage(sender
, QM_NOUSERSONCHANLEV
, cip
->name
->content
);
251 /* 2 or more args.. relates to one specific user */
252 if (!(target
=findreguser(sender
, cargv
[1])))
253 return CMD_ERROR
; /* If there was an error, findreguser will have sent a message saying why.. */
255 rcuplist
=findreguseronchannel(rcp
, target
);
258 /* To change chanlev you have to either.. */
259 if (!( cs_privcheck(QPRIV_CHANGECHANLEV
, sender
) || /* Have override privilege */
260 (rcup
&& rcuplist
&& (rcup
==rcuplist
) && CUKnown(rcup
)) || /* Be manipulting yourself (oo er..) */
261 (rcup
&& CUHasMasterPriv(rcup
) && /* Have +m or +n on the channel */
262 !(rcuplist
&& CUIsOwner(rcuplist
) && !CUIsOwner(rcup
))) /* masters can't screw with owners */
264 chanservstdmessage(sender
, QM_NOACCESSONCHAN
, cip
->name
->content
, "chanlev");
269 /* new user, we could store a count instead... that's probably better... */
272 for (count
=i
=0;i
<REGCHANUSERHASHSIZE
;i
++)
273 for (rcuplist
=rcp
->regusers
[i
];rcuplist
;rcuplist
=rcuplist
->nextbychan
)
276 if(count
>= MAXCHANLEVS
) {
277 chanservstdmessage(sender
, QM_TOOMANYCHANLEVS
);
281 rcuplist
=getregchanuser();
282 rcuplist
->user
=target
;
285 rcuplist
->changetime
=time(NULL
);
291 if (cs_privcheck(QPRIV_CHANGECHANLEV
, sender
)) {
292 /* Opers are allowed to change everything */
293 changemask
= QCUFLAG_ALL
;
297 /* Everyone can change their own flags (except +dqb), and control (and see) personal flags */
298 if (rcup
==rcuplist
) {
299 changemask
= (rcup
->flags
| QCUFLAGS_PERSONAL
) & ~(QCUFLAGS_PUNISH
);
300 flagmask
|= QCUFLAGS_PERSONAL
;
303 /* Masters are allowed to manipulate +ovagtbqdpk */
304 if (CUHasMasterPriv(rcup
))
305 changemask
|= ( QCUFLAG_KNOWN
| QCUFLAG_OP
| QCUFLAG_VOICE
| QCUFLAG_AUTOOP
| QCUFLAG_AUTOVOICE
|
306 QCUFLAG_TOPIC
| QCUFLAG_PROTECT
| QCUFLAGS_PUNISH
);
308 /* Owners are allowed to manipulate +ms as well.
309 * We allow +n to be given initially, but we check later to see if the flag has been added.
310 * if it has, abort and say "use giveowner"
313 changemask
|= ( QCUFLAG_MASTER
| QCUFLAG_OWNER
);
316 oldflags
=rcuplist
->flags
;
317 if (setflags(&(rcuplist
->flags
), changemask
, cargv
[2], rcuflags
, REJECT_UNKNOWN
| REJECT_DISALLOWED
)) {
318 chanservstdmessage(sender
, QM_INVALIDCHANLEVCHANGE
);
320 freeregchanuser(rcuplist
);
324 /* check to see if +n has been given. Opers can bypass this. */
325 if (!cs_privcheck(QPRIV_CHANGECHANLEV
, sender
) && !(oldflags
& QCUFLAG_OWNER
) && (rcuplist
->flags
& QCUFLAG_OWNER
)) {
326 rcuplist
->flags
=oldflags
;
327 chanservstdmessage(sender
, QM_USEGIVEOWNER
);
329 freeregchanuser(rcuplist
);
333 /* Fix up impossible combinations */
334 rcuplist
->flags
= cs_sanitisechanlev(rcuplist
->flags
);
336 /* Check if anything "significant" has changed */
337 if ((oldflags
^ rcuplist
->flags
) & (QCUFLAG_OWNER
| QCUFLAG_MASTER
| QCUFLAG_OP
))
338 rcuplist
->changetime
=time(NULL
);
340 if(rcuplist
->flags
== oldflags
) {
341 chanservstdmessage(sender
, QM_CHANLEVNOCHANGE
);
343 freeregchanuser(rcuplist
);
347 strcpy(flagbuf
,printflags(oldflags
,rcuflags
));
348 cs_log(sender
,"CHANLEV %s #%s %s (%s -> %s)",cip
->name
->content
,rcuplist
->user
->username
,cargv
[2],
349 flagbuf
,printflags(rcuplist
->flags
,rcuflags
));
350 csdb_chanlevhistory_insert(rcp
, sender
, rcuplist
->user
, oldflags
, rcuplist
->flags
);
352 /* Now see what we do next */
353 if (rcuplist
->flags
) {
354 /* User still valid: update or create */
356 addregusertochannel(rcuplist
);
357 csdb_createchanuser(rcuplist
);
359 csdb_updatechanuser(rcuplist
);
361 chanservstdmessage(sender
, QM_CHANLEVCHANGED
, cargv
[1], cip
->name
->content
,
362 printflags(rcuplist
->flags
& flagmask
, rcuflags
));
364 /* User has no flags: delete */
366 chanservstdmessage(sender
, QM_CHANLEVREMOVED
, cargv
[1], cip
->name
->content
);
367 csdb_deletechanuser(rcuplist
);
368 delreguserfromchannel(rcp
, target
);
370 freeregchanuser(rcuplist
);
372 if (cs_removechannelifempty(sender
, rcp
)) {
373 chanservstdmessage(sender
, QM_CHANLEVEMPTIEDCHANNEL
);
378 /* Update the channel if needed */
379 rcp
->status
|= QCSTAT_OPCHECK
;
382 if (rcuplist
== rcup
)
383 flagmask
|= QCUFLAGS_PERSONAL
;
384 if (rcuplist
&& (rcuplist
->flags
& flagmask
)) {
385 chanservstdmessage(sender
, QM_CHANUSERFLAGS
, cargv
[1], cip
->name
->content
,
386 printflags(rcuplist
->flags
& flagmask
, rcuflags
));
388 chanservstdmessage(sender
, QM_CHANUSERUNKNOWN
, cargv
[1], cip
->name
->content
);