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
00027
00028
00029
00030
00031 #include <ctype.h>
00032
00033 static struct flag_record user = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
00034 static struct flag_record victim = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
00035
00036
00037 static void cmd_pls_mask(char type, struct userrec *u, int idx, char *par)
00038 {
00039 char *chname, *who, s[UHOSTLEN], s1[UHOSTLEN], *p, *p_expire, *cmd;
00040 unsigned long int expire_time = 0, expire_foo;
00041 int sticky = 0;
00042 struct chanset_t *chan = NULL;
00043 module_entry *me;
00044
00045 cmd = type == 'b' ? "ban" : type == 'e' ? "exempt" : "invite";
00046 if (!par[0]) {
00047 dprintf(idx, "Usage: +%s <hostmask> [channel] [%%<XdXhXm>] [reason]\n", cmd);
00048 return;
00049 }
00050 who = newsplit(&par);
00051 if (par[0] && strchr(CHANMETA, par[0]))
00052 chname = newsplit(&par);
00053 else
00054 chname = 0;
00055 if (chname || !(u->flags & USER_MASTER)) {
00056 if (!chname)
00057 chname = dcc[idx].u.chat->con_chan;
00058 get_user_flagrec(u, &user, chname);
00059 chan = findchan_by_dname(chname);
00060
00061 if (!chan) {
00062 dprintf(idx, _("That channel doesn't exist!\n"));
00063 return;
00064 } else if (!glob_op(user) && !chan_op(user)) {
00065 dprintf(idx, _("You don't have access to set %ss on %s.\n"), cmd, chname);
00066 return;
00067 }
00068 } else
00069 chan = 0;
00070
00071 if (par[0] == '%') {
00072 p = newsplit(&par);
00073 p_expire = p + 1;
00074 while (*(++p) != 0) {
00075 switch (tolower(*p)) {
00076 case 'd':
00077 *p = 0;
00078 expire_foo = strtol(p_expire, NULL, 10);
00079 if (expire_foo > 365)
00080 expire_foo = 365;
00081 expire_time += 86400 * expire_foo;
00082 p_expire = p + 1;
00083 break;
00084 case 'h':
00085 *p = 0;
00086 expire_foo = strtol(p_expire, NULL, 10);
00087 if (expire_foo > 8760)
00088 expire_foo = 8760;
00089 expire_time += 3600 * expire_foo;
00090 p_expire = p + 1;
00091 break;
00092 case 'm':
00093 *p = 0;
00094 expire_foo = strtol(p_expire, NULL, 10);
00095 if (expire_foo > 525600)
00096 expire_foo = 525600;
00097 expire_time += 60 * expire_foo;
00098 p_expire = p + 1;
00099 }
00100 }
00101 }
00102 if (!par[0])
00103 par = "requested";
00104 else if (strlen(par) > MASKREASON_MAX)
00105 par[MASKREASON_MAX] = 0;
00106 if (strlen(who) > UHOSTMAX - 4)
00107 who[UHOSTMAX - 4] = 0;
00108
00109 if (!strchr(who, '!')) {
00110 if (!strchr(who, '@'))
00111 snprintf(s, sizeof s, "%s!*@*", who);
00112 else
00113 snprintf(s, sizeof s, "*!%s", who);
00114 } else if (!strchr(who, '@'))
00115 snprintf(s, sizeof s, "%s@*", who);
00116 else
00117 strlcpy(s, who, sizeof s);
00118 if ((me = module_find("server", 0, 0)) && me->funcs)
00119 snprintf(s1, sizeof s1, "%s!%s", (char *)(me->funcs[SERVER_BOTNAME]),
00120 (char *)(me->funcs[SERVER_BOTUSERHOST]));
00121 else
00122 s1[0] = 0;
00123 if (type == 'b' && s1[0] && wild_match(s, s1)) {
00124 dprintf(idx, _("I'm not going to ban myself.\n"));
00125 putlog(LOG_CMDS, "*", "#%s# attempted +ban %s", dcc[idx].nick, s);
00126 return;
00127 }
00128
00129 if (strlen(s) > 70) {
00130 s[69] = '*';
00131 s[70] = 0;
00132 }
00133 if (chan) {
00134 u_addmask(type, chan, s, dcc[idx].nick, par,
00135 expire_time ? now + expire_time : 0, 0);
00136 if (par[0] == '*') {
00137 sticky = 1;
00138 par++;
00139 putlog(LOG_CMDS, "*", "#%s# (%s) +%s %s %s (%s) (sticky)",
00140 dcc[idx].nick, dcc[idx].u.chat->con_chan, cmd, s, chan->dname, par);
00141 dprintf(idx, "New %s sticky %s: %s (%s)\n", chan->dname, cmd, s, par);
00142 } else {
00143 putlog(LOG_CMDS, "*", "#%s# (%s) +%s %s %s (%s)", dcc[idx].nick,
00144 dcc[idx].u.chat->con_chan, cmd, s, chan->dname, par);
00145 dprintf(idx, "New %s %s: %s (%s)\n", chan->dname, cmd, s, par);
00146 }
00147 if (type == 'e' || type == 'I') {
00148 add_mode(chan, '+', type, s);
00149
00150
00151
00152 } else if ((me = module_find("irc", 0, 0)))
00153 (me->funcs[IRC_CHECK_THIS_BAN])(chan, s, sticky);
00154 } else {
00155 u_addmask(type, NULL, s, dcc[idx].nick, par,
00156 expire_time ? now + expire_time : 0, 0);
00157 if (par[0] == '*') {
00158 sticky = 1;
00159 par++;
00160 putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +%s %s (%s) (sticky)",
00161 dcc[idx].nick, cmd, s, par);
00162 dprintf(idx, "New sticky %s: %s (%s)\n", cmd, s, par);
00163 } else {
00164 putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +%s %s (%s)", dcc[idx].nick,
00165 cmd, s, par);
00166 dprintf(idx, "New %s: %s (%s)\n", cmd, s, par);
00167 }
00168 if ((me = module_find("irc", 0, 0)))
00169 for (chan = chanset; chan != NULL; chan = chan->next) {
00170 if (type == 'b')
00171 (me->funcs[IRC_CHECK_THIS_BAN])(chan, s, sticky);
00172 else
00173 add_mode(chan, '+', type, s);
00174 }
00175 }
00176 }
00177
00178 static void cmd_pls_ban(struct userrec *u, int idx, char *par)
00179 {
00180 cmd_pls_mask('b', u, idx, par);
00181 }
00182
00183 static void cmd_pls_exempt(struct userrec *u, int idx, char *par)
00184 {
00185 if (!use_exempts) {
00186 dprintf(idx,
00187 _("This command can only be used with use-exempts enabled.\n"));
00188 return;
00189 }
00190 cmd_pls_mask('e', u, idx, par);
00191 }
00192
00193 static void cmd_pls_invite(struct userrec *u, int idx, char *par)
00194 {
00195 if (!use_invites) {
00196 dprintf(idx,
00197 _("This command can only be used with use-invites enabled.\n"));
00198 return;
00199 }
00200 cmd_pls_mask('I', u, idx, par);
00201 }
00202
00203 static void cmd_mns_mask(char type, struct userrec *u, int idx, char *par)
00204 {
00205 int i = 0, j;
00206 struct chanset_t *chan = NULL;
00207 char s[UHOSTLEN], *who, *chname, *cmd, *mask;
00208 masklist *m;
00209
00210 cmd = type == 'b' ? "ban" : type == 'e' ? "exempt" : "invite";
00211 if (!par[0]) {
00212 dprintf(idx, "Usage: -%s <hostmask> [channel]\n", cmd);
00213 return;
00214 }
00215 who = newsplit(&par);
00216 if (par[0] && strchr(CHANMETA, par[0]))
00217 chname = newsplit(&par);
00218 else
00219 chname = dcc[idx].u.chat->con_chan;
00220 if (chname || !(u->flags & USER_MASTER)) {
00221 if (!chname)
00222 chname = dcc[idx].u.chat->con_chan;
00223 get_user_flagrec(u, &user, chname);
00224 if (!glob_op(user) && !chan_op(user))
00225 return;
00226 }
00227 strlcpy(s, who, sizeof s);
00228 i = u_delmask(type, NULL, s, (u->flags & USER_MASTER));
00229 if (i > 0) {
00230 if (lastdeletedmask)
00231 mask = lastdeletedmask;
00232 else
00233 mask = s;
00234 putlog(LOG_CMDS, "*", "#%s# -%s %s", dcc[idx].nick, cmd, mask);
00235 dprintf(idx, "%s %s: %s\n", _("Removed"), cmd, s);
00236 for (chan = chanset; chan != NULL; chan = chan->next)
00237 add_mode(chan, '-', type, mask);
00238 return;
00239 }
00240
00241 if (chname)
00242 chan = findchan_by_dname(chname);
00243 if (chan) {
00244 m = type == 'b' ? chan->channel.ban :
00245 type == 'e' ? chan->channel.exempt : chan->channel.invite;
00246 if ((i = atoi(who)) > 0) {
00247 snprintf(s, sizeof s, "%d", i);
00248 j = u_delmask(type, chan, s, 1);
00249 if (j > 0) {
00250 if (lastdeletedmask)
00251 mask = lastdeletedmask;
00252 else
00253 mask = s;
00254 putlog(LOG_CMDS, "*", "#%s# (%s) -%s %s", dcc[idx].nick, chan->dname,
00255 cmd, mask);
00256 dprintf(idx, _("Removed %1$s channel %2$s: %3$s\n"), chan->dname, cmd,
00257 mask);
00258 add_mode(chan, '-', type, mask);
00259 return;
00260 }
00261 i = 0;
00262 for (; m && m->mask && m->mask[0]; m = m->next) {
00263 if ((!u_equals_mask(type == 'b' ? global_bans : type == 'e' ? global_exempts :
00264 global_invites, m->mask)) &&
00265 (!u_equals_mask(type == 'b' ? chan->bans : type == 'e' ? chan->exempts :
00266 chan->invites, m->mask))) {
00267 i++;
00268 if (i == -j) {
00269 add_mode(chan, '-', type, m->mask);
00270 dprintf(idx, "%s %s '%s' on %s.\n", _("Removed"), cmd,
00271 m->mask, chan->dname);
00272 putlog(LOG_CMDS, "*", "#%s# (%s) -%s %s [on channel]",
00273 dcc[idx].nick, dcc[idx].u.chat->con_chan, cmd, who);
00274 return;
00275 }
00276 }
00277 }
00278 } else {
00279 j = u_delmask(type, chan, who, 1);
00280 if (j > 0) {
00281 putlog(LOG_CMDS, "*", "#%s# (%s) -%s %s", dcc[idx].nick,
00282 dcc[idx].u.chat->con_chan, cmd, who);
00283 dprintf(idx, _("Removed %1$s channel %2$s: %3$s\n"), chname, cmd, who);
00284 add_mode(chan, '-', type, who);
00285 return;
00286 }
00287 for (; m && m->mask && m->mask[0]; m = m->next) {
00288 if (!irccmp(m->mask, who)) {
00289 add_mode(chan, '-', type, m->mask);
00290 dprintf(idx, "%s %s '%s' on %s.\n",
00291 _("Removed"), cmd, m->mask, chan->dname);
00292 putlog(LOG_CMDS, "*", "#%s# (%s) -%s %s [on channel]",
00293 dcc[idx].nick, dcc[idx].u.chat->con_chan, cmd, who);
00294 return;
00295 }
00296 }
00297 }
00298 }
00299 dprintf(idx, _("No such %1$s.\n"), cmd);
00300 }
00301
00302 static void cmd_mns_ban(struct userrec *u, int idx, char *par)
00303 {
00304 cmd_mns_mask('b', u, idx, par);
00305 }
00306
00307 static void cmd_mns_exempt(struct userrec *u, int idx, char *par)
00308 {
00309 if (!use_exempts) {
00310 dprintf(idx,
00311 _("This command can only be used with use-exempts enabled.\n"));
00312 return;
00313 }
00314 cmd_mns_mask('e', u, idx, par);
00315 }
00316
00317 static void cmd_mns_invite(struct userrec *u, int idx, char *par)
00318 {
00319 if (!use_invites) {
00320 dprintf(idx,
00321 _("This command can only be used with use-invites enabled.\n"));
00322 return;
00323 }
00324 cmd_mns_mask('I', u, idx, par);
00325 }
00326
00327 static void cmd_bans(struct userrec *u, int idx, char *par)
00328 {
00329 if (!strcasecmp(par, "all")) {
00330 putlog(LOG_CMDS, "*", "#%s# bans all", dcc[idx].nick);
00331 tell_bans(idx, 1, "");
00332 } else {
00333 putlog(LOG_CMDS, "*", "#%s# bans %s", dcc[idx].nick, par);
00334 tell_bans(idx, 0, par);
00335 }
00336 }
00337
00338 static void cmd_exempts (struct userrec *u, int idx, char *par)
00339 {
00340 if (!use_exempts) {
00341 dprintf(idx,
00342 _("This command can only be used with use-exempts enabled.\n"));
00343 return;
00344 }
00345 if (!strcasecmp(par, "all")) {
00346 putlog(LOG_CMDS, "*", "#%s# exempts all", dcc[idx].nick);
00347 tell_exempts(idx, 1, "");
00348 } else {
00349 putlog(LOG_CMDS, "*", "#%s# exempts %s", dcc[idx].nick, par);
00350 tell_exempts(idx, 0, par);
00351 }
00352 }
00353
00354 static void cmd_invites (struct userrec *u, int idx, char *par)
00355 {
00356 if (!use_invites) {
00357 dprintf(idx,
00358 _("This command can only be used with use-invites enabled.\n"));
00359 return;
00360 }
00361 if (!strcasecmp(par, "all")) {
00362 putlog(LOG_CMDS, "*", "#%s# invites all", dcc[idx].nick);
00363 tell_invites(idx, 1, "");
00364 } else {
00365 putlog(LOG_CMDS, "*", "#%s# invites %s", dcc[idx].nick, par);
00366 tell_invites(idx, 0, par);
00367 }
00368 }
00369
00370 static void cmd_info(struct userrec *u, int idx, char *par)
00371 {
00372 char s[512], *chname, *s1;
00373 int locked = 0;
00374
00375 if (!use_info) {
00376 dprintf(idx, _("Info storage is turned off.\n"));
00377 return;
00378 }
00379 s1 = get_user(&USERENTRY_INFO, u);
00380 if (s1 && s1[0] == '@')
00381 locked = 1;
00382 if (par[0] && strchr(CHANMETA, par[0])) {
00383 chname = newsplit(&par);
00384 if (!findchan_by_dname(chname)) {
00385 dprintf(idx, _("No such channel.\n"));
00386 return;
00387 }
00388 get_handle_chaninfo(dcc[idx].nick, chname, s);
00389 if (s[0] == '@')
00390 locked = 1;
00391 s1 = s;
00392 } else
00393 chname = 0;
00394 if (!par[0]) {
00395 if (s1 && s1[0] == '@')
00396 s1++;
00397 if (s1 && s1[0]) {
00398 if (chname) {
00399 dprintf(idx, "Info on %s: %s\n", chname, s1);
00400 dprintf(idx, _("Use '.info %s none' to remove it.\n"), chname);
00401 } else {
00402 dprintf(idx, _("Default info: %s\n"), s1);
00403 dprintf(idx, _("Use '.info none' to remove it.\n"));
00404 }
00405 } else
00406 dprintf(idx, _("No info has been set for you.\n"));
00407 putlog(LOG_CMDS, "*", "#%s# info %s", dcc[idx].nick, chname ? chname : "");
00408 return;
00409 }
00410 if (locked && !(u && (u->flags & USER_MASTER))) {
00411 dprintf(idx, _("Your info line is locked. Sorry.\n"));
00412 return;
00413 }
00414 if (!strcasecmp(par, "none")) {
00415 if (chname) {
00416 par[0] = 0;
00417 set_handle_chaninfo(userlist, dcc[idx].nick, chname, NULL);
00418 dprintf(idx, _("Removed your info line on %s.\n"), chname);
00419 putlog(LOG_CMDS, "*", "#%s# info %s none", dcc[idx].nick, chname);
00420 } else {
00421 set_user(&USERENTRY_INFO, u, NULL);
00422 dprintf(idx, _("Removed your default info line.\n"));
00423 putlog(LOG_CMDS, "*", "#%s# info none", dcc[idx].nick);
00424 }
00425 return;
00426 }
00427
00428
00429 if (chname) {
00430 set_handle_chaninfo(userlist, dcc[idx].nick, chname, par);
00431 dprintf(idx, _("Your info on %1$s is now: %2$s\n"), chname, par);
00432 putlog(LOG_CMDS, "*", "#%s# info %s ...", dcc[idx].nick, chname);
00433 } else {
00434 set_user(&USERENTRY_INFO, u, par);
00435 dprintf(idx, _("Your default info is now: %s\n"), par);
00436 putlog(LOG_CMDS, "*", "#%s# info ...", dcc[idx].nick);
00437 }
00438 }
00439
00440 static void cmd_chinfo(struct userrec *u, int idx, char *par)
00441 {
00442 char *handle, *chname;
00443 struct userrec *u1;
00444
00445 if (!use_info) {
00446 dprintf(idx, _("Info storage is turned off.\n"));
00447 return;
00448 }
00449 handle = newsplit(&par);
00450 if (!handle[0]) {
00451 dprintf(idx, "Usage: chinfo <handle> [channel] <new-info>\n");
00452 return;
00453 }
00454 u1 = get_user_by_handle(userlist, handle);
00455 if (!u1) {
00456 dprintf(idx, _("No such user.\n"));
00457 return;
00458 }
00459 if (par[0] && strchr(CHANMETA, par[0])) {
00460 chname = newsplit(&par);
00461 if (!findchan_by_dname(chname)) {
00462 dprintf(idx, _("No such channel.\n"));
00463 return;
00464 }
00465 } else
00466 chname = 0;
00467 if ((u1->flags & USER_BOT) && !(u->flags & USER_MASTER)) {
00468 dprintf(idx, _("You have to be master to change bots info.\n"));
00469 return;
00470 }
00471 if ((u1->flags & USER_OWNER) && !(u->flags & USER_OWNER)) {
00472 dprintf(idx, _("You can't change info for the bot owner.\n"));
00473 return;
00474 }
00475 if (chname) {
00476 get_user_flagrec(u, &user, chname);
00477 get_user_flagrec(u1, &victim, chname);
00478 if ((chan_owner(victim) || glob_owner(victim)) &&
00479 !(glob_owner(user) || chan_owner(user))) {
00480 dprintf(idx, _("You can't change info for the channel owner.\n"));
00481 return;
00482 }
00483 }
00484 putlog(LOG_CMDS, "*", "#%s# chinfo %s %s %s", dcc[idx].nick, handle,
00485 chname ? chname : par, chname ? par : "");
00486 if (!strcasecmp(par, "none"))
00487 par[0] = 0;
00488 if (chname) {
00489 set_handle_chaninfo(userlist, handle, chname, par);
00490 if (par[0] == '@')
00491 dprintf(idx, _("New info (LOCKED) for %1$s on %2$s: %3$s\n"),
00492 handle, chname, &par[1]);
00493 else if (par[0])
00494 dprintf(idx, _("New info for %1$s on %2$s: %3$s\n"), handle, chname, par);
00495 else
00496 dprintf(idx, _("Wiped info for %1$s on %2$s\n"), handle, chname);
00497 } else {
00498 set_user(&USERENTRY_INFO, u1, par[0] ? par : NULL);
00499 if (par[0] == '@')
00500 dprintf(idx, _("New default info (LOCKED) for %1$s: %2$s\n"), handle,
00501 &par[1]);
00502 else if (par[0])
00503 dprintf(idx, _("New default info for %1$s: %2$s\n"), handle, par);
00504 else
00505 dprintf(idx, _("Wiped default info for %s\n"), handle);
00506 }
00507 }
00508
00509 static void cmd_stick_yn(int idx, char *par, int yn)
00510 {
00511 int i = 0, j;
00512 struct chanset_t *chan, *achan;
00513 char *stick_type, s[UHOSTLEN], chname[81];
00514 module_entry *me;
00515
00516 stick_type = newsplit(&par);
00517 strlcpy(s, newsplit(&par), sizeof s);
00518 strlcpy(chname, newsplit(&par), sizeof chname);
00519
00520 if (strcasecmp(stick_type, "exempt") &&
00521 strcasecmp(stick_type, "invite") &&
00522 strcasecmp(stick_type, "ban")) {
00523 strlcpy(chname, s, sizeof chname);
00524 strlcpy(s, stick_type, sizeof s);
00525 }
00526 if (!s[0]) {
00527 dprintf(idx, "Usage: %sstick [ban/exempt/invite] <hostmask or number> [channel]\n",
00528 yn ? "" : "un");
00529 return;
00530 }
00531
00532 if (!strcasecmp(stick_type, "exempt")) {
00533 if (!use_exempts) {
00534 dprintf(idx,
00535 _("This command can only be used with use-exempts enabled.\n"));
00536 return;
00537 }
00538 if (!chname[0]) {
00539 i = u_setsticky_exempt(NULL, s,
00540 (dcc[idx].user->flags & USER_MASTER) ? yn : -1);
00541 if (i > 0) {
00542 putlog(LOG_CMDS, "*", "#%s# %sstick exempt %s",
00543 dcc[idx].nick, yn ? "" : "un", s);
00544 dprintf(idx, "%s: %s\n", yn ? _("Stuck exempt") : _("Unstuck exempt"),
00545 s);
00546 return;
00547 }
00548 strlcpy(chname, dcc[idx].u.chat->con_chan, sizeof chname);
00549 }
00550
00551 if (!(chan = findchan_by_dname(chname))) {
00552 dprintf(idx, _("No such channel.\n"));
00553 return;
00554 }
00555 if (i)
00556 snprintf(s, sizeof s, "%d", -i);
00557 j = u_setsticky_exempt(chan, s, yn);
00558 if (j > 0) {
00559 putlog(LOG_CMDS, "*", "#%s# %sstick exempt %s %s", dcc[idx].nick,
00560 yn ? "" : "un", s, chname);
00561 dprintf(idx, "%stuck %s exempt: %s\n", yn ? "S" : "Uns", chname, s);
00562 return;
00563 }
00564 dprintf(idx, "No such exempt.\n");
00565 return;
00566
00567 } else if (!strcasecmp(stick_type, "invite")) {
00568 if (!use_invites) {
00569 dprintf(idx,
00570 _("This command can only be used with use-invites enabled.\n"));
00571 return;
00572 }
00573 if (!chname[0]) {
00574 i = u_setsticky_invite(NULL, s,
00575 (dcc[idx].user->flags & USER_MASTER) ? yn : -1);
00576 if (i > 0) {
00577 putlog(LOG_CMDS, "*", "#%s# %sstick invite %s",
00578 dcc[idx].nick, yn ? "" : "un", s);
00579 dprintf(idx, "%stuck invite: %s\n", yn ? "S" : "Uns", s);
00580 return;
00581 }
00582 strlcpy(chname, dcc[idx].u.chat->con_chan, sizeof chname);
00583 }
00584
00585 if (!(chan = findchan_by_dname(chname))) {
00586 dprintf(idx, _("No such channel.\n"));
00587 return;
00588 }
00589 if (i)
00590 snprintf(s, sizeof s, "%d", -i);
00591 j = u_setsticky_invite(chan, s, yn);
00592 if (j > 0) {
00593 putlog(LOG_CMDS, "*", "#%s# %sstick invite %s %s", dcc[idx].nick,
00594 yn ? "" : "un", s, chname);
00595 dprintf(idx, "%stuck %s invite: %s\n", yn ? "S" : "Uns", chname, s);
00596 return;
00597 }
00598 dprintf(idx, _("No such invite.\n"));
00599 return;
00600 }
00601 if (!chname[0]) {
00602 i = u_setsticky_ban(NULL, s,
00603 (dcc[idx].user->flags & USER_MASTER) ? yn : -1);
00604 if (i > 0) {
00605 putlog(LOG_CMDS, "*", "#%s# %sstick ban %s",
00606 dcc[idx].nick, yn ? "" : "un", s);
00607 dprintf(idx, "%stuck ban: %s\n", yn ? "S" : "Uns", s);
00608 if ((me = module_find("irc", 0, 0)))
00609 for (achan = chanset; achan != NULL; achan = achan->next)
00610 (me->funcs[IRC_CHECK_THIS_BAN])(achan, s, yn);
00611 return;
00612 }
00613 strlcpy(chname, dcc[idx].u.chat->con_chan, sizeof chname);
00614 }
00615
00616 if (!(chan = findchan_by_dname(chname))) {
00617 dprintf(idx, _("No such channel.\n"));
00618 return;
00619 }
00620 if (i)
00621 snprintf(s, sizeof s, "%d", -i);
00622 j = u_setsticky_ban(chan, s, yn);
00623 if (j > 0) {
00624 putlog(LOG_CMDS, "*", "#%s# %sstick ban %s %s", dcc[idx].nick,
00625 yn ? "" : "un", s, chname);
00626 dprintf(idx, "%stuck %s ban: %s\n", yn ? "S" : "Uns", chname, s);
00627 if ((me = module_find("irc", 0, 0)))
00628 (me->funcs[IRC_CHECK_THIS_BAN])(chan, s, yn);
00629 return;
00630 }
00631 dprintf(idx, _("No such ban.\n"));
00632 }
00633
00634
00635 static void cmd_stick(struct userrec *u, int idx, char *par)
00636 {
00637 cmd_stick_yn(idx, par, 1);
00638 }
00639
00640 static void cmd_unstick(struct userrec *u, int idx, char *par)
00641 {
00642 cmd_stick_yn(idx, par, 0);
00643 }
00644
00645 static void cmd_pls_chrec(struct userrec *u, int idx, char *par)
00646 {
00647 char *nick, *chn;
00648 struct chanset_t *chan;
00649 struct userrec *u1;
00650 struct chanuserrec *chanrec;
00651
00652 if (!par[0]) {
00653 dprintf(idx, "Usage: +chrec <user> [channel]\n");
00654 return;
00655 }
00656 nick = newsplit(&par);
00657 u1 = get_user_by_handle(userlist, nick);
00658 if (!u1) {
00659 dprintf(idx, _("No such user.\n"));
00660 return;
00661 }
00662 if (!par[0])
00663 chan = findchan_by_dname(dcc[idx].u.chat->con_chan);
00664 else {
00665 chn = newsplit(&par);
00666 chan = findchan_by_dname(chn);
00667 }
00668 if (!chan) {
00669 dprintf(idx, _("No such channel.\n"));
00670 return;
00671 }
00672 get_user_flagrec(u, &user, chan->dname);
00673 get_user_flagrec(u1, &victim, chan->dname);
00674 if ((!glob_master(user) && !chan_master(user)) ||
00675 (chan_owner(victim) && !chan_owner(user) && !glob_owner(user)) ||
00676 (glob_owner(victim) && !glob_owner(user))) {
00677 dprintf(idx, _("You have no permission to do that.\n"));
00678 return;
00679 }
00680 chanrec = get_chanrec(u1, chan->dname);
00681 if (chanrec) {
00682 dprintf(idx, _("User %1$s already has a channel record for %2$s.\n"),
00683 nick, chan->dname);
00684 return;
00685 }
00686 putlog(LOG_CMDS, "*", "#%s# +chrec %s %s", dcc[idx].nick,
00687 nick, chan->dname);
00688 add_chanrec(u1, chan->dname);
00689 dprintf(idx, "Added %1$s channel record for %2$s.\n", chan->dname, nick);
00690 }
00691
00692 static void cmd_mns_chrec(struct userrec *u, int idx, char *par)
00693 {
00694 char *nick, *chn = NULL;
00695 struct userrec *u1;
00696 struct chanuserrec *chanrec;
00697
00698 if (!par[0]) {
00699 dprintf(idx, "Usage: -chrec <user> [channel]\n");
00700 return;
00701 }
00702 nick = newsplit(&par);
00703 u1 = get_user_by_handle(userlist, nick);
00704 if (!u1) {
00705 dprintf(idx, _("No such user.\n"));
00706 return;
00707 }
00708 if (!par[0]) {
00709 struct chanset_t *chan;
00710
00711 chan = findchan_by_dname(dcc[idx].u.chat->con_chan);
00712 if (chan)
00713 chn = chan->dname;
00714 else {
00715 dprintf(idx, _("Invalid console channel.\n"));
00716 return;
00717 }
00718 } else
00719 chn = newsplit(&par);
00720 get_user_flagrec(u, &user, chn);
00721 get_user_flagrec(u1, &victim, chn);
00722 if ((!glob_master(user) && !chan_master(user)) ||
00723 (chan_owner(victim) && !chan_owner(user) && !glob_owner(user)) ||
00724 (glob_owner(victim) && !glob_owner(user))) {
00725 dprintf(idx, _("You have no permission to do that.\n"));
00726 return;
00727 }
00728 chanrec = get_chanrec(u1, chn);
00729 if (!chanrec) {
00730 dprintf(idx, _("User %1$s doesn't have a channel record for %2$s.\n"),
00731 nick, chn);
00732 return;
00733 }
00734 putlog(LOG_CMDS, "*", "#%s# -chrec %s %s", dcc[idx].nick, nick, chn);
00735 del_chanrec(u1, chn);
00736 dprintf(idx, _("Removed %1$s channel record from %2$s.\n"), chn, nick);
00737 }
00738
00739 static void cmd_pls_chan(struct userrec *u, int idx, char *par)
00740 {
00741 char *chname;
00742 struct chanset_t *chan;
00743
00744 if (!par[0]) {
00745 dprintf(idx, "Usage: +chan [%s]<channel> [options]\n", CHANMETA);
00746 return;
00747 }
00748
00749 chname = newsplit(&par);
00750 if (findchan_by_dname(chname)) {
00751 dprintf(idx, _("That channel already exists!\n"));
00752 return;
00753 } else if ((chan = findchan(chname))) {
00754 dprintf(idx, _("That channel already exists as %s!\n"), chan->dname);
00755 return;
00756 } else if (strchr(CHANMETA, chname[0]) == NULL) {
00757 dprintf(idx, _("Invalid channel prefix.\n"));
00758 return;
00759 } else if (strchr(chname, ',') != NULL) {
00760 dprintf(idx, _("Invalid channel name.\n"));
00761 return;
00762 }
00763
00764 if (tcl_channel_add(0, chname, par) == TCL_ERROR)
00765 dprintf(idx, _("Invalid channel or channel options.\n"));
00766 else
00767 putlog(LOG_CMDS, "*", "#%s# +chan %s", dcc[idx].nick, chname);
00768 }
00769
00770 static void cmd_mns_chan(struct userrec *u, int idx, char *par)
00771 {
00772 char *chname;
00773 struct chanset_t *chan;
00774 int i;
00775
00776 if (!par[0]) {
00777 dprintf(idx, "Usage: -chan [%s]<channel>\n", CHANMETA);
00778 return;
00779 }
00780 chname = newsplit(&par);
00781 chan = findchan_by_dname(chname);
00782 if (!chan) {
00783 if ((chan = findchan(chname)))
00784 dprintf(idx,
00785 _("That channel exists with a short name of %s, use that.\n"),
00786 chan->dname);
00787 else
00788 dprintf(idx, _("That channel doesn't exist!\n"));
00789 return;
00790 }
00791 if (channel_static(chan)) {
00792 dprintf(idx, _("Cannot remove %s, it is not a dynamic channel!.\n"),
00793 chname);
00794 return;
00795 }
00796
00797 remove_channel(chan);
00798 dprintf(idx, _("Channel %s removed from the bot.\n"), chname);
00799 dprintf(idx, _("This includes any channel specific bans, invites, exemptions and user records that you set.\n"));
00800 putlog(LOG_CMDS, "*", "#%s# -chan %s", dcc[idx].nick, chname);
00801 for (i = 0; i < dcc_total; i++)
00802 if (dcc[i].type && (dcc[i].type->flags & DCT_CHAT) &&
00803 !irccmp(dcc[i].u.chat->con_chan, chan->dname)) {
00804 dprintf(i, _("%s is no longer a valid channel, changing your console to '*'\n"),
00805 chname);
00806 strcpy(dcc[i].u.chat->con_chan, "*");
00807 }
00808 }
00809
00810 static void cmd_chaninfo(struct userrec *u, int idx, char *par)
00811 {
00812 char *chname, work[512];
00813 struct chanset_t *chan;
00814 int ii, tmp;
00815 struct udef_struct *ul;
00816
00817 if (!par[0]) {
00818 chname = dcc[idx].u.chat->con_chan;
00819 if (chname[0] == '*') {
00820 dprintf(idx, _("Your console channel is invalid.\n"));
00821 return;
00822 }
00823 } else {
00824 chname = newsplit(&par);
00825 get_user_flagrec(u, &user, chname);
00826 if (!glob_master(user) && !chan_master(user)) {
00827 dprintf(idx, _("You don't have access to %s. \n"), chname);
00828 return;
00829 }
00830 }
00831 if (!(chan = findchan_by_dname(chname)))
00832 dprintf(idx, "No such channel defined.\n");
00833 else {
00834 dprintf(idx, "Settings for %s channel %s\n",
00835 channel_static(chan) ? "static" : "dynamic", chan->dname);
00836 get_mode_protect(chan, work);
00837 dprintf(idx, "Protect modes (chanmode): %s\n", work[0] ? work : "None");
00838 dprintf(idx, "aop_delay: %d:%d\n", chan->aop_min, chan->aop_max);
00839 if (chan->ban_time)
00840 dprintf(idx, "ban_time: %d\n", chan->ban_time);
00841 else
00842 dprintf(idx, "ban_time: 0\n");
00843 if (chan->exempt_time)
00844 dprintf(idx, "exempt_time: %d\n", chan->exempt_time);
00845 else
00846 dprintf(idx, "exempt_time: 0\n");
00847 if (chan->invite_time)
00848 dprintf(idx, "invite_time: %d\n", chan->invite_time);
00849 else
00850 dprintf(idx, "invite_time: 0\n");
00851
00852 dprintf(idx, "Other modes:\n");
00853 dprintf(idx, " %cinactive %cstatuslog %csecret\n",
00854 (chan->status & CHAN_INACTIVE) ? '+' : '-',
00855 (chan->status & CHAN_LOGSTATUS) ? '+' : '-',
00856 (chan->status & CHAN_SECRET) ? '+' : '-');
00857 dprintf(idx, " %cgreet %ccycle %cdontkickops\n",
00858 (chan->status & CHAN_GREET) ? '+' : '-',
00859 (chan->status & CHAN_CYCLE) ? '+' : '-',
00860 (chan->status & CHAN_DONTKICKOPS) ? '+' : '-');
00861 dprintf(idx, " %cautovoice %cnodesynch %cenforcebans %cdynamicbans\n",
00862 (chan->status & CHAN_AUTOVOICE) ? '+' : '-',
00863 (chan->status & CHAN_NODESYNCH) ? '+' : '-',
00864 (chan->status & CHAN_ENFORCEBANS) ? '+' : '-',
00865 (chan->status & CHAN_DYNAMICBANS) ? '+' : '-');
00866 dprintf(idx, " %cdynamicexempts %cdynamicinvites\n",
00867 (chan->ircnet_status & CHAN_DYNAMICEXEMPTS) ? '+' : '-',
00868 (chan->ircnet_status & CHAN_DYNAMICINVITES) ? '+' : '-');
00869 dprintf(idx, " %chonor-global-bans %chonor-global-exempts\n",
00870 (chan->status & CHAN_HONORGLOBALBANS) ? '+' : '-',
00871 (chan->ircnet_status & CHAN_HONORGLOBALEXEMPTS) ? '+' : '-');
00872 dprintf(idx, " %chonor-global-invites %cautoop\n",
00873 (chan->ircnet_status & CHAN_HONORGLOBALINVITES) ? '+' : '-',
00874 (chan->status & CHAN_OPONJOIN) ? '+' : '-');
00875
00876 ii = 1;
00877 tmp = 0;
00878 for (ul = udef; ul; ul = ul->next)
00879 if (ul->defined && ul->type == UDEF_FLAG) {
00880 int work_len;
00881
00882 if (!tmp) {
00883 dprintf(idx, "User defined channel flags:\n");
00884 tmp = 1;
00885 }
00886 if (ii == 1)
00887 snprintf(work, sizeof work, " ");
00888 work_len = strlen(work);
00889 snprintf(work + work_len, sizeof(work) - work_len, " %c%s",
00890 getudef(ul->values, chan->dname) ? '+' : '-', ul->name);
00891 ii++;
00892 if (ii > 4) {
00893 dprintf(idx, "%s\n", work);
00894 ii = 1;
00895 }
00896 }
00897 if (ii > 1)
00898 dprintf(idx, "%s\n", work);
00899
00900 work[0] = 0;
00901 ii = 1;
00902 tmp = 0;
00903 for (ul = udef; ul; ul = ul->next)
00904 if (ul->defined && ul->type == UDEF_INT) {
00905 int work_len = strlen(work);
00906
00907 if (!tmp) {
00908 dprintf(idx, "User defined channel settings:\n");
00909 tmp = 1;
00910 }
00911 snprintf(work + work_len, sizeof(work) - work_len, "%s: %d ",
00912 ul->name, getudef(ul->values, chan->dname));
00913 ii++;
00914 if (ii > 4) {
00915 dprintf(idx, "%s\n", work);
00916 work[0] = 0;
00917 ii = 1;
00918 }
00919 }
00920 if (ii > 1)
00921 dprintf(idx, "%s\n", work);
00922
00923 if (u->flags & USER_OWNER) {
00924 tmp = 0;
00925 for (ul = udef; ul; ul = ul->next)
00926 if (ul->defined && ul->type == UDEF_STR) {
00927 char *p = (char *)getudef(ul->values, chan->dname);
00928 if (!p) p = "{}";
00929 if (!tmp) {
00930 dprintf(idx, "User defined channel strings:\n");
00931 tmp = 1;
00932 }
00933 dprintf(idx, "%s: %s\n", ul->name, p);
00934 }
00935 }
00936 putlog(LOG_CMDS, "*", "#%s# chaninfo %s", dcc[idx].nick, chname);
00937 }
00938 }
00939
00940 static void cmd_chanset(struct userrec *u, int idx, char *par)
00941 {
00942 char *chname = NULL, answers[512], *parcpy;
00943 char *list[2], *bak, *buf;
00944 struct chanset_t *chan = NULL;
00945 int all = 0;
00946
00947 if (!par[0])
00948 dprintf(idx, "Usage: chanset [%schannel] <settings>\n", CHANMETA);
00949 else {
00950 if (strlen(par) > 2 && par[0] == '*' && par[1] == ' ') {
00951 all = 1;
00952 get_user_flagrec(u, &user, chanset ? chanset->dname : "");
00953 if (!glob_master(user)) {
00954 dprintf(idx, _("You need to be a global master to use .chanset *.\n"));
00955 return;
00956 }
00957 newsplit(&par);
00958 } else {
00959 if (strchr(CHANMETA, par[0])) {
00960 chname = newsplit(&par);
00961 get_user_flagrec(u, &user, chname);
00962 if (!glob_master(user) && !chan_master(user)) {
00963 dprintf(idx, _("You don't have access to %s. \n"), chname);
00964 return;
00965 } else if (!(chan = findchan_by_dname(chname)) && (chname[0] != '+')) {
00966 dprintf(idx, _("That channel doesn't exist!\n"));
00967 return;
00968 }
00969 if (!chan) {
00970 if (par[0])
00971 *--par = ' ';
00972 par = chname;
00973 }
00974 }
00975 if (!par[0] || par[0] == '*') {
00976 dprintf(idx, "Usage: chanset [%schannel] <settings>\n", CHANMETA);
00977 return;
00978 }
00979 if (!chan &&
00980 !(chan = findchan_by_dname(chname = dcc[idx].u.chat->con_chan))) {
00981 dprintf(idx, _("Invalid console channel.\n"));
00982 return;
00983 }
00984 }
00985 if (all)
00986 chan = chanset;
00987 bak = par;
00988 buf = malloc(strlen(par) + 1);
00989 while (chan) {
00990 chname = chan->dname;
00991 strcpy(buf, bak);
00992 par = buf;
00993 list[0] = newsplit(&par);
00994 answers[0] = 0;
00995 while (list[0][0]) {
00996 if (list[0][0] == '+' || list[0][0] == '-') {
00997 if (tcl_channel_modify(0, chan, 1, list) == TCL_OK) {
00998 strcat(answers, list[0]);
00999 strcat(answers, " ");
01000 } else if (!all || !chan->next)
01001 dprintf(idx, "Error trying to set %s for %s, invalid mode\n",
01002 list[0], all ? "all channels" : chname);
01003 list[0] = newsplit(&par);
01004 continue;
01005 }
01006
01007
01008
01009 list[1] = par;
01010
01011
01012
01013 parcpy = strdup(par);
01014 if (tcl_channel_modify(0, chan, 2, list) == TCL_OK) {
01015 strcat(answers, list[0]);
01016 strcat(answers, " { ");
01017 strcat(answers, parcpy);
01018 strcat(answers, " }");
01019 } else if (!all || !chan->next)
01020 dprintf(idx, "Error trying to set %s for %s, invalid option\n",
01021 list[0], all ? "all channels" : chname);
01022 free(parcpy);
01023 break;
01024 }
01025 if (!all && answers[0]) {
01026 dprintf(idx, "Successfully set modes { %s } on %s.\n",
01027 answers, chname);
01028 putlog(LOG_CMDS, "*", "#%s# chanset %s %s", dcc[idx].nick, chname,
01029 answers);
01030 }
01031 if (!all)
01032 chan = NULL;
01033 else
01034 chan = chan->next;
01035 }
01036 if (all && answers[0]) {
01037 dprintf(idx, "Successfully set modes { %s } on all channels.\n",
01038 answers);
01039 putlog(LOG_CMDS, "*", "#%s# chanset * %s", dcc[idx].nick, answers);
01040 }
01041 free(buf);
01042 }
01043 }
01044
01045 static void cmd_chansave(struct userrec *u, int idx, char *par)
01046 {
01047 if (!chanfile[0])
01048 dprintf(idx, _("No channel saving file defined.\n"));
01049 else {
01050 dprintf(idx, _("Saving all dynamic channel settings.\n"));
01051 putlog(LOG_CMDS, "*", "#%s# chansave", dcc[idx].nick);
01052 write_channels();
01053 }
01054 }
01055
01056 static void cmd_chanload(struct userrec *u, int idx, char *par)
01057 {
01058 if (!chanfile[0])
01059 dprintf(idx, _("No channel saving file defined.\n"));
01060 else {
01061 dprintf(idx, _("Reloading all dynamic channel settings.\n"));
01062 putlog(LOG_CMDS, "*", "#%s# chanload", dcc[idx].nick);
01063 setstatic = 0;
01064 read_channels(1);
01065 }
01066 }
01067
01068
01069
01070
01071
01072
01073
01074
01075 static cmd_t C_dcc_irc[] =
01076 {
01077 {"+ban", "o|o", (Function) cmd_pls_ban, NULL},
01078 {"+exempt", "o|o", (Function) cmd_pls_exempt, NULL},
01079 {"+invite", "o|o", (Function) cmd_pls_invite, NULL},
01080 {"+chan", "n", (Function) cmd_pls_chan, NULL},
01081 {"+chrec", "m|m", (Function) cmd_pls_chrec, NULL},
01082 {"-ban", "o|o", (Function) cmd_mns_ban, NULL},
01083 {"-chan", "n", (Function) cmd_mns_chan, NULL},
01084 {"-chrec", "m|m", (Function) cmd_mns_chrec, NULL},
01085 {"bans", "o|o", (Function) cmd_bans, NULL},
01086 {"-exempt", "o|o", (Function) cmd_mns_exempt, NULL},
01087 {"-invite", "o|o", (Function) cmd_mns_invite, NULL},
01088 {"exempts", "o|o", (Function) cmd_exempts, NULL},
01089 {"invites", "o|o", (Function) cmd_invites, NULL},
01090 {"chaninfo", "m|m", (Function) cmd_chaninfo, NULL},
01091 {"chanload", "n|n", (Function) cmd_chanload, NULL},
01092 {"chanset", "n|n", (Function) cmd_chanset, NULL},
01093 {"chansave", "n|n", (Function) cmd_chansave, NULL},
01094 {"chinfo", "m|m", (Function) cmd_chinfo, NULL},
01095 {"info", "", (Function) cmd_info, NULL},
01096 {"stick", "o|o", (Function) cmd_stick, NULL},
01097 {"unstick", "o|o", (Function) cmd_unstick, NULL},
01098 {NULL, NULL, NULL, NULL}
01099 };