]>
jfr.im git - irc/quakenet/newserv.git/blob - chanserv/chancmds/chanlev.c
559e05145b632cde2c809cd81d5882c0a06532af
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
[TIMELEN
],time2
[TIMELEN
];
98 flag_t flagmask
, changemask
, flags
, oldflags
;
106 chanservstdmessage(sender
, QM_NOTENOUGHPARAMS
, "chanlev");
110 if (!(cip
=cs_checkaccess(sender
, cargv
[0], CA_KNOWN
,
111 NULL
, "chanlev", QPRIV_VIEWFULLCHANLEV
, 0)))
114 rcp
=cip
->exts
[chanservext
];
115 rcup
=findreguseronchannel(rcp
, rup
);
117 /* Set flagmask for +v/+o users (can't see bans etc.) */
118 flagmask
= (QCUFLAG_OWNER
| QCUFLAG_MASTER
| QCUFLAG_OP
| QCUFLAG_VOICE
| QCUFLAG_AUTOVOICE
|
119 QCUFLAG_AUTOOP
| QCUFLAG_TOPIC
| QCUFLAG_PROTECT
| QCUFLAG_KNOWN
);
121 /* masters and above can see everything except personal flags */
122 if (rcup
&& CUHasMasterPriv(rcup
)) {
123 flagmask
= QCUFLAG_ALL
& ~QCUFLAGS_PERSONAL
;
127 /* Staff access, show everything */
128 if (cs_privcheck(QPRIV_VIEWFULLCHANLEV
, sender
)) {
129 flagmask
= QCUFLAG_ALL
;
134 /* One arg: list chanlev */
135 int ncnt
=0,mcnt
=0,ocnt
=0,vcnt
=0,kcnt
=0,bcnt
=0;
137 if (cs_privcheck(QPRIV_VIEWFULLCHANLEV
, sender
)) {
138 reguser
*founder
=NULL
, *addedby
=NULL
;
139 addedby
=findreguserbyID(rcp
->addedby
);
140 chanservstdmessage(sender
, QM_ADDEDBY
, addedby
? addedby
->username
: "(unknown)");
141 founder
=findreguserbyID(rcp
->founder
);
142 chanservstdmessage(sender
, QM_FOUNDER
, founder
? founder
->username
: "(unknown)");
144 chanservstdmessage(sender
, QM_CHANTYPE
, chantypes
[rcp
->chantype
]->content
);
148 if (CIsSuspended(rcp
) && cs_privcheck(QPRIV_VIEWCHANSUSPENSION
, sender
)) {
151 if(cs_privcheck(QPRIV_VIEWSUSPENDEDBY
, sender
)) {
152 reguser
*trup
= findreguserbyID(rcp
->suspendby
);
154 bywhom
= trup
->username
;
156 bywhom
= "(unknown)";
162 chanservstdmessage(sender
, QM_CHANLEV_SUSPENDREASON
, rcp
->suspendreason
?rcp
->suspendreason
->content
:"(no reason)");
163 chanservstdmessage(sender
, QM_CHANLEV_SUSPENDBY
, bywhom
);
164 chanservstdmessage(sender
, QM_CHANLEV_SUSPENDSINCE
, rcp
->suspendtime
);
167 if (rcp
->comment
&& (cs_privcheck(QPRIV_VIEWCOMMENTS
, sender
)))
168 chanservstdmessage(sender
, QM_SHORT_COMMENT
, rcp
->comment
->content
);
171 for (i
=0,usercount
=0;i
<REGCHANUSERHASHSIZE
;i
++)
172 for (rcuplist
=rcp
->regusers
[i
];rcuplist
;rcuplist
=rcuplist
->nextbychan
)
176 rusers
=(regchanuser
**)malloc(usercount
* sizeof(regchanuser
*));
179 for (j
=i
=0;i
<REGCHANUSERHASHSIZE
;i
++) {
180 for (rcuplist
=rcp
->regusers
[i
];rcuplist
;rcuplist
=rcuplist
->nextbychan
) {
181 if (!(flags
=rcuplist
->flags
& flagmask
))
184 rusers
[j
++]=rcuplist
;
189 qsort(rusers
, j
, sizeof(regchanuser
*), compareflags
);
195 if (!(flags
=rcuplist
->flags
& flagmask
))
198 /* If you're listing yourself, we should show personal flags too */
199 if (rcuplist
==rcup
) {
200 flags
=rcuplist
->flags
& (flagmask
| QCUFLAGS_PERSONAL
);
203 /* Do the count here; note that +n's aren't counted as +m (and so on). We're not
204 * using the IsX() macros because the displayed count needs to match up with
205 * the displayed flags... */
206 if (flags
& QCUFLAG_OWNER
) ncnt
++; else
207 if (flags
& QCUFLAG_MASTER
) mcnt
++; else
208 if (flags
& QCUFLAG_OP
) ocnt
++; else
209 if (flags
& QCUFLAG_VOICE
) vcnt
++; else
210 if (flags
& QCUFLAG_KNOWN
) kcnt
++;
211 if (flags
& QCUFLAG_BANNED
) bcnt
++;
214 chanservstdmessage(sender
, QM_CHANLEVHEADER
, cip
->name
->content
);
216 chanservstdmessage(sender
, QM_CHANLEVCOLFULL
);
218 chanservstdmessage(sender
, QM_CHANLEVCOLSHORT
);
223 if (!rcuplist
->usetime
) {
224 strcpy(time1
,"Never");
226 q9strftime(time1
,sizeof(time1
),rcuplist
->usetime
);
228 if (!rcuplist
->changetime
) {
229 strcpy(time2
, "Unknown");
231 q9strftime(time2
,sizeof(time2
),rcuplist
->changetime
);
233 chanservsendmessage(sender
, " %-15s %-13s %-14s %-14s %s", rcuplist
->user
->username
,
234 printflags(flags
, rcuflags
), time1
, time2
, rcuplist
->info
?rcuplist
->info
->content
:"");
236 chanservsendmessage(sender
, " %-15s %s", rcuplist
->user
->username
, printflags(flags
, rcuflags
));
240 chanservstdmessage(sender
, QM_ENDOFLIST
);
241 chanservstdmessage(sender
, QM_CHANLEVSUMMARY
, j
, ncnt
, mcnt
, ocnt
, vcnt
, kcnt
, bcnt
);
243 chanservstdmessage(sender
, QM_NOUSERSONCHANLEV
, cip
->name
->content
);
248 /* 2 or more args.. relates to one specific user */
249 if (!(target
=findreguser(sender
, cargv
[1])))
250 return CMD_ERROR
; /* If there was an error, findreguser will have sent a message saying why.. */
252 rcuplist
=findreguseronchannel(rcp
, target
);
255 /* To change chanlev you have to either.. */
256 if (!( cs_privcheck(QPRIV_CHANGECHANLEV
, sender
) || /* Have override privilege */
257 (rcup
&& rcuplist
&& (rcup
==rcuplist
) && CUKnown(rcup
)) || /* Be manipulting yourself (oo er..) */
258 (rcup
&& CUHasMasterPriv(rcup
) && /* Have +m or +n on the channel */
259 !(rcuplist
&& CUIsOwner(rcuplist
) && !CUIsOwner(rcup
))) /* masters can't screw with owners */
261 chanservstdmessage(sender
, QM_NOACCESSONCHAN
, cip
->name
->content
, "chanlev");
266 /* new user, we could store a count instead... that's probably better... */
269 for (count
=i
=0;i
<REGCHANUSERHASHSIZE
;i
++)
270 for (rcuplist
=rcp
->regusers
[i
];rcuplist
;rcuplist
=rcuplist
->nextbychan
)
273 if(count
>= MAXCHANLEVS
) {
274 chanservstdmessage(sender
, QM_TOOMANYCHANLEVS
);
278 rcuplist
=getregchanuser();
279 rcuplist
->user
=target
;
282 rcuplist
->changetime
=time(NULL
);
288 if (cs_privcheck(QPRIV_CHANGECHANLEV
, sender
)) {
289 /* Opers are allowed to change everything */
290 changemask
= QCUFLAG_ALL
;
294 /* Everyone can change their own flags (except +dqb), and control (and see) personal flags */
295 if (rcup
==rcuplist
) {
296 changemask
= (rcup
->flags
| QCUFLAGS_PERSONAL
) & ~(QCUFLAGS_PUNISH
);
297 flagmask
|= QCUFLAGS_PERSONAL
;
300 /* Masters are allowed to manipulate +ovagtbqdpk */
301 if (CUHasMasterPriv(rcup
))
302 changemask
|= ( QCUFLAG_KNOWN
| QCUFLAG_OP
| QCUFLAG_VOICE
| QCUFLAG_AUTOOP
| QCUFLAG_AUTOVOICE
|
303 QCUFLAG_TOPIC
| QCUFLAG_PROTECT
| QCUFLAGS_PUNISH
);
305 /* Owners are allowed to manipulate +ms as well.
306 * We allow +n to be given initially, but we check later to see if the flag has been added.
307 * if it has, abort and say "use giveowner"
310 changemask
|= ( QCUFLAG_MASTER
| QCUFLAG_OWNER
);
313 oldflags
=rcuplist
->flags
;
314 if (setflags(&(rcuplist
->flags
), changemask
, cargv
[2], rcuflags
, REJECT_UNKNOWN
| REJECT_DISALLOWED
)) {
315 chanservstdmessage(sender
, QM_INVALIDCHANLEVCHANGE
);
317 freeregchanuser(rcuplist
);
321 /* check to see if +n has been given. Opers can bypass this. */
322 if (!cs_privcheck(QPRIV_CHANGECHANLEV
, sender
) && !(oldflags
& QCUFLAG_OWNER
) && (rcuplist
->flags
& QCUFLAG_OWNER
)) {
323 rcuplist
->flags
=oldflags
;
324 chanservstdmessage(sender
, QM_USEGIVEOWNER
);
326 freeregchanuser(rcuplist
);
330 /* Fix up impossible combinations */
331 rcuplist
->flags
= cs_sanitisechanlev(rcuplist
->flags
);
333 /* Check if anything "significant" has changed */
334 if ((oldflags
^ rcuplist
->flags
) & (QCUFLAG_OWNER
| QCUFLAG_MASTER
| QCUFLAG_OP
))
335 rcuplist
->changetime
=time(NULL
);
337 if(rcuplist
->flags
== oldflags
) {
338 chanservstdmessage(sender
, QM_CHANLEVNOCHANGE
);
340 freeregchanuser(rcuplist
);
344 strcpy(flagbuf
,printflags(oldflags
,rcuflags
));
345 cs_log(sender
,"CHANLEV %s #%s %s (%s -> %s)",cip
->name
->content
,rcuplist
->user
->username
,cargv
[2],
346 flagbuf
,printflags(rcuplist
->flags
,rcuflags
));
347 csdb_chanlevhistory_insert(rcp
, sender
, rcuplist
->user
, oldflags
, rcuplist
->flags
);
349 /* Now see what we do next */
350 if (rcuplist
->flags
) {
351 /* User still valid: update or create */
353 addregusertochannel(rcuplist
);
354 csdb_createchanuser(rcuplist
);
356 csdb_updatechanuser(rcuplist
);
358 chanservstdmessage(sender
, QM_CHANLEVCHANGED
, cargv
[1], cip
->name
->content
,
359 printflags(rcuplist
->flags
& flagmask
, rcuflags
));
361 /* User has no flags: delete */
363 chanservstdmessage(sender
, QM_CHANLEVREMOVED
, cargv
[1], cip
->name
->content
);
364 csdb_deletechanuser(rcuplist
);
365 delreguserfromchannel(rcp
, target
);
367 freeregchanuser(rcuplist
);
369 if (cs_removechannelifempty(sender
, rcp
)) {
370 chanservstdmessage(sender
, QM_CHANLEVEMPTIEDCHANNEL
);
375 /* Update the channel if needed */
376 rcp
->status
|= QCSTAT_OPCHECK
;
379 if (rcuplist
== rcup
)
380 flagmask
|= QCUFLAGS_PERSONAL
;
381 if (rcuplist
&& (rcuplist
->flags
& flagmask
)) {
382 chanservstdmessage(sender
, QM_CHANUSERFLAGS
, cargv
[1], cip
->name
->content
,
383 printflags(rcuplist
->flags
& flagmask
, rcuflags
));
385 chanservstdmessage(sender
, QM_CHANUSERUNKNOWN
, cargv
[1], cip
->name
->content
);