00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "module.h"
00017
00018 int do_xop(User * u, char *xname, int xlev, int *xmsgs);
00019 int do_aop(User * u);
00020 int do_hop(User * u);
00021 int do_sop(User * u);
00022 int do_vop(User * u);
00023
00024 void myChanServHelp(User * u);
00025
00026 int xop_msgs[4][14] = {
00027 {CHAN_AOP_SYNTAX,
00028 CHAN_AOP_DISABLED,
00029 CHAN_AOP_NICKS_ONLY,
00030 CHAN_AOP_ADDED,
00031 CHAN_AOP_MOVED,
00032 CHAN_AOP_NO_SUCH_ENTRY,
00033 CHAN_AOP_NOT_FOUND,
00034 CHAN_AOP_NO_MATCH,
00035 CHAN_AOP_DELETED,
00036 CHAN_AOP_DELETED_ONE,
00037 CHAN_AOP_DELETED_SEVERAL,
00038 CHAN_AOP_LIST_EMPTY,
00039 CHAN_AOP_LIST_HEADER,
00040 CHAN_AOP_CLEAR},
00041 {CHAN_SOP_SYNTAX,
00042 CHAN_SOP_DISABLED,
00043 CHAN_SOP_NICKS_ONLY,
00044 CHAN_SOP_ADDED,
00045 CHAN_SOP_MOVED,
00046 CHAN_SOP_NO_SUCH_ENTRY,
00047 CHAN_SOP_NOT_FOUND,
00048 CHAN_SOP_NO_MATCH,
00049 CHAN_SOP_DELETED,
00050 CHAN_SOP_DELETED_ONE,
00051 CHAN_SOP_DELETED_SEVERAL,
00052 CHAN_SOP_LIST_EMPTY,
00053 CHAN_SOP_LIST_HEADER,
00054 CHAN_SOP_CLEAR},
00055 {CHAN_VOP_SYNTAX,
00056 CHAN_VOP_DISABLED,
00057 CHAN_VOP_NICKS_ONLY,
00058 CHAN_VOP_ADDED,
00059 CHAN_VOP_MOVED,
00060 CHAN_VOP_NO_SUCH_ENTRY,
00061 CHAN_VOP_NOT_FOUND,
00062 CHAN_VOP_NO_MATCH,
00063 CHAN_VOP_DELETED,
00064 CHAN_VOP_DELETED_ONE,
00065 CHAN_VOP_DELETED_SEVERAL,
00066 CHAN_VOP_LIST_EMPTY,
00067 CHAN_VOP_LIST_HEADER,
00068 CHAN_VOP_CLEAR},
00069 {CHAN_HOP_SYNTAX,
00070 CHAN_HOP_DISABLED,
00071 CHAN_HOP_NICKS_ONLY,
00072 CHAN_HOP_ADDED,
00073 CHAN_HOP_MOVED,
00074 CHAN_HOP_NO_SUCH_ENTRY,
00075 CHAN_HOP_NOT_FOUND,
00076 CHAN_HOP_NO_MATCH,
00077 CHAN_HOP_DELETED,
00078 CHAN_HOP_DELETED_ONE,
00079 CHAN_HOP_DELETED_SEVERAL,
00080 CHAN_HOP_LIST_EMPTY,
00081 CHAN_HOP_LIST_HEADER,
00082 CHAN_HOP_CLEAR}
00083 };
00084
00091 int AnopeInit(int argc, char **argv)
00092 {
00093 Command *c;
00094
00095 moduleAddAuthor("Anope");
00096 moduleAddVersion("$Id: cs_xop.c 1318 2007-12-15 15:50:16Z geniusdex $");
00097 moduleSetType(CORE);
00098
00099 c = createCommand("AOP", do_aop, NULL, CHAN_HELP_AOP, -1, -1, -1, -1);
00100 moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00101 if (ircd->halfop) {
00102 c = createCommand("HOP", do_hop, NULL, CHAN_HELP_HOP, -1, -1, -1,
00103 -1);
00104 moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00105 }
00106 c = createCommand("SOP", do_sop, NULL, CHAN_HELP_SOP, -1, -1, -1, -1);
00107 moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00108 c = createCommand("VOP", do_vop, NULL, CHAN_HELP_VOP, -1, -1, -1, -1);
00109 moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00110
00111 moduleSetChanHelp(myChanServHelp);
00112
00113 return MOD_CONT;
00114 }
00115
00119 void AnopeFini(void)
00120 {
00121
00122 }
00123
00124
00125
00130 void myChanServHelp(User * u)
00131 {
00132 notice_lang(s_ChanServ, u, CHAN_HELP_CMD_SOP);
00133 notice_lang(s_ChanServ, u, CHAN_HELP_CMD_AOP);
00134 if (ircd->halfop) {
00135 notice_lang(s_ChanServ, u, CHAN_HELP_CMD_HOP);
00136 }
00137 notice_lang(s_ChanServ, u, CHAN_HELP_CMD_VOP);
00138 }
00139
00145 int do_aop(User * u)
00146 {
00147 return do_xop(u, "AOP", ACCESS_AOP, xop_msgs[0]);
00148 }
00149
00150
00151
00152 int do_hop(User * u)
00153 {
00154 return do_xop(u, "HOP", ACCESS_HOP, xop_msgs[3]);
00155 }
00156
00157
00158
00159 int do_sop(User * u)
00160 {
00161 return do_xop(u, "SOP", ACCESS_SOP, xop_msgs[1]);
00162 }
00163
00164
00165
00166 int do_vop(User * u)
00167 {
00168 return do_xop(u, "VOP", ACCESS_VOP, xop_msgs[2]);
00169 }
00170
00171
00172
00173
00174
00175 int xop_del(User * u, ChannelInfo * ci, ChanAccess * access, int *perm, int uacc, int xlev)
00176 {
00177 if (!access->in_use || access->level != xlev)
00178 return 0;
00179 if (!is_services_admin(u) && uacc <= access->level) {
00180 (*perm)++;
00181 return 0;
00182 }
00183 access->nc = NULL;
00184 access->in_use = 0;
00185 send_event(EVENT_ACCESS_DEL, 3, ci->name, u->nick, access->nc->display);
00186 return 1;
00187 }
00188
00189 int xop_del_callback(User * u, int num, va_list args)
00190 {
00191 ChannelInfo *ci = va_arg(args, ChannelInfo *);
00192 int *last = va_arg(args, int *);
00193 int *perm = va_arg(args, int *);
00194 int uacc = va_arg(args, int);
00195 int xlev = va_arg(args, int);
00196
00197 if (num < 1 || num > ci->accesscount)
00198 return 0;
00199 *last = num;
00200
00201 return xop_del(u, ci, &ci->access[num - 1], perm, uacc, xlev);
00202 }
00203
00204
00205 int xop_list(User * u, int index, ChannelInfo * ci,
00206 int *sent_header, int xlev, int xmsg)
00207 {
00208 ChanAccess *access = &ci->access[index];
00209
00210 if (!access->in_use || access->level != xlev)
00211 return 0;
00212
00213 if (!*sent_header) {
00214 notice_lang(s_ChanServ, u, xmsg, ci->name);
00215 *sent_header = 1;
00216 }
00217
00218 notice_lang(s_ChanServ, u, CHAN_XOP_LIST_FORMAT, index + 1,
00219 access->nc->display);
00220 return 1;
00221 }
00222
00223 int xop_list_callback(User * u, int num, va_list args)
00224 {
00225 ChannelInfo *ci = va_arg(args, ChannelInfo *);
00226 int *sent_header = va_arg(args, int *);
00227 int xlev = va_arg(args, int);
00228 int xmsg = va_arg(args, int);
00229
00230 if (num < 1 || num > ci->accesscount)
00231 return 0;
00232
00233 return xop_list(u, num - 1, ci, sent_header, xlev, xmsg);
00234 }
00235
00236
00237 int do_xop(User * u, char *xname, int xlev, int *xmsgs)
00238 {
00239 char *chan = strtok(NULL, " ");
00240 char *cmd = strtok(NULL, " ");
00241 char *nick = strtok(NULL, " ");
00242 char event_access[BUFSIZE];
00243
00244 ChannelInfo *ci;
00245 NickAlias *na;
00246 NickCore *nc;
00247
00248 int i;
00249 int change = 0;
00250 short ulev;
00251 int is_list = (cmd && stricmp(cmd, "LIST") == 0);
00252 int is_servadmin = is_services_admin(u);
00253 ChanAccess *access;
00254
00255
00256
00257
00258 if (!cmd || ((is_list || !stricmp(cmd, "CLEAR")) ? 0 : !nick)) {
00259 syntax_error(s_ChanServ, u, xname, xmsgs[0]);
00260 } else if (!(ci = cs_findchan(chan))) {
00261 notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
00262 } else if (ci->flags & CI_VERBOTEN) {
00263 notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
00264 } else if (!(ci->flags & CI_XOP)) {
00265 notice_lang(s_ChanServ, u, CHAN_XOP_ACCESS, s_ChanServ);
00266 } else if (stricmp(cmd, "ADD") == 0) {
00267 if (readonly) {
00268 notice_lang(s_ChanServ, u, xmsgs[1]);
00269 return MOD_CONT;
00270 }
00271
00272 ulev = get_access(u, ci);
00273
00274 if ((xlev >= ulev || ulev < ACCESS_AOP) && !is_servadmin) {
00275 notice_lang(s_ChanServ, u, PERMISSION_DENIED);
00276 return MOD_CONT;
00277 }
00278
00279 na = findnick(nick);
00280 if (!na) {
00281 notice_lang(s_ChanServ, u, xmsgs[2]);
00282 return MOD_CONT;
00283 } else if (na->status & NS_VERBOTEN) {
00284 notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, na->nick);
00285 return MOD_CONT;
00286 }
00287
00288 nc = na->nc;
00289 for (access = ci->access, i = 0; i < ci->accesscount;
00290 access++, i++) {
00291 if (access->nc == nc) {
00295 if ((access->level >= ulev) && (!is_servadmin)) {
00296 notice_lang(s_ChanServ, u, PERMISSION_DENIED);
00297 return MOD_CONT;
00298 }
00299 change++;
00300 break;
00301 }
00302 }
00303
00304 if (!change) {
00305
00306
00307
00308
00309
00310
00311
00312 if (i < CSAccessMax) {
00313 ci->accesscount++;
00314 ci->access =
00315 srealloc(ci->access,
00316 sizeof(ChanAccess) * ci->accesscount);
00317 } else {
00318 notice_lang(s_ChanServ, u, CHAN_XOP_REACHED_LIMIT,
00319 CSAccessMax);
00320 return MOD_CONT;
00321 }
00322
00323 access = &ci->access[i];
00324 access->nc = nc;
00325 }
00326
00327 access->in_use = 1;
00328 access->level = xlev;
00329 access->last_seen = 0;
00330
00331 alog("%s: %s!%s@%s (level %d) %s access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->username, u->host, ulev, change ? "changed" : "set", access->level, na->nick, nc->display, ci->name);
00332
00333 snprintf(event_access, BUFSIZE, "%d", access->level);
00334
00335 if (!change) {
00336 send_event(EVENT_ACCESS_ADD, 4, ci->name, u->nick, na->nick,
00337 event_access);
00338 notice_lang(s_ChanServ, u, xmsgs[3], access->nc->display,
00339 ci->name);
00340 } else {
00341 send_event(EVENT_ACCESS_CHANGE, 4, ci->name, u->nick, na->nick,
00342 event_access);
00343 notice_lang(s_ChanServ, u, xmsgs[4], access->nc->display,
00344 ci->name);
00345 }
00346
00347 } else if (stricmp(cmd, "DEL") == 0) {
00348 int deleted, a, b;
00349 if (readonly) {
00350 notice_lang(s_ChanServ, u, xmsgs[1]);
00351 return MOD_CONT;
00352 }
00353
00354 if (ci->accesscount == 0) {
00355 notice_lang(s_ChanServ, u, xmsgs[11], chan);
00356 return MOD_CONT;
00357 }
00358
00359 ulev = get_access(u, ci);
00360
00361 if ((xlev >= ulev || ulev < ACCESS_AOP) && !is_servadmin) {
00362 notice_lang(s_ChanServ, u, PERMISSION_DENIED);
00363 return MOD_CONT;
00364 }
00365
00366
00367 if (isdigit(*nick) && strspn(nick, "1234567890,-") == strlen(nick)) {
00368 int count, last = -1, perm = 0;
00369 deleted =
00370 process_numlist(nick, &count, xop_del_callback, u, ci,
00371 &last, &perm, ulev, xlev);
00372 if (!deleted) {
00373 if (perm) {
00374 notice_lang(s_ChanServ, u, PERMISSION_DENIED);
00375 } else if (count == 1) {
00376 notice_lang(s_ChanServ, u, xmsgs[5], last, ci->name);
00377 } else {
00378 notice_lang(s_ChanServ, u, xmsgs[7], ci->name);
00379 }
00380 } else if (deleted == 1) {
00381 notice_lang(s_ChanServ, u, xmsgs[9], ci->name);
00382 } else {
00383 notice_lang(s_ChanServ, u, xmsgs[10], deleted, ci->name);
00384 }
00385 } else {
00386 na = findnick(nick);
00387 if (!na) {
00388 notice_lang(s_ChanServ, u, NICK_X_NOT_REGISTERED, nick);
00389 return MOD_CONT;
00390 }
00391 nc = na->nc;
00392
00393 for (i = 0; i < ci->accesscount; i++)
00394 if (ci->access[i].nc == nc && ci->access[i].level == xlev)
00395 break;
00396
00397 if (i == ci->accesscount) {
00398 notice_lang(s_ChanServ, u, xmsgs[6], nick, chan);
00399 return MOD_CONT;
00400 }
00401
00402 access = &ci->access[i];
00403 if (!is_servadmin && ulev <= access->level) {
00404 deleted = 0;
00405 notice_lang(s_ChanServ, u, PERMISSION_DENIED);
00406 } else {
00407 notice_lang(s_ChanServ, u, xmsgs[8], access->nc->display,
00408 ci->name);
00409 access->nc = NULL;
00410 access->in_use = 0;
00411 send_event(EVENT_ACCESS_DEL, 3, ci->name, u->nick,
00412 na->nick);
00413 deleted = 1;
00414 }
00415 }
00416 if (deleted) {
00417
00418 for (b = 0; b < ci->accesscount; b++) {
00419 if (ci->access[b].in_use) {
00420 for (a = 0; a < ci->accesscount; a++) {
00421 if (a > b)
00422 break;
00423 if (!ci->access[a].in_use) {
00424 ci->access[a].in_use = 1;
00425 ci->access[a].level = ci->access[b].level;
00426 ci->access[a].nc = ci->access[b].nc;
00427 ci->access[a].last_seen =
00428 ci->access[b].last_seen;
00429 ci->access[b].nc = NULL;
00430 ci->access[b].in_use = 0;
00431 break;
00432 }
00433 }
00434 }
00435 }
00436
00437
00438
00439
00440
00441 for (i = ci->accesscount - 1; i >= 0; i--) {
00442 if (ci->access[i].in_use == 1)
00443 break;
00444
00445 ci->accesscount--;
00446 }
00447 ci->access =
00448 srealloc(ci->access,sizeof(ChanAccess) * ci->accesscount);
00449 }
00450 } else if (stricmp(cmd, "LIST") == 0) {
00451 int sent_header = 0;
00452
00453 ulev = get_access(u, ci);
00454
00455 if (!is_servadmin && ulev < ACCESS_AOP) {
00456 notice_lang(s_ChanServ, u, ACCESS_DENIED);
00457 return MOD_CONT;
00458 }
00459
00460 if (ci->accesscount == 0) {
00461 notice_lang(s_ChanServ, u, xmsgs[11], ci->name);
00462 return MOD_CONT;
00463 }
00464
00465 if (nick && strspn(nick, "1234567890,-") == strlen(nick)) {
00466 process_numlist(nick, NULL, xop_list_callback, u, ci,
00467 &sent_header, xlev, xmsgs[12]);
00468 } else {
00469 for (i = 0; i < ci->accesscount; i++) {
00470 if (nick && ci->access[i].nc
00471 && !match_wild_nocase(nick, ci->access[i].nc->display))
00472 continue;
00473 xop_list(u, i, ci, &sent_header, xlev, xmsgs[12]);
00474 }
00475 }
00476 if (!sent_header)
00477 notice_lang(s_ChanServ, u, xmsgs[7], chan);
00478 } else if (stricmp(cmd, "CLEAR") == 0) {
00479 if (readonly) {
00480 notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED);
00481 return MOD_CONT;
00482 }
00483
00484 if (ci->accesscount == 0) {
00485 notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_EMPTY, chan);
00486 return MOD_CONT;
00487 }
00488
00489 if (!is_servadmin && !is_founder(u, ci)) {
00490 notice_lang(s_ChanServ, u, PERMISSION_DENIED);
00491 return MOD_CONT;
00492 }
00493
00494 for (i = 0; i < ci->accesscount; i++) {
00495 if (ci->access[i].in_use && ci->access[i].level == xlev) {
00496 ci->access[i].nc = NULL;
00497 ci->access[i].in_use = 0;
00498 }
00499 }
00500
00501 send_event(EVENT_ACCESS_CLEAR, 2, ci->name, u->nick);
00502
00503 notice_lang(s_ChanServ, u, xmsgs[13], ci->name);
00504 } else {
00505 syntax_error(s_ChanServ, u, xname, xmsgs[0]);
00506 }
00507 return MOD_CONT;
00508 }