00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <ctype.h>
00027
00028 static struct flag_record user = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00029 static struct flag_record victim = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00030
00031
00032 static void cmd_pls_ban(struct userrec *u, int idx, char *par)
00033 {
00034 char *chname, *who, s[UHOSTLEN], s1[UHOSTLEN], *p, *p_expire;
00035 unsigned long int expire_time = 0, expire_foo;
00036 int sticky = 0;
00037 struct chanset_t *chan = NULL;
00038 module_entry *me;
00039
00040 if (!par[0]) {
00041 dprintf(idx, "Usage: +ban <hostmask> [channel] [%%<XdXhXm>] [reason]\n");
00042 } else {
00043 who = newsplit(&par);
00044 if (par[0] && strchr(CHANMETA, par[0]))
00045 chname = newsplit(&par);
00046 else
00047 chname = 0;
00048 if (chname || !(u->flags & USER_OP)) {
00049 if (!chname)
00050 chname = dcc[idx].u.chat->con_chan;
00051 get_user_flagrec(u, &user, chname);
00052 chan = findchan_by_dname(chname);
00053
00054 if (!chan) {
00055 dprintf(idx, "That channel doesn't exist!\n");
00056 return;
00057 } else if (!((glob_op(user) && !chan_deop(user)) || (glob_halfop(user) &&
00058 !chan_dehalfop(user)) || chan_op(user) || chan_halfop(user))) {
00059 dprintf(idx, "You don't have access to set bans on %s.\n", chname);
00060 return;
00061 }
00062 } else
00063 chan = 0;
00064
00065 if (par[0] == '%') {
00066 p = newsplit(&par);
00067 p_expire = p + 1;
00068 while (*(++p) != 0) {
00069 switch (tolower((unsigned) *p)) {
00070 case 'd':
00071 *p = 0;
00072 expire_foo = strtol(p_expire, NULL, 10);
00073 if (expire_foo > 365)
00074 expire_foo = 365;
00075 expire_time += 86400 * expire_foo;
00076 p_expire = p + 1;
00077 break;
00078 case 'h':
00079 *p = 0;
00080 expire_foo = strtol(p_expire, NULL, 10);
00081 if (expire_foo > 8760)
00082 expire_foo = 8760;
00083 expire_time += 3600 * expire_foo;
00084 p_expire = p + 1;
00085 break;
00086 case 'm':
00087 *p = 0;
00088 expire_foo = strtol(p_expire, NULL, 10);
00089 if (expire_foo > 525600)
00090 expire_foo = 525600;
00091 expire_time += 60 * expire_foo;
00092 p_expire = p + 1;
00093 }
00094 }
00095 }
00096 if (!par[0])
00097 par = "requested";
00098 else if (strlen(par) > MASKREASON_MAX)
00099 par[MASKREASON_MAX] = 0;
00100 if (strlen(who) > UHOSTMAX - 4)
00101 who[UHOSTMAX - 4] = 0;
00102
00103 if (!strchr(who, '!')) {
00104 if (!strchr(who, '@'))
00105 egg_snprintf(s, sizeof s, "%s!*@*", who);
00106 else
00107 egg_snprintf(s, sizeof s, "*!%s", who);
00108 } else if (!strchr(who, '@'))
00109 egg_snprintf(s, sizeof s, "%s@*", who);
00110 else
00111 strncpyz(s, who, sizeof s);
00112 if ((me = module_find("server", 0, 0)) && me->funcs)
00113 egg_snprintf(s1, sizeof s1, "%s!%s", me->funcs[SERVER_BOTNAME],
00114 me->funcs[SERVER_BOTUSERHOST]);
00115 else
00116 egg_snprintf(s1, sizeof s1, "%s!%s@%s", origbotname, botuser, hostname);
00117 if (match_addr(s, s1)) {
00118 dprintf(idx, "I'm not going to ban myself.\n");
00119 putlog(LOG_CMDS, "*", "#%s# attempted +ban %s", dcc[idx].nick, s);
00120 } else {
00121
00122 if (strlen(s) > 70) {
00123 s[69] = '*';
00124 s[70] = 0;
00125 }
00126 if (chan) {
00127 u_addban(chan, s, dcc[idx].nick, par,
00128 expire_time ? now + expire_time : 0, 0);
00129 if (par[0] == '*') {
00130 sticky = 1;
00131 par++;
00132 putlog(LOG_CMDS, "*", "#%s# (%s) +ban %s %s (%s) (sticky)",
00133 dcc[idx].nick, dcc[idx].u.chat->con_chan, s, chan->dname, par);
00134 dprintf(idx, "New %s sticky ban: %s (%s)\n", chan->dname, s, par);
00135 } else {
00136 putlog(LOG_CMDS, "*", "#%s# (%s) +ban %s %s (%s)", dcc[idx].nick,
00137 dcc[idx].u.chat->con_chan, s, chan->dname, par);
00138 dprintf(idx, "New %s ban: %s (%s)\n", chan->dname, s, par);
00139 }
00140
00141
00142
00143 if ((me = module_find("irc", 0, 0)))
00144 (me->funcs[IRC_CHECK_THIS_BAN]) (chan, s, sticky);
00145 } else {
00146 u_addban(NULL, s, dcc[idx].nick, par,
00147 expire_time ? now + expire_time : 0, 0);
00148 if (par[0] == '*') {
00149 sticky = 1;
00150 par++;
00151 putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +ban %s (%s) (sticky)",
00152 dcc[idx].nick, s, par);
00153 dprintf(idx, "New sticky ban: %s (%s)\n", s, par);
00154 } else {
00155 putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +ban %s (%s)", dcc[idx].nick,
00156 s, par);
00157 dprintf(idx, "New ban: %s (%s)\n", s, par);
00158 }
00159 if ((me = module_find("irc", 0, 0)))
00160 for (chan = chanset; chan != NULL; chan = chan->next)
00161 (me->funcs[IRC_CHECK_THIS_BAN]) (chan, s, sticky);
00162 }
00163 }
00164 }
00165 }
00166
00167 static void cmd_pls_exempt(struct userrec *u, int idx, char *par)
00168 {
00169 char *chname, *who, s[UHOSTLEN], s1[UHOSTLEN], *p, *p_expire;
00170 unsigned long int expire_time = 0, expire_foo;
00171 struct chanset_t *chan = NULL;
00172 module_entry *me;
00173
00174 if (!use_exempts) {
00175 dprintf(idx, "This command can only be used with use-exempts enabled.\n");
00176 return;
00177 }
00178 if (!par[0]) {
00179 dprintf(idx, "Usage: +exempt <hostmask> [channel] [%%<XdXhXm>] [reason]\n");
00180 } else {
00181 who = newsplit(&par);
00182 if (par[0] && strchr(CHANMETA, par[0]))
00183 chname = newsplit(&par);
00184 else
00185 chname = 0;
00186 if (chname || !(u->flags & USER_OP)) {
00187 if (!chname)
00188 chname = dcc[idx].u.chat->con_chan;
00189 get_user_flagrec(u, &user, chname);
00190 chan = findchan_by_dname(chname);
00191
00192 if (!chan) {
00193 dprintf(idx, "That channel doesn't exist!\n");
00194 return;
00195 } else if (!((glob_op(user) && !chan_deop(user)) || (glob_halfop(user) &&
00196 !chan_dehalfop(user)) || chan_op(user) || chan_halfop(user))) {
00197 dprintf(idx, "You don't have access to set exempts on %s.\n", chname);
00198 return;
00199 }
00200 } else
00201 chan = 0;
00202
00203 if (par[0] == '%') {
00204 p = newsplit(&par);
00205 p_expire = p + 1;
00206 while (*(++p) != 0) {
00207 switch (tolower((unsigned) *p)) {
00208 case 'd':
00209 *p = 0;
00210 expire_foo = strtol(p_expire, NULL, 10);
00211 if (expire_foo > 365)
00212 expire_foo = 365;
00213 expire_time += 86400 * expire_foo;
00214 p_expire = p + 1;
00215 break;
00216 case 'h':
00217 *p = 0;
00218 expire_foo = strtol(p_expire, NULL, 10);
00219 if (expire_foo > 8760)
00220 expire_foo = 8760;
00221 expire_time += 3600 * expire_foo;
00222 p_expire = p + 1;
00223 break;
00224 case 'm':
00225 *p = 0;
00226 expire_foo = strtol(p_expire, NULL, 10);
00227 if (expire_foo > 525600)
00228 expire_foo = 525600;
00229 expire_time += 60 * expire_foo;
00230 p_expire = p + 1;
00231 }
00232 }
00233 }
00234 if (!par[0])
00235 par = "requested";
00236 else if (strlen(par) > MASKREASON_MAX)
00237 par[MASKREASON_MAX] = 0;
00238 if (strlen(who) > UHOSTMAX - 4)
00239 who[UHOSTMAX - 4] = 0;
00240
00241 if (!strchr(who, '!')) {
00242 if (!strchr(who, '@'))
00243 egg_snprintf(s, sizeof s, "%s!*@*", who);
00244 else
00245 egg_snprintf(s, sizeof s, "*!%s", who);
00246 } else if (!strchr(who, '@'))
00247 egg_snprintf(s, sizeof s, "%s@*", who);
00248 else
00249 strncpyz(s, who, sizeof s);
00250 if ((me = module_find("server", 0, 0)) && me->funcs)
00251 egg_snprintf(s1, sizeof s1, "%s!%s", me->funcs[SERVER_BOTNAME],
00252 me->funcs[SERVER_BOTUSERHOST]);
00253 else
00254 egg_snprintf(s1, sizeof s1, "%s!%s@%s", origbotname, botuser, hostname);
00255
00256
00257 if (strlen(s) > 70) {
00258 s[69] = '*';
00259 s[70] = 0;
00260 }
00261 if (chan) {
00262 u_addexempt(chan, s, dcc[idx].nick, par,
00263 expire_time ? now + expire_time : 0, 0);
00264 if (par[0] == '*') {
00265 par++;
00266 putlog(LOG_CMDS, "*", "#%s# (%s) +exempt %s %s (%s) (sticky)",
00267 dcc[idx].nick, dcc[idx].u.chat->con_chan, s, chan->dname, par);
00268 dprintf(idx, "New %s sticky exempt: %s (%s)\n", chan->dname, s, par);
00269 } else {
00270 putlog(LOG_CMDS, "*", "#%s# (%s) +exempt %s %s (%s)", dcc[idx].nick,
00271 dcc[idx].u.chat->con_chan, s, chan->dname, par);
00272 dprintf(idx, "New %s exempt: %s (%s)\n", chan->dname, s, par);
00273 }
00274 add_mode(chan, '+', 'e', s);
00275 } else {
00276 u_addexempt(NULL, s, dcc[idx].nick, par,
00277 expire_time ? now + expire_time : 0, 0);
00278 if (par[0] == '*') {
00279 par++;
00280 putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +exempt %s (%s) (sticky)",
00281 dcc[idx].nick, s, par);
00282 dprintf(idx, "New sticky exempt: %s (%s)\n", s, par);
00283 } else {
00284 putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +exempt %s (%s)", dcc[idx].nick,
00285 s, par);
00286 dprintf(idx, "New exempt: %s (%s)\n", s, par);
00287 }
00288 for (chan = chanset; chan != NULL; chan = chan->next)
00289 add_mode(chan, '+', 'e', s);
00290 }
00291 }
00292 }
00293
00294 static void cmd_pls_invite(struct userrec *u, int idx, char *par)
00295 {
00296 char *chname, *who, s[UHOSTLEN], s1[UHOSTLEN], *p, *p_expire;
00297 unsigned long int expire_time = 0, expire_foo;
00298 struct chanset_t *chan = NULL;
00299 module_entry *me;
00300
00301 if (!use_invites) {
00302 dprintf(idx, "This command can only be used with use-invites enabled.\n");
00303 return;
00304 }
00305
00306 if (!par[0]) {
00307 dprintf(idx, "Usage: +invite <hostmask> [channel] [%%<XdXhXm>] [reason]\n");
00308 } else {
00309 who = newsplit(&par);
00310 if (par[0] && strchr(CHANMETA, par[0]))
00311 chname = newsplit(&par);
00312 else
00313 chname = 0;
00314 if (chname || !(u->flags & USER_OP)) {
00315 if (!chname)
00316 chname = dcc[idx].u.chat->con_chan;
00317 get_user_flagrec(u, &user, chname);
00318 chan = findchan_by_dname(chname);
00319
00320 if (!chan) {
00321 dprintf(idx, "That channel doesn't exist!\n");
00322 return;
00323 } else if (!((glob_op(user) && !chan_deop(user)) || (glob_halfop(user) &&
00324 !chan_dehalfop(user)) || chan_op(user) || chan_halfop(user))) {
00325 dprintf(idx, "You don't have access to set invites on %s.\n", chname);
00326 return;
00327 }
00328 } else
00329 chan = 0;
00330
00331 if (par[0] == '%') {
00332 p = newsplit(&par);
00333 p_expire = p + 1;
00334 while (*(++p) != 0) {
00335 switch (tolower((unsigned) *p)) {
00336 case 'd':
00337 *p = 0;
00338 expire_foo = strtol(p_expire, NULL, 10);
00339 if (expire_foo > 365)
00340 expire_foo = 365;
00341 expire_time += 86400 * expire_foo;
00342 p_expire = p + 1;
00343 break;
00344 case 'h':
00345 *p = 0;
00346 expire_foo = strtol(p_expire, NULL, 10);
00347 if (expire_foo > 8760)
00348 expire_foo = 8760;
00349 expire_time += 3600 * expire_foo;
00350 p_expire = p + 1;
00351 break;
00352 case 'm':
00353 *p = 0;
00354 expire_foo = strtol(p_expire, NULL, 10);
00355 if (expire_foo > 525600)
00356 expire_foo = 525600;
00357 expire_time += 60 * expire_foo;
00358 p_expire = p + 1;
00359 }
00360 }
00361 }
00362 if (!par[0])
00363 par = "requested";
00364 else if (strlen(par) > MASKREASON_MAX)
00365 par[MASKREASON_MAX] = 0;
00366 if (strlen(who) > UHOSTMAX - 4)
00367 who[UHOSTMAX - 4] = 0;
00368
00369 if (!strchr(who, '!')) {
00370 if (!strchr(who, '@'))
00371 egg_snprintf(s, sizeof s, "%s!*@*", who);
00372 else
00373 egg_snprintf(s, sizeof s, "*!%s", who);
00374 } else if (!strchr(who, '@'))
00375 egg_snprintf(s, sizeof s, "%s@*", who);
00376 else
00377 strncpyz(s, who, sizeof s);
00378 if ((me = module_find("server", 0, 0)) && me->funcs)
00379 egg_snprintf(s1, sizeof s1, "%s!%s", me->funcs[SERVER_BOTNAME],
00380 me->funcs[SERVER_BOTUSERHOST]);
00381 else
00382 egg_snprintf(s1, sizeof s1, "%s!%s@%s", origbotname, botuser, hostname);
00383
00384
00385 if (strlen(s) > 70) {
00386 s[69] = '*';
00387 s[70] = 0;
00388 }
00389 if (chan) {
00390 u_addinvite(chan, s, dcc[idx].nick, par,
00391 expire_time ? now + expire_time : 0, 0);
00392 if (par[0] == '*') {
00393 par++;
00394 putlog(LOG_CMDS, "*", "#%s# (%s) +invite %s %s (%s) (sticky)",
00395 dcc[idx].nick, dcc[idx].u.chat->con_chan, s, chan->dname, par);
00396 dprintf(idx, "New %s sticky invite: %s (%s)\n", chan->dname, s, par);
00397 } else {
00398 putlog(LOG_CMDS, "*", "#%s# (%s) +invite %s %s (%s)", dcc[idx].nick,
00399 dcc[idx].u.chat->con_chan, s, chan->dname, par);
00400 dprintf(idx, "New %s invite: %s (%s)\n", chan->dname, s, par);
00401 }
00402 add_mode(chan, '+', 'I', s);
00403 } else {
00404 u_addinvite(NULL, s, dcc[idx].nick, par,
00405 expire_time ? now + expire_time : 0, 0);
00406 if (par[0] == '*') {
00407 par++;
00408 putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +invite %s (%s) (sticky)",
00409 dcc[idx].nick, s, par);
00410 dprintf(idx, "New sticky invite: %s (%s)\n", s, par);
00411 } else {
00412 putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +invite %s (%s)", dcc[idx].nick,
00413 s, par);
00414 dprintf(idx, "New invite: %s (%s)\n", s, par);
00415 }
00416 for (chan = chanset; chan != NULL; chan = chan->next)
00417 add_mode(chan, '+', 'I', s);
00418 }
00419 }
00420 }
00421
00422 static void cmd_mns_ban(struct userrec *u, int idx, char *par)
00423 {
00424 int console = 0, i = 0, j;
00425 struct chanset_t *chan = NULL;
00426 char s[UHOSTLEN], *ban, *chname, *mask;
00427 masklist *b;
00428
00429 if (!par[0]) {
00430 dprintf(idx, "Usage: -ban <hostmask|ban #> [channel]\n");
00431 return;
00432 }
00433 ban = newsplit(&par);
00434 if (par[0] && strchr(CHANMETA, par[0]))
00435 chname = newsplit(&par);
00436 else {
00437 chname = dcc[idx].u.chat->con_chan;
00438 console = 1;
00439 }
00440 if (chname || !(u->flags & USER_OP)) {
00441 if (!chname)
00442 chname = dcc[idx].u.chat->con_chan;
00443 get_user_flagrec(u, &user, chname);
00444
00445 if ((!chan_op(user) && (!glob_op(user) || chan_deop(user))) &&
00446 (!chan_halfop(user) && (!glob_halfop(user) || chan_dehalfop(user)))) {
00447 dprintf(idx, "You don't have access to remove bans on %s.\n", chname);
00448 return;
00449 }
00450 }
00451 strncpyz(s, ban, sizeof s);
00452 if (console) {
00453 i = u_delban(NULL, s, (u->flags & USER_OP));
00454 if (i > 0) {
00455 if (lastdeletedmask)
00456 mask = lastdeletedmask;
00457 else
00458 mask = s;
00459 putlog(LOG_CMDS, "*", "#%s# -ban %s", dcc[idx].nick, mask);
00460 dprintf(idx, "%s: %s\n", IRC_REMOVEDBAN, mask);
00461 for (chan = chanset; chan != NULL; chan = chan->next)
00462 add_mode(chan, '-', 'b', mask);
00463 return;
00464 }
00465 }
00466
00467 if (chname)
00468 chan = findchan_by_dname(chname);
00469 if (!chan) {
00470 dprintf(idx, "Invalid channel.\n");
00471 return;
00472 }
00473 if (str_isdigit(ban)) {
00474 i = atoi(ban);
00475
00476 egg_snprintf(s, sizeof s, "%d", i);
00477 j = u_delban(0, s, 0);
00478 if (j < 0) {
00479 egg_snprintf(s, sizeof s, "%d", -j);
00480 j = u_delban(chan, s, 1);
00481 if (j > 0) {
00482 if (lastdeletedmask)
00483 mask = lastdeletedmask;
00484 else
00485 mask = s;
00486 putlog(LOG_CMDS, "*", "#%s# (%s) -ban %s", dcc[idx].nick, chan->dname,
00487 mask);
00488 dprintf(idx, "Removed %s channel ban: %s\n", chan->dname, mask);
00489 add_mode(chan, '-', 'b', mask);
00490 return;
00491 }
00492 }
00493 i = 0;
00494 for (b = chan->channel.ban; b && b->mask && b->mask[0]; b = b->next) {
00495 if ((!u_equals_mask(global_bans, b->mask)) &&
00496 (!u_equals_mask(chan->bans, b->mask))) {
00497 i++;
00498 if (i == -j) {
00499 add_mode(chan, '-', 'b', b->mask);
00500 dprintf(idx, "%s '%s' on %s.\n", IRC_REMOVEDBAN,
00501 b->mask, chan->dname);
00502 putlog(LOG_CMDS, "*", "#%s# (%s) -ban %s [on channel]",
00503 dcc[idx].nick, dcc[idx].u.chat->con_chan, ban);
00504 return;
00505 }
00506 }
00507 }
00508 } else {
00509 j = u_delban(chan, ban, 1);
00510 if (j > 0) {
00511 putlog(LOG_CMDS, "*", "#%s# (%s) -ban %s", dcc[idx].nick,
00512 dcc[idx].u.chat->con_chan, ban);
00513 dprintf(idx, "Removed %s channel ban: %s\n", chname, ban);
00514 add_mode(chan, '-', 'b', ban);
00515 return;
00516 }
00517 for (b = chan->channel.ban; b && b->mask && b->mask[0]; b = b->next) {
00518 if (!rfc_casecmp(b->mask, ban)) {
00519 add_mode(chan, '-', 'b', b->mask);
00520 dprintf(idx, "%s '%s' on %s.\n", IRC_REMOVEDBAN, b->mask, chan->dname);
00521 putlog(LOG_CMDS, "*", "#%s# (%s) -ban %s [on channel]",
00522 dcc[idx].nick, dcc[idx].u.chat->con_chan, ban);
00523 return;
00524 }
00525 }
00526 }
00527 dprintf(idx, "No such ban.\n");
00528 }
00529
00530 static void cmd_mns_exempt(struct userrec *u, int idx, char *par)
00531 {
00532 int console = 0, i = 0, j;
00533 struct chanset_t *chan = NULL;
00534 char s[UHOSTLEN], *exempt, *chname, *mask;
00535 masklist *e;
00536
00537 if (!use_exempts) {
00538 dprintf(idx, "This command can only be used with use-exempts enabled.\n");
00539 return;
00540 }
00541 if (!par[0]) {
00542 dprintf(idx, "Usage: -exempt <hostmask|exempt #> [channel]\n");
00543 return;
00544 }
00545 exempt = newsplit(&par);
00546 if (par[0] && strchr(CHANMETA, par[0]))
00547 chname = newsplit(&par);
00548 else {
00549 chname = dcc[idx].u.chat->con_chan;
00550 console = 1;
00551 }
00552 if (chname || !(u->flags & USER_OP)) {
00553 if (!chname)
00554 chname = dcc[idx].u.chat->con_chan;
00555 get_user_flagrec(u, &user, chname);
00556 if ((!chan_op(user) && (!glob_op(user) || chan_deop(user))) &&
00557 (!chan_halfop(user) && (!glob_halfop(user) || chan_dehalfop(user)))) {
00558 dprintf(idx, "You don't have access to remove exempts on %s.\n", chname);
00559 return;
00560 }
00561 }
00562 strncpyz(s, exempt, sizeof s);
00563 if (console) {
00564 i = u_delexempt(NULL, s, (u->flags & USER_OP));
00565 if (i > 0) {
00566 if (lastdeletedmask)
00567 mask = lastdeletedmask;
00568 else
00569 mask = s;
00570 putlog(LOG_CMDS, "*", "#%s# -exempt %s", dcc[idx].nick, mask);
00571 dprintf(idx, "%s: %s\n", IRC_REMOVEDEXEMPT, mask);
00572 for (chan = chanset; chan != NULL; chan = chan->next)
00573 add_mode(chan, '-', 'e', mask);
00574 return;
00575 }
00576 }
00577
00578 if (chname)
00579 chan = findchan_by_dname(chname);
00580 if (!chan) {
00581 dprintf(idx, "Invalid channel.\n");
00582 return;
00583 }
00584 if (str_isdigit(exempt)) {
00585 i = atoi(exempt);
00586
00587 egg_snprintf(s, sizeof s, "%d", i);
00588 j = u_delexempt(0, s, 0);
00589 if (j < 0) {
00590 egg_snprintf(s, sizeof s, "%d", -j);
00591 j = u_delexempt(chan, s, 1);
00592 if (j > 0) {
00593 if (lastdeletedmask)
00594 mask = lastdeletedmask;
00595 else
00596 mask = s;
00597 putlog(LOG_CMDS, "*", "#%s# (%s) -exempt %s", dcc[idx].nick,
00598 chan->dname, mask);
00599 dprintf(idx, "Removed %s channel exempt: %s\n", chan->dname, mask);
00600 add_mode(chan, '-', 'e', mask);
00601 return;
00602 }
00603 }
00604 i = 0;
00605 for (e = chan->channel.exempt; e && e->mask && e->mask[0]; e = e->next) {
00606 if (!u_equals_mask(global_exempts, e->mask) &&
00607 !u_equals_mask(chan->exempts, e->mask)) {
00608 i++;
00609 if (i == -j) {
00610 add_mode(chan, '-', 'e', e->mask);
00611 dprintf(idx, "%s '%s' on %s.\n", IRC_REMOVEDEXEMPT,
00612 e->mask, chan->dname);
00613 putlog(LOG_CMDS, "*", "#%s# (%s) -exempt %s [on channel]",
00614 dcc[idx].nick, dcc[idx].u.chat->con_chan, exempt);
00615 return;
00616 }
00617 }
00618 }
00619 } else {
00620 j = u_delexempt(chan, exempt, 1);
00621 if (j > 0) {
00622 putlog(LOG_CMDS, "*", "#%s# (%s) -exempt %s", dcc[idx].nick,
00623 dcc[idx].u.chat->con_chan, exempt);
00624 dprintf(idx, "Removed %s channel exempt: %s\n", chname, exempt);
00625 add_mode(chan, '-', 'e', exempt);
00626 return;
00627 }
00628 for (e = chan->channel.exempt; e && e->mask && e->mask[0]; e = e->next) {
00629 if (!rfc_casecmp(e->mask, exempt)) {
00630 add_mode(chan, '-', 'e', e->mask);
00631 dprintf(idx, "%s '%s' on %s.\n",
00632 IRC_REMOVEDEXEMPT, e->mask, chan->dname);
00633 putlog(LOG_CMDS, "*", "#%s# (%s) -exempt %s [on channel]",
00634 dcc[idx].nick, dcc[idx].u.chat->con_chan, exempt);
00635 return;
00636 }
00637 }
00638 }
00639 dprintf(idx, "No such exemption.\n");
00640 }
00641
00642 static void cmd_mns_invite(struct userrec *u, int idx, char *par)
00643 {
00644 int console = 0, i = 0, j;
00645 struct chanset_t *chan = NULL;
00646 char s[UHOSTLEN], *invite, *chname, *mask;
00647 masklist *inv;
00648
00649 if (!use_invites) {
00650 dprintf(idx, "This command can only be used with use-invites enabled.\n");
00651 return;
00652 }
00653 if (!par[0]) {
00654 dprintf(idx, "Usage: -invite <hostmask|invite #> [channel]\n");
00655 return;
00656 }
00657 invite = newsplit(&par);
00658 if (par[0] && strchr(CHANMETA, par[0]))
00659 chname = newsplit(&par);
00660 else {
00661 chname = dcc[idx].u.chat->con_chan;
00662 console = 1;
00663 }
00664 if (chname || !(u->flags & USER_OP)) {
00665 if (!chname)
00666 chname = dcc[idx].u.chat->con_chan;
00667 get_user_flagrec(u, &user, chname);
00668 if ((!chan_op(user) && (!glob_op(user) || chan_deop(user))) &&
00669 (!chan_halfop(user) && (!glob_halfop(user) || chan_dehalfop(user)))) {
00670 dprintf(idx, "You don't have access to remove invites on %s.\n", chname);
00671 return;
00672 }
00673 }
00674 strncpyz(s, invite, sizeof s);
00675 if (console) {
00676 i = u_delinvite(NULL, s, (u->flags & USER_OP));
00677 if (i > 0) {
00678 if (lastdeletedmask)
00679 mask = lastdeletedmask;
00680 else
00681 mask = s;
00682 putlog(LOG_CMDS, "*", "#%s# -invite %s", dcc[idx].nick, mask);
00683 dprintf(idx, "%s: %s\n", IRC_REMOVEDINVITE, mask);
00684 for (chan = chanset; chan != NULL; chan = chan->next)
00685 add_mode(chan, '-', 'I', mask);
00686 return;
00687 }
00688 }
00689
00690 if (chname)
00691 chan = findchan_by_dname(chname);
00692 if (!chan) {
00693 dprintf(idx, "Invalid channel.\n");
00694 return;
00695 }
00696 if (str_isdigit(invite)) {
00697 i = atoi(invite);
00698
00699 egg_snprintf(s, sizeof s, "%d", i);
00700 j = u_delinvite(0, s, 0);
00701 if (j < 0) {
00702 egg_snprintf(s, sizeof s, "%d", -j);
00703 j = u_delinvite(chan, s, 1);
00704 if (j > 0) {
00705 if (lastdeletedmask)
00706 mask = lastdeletedmask;
00707 else
00708 mask = s;
00709 putlog(LOG_CMDS, "*", "#%s# (%s) -invite %s", dcc[idx].nick,
00710 chan->dname, mask);
00711 dprintf(idx, "Removed %s channel invite: %s\n", chan->dname, mask);
00712 add_mode(chan, '-', 'I', mask);
00713 return;
00714 }
00715 }
00716 i = 0;
00717 for (inv = chan->channel.invite; inv && inv->mask && inv->mask[0];
00718 inv = inv->next) {
00719 if (!u_equals_mask(global_invites, inv->mask) &&
00720 !u_equals_mask(chan->invites, inv->mask)) {
00721 i++;
00722 if (i == -j) {
00723 add_mode(chan, '-', 'I', inv->mask);
00724 dprintf(idx, "%s '%s' on %s.\n", IRC_REMOVEDINVITE,
00725 inv->mask, chan->dname);
00726 putlog(LOG_CMDS, "*", "#%s# (%s) -invite %s [on channel]",
00727 dcc[idx].nick, dcc[idx].u.chat->con_chan, invite);
00728 return;
00729 }
00730 }
00731 }
00732 } else {
00733 j = u_delinvite(chan, invite, 1);
00734 if (j > 0) {
00735 putlog(LOG_CMDS, "*", "#%s# (%s) -invite %s", dcc[idx].nick,
00736 dcc[idx].u.chat->con_chan, invite);
00737 dprintf(idx, "Removed %s channel invite: %s\n", chname, invite);
00738 add_mode(chan, '-', 'I', invite);
00739 return;
00740 }
00741 for (inv = chan->channel.invite; inv && inv->mask && inv->mask[0];
00742 inv = inv->next) {
00743 if (!rfc_casecmp(inv->mask, invite)) {
00744 add_mode(chan, '-', 'I', inv->mask);
00745 dprintf(idx, "%s '%s' on %s.\n",
00746 IRC_REMOVEDINVITE, inv->mask, chan->dname);
00747 putlog(LOG_CMDS, "*", "#%s# (%s) -invite %s [on channel]",
00748 dcc[idx].nick, dcc[idx].u.chat->con_chan, invite);
00749 return;
00750 }
00751 }
00752 }
00753 dprintf(idx, "No such invite.\n");
00754 }
00755
00756 static void cmd_bans(struct userrec *u, int idx, char *par)
00757 {
00758 if (!egg_strcasecmp(par, "all")) {
00759 putlog(LOG_CMDS, "*", "#%s# bans all", dcc[idx].nick);
00760 tell_bans(idx, 1, "");
00761 } else {
00762 putlog(LOG_CMDS, "*", "#%s# bans %s", dcc[idx].nick, par);
00763 tell_bans(idx, 0, par);
00764 }
00765 }
00766
00767 static void cmd_exempts(struct userrec *u, int idx, char *par)
00768 {
00769 if (!use_exempts) {
00770 dprintf(idx, "This command can only be used with use-exempts enabled.\n");
00771 return;
00772 }
00773 if (!egg_strcasecmp(par, "all")) {
00774 putlog(LOG_CMDS, "*", "#%s# exempts all", dcc[idx].nick);
00775 tell_exempts(idx, 1, "");
00776 } else {
00777 putlog(LOG_CMDS, "*", "#%s# exempts %s", dcc[idx].nick, par);
00778 tell_exempts(idx, 0, par);
00779 }
00780 }
00781
00782 static void cmd_invites(struct userrec *u, int idx, char *par)
00783 {
00784 if (!use_invites) {
00785 dprintf(idx, "This command can only be used with use-invites enabled.\n");
00786 return;
00787 }
00788 if (!egg_strcasecmp(par, "all")) {
00789 putlog(LOG_CMDS, "*", "#%s# invites all", dcc[idx].nick);
00790 tell_invites(idx, 1, "");
00791 } else {
00792 putlog(LOG_CMDS, "*", "#%s# invites %s", dcc[idx].nick, par);
00793 tell_invites(idx, 0, par);
00794 }
00795 }
00796
00797 static void cmd_info(struct userrec *u, int idx, char *par)
00798 {
00799 char s[512], *chname, *s1;
00800 int locked = 0;
00801
00802 if (!use_info) {
00803 dprintf(idx, "Info storage is turned off.\n");
00804 return;
00805 }
00806 s1 = get_user(&USERENTRY_INFO, u);
00807 if (s1 && s1[0] == '@')
00808 locked = 1;
00809 if (par[0] && strchr(CHANMETA, par[0])) {
00810 chname = newsplit(&par);
00811 if (!findchan_by_dname(chname)) {
00812 dprintf(idx, "No such channel.\n");
00813 return;
00814 }
00815 get_handle_chaninfo(dcc[idx].nick, chname, s);
00816 if (s[0] == '@')
00817 locked = 1;
00818 s1 = s;
00819 } else
00820 chname = 0;
00821 if (!par[0]) {
00822 if (s1 && s1[0] == '@')
00823 s1++;
00824 if (s1 && s1[0]) {
00825 if (chname) {
00826 dprintf(idx, "Info on %s: %s\n", chname, s1);
00827 dprintf(idx, "Use '.info %s none' to remove it.\n", chname);
00828 } else {
00829 dprintf(idx, "Default info: %s\n", s1);
00830 dprintf(idx, "Use '.info none' to remove it.\n");
00831 }
00832 } else
00833 dprintf(idx, "No info has been set for you.\n");
00834 putlog(LOG_CMDS, "*", "#%s# info %s", dcc[idx].nick, chname ? chname : "");
00835 return;
00836 }
00837 if (locked && !(u && (u->flags & USER_MASTER))) {
00838 dprintf(idx, "Your info line is locked. Sorry.\n");
00839 return;
00840 }
00841 if (!egg_strcasecmp(par, "none")) {
00842 if (chname) {
00843 par[0] = 0;
00844 set_handle_chaninfo(userlist, dcc[idx].nick, chname, NULL);
00845 dprintf(idx, "Removed your info line on %s.\n", chname);
00846 putlog(LOG_CMDS, "*", "#%s# info %s none", dcc[idx].nick, chname);
00847 } else {
00848 set_user(&USERENTRY_INFO, u, NULL);
00849 dprintf(idx, "Removed your default info line.\n");
00850 putlog(LOG_CMDS, "*", "#%s# info none", dcc[idx].nick);
00851 }
00852 return;
00853 }
00854
00855
00856 if (chname) {
00857 set_handle_chaninfo(userlist, dcc[idx].nick, chname, par);
00858 dprintf(idx, "Your info on %s is now: %s\n", chname, par);
00859 putlog(LOG_CMDS, "*", "#%s# info %s ...", dcc[idx].nick, chname);
00860 } else {
00861 set_user(&USERENTRY_INFO, u, par);
00862 dprintf(idx, "Your default info is now: %s\n", par);
00863 putlog(LOG_CMDS, "*", "#%s# info ...", dcc[idx].nick);
00864 }
00865 }
00866
00867 static void cmd_chinfo(struct userrec *u, int idx, char *par)
00868 {
00869 char *handle, *chname;
00870 struct userrec *u1;
00871
00872 if (!use_info) {
00873 dprintf(idx, "Info storage is turned off.\n");
00874 return;
00875 }
00876 handle = newsplit(&par);
00877 if (!handle[0]) {
00878 dprintf(idx, "Usage: chinfo <handle> [channel] <new-info>\n");
00879 return;
00880 }
00881 u1 = get_user_by_handle(userlist, handle);
00882 if (!u1) {
00883 dprintf(idx, "No such user.\n");
00884 return;
00885 }
00886 if (par[0] && strchr(CHANMETA, par[0])) {
00887 chname = newsplit(&par);
00888 if (!findchan_by_dname(chname)) {
00889 dprintf(idx, "No such channel.\n");
00890 return;
00891 }
00892 } else
00893 chname = 0;
00894 if ((u1->flags & USER_BOT) && !(u->flags & USER_MASTER)) {
00895 dprintf(idx, "You have to be master to change bots info.\n");
00896 return;
00897 }
00898 if ((u1->flags & USER_OWNER) && !(u->flags & USER_OWNER)) {
00899 dprintf(idx, "You can't change info for the bot owner.\n");
00900 return;
00901 }
00902 if (chname) {
00903 get_user_flagrec(u, &user, chname);
00904 get_user_flagrec(u1, &victim, chname);
00905 if ((chan_owner(victim) || glob_owner(victim)) &&
00906 !(glob_owner(user) || chan_owner(user))) {
00907 dprintf(idx, "You can't change info for the channel owner.\n");
00908 return;
00909 }
00910 }
00911 putlog(LOG_CMDS, "*", "#%s# chinfo %s %s %s", dcc[idx].nick, handle,
00912 chname ? chname : par, chname ? par : "");
00913 if (!egg_strcasecmp(par, "none"))
00914 par[0] = 0;
00915 if (chname) {
00916 set_handle_chaninfo(userlist, handle, chname, par);
00917 if (par[0] == '@')
00918 dprintf(idx, "New info (LOCKED) for %s on %s: %s\n", handle, chname,
00919 &par[1]);
00920 else if (par[0])
00921 dprintf(idx, "New info for %s on %s: %s\n", handle, chname, par);
00922 else
00923 dprintf(idx, "Wiped info for %s on %s\n", handle, chname);
00924 } else {
00925 set_user(&USERENTRY_INFO, u1, par[0] ? par : NULL);
00926 if (par[0] == '@')
00927 dprintf(idx, "New default info (LOCKED) for %s: %s\n", handle, &par[1]);
00928 else if (par[0])
00929 dprintf(idx, "New default info for %s: %s\n", handle, par);
00930 else
00931 dprintf(idx, "Wiped default info for %s\n", handle);
00932 }
00933 }
00934
00935 static void cmd_stick_yn(int idx, char *par, int yn)
00936 {
00937 int i = 0, j;
00938 struct chanset_t *chan, *achan;
00939 char *stick_type, s[UHOSTLEN], chname[81];
00940 module_entry *me;
00941
00942 stick_type = newsplit(&par);
00943 strncpyz(s, newsplit(&par), sizeof s);
00944 strncpyz(chname, newsplit(&par), sizeof chname);
00945
00946 if (egg_strcasecmp(stick_type, "exempt") &&
00947 egg_strcasecmp(stick_type, "invite") &&
00948 egg_strcasecmp(stick_type, "ban")) {
00949 strncpyz(chname, s, sizeof chname);
00950 strncpyz(s, stick_type, sizeof s);
00951 }
00952 if (!s[0]) {
00953 dprintf(idx, "Usage: %sstick [ban/exempt/invite] <hostmask or number> "
00954 "[channel]\n", yn ? "" : "un");
00955 return;
00956 }
00957
00958 if (!egg_strcasecmp(stick_type, "exempt")) {
00959 if (!use_exempts) {
00960 dprintf(idx, "This command can only be used with use-exempts "
00961 "enabled.\n");
00962 return;
00963 }
00964 if (!chname[0]) {
00965 i = u_setsticky_exempt(NULL, s,
00966 (dcc[idx].user->flags & USER_OP) ? yn : -1);
00967 if (i > 0) {
00968 putlog(LOG_CMDS, "*", "#%s# %sstick exempt %s",
00969 dcc[idx].nick, yn ? "" : "un", s);
00970 dprintf(idx, "%stuck exempt: %s\n", yn ? "S" : "Uns", s);
00971 return;
00972 }
00973 strncpyz(chname, dcc[idx].u.chat->con_chan, sizeof chname);
00974 }
00975
00976 if (!(chan = findchan_by_dname(chname))) {
00977 dprintf(idx, "No such channel.\n");
00978 return;
00979 }
00980 if (str_isdigit(s)) {
00981
00982 j = u_setsticky_exempt(NULL, s, -1);
00983 if (j < 0)
00984 egg_snprintf(s, sizeof s, "%d", -j);
00985 }
00986 j = u_setsticky_exempt(chan, s, yn);
00987 if (j > 0) {
00988 putlog(LOG_CMDS, "*", "#%s# %sstick exempt %s %s", dcc[idx].nick,
00989 yn ? "" : "un", s, chname);
00990 dprintf(idx, "%stuck %s exempt: %s\n", yn ? "S" : "Uns", chname, s);
00991 return;
00992 }
00993 dprintf(idx, "No such exempt.\n");
00994 return;
00995 }
00996
00997 else if (!egg_strcasecmp(stick_type, "invite")) {
00998 if (!use_invites) {
00999 dprintf(idx, "This command can only be used with use-invites enabled.\n");
01000 return;
01001 }
01002 if (!chname[0]) {
01003 i = u_setsticky_invite(NULL, s,
01004 (dcc[idx].user->flags & USER_OP) ? yn : -1);
01005 if (i > 0) {
01006 putlog(LOG_CMDS, "*", "#%s# %sstick invite %s",
01007 dcc[idx].nick, yn ? "" : "un", s);
01008 dprintf(idx, "%stuck invite: %s\n", yn ? "S" : "Uns", s);
01009 return;
01010 }
01011 strncpyz(chname, dcc[idx].u.chat->con_chan, sizeof chname);
01012 }
01013
01014 if (!(chan = findchan_by_dname(chname))) {
01015 dprintf(idx, "No such channel.\n");
01016 return;
01017 }
01018 if (str_isdigit(s)) {
01019
01020 j = u_setsticky_invite(NULL, s, -1);
01021 if (j < 0)
01022 egg_snprintf(s, sizeof s, "%d", -j);
01023 }
01024 j = u_setsticky_invite(chan, s, yn);
01025 if (j > 0) {
01026 putlog(LOG_CMDS, "*", "#%s# %sstick invite %s %s", dcc[idx].nick,
01027 yn ? "" : "un", s, chname);
01028 dprintf(idx, "%stuck %s invite: %s\n", yn ? "S" : "Uns", chname, s);
01029 return;
01030 }
01031 dprintf(idx, "No such invite.\n");
01032 return;
01033 }
01034 if (!chname[0]) {
01035 i = u_setsticky_ban(NULL, s,
01036 (dcc[idx].user->flags & USER_OP) ? yn : -1);
01037 if (i > 0) {
01038 putlog(LOG_CMDS, "*", "#%s# %sstick ban %s",
01039 dcc[idx].nick, yn ? "" : "un", s);
01040 dprintf(idx, "%stuck ban: %s\n", yn ? "S" : "Uns", s);
01041 if ((me = module_find("irc", 0, 0)))
01042 for (achan = chanset; achan != NULL; achan = achan->next)
01043 (me->funcs[IRC_CHECK_THIS_BAN]) (achan, s, yn);
01044 return;
01045 }
01046 strncpyz(chname, dcc[idx].u.chat->con_chan, sizeof chname);
01047 }
01048
01049 if (!(chan = findchan_by_dname(chname))) {
01050 dprintf(idx, "No such channel.\n");
01051 return;
01052 }
01053 if (str_isdigit(s)) {
01054
01055 j = u_setsticky_ban(NULL, s, -1);
01056 if (j < 0)
01057 egg_snprintf(s, sizeof s, "%d", -j);
01058 }
01059 j = u_setsticky_ban(chan, s, yn);
01060 if (j > 0) {
01061 putlog(LOG_CMDS, "*", "#%s# %sstick ban %s %s", dcc[idx].nick,
01062 yn ? "" : "un", s, chname);
01063 dprintf(idx, "%stuck %s ban: %s\n", yn ? "S" : "Uns", chname, s);
01064 if ((me = module_find("irc", 0, 0)))
01065 (me->funcs[IRC_CHECK_THIS_BAN]) (chan, s, yn);
01066 return;
01067 }
01068 dprintf(idx, "No such ban.\n");
01069 }
01070
01071
01072 static void cmd_stick(struct userrec *u, int idx, char *par)
01073 {
01074 cmd_stick_yn(idx, par, 1);
01075 }
01076
01077 static void cmd_unstick(struct userrec *u, int idx, char *par)
01078 {
01079 cmd_stick_yn(idx, par, 0);
01080 }
01081
01082 static void cmd_pls_chrec(struct userrec *u, int idx, char *par)
01083 {
01084 char *nick, *chn;
01085 struct chanset_t *chan;
01086 struct userrec *u1;
01087 struct chanuserrec *chanrec;
01088
01089 if (!par[0]) {
01090 dprintf(idx, "Usage: +chrec <user> [channel]\n");
01091 return;
01092 }
01093 nick = newsplit(&par);
01094 u1 = get_user_by_handle(userlist, nick);
01095 if (!u1) {
01096 dprintf(idx, "No such user.\n");
01097 return;
01098 }
01099 if (!par[0])
01100 chan = findchan_by_dname(dcc[idx].u.chat->con_chan);
01101 else {
01102 chn = newsplit(&par);
01103 chan = findchan_by_dname(chn);
01104 }
01105 if (!chan) {
01106 dprintf(idx, "No such channel.\n");
01107 return;
01108 }
01109 get_user_flagrec(u, &user, chan->dname);
01110 get_user_flagrec(u1, &victim, chan->dname);
01111 if ((!glob_master(user) && !chan_master(user)) ||
01112 (chan_owner(victim) && !chan_owner(user) && !glob_owner(user)) ||
01113 (glob_owner(victim) && !glob_owner(user))) {
01114 dprintf(idx, "You have no permission to do that.\n");
01115 return;
01116 }
01117 chanrec = get_chanrec(u1, chan->dname);
01118 if (chanrec) {
01119 dprintf(idx, "User %s already has a channel record for %s.\n",
01120 nick, chan->dname);
01121 return;
01122 }
01123 putlog(LOG_CMDS, "*", "#%s# +chrec %s %s", dcc[idx].nick, nick, chan->dname);
01124 add_chanrec(u1, chan->dname);
01125 dprintf(idx, "Added %s channel record for %s.\n", chan->dname, nick);
01126 }
01127
01128 static void cmd_mns_chrec(struct userrec *u, int idx, char *par)
01129 {
01130 char *nick, *chn = NULL;
01131 struct userrec *u1;
01132 struct chanuserrec *chanrec;
01133
01134 if (!par[0]) {
01135 dprintf(idx, "Usage: -chrec <user> [channel]\n");
01136 return;
01137 }
01138 nick = newsplit(&par);
01139 u1 = get_user_by_handle(userlist, nick);
01140 if (!u1) {
01141 dprintf(idx, "No such user.\n");
01142 return;
01143 }
01144 if (!par[0]) {
01145 struct chanset_t *chan;
01146
01147 chan = findchan_by_dname(dcc[idx].u.chat->con_chan);
01148 if (chan)
01149 chn = chan->dname;
01150 else {
01151 dprintf(idx, "Invalid console channel.\n");
01152 return;
01153 }
01154 } else
01155 chn = newsplit(&par);
01156 get_user_flagrec(u, &user, chn);
01157 get_user_flagrec(u1, &victim, chn);
01158 if ((!glob_master(user) && !chan_master(user)) ||
01159 (chan_owner(victim) && !chan_owner(user) && !glob_owner(user)) ||
01160 (glob_owner(victim) && !glob_owner(user))) {
01161 dprintf(idx, "You have no permission to do that.\n");
01162 return;
01163 }
01164 chanrec = get_chanrec(u1, chn);
01165 if (!chanrec) {
01166 dprintf(idx, "User %s doesn't have a channel record for %s.\n", nick, chn);
01167 return;
01168 }
01169 putlog(LOG_CMDS, "*", "#%s# -chrec %s %s", dcc[idx].nick, nick, chn);
01170 del_chanrec(u1, chn);
01171 dprintf(idx, "Removed %s channel record from %s.\n", chn, nick);
01172 }
01173
01174 static void cmd_pls_chan(struct userrec *u, int idx, char *par)
01175 {
01176 int i, argc;
01177 EGG_CONST char **argv;
01178 char *chname;
01179 struct chanset_t *chan;
01180
01181 if (!par[0]) {
01182 dprintf(idx, "Usage: +chan [%s]<channel> [options]\n", CHANMETA);
01183 return;
01184 }
01185
01186 chname = newsplit(&par);
01187 if (findchan_by_dname(chname)) {
01188 dprintf(idx, "That channel already exists!\n");
01189 return;
01190 } else if ((chan = findchan(chname))) {
01191 dprintf(idx, "That channel already exists as %s!\n", chan->dname);
01192 return;
01193 } else if (strchr(CHANMETA, chname[0]) == NULL) {
01194 dprintf(idx, "Invalid channel prefix.\n");
01195 return;
01196 } else if (strchr(chname, ',') != NULL) {
01197 dprintf(idx, "Invalid channel name.\n");
01198 return;
01199 }
01200
01201 if (Tcl_SplitList(NULL, par, &argc, &argv ) == TCL_ERROR) {
01202 dprintf(idx, "Invalid channel options.\n");
01203 return;
01204 }
01205 for (i = 0; i < argc; i++) {
01206 if ((!strncmp(argv[i], "need-", 5) || !strcmp(argv[i] + 1, "static"))
01207 && (!(u->flags & USER_OWNER) || (!isowner(dcc[idx].nick)
01208 && must_be_owner))) {
01209 dprintf(idx, "Due to security concerns, only permanent owners can "
01210 "set the need-* and +/-static modes.\n");
01211 Tcl_Free((char *) argv);
01212 return;
01213 }
01214 if (argv[i][0] == '-' || argv[i][0] == '+')
01215 continue;
01216 i++;
01217 }
01218 Tcl_Free((char *) argv);
01219
01220 if (tcl_channel_add(0, chname, par) == TCL_ERROR)
01221 dprintf(idx, "Invalid channel or channel options.\n");
01222 else
01223 putlog(LOG_CMDS, "*", "#%s# +chan %s", dcc[idx].nick, chname);
01224 }
01225
01226 static void cmd_mns_chan(struct userrec *u, int idx, char *par)
01227 {
01228 char *chname;
01229 struct chanset_t *chan;
01230 int i;
01231
01232 if (!par[0]) {
01233 dprintf(idx, "Usage: -chan [%s]<channel>\n", CHANMETA);
01234 return;
01235 }
01236 chname = newsplit(&par);
01237 chan = findchan_by_dname(chname);
01238 if (!chan) {
01239 if ((chan = findchan(chname)))
01240 dprintf(idx, "That channel exists with a short name of %s, use that.\n",
01241 chan->dname);
01242 else
01243 dprintf(idx, "That channel doesn't exist!\n");
01244 return;
01245 }
01246 if (channel_static(chan)) {
01247 dprintf(idx, "Cannot remove %s, it is a static channel!\n", chname);
01248 return;
01249 }
01250
01251 for (i = 0; i < dcc_total; i++)
01252 if ((dcc[i].type->flags & DCT_CHAT) &&
01253 !rfc_casecmp(dcc[i].u.chat->con_chan, chan->dname)) {
01254 dprintf(i, "%s is no longer a valid channel, changing your console "
01255 "to '*'\n", chname);
01256 strcpy(dcc[i].u.chat->con_chan, "*");
01257 }
01258 remove_channel(chan);
01259 dprintf(idx, "Channel %s removed from the bot.\n", chname);
01260 dprintf(idx, "This includes any channel specific bans, invites, exemptions "
01261 "and user records that you set.\n");
01262 putlog(LOG_CMDS, "*", "#%s# -chan %s", dcc[idx].nick, chname);
01263 }
01264
01265 static void cmd_chaninfo(struct userrec *u, int idx, char *par)
01266 {
01267 char *chname, work[512];
01268 struct chanset_t *chan;
01269 int ii, tmp;
01270 struct udef_struct *ul;
01271
01272 if (!par[0]) {
01273 chname = dcc[idx].u.chat->con_chan;
01274 if (chname[0] == '*') {
01275 dprintf(idx, "Your console channel is invalid.\n");
01276 return;
01277 }
01278 } else {
01279 chname = newsplit(&par);
01280 get_user_flagrec(u, &user, chname);
01281 if (!glob_master(user) && !chan_master(user)) {
01282 dprintf(idx, "You don't have access to %s.\n", chname);
01283 return;
01284 }
01285 }
01286 if (!(chan = findchan_by_dname(chname)))
01287 dprintf(idx, "No such channel defined.\n");
01288 else {
01289 dprintf(idx, "Settings for %s channel %s:\n",
01290 channel_static(chan) ? "static" : "dynamic", chan->dname);
01291 get_mode_protect(chan, work);
01292 dprintf(idx, "Protect modes (chanmode): %s\n", work[0] ? work : "None");
01293 if (chan->idle_kick)
01294 dprintf(idx, "Idle Kick after (idle-kick): %d\n", chan->idle_kick);
01295 else
01296 dprintf(idx, "Idle Kick after (idle-kick): DON'T!\n");
01297 if (chan->stopnethack_mode)
01298 dprintf(idx, "stopnethack-mode: %d\n", chan->stopnethack_mode);
01299 else
01300 dprintf(idx, "stopnethack: DON'T!\n");
01301 dprintf(idx, "aop-delay: %d:%d\n", chan->aop_min, chan->aop_max);
01302 if (chan->revenge_mode)
01303 dprintf(idx, "revenge-mode: %d\n", chan->revenge_mode);
01304 else
01305 dprintf(idx, "revenge-mode: 0\n");
01306 dprintf(idx, "ban-type: %d\n", chan->ban_type);
01307 if (chan->ban_time)
01308 dprintf(idx, "ban-time: %d\n", chan->ban_time);
01309 else
01310 dprintf(idx, "ban-time: 0\n");
01311 if (chan->exempt_time)
01312 dprintf(idx, "exempt-time: %d\n", chan->exempt_time);
01313 else
01314 dprintf(idx, "exempt-time: 0\n");
01315 if (chan->invite_time)
01316 dprintf(idx, "invite-time: %d\n", chan->invite_time);
01317 else
01318 dprintf(idx, "invite-time: 0\n");
01319
01320 if (u->flags & USER_OWNER) {
01321 if (chan->need_op[0])
01322 dprintf(idx, "To regain op's (need-op):\n%s\n", chan->need_op);
01323 if (chan->need_invite[0])
01324 dprintf(idx, "To get invite (need-invite):\n%s\n", chan->need_invite);
01325 if (chan->need_key[0])
01326 dprintf(idx, "To get key (need-key):\n%s\n", chan->need_key);
01327 if (chan->need_unban[0])
01328 dprintf(idx, "If I'm banned (need-unban):\n%s\n", chan->need_unban);
01329 if (chan->need_limit[0])
01330 dprintf(idx, "When channel full (need-limit):\n%s\n",
01331 chan->need_limit);
01332 }
01333 dprintf(idx, "Other modes:\n");
01334 dprintf(idx,
01335 " %cinactive %cstatuslog %csecret "
01336 "%cshared\n", (chan->status & CHAN_INACTIVE) ? '+' : '-',
01337 (chan->status & CHAN_LOGSTATUS) ? '+' : '-',
01338 (chan->status & CHAN_SECRET) ? '+' : '-',
01339 (chan->status & CHAN_SHARED) ? '+' : '-');
01340 dprintf(idx,
01341 " %cgreet %cseen %ccycle "
01342 "%cdontkickops\n", (chan->status & CHAN_GREET) ? '+' : '-',
01343 (chan->status & CHAN_SEEN) ? '+' : '-',
01344 (chan->status & CHAN_CYCLE) ? '+' : '-',
01345 (chan->status & CHAN_DONTKICKOPS) ? '+' : '-');
01346 dprintf(idx,
01347 " %cprotectops %cprotectfriends %crevenge "
01348 "%crevengebot\n", (chan->status & CHAN_PROTECTOPS) ? '+' : '-',
01349 (chan->status & CHAN_PROTECTFRIENDS) ? '+' : '-',
01350 (chan->status & CHAN_REVENGE) ? '+' : '-',
01351 (chan->status & CHAN_REVENGEBOT) ? '+' : '-');
01352 dprintf(idx,
01353 " %cbitch %cautoop %cautovoice "
01354 "%cnodesynch\n", (chan->status & CHAN_BITCH) ? '+' : '-',
01355 (chan->status & CHAN_OPONJOIN) ? '+' : '-',
01356 (chan->status & CHAN_AUTOVOICE) ? '+' : '-',
01357 (chan->status & CHAN_NODESYNCH) ? '+' : '-');
01358 dprintf(idx,
01359 " %cenforcebans %cdynamicbans %cuserbans "
01360 "%cautohalfop\n", (chan->status & CHAN_ENFORCEBANS) ? '+' : '-',
01361 (chan->status & CHAN_DYNAMICBANS) ? '+' : '-',
01362 (chan->status & CHAN_NOUSERBANS) ? '-' : '+',
01363 (chan->status & CHAN_AUTOHALFOP) ? '+' : '-');
01364 dprintf(idx, " %cprotecthalfops %cstatic\n",
01365 (chan->status & CHAN_PROTECTHALFOPS) ? '+' : '-',
01366 (chan->status & CHAN_STATIC) ? '+' : '-');
01367 dprintf(idx,
01368 " %cdynamicexempts %cuserexempts %cdynamicinvites "
01369 "%cuserinvites\n",
01370 (chan->ircnet_status & CHAN_DYNAMICEXEMPTS) ? '+' : '-',
01371 (chan->ircnet_status & CHAN_NOUSEREXEMPTS) ? '-' : '+',
01372 (chan->ircnet_status & CHAN_DYNAMICINVITES) ? '+' : '-',
01373 (chan->ircnet_status & CHAN_NOUSERINVITES) ? '-' : '+');
01374
01375 ii = 1;
01376 tmp = 0;
01377 for (ul = udef; ul; ul = ul->next)
01378 if (ul->defined && ul->type == UDEF_FLAG) {
01379 int work_len;
01380
01381 if (!tmp) {
01382 dprintf(idx, "User defined channel flags:\n");
01383 tmp = 1;
01384 }
01385 if (ii == 1)
01386 egg_snprintf(work, sizeof work, " ");
01387 work_len = strlen(work);
01388 egg_snprintf(work + work_len, sizeof(work) - work_len, " %c%s",
01389 getudef(ul->values, chan->dname) ? '+' : '-', ul->name);
01390 ii++;
01391 if (ii > 4) {
01392 dprintf(idx, "%s\n", work);
01393 ii = 1;
01394 }
01395 }
01396 if (ii > 1)
01397 dprintf(idx, "%s\n", work);
01398
01399 work[0] = 0;
01400 ii = 1;
01401 tmp = 0;
01402 for (ul = udef; ul; ul = ul->next)
01403 if (ul->defined && ul->type == UDEF_INT) {
01404 int work_len = strlen(work);
01405
01406 if (!tmp) {
01407 dprintf(idx, "User defined channel settings:\n");
01408 tmp = 1;
01409 }
01410 egg_snprintf(work + work_len, sizeof(work) - work_len, "%s: %d ",
01411 ul->name, getudef(ul->values, chan->dname));
01412 ii++;
01413 if (ii > 4) {
01414 dprintf(idx, "%s\n", work);
01415 work[0] = 0;
01416 ii = 1;
01417 }
01418 }
01419 if (ii > 1)
01420 dprintf(idx, "%s\n", work);
01421
01422 if (u->flags & USER_OWNER) {
01423 tmp = 0;
01424
01425 for (ul = udef; ul; ul = ul->next) {
01426 if (ul->defined && ul->type == UDEF_STR) {
01427 char *p = (char *) getudef(ul->values, chan->dname);
01428
01429 if (!p)
01430 p = "{}";
01431
01432 if (!tmp) {
01433 dprintf(idx, "User defined channel strings:\n");
01434 tmp = 1;
01435 }
01436 dprintf(idx, "%s: %s\n", ul->name, p);
01437 }
01438 }
01439 }
01440
01441
01442 dprintf(idx, "flood settings: chan ctcp join kick deop nick\n");
01443 dprintf(idx, "number: %3d %3d %3d %3d %3d %3d\n",
01444 chan->flood_pub_thr, chan->flood_ctcp_thr,
01445 chan->flood_join_thr, chan->flood_kick_thr,
01446 chan->flood_deop_thr, chan->flood_nick_thr);
01447 dprintf(idx, "time : %3d %3d %3d %3d %3d %3d\n",
01448 chan->flood_pub_time, chan->flood_ctcp_time,
01449 chan->flood_join_time, chan->flood_kick_time,
01450 chan->flood_deop_time, chan->flood_nick_time);
01451 putlog(LOG_CMDS, "*", "#%s# chaninfo %s", dcc[idx].nick, chname);
01452 }
01453 }
01454
01455 static void cmd_chanset(struct userrec *u, int idx, char *par)
01456 {
01457 char *chname = NULL, answers[512], *parcpy;
01458 char *list[2], *bak, *buf;
01459 struct chanset_t *chan = NULL;
01460 int all = 0;
01461
01462 if (!par[0])
01463 dprintf(idx, "Usage: chanset [%schannel] <settings>\n", CHANMETA);
01464 else {
01465 if (strlen(par) > 2 && par[0] == '*' && par[1] == ' ') {
01466 all = 1;
01467 get_user_flagrec(u, &user, chanset ? chanset->dname : "");
01468 if (!glob_master(user)) {
01469 dprintf(idx, "You need to be a global master to use .chanset *.\n");
01470 return;
01471 }
01472 newsplit(&par);
01473 } else {
01474 if (strchr(CHANMETA, par[0])) {
01475 chname = newsplit(&par);
01476 get_user_flagrec(u, &user, chname);
01477 if (!glob_master(user) && !chan_master(user)) {
01478 dprintf(idx, "You don't have access to %s. \n", chname);
01479 return;
01480 } else if (!(chan = findchan_by_dname(chname)) && (chname[0] != '+')) {
01481 dprintf(idx, "That channel doesn't exist!\n");
01482 return;
01483 }
01484 if (!chan) {
01485 if (par[0])
01486 *--par = ' ';
01487 par = chname;
01488 }
01489 }
01490 if (!par[0] || par[0] == '*') {
01491 dprintf(idx, "Usage: chanset [%schannel] <settings>\n", CHANMETA);
01492 return;
01493 }
01494 if (!chan &&
01495 !(chan = findchan_by_dname(chname = dcc[idx].u.chat->con_chan))) {
01496 dprintf(idx, "Invalid console channel.\n");
01497 return;
01498 }
01499 }
01500 if (all)
01501 chan = chanset;
01502 bak = par;
01503 buf = nmalloc(strlen(par) + 1);
01504 while (chan) {
01505 chname = chan->dname;
01506 strcpy(buf, bak);
01507 par = buf;
01508 list[0] = newsplit(&par);
01509 answers[0] = 0;
01510 while (list[0][0]) {
01511 if (list[0][0] == '+' || list[0][0] == '-' ||
01512 (!strcmp(list[0], "dont-idle-kick"))) {
01513 if (!strcmp(list[0] + 1, "static") && must_be_owner &&
01514 !(isowner(dcc[idx].nick))) {
01515 dprintf(idx, "Only permanent owners can modify the static flag.\n");
01516 nfree(buf);
01517 return;
01518 }
01519 if (tcl_channel_modify(0, chan, 1, list) == TCL_OK) {
01520 strcat(answers, list[0]);
01521 strcat(answers, " ");
01522 } else if (!all || !chan->next)
01523 dprintf(idx, "Error trying to set %s for %s, invalid mode.\n",
01524 list[0], all ? "all channels" : chname);
01525 list[0] = newsplit(&par);
01526 continue;
01527 }
01528
01529
01530
01531
01532 if (strncmp(list[0], "need-", 5) || (u->flags & USER_OWNER)) {
01533 if (!strncmp(list[0], "need-", 5) && !(isowner(dcc[idx].nick)) &&
01534 must_be_owner) {
01535 dprintf(idx, "Due to security concerns, only permanent owners can set these modes.\n");
01536 nfree(buf);
01537 return;
01538 }
01539 list[1] = par;
01540
01541
01542
01543 parcpy = nmalloc(strlen(par) + 1);
01544 strcpy(parcpy, par);
01545 if (tcl_channel_modify(0, chan, 2, list) == TCL_OK) {
01546 strcat(answers, list[0]);
01547 strcat(answers, " { ");
01548 strcat(answers, parcpy);
01549 strcat(answers, " }");
01550 } else if (!all || !chan->next)
01551 dprintf(idx, "Error trying to set %s for %s, invalid option\n",
01552 list[0], all ? "all channels" : chname);
01553 nfree(parcpy);
01554 }
01555 break;
01556 }
01557 if (!all && answers[0]) {
01558 dprintf(idx, "Successfully set modes { %s } on %s.\n", answers,
01559 chname);
01560 putlog(LOG_CMDS, "*", "#%s# chanset %s %s", dcc[idx].nick, chname,
01561 answers);
01562 }
01563 if (!all)
01564 chan = NULL;
01565 else
01566 chan = chan->next;
01567 }
01568 if (all && answers[0]) {
01569 dprintf(idx, "Successfully set modes { %s } on all channels.\n",
01570 answers);
01571 putlog(LOG_CMDS, "*", "#%s# chanset * %s", dcc[idx].nick, answers);
01572 }
01573 nfree(buf);
01574 }
01575 }
01576
01577 static void cmd_chansave(struct userrec *u, int idx, char *par)
01578 {
01579 if (!chanfile[0])
01580 dprintf(idx, "No channel saving file defined.\n");
01581 else {
01582 dprintf(idx, "Saving all dynamic channel settings.\n");
01583 putlog(LOG_CMDS, "*", "#%s# chansave", dcc[idx].nick);
01584 write_channels();
01585 }
01586 }
01587
01588 static void cmd_chanload(struct userrec *u, int idx, char *par)
01589 {
01590 if (!chanfile[0])
01591 dprintf(idx, "No channel saving file defined.\n");
01592 else {
01593 dprintf(idx, "Reloading all dynamic channel settings.\n");
01594 putlog(LOG_CMDS, "*", "#%s# chanload", dcc[idx].nick);
01595 read_channels(1, 1);
01596 }
01597 }
01598
01599
01600
01601
01602
01603
01604
01605
01606 static cmd_t C_dcc_irc[] = {
01607 {"+ban", "ol|ol", (IntFunc) cmd_pls_ban, NULL},
01608 {"+exempt", "ol|ol", (IntFunc) cmd_pls_exempt, NULL},
01609 {"+invite", "ol|ol", (IntFunc) cmd_pls_invite, NULL},
01610 {"+chan", "n", (IntFunc) cmd_pls_chan, NULL},
01611 {"+chrec", "m|m", (IntFunc) cmd_pls_chrec, NULL},
01612 {"-ban", "ol|ol", (IntFunc) cmd_mns_ban, NULL},
01613 {"-chan", "n", (IntFunc) cmd_mns_chan, NULL},
01614 {"-chrec", "m|m", (IntFunc) cmd_mns_chrec, NULL},
01615 {"bans", "ol|ol", (IntFunc) cmd_bans, NULL},
01616 {"-exempt", "ol|ol", (IntFunc) cmd_mns_exempt, NULL},
01617 {"-invite", "ol|ol", (IntFunc) cmd_mns_invite, NULL},
01618 {"exempts", "ol|ol", (IntFunc) cmd_exempts, NULL},
01619 {"invites", "ol|ol", (IntFunc) cmd_invites, NULL},
01620 {"chaninfo", "m|m", (IntFunc) cmd_chaninfo, NULL},
01621 {"chanload", "n|n", (IntFunc) cmd_chanload, NULL},
01622 {"chanset", "n|n", (IntFunc) cmd_chanset, NULL},
01623 {"chansave", "n|n", (IntFunc) cmd_chansave, NULL},
01624 {"chinfo", "m|m", (IntFunc) cmd_chinfo, NULL},
01625 {"info", "", (IntFunc) cmd_info, NULL},
01626 {"stick", "ol|ol", (IntFunc) cmd_stick, NULL},
01627 {"unstick", "ol|ol", (IntFunc) cmd_unstick, NULL},
01628 {NULL, NULL, NULL, NULL}
01629 };