PageRenderTime 60ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/mod/channels.mod/cmdschan.c

https://github.com/eggheads/eggdrop-1.8
C | 1616 lines | 1484 code | 62 blank | 70 comment | 475 complexity | fb38f4bc1af74298e43de719eaaa26fe MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * cmdschan.c -- part of channels.mod
  3. * commands from a user via dcc that cause server interaction
  4. *
  5. * $Id: cmdschan.c,v 1.3 2010/10/11 08:46:10 pseudo Exp $
  6. */
  7. /*
  8. * Copyright (C) 1997 Robey Pointer
  9. * Copyright (C) 1999 - 2010 Eggheads Development Team
  10. *
  11. * This program is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU General Public License
  13. * as published by the Free Software Foundation; either version 2
  14. * of the License, or (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24. */
  25. #include <ctype.h>
  26. static struct flag_record user = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
  27. static struct flag_record victim = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
  28. static void cmd_pls_ban(struct userrec *u, int idx, char *par)
  29. {
  30. char *chname, *who, s[UHOSTLEN], s1[UHOSTLEN], *p, *p_expire;
  31. unsigned long int expire_time = 0, expire_foo;
  32. int sticky = 0;
  33. struct chanset_t *chan = NULL;
  34. module_entry *me;
  35. if (!par[0]) {
  36. dprintf(idx, "Usage: +ban <hostmask> [channel] [%%<XdXhXm>] [reason]\n");
  37. } else {
  38. who = newsplit(&par);
  39. if (par[0] && strchr(CHANMETA, par[0]))
  40. chname = newsplit(&par);
  41. else
  42. chname = 0;
  43. if (chname || !(u->flags & USER_OP)) {
  44. if (!chname)
  45. chname = dcc[idx].u.chat->con_chan;
  46. get_user_flagrec(u, &user, chname);
  47. chan = findchan_by_dname(chname);
  48. /* *shrug* ??? (guppy:10Feb1999) */
  49. if (!chan) {
  50. dprintf(idx, "That channel doesn't exist!\n");
  51. return;
  52. } else if (!((glob_op(user) && !chan_deop(user)) || (glob_halfop(user) &&
  53. !chan_dehalfop(user)) || chan_op(user) || chan_halfop(user))) {
  54. dprintf(idx, "You don't have access to set bans on %s.\n", chname);
  55. return;
  56. }
  57. } else
  58. chan = 0;
  59. /* Added by Q and Solal -- Requested by Arty2, special thanx :) */
  60. if (par[0] == '%') {
  61. p = newsplit(&par);
  62. p_expire = p + 1;
  63. while (*(++p) != 0) {
  64. switch (tolower((unsigned) *p)) {
  65. case 'd':
  66. *p = 0;
  67. expire_foo = strtol(p_expire, NULL, 10);
  68. if (expire_foo > 365)
  69. expire_foo = 365;
  70. expire_time += 86400 * expire_foo;
  71. p_expire = p + 1;
  72. break;
  73. case 'h':
  74. *p = 0;
  75. expire_foo = strtol(p_expire, NULL, 10);
  76. if (expire_foo > 8760)
  77. expire_foo = 8760;
  78. expire_time += 3600 * expire_foo;
  79. p_expire = p + 1;
  80. break;
  81. case 'm':
  82. *p = 0;
  83. expire_foo = strtol(p_expire, NULL, 10);
  84. if (expire_foo > 525600)
  85. expire_foo = 525600;
  86. expire_time += 60 * expire_foo;
  87. p_expire = p + 1;
  88. }
  89. }
  90. }
  91. if (!par[0])
  92. par = "requested";
  93. else if (strlen(par) > MASKREASON_MAX)
  94. par[MASKREASON_MAX] = 0;
  95. if (strlen(who) > UHOSTMAX - 4)
  96. who[UHOSTMAX - 4] = 0;
  97. /* Fix missing ! or @ BEFORE checking against myself */
  98. if (!strchr(who, '!')) {
  99. if (!strchr(who, '@'))
  100. egg_snprintf(s, sizeof s, "%s!*@*", who); /* Lame nick ban */
  101. else
  102. egg_snprintf(s, sizeof s, "*!%s", who);
  103. } else if (!strchr(who, '@'))
  104. egg_snprintf(s, sizeof s, "%s@*", who); /* brain-dead? */
  105. else
  106. strncpyz(s, who, sizeof s);
  107. if ((me = module_find("server", 0, 0)) && me->funcs) {
  108. egg_snprintf(s1, sizeof s1, "%s!%s", me->funcs[SERVER_BOTNAME],
  109. me->funcs[SERVER_BOTUSERHOST]);
  110. if (match_addr(s, s1)) {
  111. dprintf(idx, "I'm not going to ban myself.\n");
  112. putlog(LOG_CMDS, "*", "#%s# attempted +ban %s", dcc[idx].nick, s);
  113. return;
  114. }
  115. }
  116. /* IRC can't understand bans longer than 70 characters */
  117. if (strlen(s) > 70) {
  118. s[69] = '*';
  119. s[70] = 0;
  120. }
  121. if (chan) {
  122. u_addban(chan, s, dcc[idx].nick, par,
  123. expire_time ? now + expire_time : 0, 0);
  124. if (par[0] == '*') {
  125. sticky = 1;
  126. par++;
  127. putlog(LOG_CMDS, "*", "#%s# (%s) +ban %s %s (%s) (sticky)",
  128. dcc[idx].nick, dcc[idx].u.chat->con_chan, s, chan->dname, par);
  129. dprintf(idx, "New %s sticky ban: %s (%s)\n", chan->dname, s, par);
  130. } else {
  131. putlog(LOG_CMDS, "*", "#%s# (%s) +ban %s %s (%s)", dcc[idx].nick,
  132. dcc[idx].u.chat->con_chan, s, chan->dname, par);
  133. dprintf(idx, "New %s ban: %s (%s)\n", chan->dname, s, par);
  134. }
  135. /* Avoid unnesessary modes if you got +dynamicbans, and there is
  136. * no reason to set mode if irc.mod aint loaded. (dw 001120)
  137. */
  138. if ((me = module_find("irc", 0, 0)))
  139. (me->funcs[IRC_CHECK_THIS_BAN]) (chan, s, sticky);
  140. } else {
  141. u_addban(NULL, s, dcc[idx].nick, par,
  142. expire_time ? now + expire_time : 0, 0);
  143. if (par[0] == '*') {
  144. sticky = 1;
  145. par++;
  146. putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +ban %s (%s) (sticky)",
  147. dcc[idx].nick, s, par);
  148. dprintf(idx, "New sticky ban: %s (%s)\n", s, par);
  149. } else {
  150. putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +ban %s (%s)", dcc[idx].nick,
  151. s, par);
  152. dprintf(idx, "New ban: %s (%s)\n", s, par);
  153. }
  154. if ((me = module_find("irc", 0, 0)))
  155. for (chan = chanset; chan != NULL; chan = chan->next)
  156. (me->funcs[IRC_CHECK_THIS_BAN]) (chan, s, sticky);
  157. }
  158. }
  159. }
  160. static void cmd_pls_exempt(struct userrec *u, int idx, char *par)
  161. {
  162. char *chname, *who, s[UHOSTLEN], *p, *p_expire;
  163. unsigned long int expire_time = 0, expire_foo;
  164. struct chanset_t *chan = NULL;
  165. if (!use_exempts) {
  166. dprintf(idx, "This command can only be used with use-exempts enabled.\n");
  167. return;
  168. }
  169. if (!par[0]) {
  170. dprintf(idx, "Usage: +exempt <hostmask> [channel] [%%<XdXhXm>] [reason]\n");
  171. } else {
  172. who = newsplit(&par);
  173. if (par[0] && strchr(CHANMETA, par[0]))
  174. chname = newsplit(&par);
  175. else
  176. chname = 0;
  177. if (chname || !(u->flags & USER_OP)) {
  178. if (!chname)
  179. chname = dcc[idx].u.chat->con_chan;
  180. get_user_flagrec(u, &user, chname);
  181. chan = findchan_by_dname(chname);
  182. /* *shrug* ??? (guppy:10Feb99) */
  183. if (!chan) {
  184. dprintf(idx, "That channel doesn't exist!\n");
  185. return;
  186. } else if (!((glob_op(user) && !chan_deop(user)) || (glob_halfop(user) &&
  187. !chan_dehalfop(user)) || chan_op(user) || chan_halfop(user))) {
  188. dprintf(idx, "You don't have access to set exempts on %s.\n", chname);
  189. return;
  190. }
  191. } else
  192. chan = 0;
  193. /* Added by Q and Solal - Requested by Arty2, special thanx :) */
  194. if (par[0] == '%') {
  195. p = newsplit(&par);
  196. p_expire = p + 1;
  197. while (*(++p) != 0) {
  198. switch (tolower((unsigned) *p)) {
  199. case 'd':
  200. *p = 0;
  201. expire_foo = strtol(p_expire, NULL, 10);
  202. if (expire_foo > 365)
  203. expire_foo = 365;
  204. expire_time += 86400 * expire_foo;
  205. p_expire = p + 1;
  206. break;
  207. case 'h':
  208. *p = 0;
  209. expire_foo = strtol(p_expire, NULL, 10);
  210. if (expire_foo > 8760)
  211. expire_foo = 8760;
  212. expire_time += 3600 * expire_foo;
  213. p_expire = p + 1;
  214. break;
  215. case 'm':
  216. *p = 0;
  217. expire_foo = strtol(p_expire, NULL, 10);
  218. if (expire_foo > 525600)
  219. expire_foo = 525600;
  220. expire_time += 60 * expire_foo;
  221. p_expire = p + 1;
  222. }
  223. }
  224. }
  225. if (!par[0])
  226. par = "requested";
  227. else if (strlen(par) > MASKREASON_MAX)
  228. par[MASKREASON_MAX] = 0;
  229. if (strlen(who) > UHOSTMAX - 4)
  230. who[UHOSTMAX - 4] = 0;
  231. /* Fix missing ! or @ BEFORE checking against myself */
  232. if (!strchr(who, '!')) {
  233. if (!strchr(who, '@'))
  234. egg_snprintf(s, sizeof s, "%s!*@*", who); /* Lame nick exempt */
  235. else
  236. egg_snprintf(s, sizeof s, "*!%s", who);
  237. } else if (!strchr(who, '@'))
  238. egg_snprintf(s, sizeof s, "%s@*", who); /* brain-dead? */
  239. else
  240. strncpyz(s, who, sizeof s);
  241. /* IRC can't understand exempts longer than 70 characters */
  242. if (strlen(s) > 70) {
  243. s[69] = '*';
  244. s[70] = 0;
  245. }
  246. if (chan) {
  247. u_addexempt(chan, s, dcc[idx].nick, par,
  248. expire_time ? now + expire_time : 0, 0);
  249. if (par[0] == '*') {
  250. par++;
  251. putlog(LOG_CMDS, "*", "#%s# (%s) +exempt %s %s (%s) (sticky)",
  252. dcc[idx].nick, dcc[idx].u.chat->con_chan, s, chan->dname, par);
  253. dprintf(idx, "New %s sticky exempt: %s (%s)\n", chan->dname, s, par);
  254. } else {
  255. putlog(LOG_CMDS, "*", "#%s# (%s) +exempt %s %s (%s)", dcc[idx].nick,
  256. dcc[idx].u.chat->con_chan, s, chan->dname, par);
  257. dprintf(idx, "New %s exempt: %s (%s)\n", chan->dname, s, par);
  258. }
  259. add_mode(chan, '+', 'e', s);
  260. } else {
  261. u_addexempt(NULL, s, dcc[idx].nick, par,
  262. expire_time ? now + expire_time : 0, 0);
  263. if (par[0] == '*') {
  264. par++;
  265. putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +exempt %s (%s) (sticky)",
  266. dcc[idx].nick, s, par);
  267. dprintf(idx, "New sticky exempt: %s (%s)\n", s, par);
  268. } else {
  269. putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +exempt %s (%s)", dcc[idx].nick,
  270. s, par);
  271. dprintf(idx, "New exempt: %s (%s)\n", s, par);
  272. }
  273. for (chan = chanset; chan != NULL; chan = chan->next)
  274. add_mode(chan, '+', 'e', s);
  275. }
  276. }
  277. }
  278. static void cmd_pls_invite(struct userrec *u, int idx, char *par)
  279. {
  280. char *chname, *who, s[UHOSTLEN], *p, *p_expire;
  281. unsigned long int expire_time = 0, expire_foo;
  282. struct chanset_t *chan = NULL;
  283. if (!use_invites) {
  284. dprintf(idx, "This command can only be used with use-invites enabled.\n");
  285. return;
  286. }
  287. if (!par[0]) {
  288. dprintf(idx, "Usage: +invite <hostmask> [channel] [%%<XdXhXm>] [reason]\n");
  289. } else {
  290. who = newsplit(&par);
  291. if (par[0] && strchr(CHANMETA, par[0]))
  292. chname = newsplit(&par);
  293. else
  294. chname = 0;
  295. if (chname || !(u->flags & USER_OP)) {
  296. if (!chname)
  297. chname = dcc[idx].u.chat->con_chan;
  298. get_user_flagrec(u, &user, chname);
  299. chan = findchan_by_dname(chname);
  300. /* *shrug* ??? (guppy:10Feb99) */
  301. if (!chan) {
  302. dprintf(idx, "That channel doesn't exist!\n");
  303. return;
  304. } else if (!((glob_op(user) && !chan_deop(user)) || (glob_halfop(user) &&
  305. !chan_dehalfop(user)) || chan_op(user) || chan_halfop(user))) {
  306. dprintf(idx, "You don't have access to set invites on %s.\n", chname);
  307. return;
  308. }
  309. } else
  310. chan = 0;
  311. /* Added by Q and Solal - Requested by Arty2, special thanx :) */
  312. if (par[0] == '%') {
  313. p = newsplit(&par);
  314. p_expire = p + 1;
  315. while (*(++p) != 0) {
  316. switch (tolower((unsigned) *p)) {
  317. case 'd':
  318. *p = 0;
  319. expire_foo = strtol(p_expire, NULL, 10);
  320. if (expire_foo > 365)
  321. expire_foo = 365;
  322. expire_time += 86400 * expire_foo;
  323. p_expire = p + 1;
  324. break;
  325. case 'h':
  326. *p = 0;
  327. expire_foo = strtol(p_expire, NULL, 10);
  328. if (expire_foo > 8760)
  329. expire_foo = 8760;
  330. expire_time += 3600 * expire_foo;
  331. p_expire = p + 1;
  332. break;
  333. case 'm':
  334. *p = 0;
  335. expire_foo = strtol(p_expire, NULL, 10);
  336. if (expire_foo > 525600)
  337. expire_foo = 525600;
  338. expire_time += 60 * expire_foo;
  339. p_expire = p + 1;
  340. }
  341. }
  342. }
  343. if (!par[0])
  344. par = "requested";
  345. else if (strlen(par) > MASKREASON_MAX)
  346. par[MASKREASON_MAX] = 0;
  347. if (strlen(who) > UHOSTMAX - 4)
  348. who[UHOSTMAX - 4] = 0;
  349. /* Fix missing ! or @ BEFORE checking against myself */
  350. if (!strchr(who, '!')) {
  351. if (!strchr(who, '@'))
  352. egg_snprintf(s, sizeof s, "%s!*@*", who); /* Lame nick invite */
  353. else
  354. egg_snprintf(s, sizeof s, "*!%s", who);
  355. } else if (!strchr(who, '@'))
  356. egg_snprintf(s, sizeof s, "%s@*", who); /* brain-dead? */
  357. else
  358. strncpyz(s, who, sizeof s);
  359. /* IRC can't understand invites longer than 70 characters */
  360. if (strlen(s) > 70) {
  361. s[69] = '*';
  362. s[70] = 0;
  363. }
  364. if (chan) {
  365. u_addinvite(chan, s, dcc[idx].nick, par,
  366. expire_time ? now + expire_time : 0, 0);
  367. if (par[0] == '*') {
  368. par++;
  369. putlog(LOG_CMDS, "*", "#%s# (%s) +invite %s %s (%s) (sticky)",
  370. dcc[idx].nick, dcc[idx].u.chat->con_chan, s, chan->dname, par);
  371. dprintf(idx, "New %s sticky invite: %s (%s)\n", chan->dname, s, par);
  372. } else {
  373. putlog(LOG_CMDS, "*", "#%s# (%s) +invite %s %s (%s)", dcc[idx].nick,
  374. dcc[idx].u.chat->con_chan, s, chan->dname, par);
  375. dprintf(idx, "New %s invite: %s (%s)\n", chan->dname, s, par);
  376. }
  377. add_mode(chan, '+', 'I', s);
  378. } else {
  379. u_addinvite(NULL, s, dcc[idx].nick, par,
  380. expire_time ? now + expire_time : 0, 0);
  381. if (par[0] == '*') {
  382. par++;
  383. putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +invite %s (%s) (sticky)",
  384. dcc[idx].nick, s, par);
  385. dprintf(idx, "New sticky invite: %s (%s)\n", s, par);
  386. } else {
  387. putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +invite %s (%s)", dcc[idx].nick,
  388. s, par);
  389. dprintf(idx, "New invite: %s (%s)\n", s, par);
  390. }
  391. for (chan = chanset; chan != NULL; chan = chan->next)
  392. add_mode(chan, '+', 'I', s);
  393. }
  394. }
  395. }
  396. static void cmd_mns_ban(struct userrec *u, int idx, char *par)
  397. {
  398. int console = 0, i = 0, j;
  399. struct chanset_t *chan = NULL;
  400. char s[UHOSTLEN], *ban, *chname, *mask;
  401. masklist *b;
  402. if (!par[0]) {
  403. dprintf(idx, "Usage: -ban <hostmask|ban #> [channel]\n");
  404. return;
  405. }
  406. ban = newsplit(&par);
  407. if (par[0] && strchr(CHANMETA, par[0]))
  408. chname = newsplit(&par);
  409. else {
  410. chname = dcc[idx].u.chat->con_chan;
  411. console = 1;
  412. }
  413. if (chname || !(u->flags & USER_OP)) {
  414. if (!chname)
  415. chname = dcc[idx].u.chat->con_chan;
  416. get_user_flagrec(u, &user, chname);
  417. if ((!chan_op(user) && (!glob_op(user) || chan_deop(user))) &&
  418. (!chan_halfop(user) && (!glob_halfop(user) || chan_dehalfop(user)))) {
  419. dprintf(idx, "You don't have access to remove bans on %s.\n", chname);
  420. return;
  421. }
  422. }
  423. strncpyz(s, ban, sizeof s);
  424. if (console) {
  425. i = u_delban(NULL, s, (u->flags & USER_OP));
  426. if (i > 0) {
  427. if (lastdeletedmask)
  428. mask = lastdeletedmask;
  429. else
  430. mask = s;
  431. putlog(LOG_CMDS, "*", "#%s# -ban %s", dcc[idx].nick, mask);
  432. dprintf(idx, "%s: %s\n", IRC_REMOVEDBAN, mask);
  433. for (chan = chanset; chan != NULL; chan = chan->next)
  434. add_mode(chan, '-', 'b', mask);
  435. return;
  436. }
  437. }
  438. /* Channel-specific ban? */
  439. if (chname)
  440. chan = findchan_by_dname(chname);
  441. if (!chan) {
  442. dprintf(idx, "Invalid channel.\n");
  443. return;
  444. }
  445. if (str_isdigit(ban)) {
  446. i = atoi(ban);
  447. /* substract the numer of global bans to get the number of the channel ban */
  448. egg_snprintf(s, sizeof s, "%d", i);
  449. j = u_delban(0, s, 0);
  450. if (j < 0) {
  451. egg_snprintf(s, sizeof s, "%d", -j);
  452. j = u_delban(chan, s, 1);
  453. if (j > 0) {
  454. if (lastdeletedmask)
  455. mask = lastdeletedmask;
  456. else
  457. mask = s;
  458. putlog(LOG_CMDS, "*", "#%s# (%s) -ban %s", dcc[idx].nick, chan->dname,
  459. mask);
  460. dprintf(idx, "Removed %s channel ban: %s\n", chan->dname, mask);
  461. add_mode(chan, '-', 'b', mask);
  462. return;
  463. }
  464. }
  465. i = 0;
  466. for (b = chan->channel.ban; b && b->mask && b->mask[0]; b = b->next) {
  467. if ((!u_equals_mask(global_bans, b->mask)) &&
  468. (!u_equals_mask(chan->bans, b->mask))) {
  469. i++;
  470. if (i == -j) {
  471. add_mode(chan, '-', 'b', b->mask);
  472. dprintf(idx, "%s '%s' on %s.\n", IRC_REMOVEDBAN,
  473. b->mask, chan->dname);
  474. putlog(LOG_CMDS, "*", "#%s# (%s) -ban %s [on channel]",
  475. dcc[idx].nick, dcc[idx].u.chat->con_chan, ban);
  476. return;
  477. }
  478. }
  479. }
  480. } else {
  481. j = u_delban(chan, ban, 1);
  482. if (j > 0) {
  483. putlog(LOG_CMDS, "*", "#%s# (%s) -ban %s", dcc[idx].nick,
  484. dcc[idx].u.chat->con_chan, ban);
  485. dprintf(idx, "Removed %s channel ban: %s\n", chname, ban);
  486. add_mode(chan, '-', 'b', ban);
  487. return;
  488. }
  489. for (b = chan->channel.ban; b && b->mask && b->mask[0]; b = b->next) {
  490. if (!rfc_casecmp(b->mask, ban)) {
  491. add_mode(chan, '-', 'b', b->mask);
  492. dprintf(idx, "%s '%s' on %s.\n", IRC_REMOVEDBAN, b->mask, chan->dname);
  493. putlog(LOG_CMDS, "*", "#%s# (%s) -ban %s [on channel]",
  494. dcc[idx].nick, dcc[idx].u.chat->con_chan, ban);
  495. return;
  496. }
  497. }
  498. }
  499. dprintf(idx, "No such ban.\n");
  500. }
  501. static void cmd_mns_exempt(struct userrec *u, int idx, char *par)
  502. {
  503. int console = 0, i = 0, j;
  504. struct chanset_t *chan = NULL;
  505. char s[UHOSTLEN], *exempt, *chname, *mask;
  506. masklist *e;
  507. if (!use_exempts) {
  508. dprintf(idx, "This command can only be used with use-exempts enabled.\n");
  509. return;
  510. }
  511. if (!par[0]) {
  512. dprintf(idx, "Usage: -exempt <hostmask|exempt #> [channel]\n");
  513. return;
  514. }
  515. exempt = newsplit(&par);
  516. if (par[0] && strchr(CHANMETA, par[0]))
  517. chname = newsplit(&par);
  518. else {
  519. chname = dcc[idx].u.chat->con_chan;
  520. console = 1;
  521. }
  522. if (chname || !(u->flags & USER_OP)) {
  523. if (!chname)
  524. chname = dcc[idx].u.chat->con_chan;
  525. get_user_flagrec(u, &user, chname);
  526. if ((!chan_op(user) && (!glob_op(user) || chan_deop(user))) &&
  527. (!chan_halfop(user) && (!glob_halfop(user) || chan_dehalfop(user)))) {
  528. dprintf(idx, "You don't have access to remove exempts on %s.\n", chname);
  529. return;
  530. }
  531. }
  532. strncpyz(s, exempt, sizeof s);
  533. if (console) {
  534. i = u_delexempt(NULL, s, (u->flags & USER_OP));
  535. if (i > 0) {
  536. if (lastdeletedmask)
  537. mask = lastdeletedmask;
  538. else
  539. mask = s;
  540. putlog(LOG_CMDS, "*", "#%s# -exempt %s", dcc[idx].nick, mask);
  541. dprintf(idx, "%s: %s\n", IRC_REMOVEDEXEMPT, mask);
  542. for (chan = chanset; chan != NULL; chan = chan->next)
  543. add_mode(chan, '-', 'e', mask);
  544. return;
  545. }
  546. }
  547. /* Channel-specific exempt? */
  548. if (chname)
  549. chan = findchan_by_dname(chname);
  550. if (!chan) {
  551. dprintf(idx, "Invalid channel.\n");
  552. return;
  553. }
  554. if (str_isdigit(exempt)) {
  555. i = atoi(exempt);
  556. /* substract the numer of global exempts to get the number of the channel exempt */
  557. egg_snprintf(s, sizeof s, "%d", i);
  558. j = u_delexempt(0, s, 0);
  559. if (j < 0) {
  560. egg_snprintf(s, sizeof s, "%d", -j);
  561. j = u_delexempt(chan, s, 1);
  562. if (j > 0) {
  563. if (lastdeletedmask)
  564. mask = lastdeletedmask;
  565. else
  566. mask = s;
  567. putlog(LOG_CMDS, "*", "#%s# (%s) -exempt %s", dcc[idx].nick,
  568. chan->dname, mask);
  569. dprintf(idx, "Removed %s channel exempt: %s\n", chan->dname, mask);
  570. add_mode(chan, '-', 'e', mask);
  571. return;
  572. }
  573. }
  574. i = 0;
  575. for (e = chan->channel.exempt; e && e->mask && e->mask[0]; e = e->next) {
  576. if (!u_equals_mask(global_exempts, e->mask) &&
  577. !u_equals_mask(chan->exempts, e->mask)) {
  578. i++;
  579. if (i == -j) {
  580. add_mode(chan, '-', 'e', e->mask);
  581. dprintf(idx, "%s '%s' on %s.\n", IRC_REMOVEDEXEMPT,
  582. e->mask, chan->dname);
  583. putlog(LOG_CMDS, "*", "#%s# (%s) -exempt %s [on channel]",
  584. dcc[idx].nick, dcc[idx].u.chat->con_chan, exempt);
  585. return;
  586. }
  587. }
  588. }
  589. } else {
  590. j = u_delexempt(chan, exempt, 1);
  591. if (j > 0) {
  592. putlog(LOG_CMDS, "*", "#%s# (%s) -exempt %s", dcc[idx].nick,
  593. dcc[idx].u.chat->con_chan, exempt);
  594. dprintf(idx, "Removed %s channel exempt: %s\n", chname, exempt);
  595. add_mode(chan, '-', 'e', exempt);
  596. return;
  597. }
  598. for (e = chan->channel.exempt; e && e->mask && e->mask[0]; e = e->next) {
  599. if (!rfc_casecmp(e->mask, exempt)) {
  600. add_mode(chan, '-', 'e', e->mask);
  601. dprintf(idx, "%s '%s' on %s.\n",
  602. IRC_REMOVEDEXEMPT, e->mask, chan->dname);
  603. putlog(LOG_CMDS, "*", "#%s# (%s) -exempt %s [on channel]",
  604. dcc[idx].nick, dcc[idx].u.chat->con_chan, exempt);
  605. return;
  606. }
  607. }
  608. }
  609. dprintf(idx, "No such exemption.\n");
  610. }
  611. static void cmd_mns_invite(struct userrec *u, int idx, char *par)
  612. {
  613. int console = 0, i = 0, j;
  614. struct chanset_t *chan = NULL;
  615. char s[UHOSTLEN], *invite, *chname, *mask;
  616. masklist *inv;
  617. if (!use_invites) {
  618. dprintf(idx, "This command can only be used with use-invites enabled.\n");
  619. return;
  620. }
  621. if (!par[0]) {
  622. dprintf(idx, "Usage: -invite <hostmask|invite #> [channel]\n");
  623. return;
  624. }
  625. invite = newsplit(&par);
  626. if (par[0] && strchr(CHANMETA, par[0]))
  627. chname = newsplit(&par);
  628. else {
  629. chname = dcc[idx].u.chat->con_chan;
  630. console = 1;
  631. }
  632. if (chname || !(u->flags & USER_OP)) {
  633. if (!chname)
  634. chname = dcc[idx].u.chat->con_chan;
  635. get_user_flagrec(u, &user, chname);
  636. if ((!chan_op(user) && (!glob_op(user) || chan_deop(user))) &&
  637. (!chan_halfop(user) && (!glob_halfop(user) || chan_dehalfop(user)))) {
  638. dprintf(idx, "You don't have access to remove invites on %s.\n", chname);
  639. return;
  640. }
  641. }
  642. strncpyz(s, invite, sizeof s);
  643. if (console) {
  644. i = u_delinvite(NULL, s, (u->flags & USER_OP));
  645. if (i > 0) {
  646. if (lastdeletedmask)
  647. mask = lastdeletedmask;
  648. else
  649. mask = s;
  650. putlog(LOG_CMDS, "*", "#%s# -invite %s", dcc[idx].nick, mask);
  651. dprintf(idx, "%s: %s\n", IRC_REMOVEDINVITE, mask);
  652. for (chan = chanset; chan != NULL; chan = chan->next)
  653. add_mode(chan, '-', 'I', mask);
  654. return;
  655. }
  656. }
  657. /* Channel-specific invite? */
  658. if (chname)
  659. chan = findchan_by_dname(chname);
  660. if (!chan) {
  661. dprintf(idx, "Invalid channel.\n");
  662. return;
  663. }
  664. if (str_isdigit(invite)) {
  665. i = atoi(invite);
  666. /* substract the numer of global invites to get the number of the channel invite */
  667. egg_snprintf(s, sizeof s, "%d", i);
  668. j = u_delinvite(0, s, 0);
  669. if (j < 0) {
  670. egg_snprintf(s, sizeof s, "%d", -j);
  671. j = u_delinvite(chan, s, 1);
  672. if (j > 0) {
  673. if (lastdeletedmask)
  674. mask = lastdeletedmask;
  675. else
  676. mask = s;
  677. putlog(LOG_CMDS, "*", "#%s# (%s) -invite %s", dcc[idx].nick,
  678. chan->dname, mask);
  679. dprintf(idx, "Removed %s channel invite: %s\n", chan->dname, mask);
  680. add_mode(chan, '-', 'I', mask);
  681. return;
  682. }
  683. }
  684. i = 0;
  685. for (inv = chan->channel.invite; inv && inv->mask && inv->mask[0];
  686. inv = inv->next) {
  687. if (!u_equals_mask(global_invites, inv->mask) &&
  688. !u_equals_mask(chan->invites, inv->mask)) {
  689. i++;
  690. if (i == -j) {
  691. add_mode(chan, '-', 'I', inv->mask);
  692. dprintf(idx, "%s '%s' on %s.\n", IRC_REMOVEDINVITE,
  693. inv->mask, chan->dname);
  694. putlog(LOG_CMDS, "*", "#%s# (%s) -invite %s [on channel]",
  695. dcc[idx].nick, dcc[idx].u.chat->con_chan, invite);
  696. return;
  697. }
  698. }
  699. }
  700. } else {
  701. j = u_delinvite(chan, invite, 1);
  702. if (j > 0) {
  703. putlog(LOG_CMDS, "*", "#%s# (%s) -invite %s", dcc[idx].nick,
  704. dcc[idx].u.chat->con_chan, invite);
  705. dprintf(idx, "Removed %s channel invite: %s\n", chname, invite);
  706. add_mode(chan, '-', 'I', invite);
  707. return;
  708. }
  709. for (inv = chan->channel.invite; inv && inv->mask && inv->mask[0];
  710. inv = inv->next) {
  711. if (!rfc_casecmp(inv->mask, invite)) {
  712. add_mode(chan, '-', 'I', inv->mask);
  713. dprintf(idx, "%s '%s' on %s.\n",
  714. IRC_REMOVEDINVITE, inv->mask, chan->dname);
  715. putlog(LOG_CMDS, "*", "#%s# (%s) -invite %s [on channel]",
  716. dcc[idx].nick, dcc[idx].u.chat->con_chan, invite);
  717. return;
  718. }
  719. }
  720. }
  721. dprintf(idx, "No such invite.\n");
  722. }
  723. static void cmd_bans(struct userrec *u, int idx, char *par)
  724. {
  725. if (!egg_strcasecmp(par, "all")) {
  726. putlog(LOG_CMDS, "*", "#%s# bans all", dcc[idx].nick);
  727. tell_bans(idx, 1, "");
  728. } else {
  729. putlog(LOG_CMDS, "*", "#%s# bans %s", dcc[idx].nick, par);
  730. tell_bans(idx, 0, par);
  731. }
  732. }
  733. static void cmd_exempts(struct userrec *u, int idx, char *par)
  734. {
  735. if (!use_exempts) {
  736. dprintf(idx, "This command can only be used with use-exempts enabled.\n");
  737. return;
  738. }
  739. if (!egg_strcasecmp(par, "all")) {
  740. putlog(LOG_CMDS, "*", "#%s# exempts all", dcc[idx].nick);
  741. tell_exempts(idx, 1, "");
  742. } else {
  743. putlog(LOG_CMDS, "*", "#%s# exempts %s", dcc[idx].nick, par);
  744. tell_exempts(idx, 0, par);
  745. }
  746. }
  747. static void cmd_invites(struct userrec *u, int idx, char *par)
  748. {
  749. if (!use_invites) {
  750. dprintf(idx, "This command can only be used with use-invites enabled.\n");
  751. return;
  752. }
  753. if (!egg_strcasecmp(par, "all")) {
  754. putlog(LOG_CMDS, "*", "#%s# invites all", dcc[idx].nick);
  755. tell_invites(idx, 1, "");
  756. } else {
  757. putlog(LOG_CMDS, "*", "#%s# invites %s", dcc[idx].nick, par);
  758. tell_invites(idx, 0, par);
  759. }
  760. }
  761. static void cmd_info(struct userrec *u, int idx, char *par)
  762. {
  763. char s[512], *chname, *s1;
  764. int locked = 0;
  765. if (!use_info) {
  766. dprintf(idx, "Info storage is turned off.\n");
  767. return;
  768. }
  769. s1 = get_user(&USERENTRY_INFO, u);
  770. if (s1 && s1[0] == '@')
  771. locked = 1;
  772. if (par[0] && strchr(CHANMETA, par[0])) {
  773. chname = newsplit(&par);
  774. if (!findchan_by_dname(chname)) {
  775. dprintf(idx, "No such channel.\n");
  776. return;
  777. }
  778. get_handle_chaninfo(dcc[idx].nick, chname, s);
  779. if (s[0] == '@')
  780. locked = 1;
  781. s1 = s;
  782. } else
  783. chname = 0;
  784. if (!par[0]) {
  785. if (s1 && s1[0] == '@')
  786. s1++;
  787. if (s1 && s1[0]) {
  788. if (chname) {
  789. dprintf(idx, "Info on %s: %s\n", chname, s1);
  790. dprintf(idx, "Use '.info %s none' to remove it.\n", chname);
  791. } else {
  792. dprintf(idx, "Default info: %s\n", s1);
  793. dprintf(idx, "Use '.info none' to remove it.\n");
  794. }
  795. } else
  796. dprintf(idx, "No info has been set for you.\n");
  797. putlog(LOG_CMDS, "*", "#%s# info %s", dcc[idx].nick, chname ? chname : "");
  798. return;
  799. }
  800. if (locked && !(u && (u->flags & USER_MASTER))) {
  801. dprintf(idx, "Your info line is locked. Sorry.\n");
  802. return;
  803. }
  804. if (!egg_strcasecmp(par, "none")) {
  805. if (chname) {
  806. par[0] = 0;
  807. set_handle_chaninfo(userlist, dcc[idx].nick, chname, NULL);
  808. dprintf(idx, "Removed your info line on %s.\n", chname);
  809. putlog(LOG_CMDS, "*", "#%s# info %s none", dcc[idx].nick, chname);
  810. } else {
  811. set_user(&USERENTRY_INFO, u, NULL);
  812. dprintf(idx, "Removed your default info line.\n");
  813. putlog(LOG_CMDS, "*", "#%s# info none", dcc[idx].nick);
  814. }
  815. return;
  816. }
  817. /* if (par[0] == '@') This is stupid, and prevents a users info from being locked */
  818. /* par++; without .tcl, or a tcl script, aka, 'half-assed' -poptix 4Jun01 */
  819. if (chname) {
  820. set_handle_chaninfo(userlist, dcc[idx].nick, chname, par);
  821. dprintf(idx, "Your info on %s is now: %s\n", chname, par);
  822. putlog(LOG_CMDS, "*", "#%s# info %s ...", dcc[idx].nick, chname);
  823. } else {
  824. set_user(&USERENTRY_INFO, u, par);
  825. dprintf(idx, "Your default info is now: %s\n", par);
  826. putlog(LOG_CMDS, "*", "#%s# info ...", dcc[idx].nick);
  827. }
  828. }
  829. static void cmd_chinfo(struct userrec *u, int idx, char *par)
  830. {
  831. char *handle, *chname;
  832. struct userrec *u1;
  833. if (!use_info) {
  834. dprintf(idx, "Info storage is turned off.\n");
  835. return;
  836. }
  837. handle = newsplit(&par);
  838. if (!handle[0]) {
  839. dprintf(idx, "Usage: chinfo <handle> [channel] <new-info>\n");
  840. return;
  841. }
  842. u1 = get_user_by_handle(userlist, handle);
  843. if (!u1) {
  844. dprintf(idx, "No such user.\n");
  845. return;
  846. }
  847. if (par[0] && strchr(CHANMETA, par[0])) {
  848. chname = newsplit(&par);
  849. if (!findchan_by_dname(chname)) {
  850. dprintf(idx, "No such channel.\n");
  851. return;
  852. }
  853. } else
  854. chname = 0;
  855. if ((u1->flags & USER_BOT) && !(u->flags & USER_MASTER)) {
  856. dprintf(idx, "You have to be master to change bots info.\n");
  857. return;
  858. }
  859. if ((u1->flags & USER_OWNER) && !(u->flags & USER_OWNER)) {
  860. dprintf(idx, "You can't change info for the bot owner.\n");
  861. return;
  862. }
  863. if (chname) {
  864. get_user_flagrec(u, &user, chname);
  865. get_user_flagrec(u1, &victim, chname);
  866. if ((chan_owner(victim) || glob_owner(victim)) &&
  867. !(glob_owner(user) || chan_owner(user))) {
  868. dprintf(idx, "You can't change info for the channel owner.\n");
  869. return;
  870. }
  871. }
  872. putlog(LOG_CMDS, "*", "#%s# chinfo %s %s %s", dcc[idx].nick, handle,
  873. chname ? chname : par, chname ? par : "");
  874. if (!egg_strcasecmp(par, "none"))
  875. par[0] = 0;
  876. if (chname) {
  877. set_handle_chaninfo(userlist, handle, chname, par);
  878. if (par[0] == '@')
  879. dprintf(idx, "New info (LOCKED) for %s on %s: %s\n", handle, chname,
  880. &par[1]);
  881. else if (par[0])
  882. dprintf(idx, "New info for %s on %s: %s\n", handle, chname, par);
  883. else
  884. dprintf(idx, "Wiped info for %s on %s\n", handle, chname);
  885. } else {
  886. set_user(&USERENTRY_INFO, u1, par[0] ? par : NULL);
  887. if (par[0] == '@')
  888. dprintf(idx, "New default info (LOCKED) for %s: %s\n", handle, &par[1]);
  889. else if (par[0])
  890. dprintf(idx, "New default info for %s: %s\n", handle, par);
  891. else
  892. dprintf(idx, "Wiped default info for %s\n", handle);
  893. }
  894. }
  895. static void cmd_stick_yn(int idx, char *par, int yn)
  896. {
  897. int i = 0, j;
  898. struct chanset_t *chan, *achan;
  899. char *stick_type, s[UHOSTLEN], chname[81];
  900. module_entry *me;
  901. stick_type = newsplit(&par);
  902. strncpyz(s, newsplit(&par), sizeof s);
  903. strncpyz(chname, newsplit(&par), sizeof chname);
  904. if (egg_strcasecmp(stick_type, "exempt") &&
  905. egg_strcasecmp(stick_type, "invite") &&
  906. egg_strcasecmp(stick_type, "ban")) {
  907. strncpyz(chname, s, sizeof chname);
  908. strncpyz(s, stick_type, sizeof s);
  909. }
  910. if (!s[0]) {
  911. dprintf(idx, "Usage: %sstick [ban/exempt/invite] <hostmask or number> "
  912. "[channel]\n", yn ? "" : "un");
  913. return;
  914. }
  915. /* Now deal with exemptions */
  916. if (!egg_strcasecmp(stick_type, "exempt")) {
  917. if (!use_exempts) {
  918. dprintf(idx, "This command can only be used with use-exempts "
  919. "enabled.\n");
  920. return;
  921. }
  922. if (!chname[0]) {
  923. i = u_setsticky_exempt(NULL, s,
  924. (dcc[idx].user->flags & USER_OP) ? yn : -1);
  925. if (i > 0) {
  926. putlog(LOG_CMDS, "*", "#%s# %sstick exempt %s",
  927. dcc[idx].nick, yn ? "" : "un", s);
  928. dprintf(idx, "%stuck exempt: %s\n", yn ? "S" : "Uns", s);
  929. return;
  930. }
  931. strncpyz(chname, dcc[idx].u.chat->con_chan, sizeof chname);
  932. }
  933. /* Channel-specific exempt? */
  934. if (!(chan = findchan_by_dname(chname))) {
  935. dprintf(idx, "No such channel.\n");
  936. return;
  937. }
  938. if (str_isdigit(s)) {
  939. /* substract the numer of global exempts to get the number of the channel exempt */
  940. j = u_setsticky_exempt(NULL, s, -1);
  941. if (j < 0)
  942. egg_snprintf(s, sizeof s, "%d", -j);
  943. }
  944. j = u_setsticky_exempt(chan, s, yn);
  945. if (j > 0) {
  946. putlog(LOG_CMDS, "*", "#%s# %sstick exempt %s %s", dcc[idx].nick,
  947. yn ? "" : "un", s, chname);
  948. dprintf(idx, "%stuck %s exempt: %s\n", yn ? "S" : "Uns", chname, s);
  949. return;
  950. }
  951. dprintf(idx, "No such exempt.\n");
  952. return;
  953. }
  954. /* Now the invites */
  955. else if (!egg_strcasecmp(stick_type, "invite")) {
  956. if (!use_invites) {
  957. dprintf(idx, "This command can only be used with use-invites enabled.\n");
  958. return;
  959. }
  960. if (!chname[0]) {
  961. i = u_setsticky_invite(NULL, s,
  962. (dcc[idx].user->flags & USER_OP) ? yn : -1);
  963. if (i > 0) {
  964. putlog(LOG_CMDS, "*", "#%s# %sstick invite %s",
  965. dcc[idx].nick, yn ? "" : "un", s);
  966. dprintf(idx, "%stuck invite: %s\n", yn ? "S" : "Uns", s);
  967. return;
  968. }
  969. strncpyz(chname, dcc[idx].u.chat->con_chan, sizeof chname);
  970. }
  971. /* Channel-specific invite? */
  972. if (!(chan = findchan_by_dname(chname))) {
  973. dprintf(idx, "No such channel.\n");
  974. return;
  975. }
  976. if (str_isdigit(s)) {
  977. /* substract the numer of global invites to get the number of the channel invite */
  978. j = u_setsticky_invite(NULL, s, -1);
  979. if (j < 0)
  980. egg_snprintf(s, sizeof s, "%d", -j);
  981. }
  982. j = u_setsticky_invite(chan, s, yn);
  983. if (j > 0) {
  984. putlog(LOG_CMDS, "*", "#%s# %sstick invite %s %s", dcc[idx].nick,
  985. yn ? "" : "un", s, chname);
  986. dprintf(idx, "%stuck %s invite: %s\n", yn ? "S" : "Uns", chname, s);
  987. return;
  988. }
  989. dprintf(idx, "No such invite.\n");
  990. return;
  991. }
  992. if (!chname[0]) {
  993. i = u_setsticky_ban(NULL, s,
  994. (dcc[idx].user->flags & USER_OP) ? yn : -1);
  995. if (i > 0) {
  996. putlog(LOG_CMDS, "*", "#%s# %sstick ban %s",
  997. dcc[idx].nick, yn ? "" : "un", s);
  998. dprintf(idx, "%stuck ban: %s\n", yn ? "S" : "Uns", s);
  999. if ((me = module_find("irc", 0, 0)))
  1000. for (achan = chanset; achan != NULL; achan = achan->next)
  1001. (me->funcs[IRC_CHECK_THIS_BAN]) (achan, s, yn);
  1002. return;
  1003. }
  1004. strncpyz(chname, dcc[idx].u.chat->con_chan, sizeof chname);
  1005. }
  1006. /* Channel-specific ban? */
  1007. if (!(chan = findchan_by_dname(chname))) {
  1008. dprintf(idx, "No such channel.\n");
  1009. return;
  1010. }
  1011. if (str_isdigit(s)) {
  1012. /* substract the numer of global bans to get the number of the channel ban */
  1013. j = u_setsticky_ban(NULL, s, -1);
  1014. if (j < 0)
  1015. egg_snprintf(s, sizeof s, "%d", -j);
  1016. }
  1017. j = u_setsticky_ban(chan, s, yn);
  1018. if (j > 0) {
  1019. putlog(LOG_CMDS, "*", "#%s# %sstick ban %s %s", dcc[idx].nick,
  1020. yn ? "" : "un", s, chname);
  1021. dprintf(idx, "%stuck %s ban: %s\n", yn ? "S" : "Uns", chname, s);
  1022. if ((me = module_find("irc", 0, 0)))
  1023. (me->funcs[IRC_CHECK_THIS_BAN]) (chan, s, yn);
  1024. return;
  1025. }
  1026. dprintf(idx, "No such ban.\n");
  1027. }
  1028. static void cmd_stick(struct userrec *u, int idx, char *par)
  1029. {
  1030. cmd_stick_yn(idx, par, 1);
  1031. }
  1032. static void cmd_unstick(struct userrec *u, int idx, char *par)
  1033. {
  1034. cmd_stick_yn(idx, par, 0);
  1035. }
  1036. static void cmd_pls_chrec(struct userrec *u, int idx, char *par)
  1037. {
  1038. char *nick, *chn;
  1039. struct chanset_t *chan;
  1040. struct userrec *u1;
  1041. struct chanuserrec *chanrec;
  1042. if (!par[0]) {
  1043. dprintf(idx, "Usage: +chrec <user> [channel]\n");
  1044. return;
  1045. }
  1046. nick = newsplit(&par);
  1047. u1 = get_user_by_handle(userlist, nick);
  1048. if (!u1) {
  1049. dprintf(idx, "No such user.\n");
  1050. return;
  1051. }
  1052. if (!par[0])
  1053. chan = findchan_by_dname(dcc[idx].u.chat->con_chan);
  1054. else {
  1055. chn = newsplit(&par);
  1056. chan = findchan_by_dname(chn);
  1057. }
  1058. if (!chan) {
  1059. dprintf(idx, "No such channel.\n");
  1060. return;
  1061. }
  1062. get_user_flagrec(u, &user, chan->dname);
  1063. get_user_flagrec(u1, &victim, chan->dname);
  1064. if ((!glob_master(user) && !chan_master(user)) || /* drummer */
  1065. (chan_owner(victim) && !chan_owner(user) && !glob_owner(user)) ||
  1066. (glob_owner(victim) && !glob_owner(user))) {
  1067. dprintf(idx, "You have no permission to do that.\n");
  1068. return;
  1069. }
  1070. chanrec = get_chanrec(u1, chan->dname);
  1071. if (chanrec) {
  1072. dprintf(idx, "User %s already has a channel record for %s.\n",
  1073. nick, chan->dname);
  1074. return;
  1075. }
  1076. putlog(LOG_CMDS, "*", "#%s# +chrec %s %s", dcc[idx].nick, nick, chan->dname);
  1077. add_chanrec(u1, chan->dname);
  1078. dprintf(idx, "Added %s channel record for %s.\n", chan->dname, nick);
  1079. }
  1080. static void cmd_mns_chrec(struct userrec *u, int idx, char *par)
  1081. {
  1082. char *nick, *chn = NULL;
  1083. struct userrec *u1;
  1084. struct chanuserrec *chanrec;
  1085. if (!par[0]) {
  1086. dprintf(idx, "Usage: -chrec <user> [channel]\n");
  1087. return;
  1088. }
  1089. nick = newsplit(&par);
  1090. u1 = get_user_by_handle(userlist, nick);
  1091. if (!u1) {
  1092. dprintf(idx, "No such user.\n");
  1093. return;
  1094. }
  1095. if (!par[0]) {
  1096. struct chanset_t *chan;
  1097. chan = findchan_by_dname(dcc[idx].u.chat->con_chan);
  1098. if (chan)
  1099. chn = chan->dname;
  1100. else {
  1101. dprintf(idx, "Invalid console channel.\n");
  1102. return;
  1103. }
  1104. } else
  1105. chn = newsplit(&par);
  1106. get_user_flagrec(u, &user, chn);
  1107. get_user_flagrec(u1, &victim, chn);
  1108. if ((!glob_master(user) && !chan_master(user)) || /* drummer */
  1109. (chan_owner(victim) && !chan_owner(user) && !glob_owner(user)) ||
  1110. (glob_owner(victim) && !glob_owner(user))) {
  1111. dprintf(idx, "You have no permission to do that.\n");
  1112. return;
  1113. }
  1114. chanrec = get_chanrec(u1, chn);
  1115. if (!chanrec) {
  1116. dprintf(idx, "User %s doesn't have a channel record for %s.\n", nick, chn);
  1117. return;
  1118. }
  1119. putlog(LOG_CMDS, "*", "#%s# -chrec %s %s", dcc[idx].nick, nick, chn);
  1120. del_chanrec(u1, chn);
  1121. dprintf(idx, "Removed %s channel record from %s.\n", chn, nick);
  1122. }
  1123. static void cmd_pls_chan(struct userrec *u, int idx, char *par)
  1124. {
  1125. int i, argc;
  1126. EGG_CONST char **argv;
  1127. char *chname;
  1128. struct chanset_t *chan;
  1129. if (!par[0]) {
  1130. dprintf(idx, "Usage: +chan [%s]<channel> [options]\n", CHANMETA);
  1131. return;
  1132. }
  1133. chname = newsplit(&par);
  1134. if (findchan_by_dname(chname)) {
  1135. dprintf(idx, "That channel already exists!\n");
  1136. return;
  1137. } else if ((chan = findchan(chname))) {
  1138. dprintf(idx, "That channel already exists as %s!\n", chan->dname);
  1139. return;
  1140. } else if (strchr(CHANMETA, chname[0]) == NULL) {
  1141. dprintf(idx, "Invalid channel prefix.\n");
  1142. return;
  1143. } else if (strchr(chname, ',') != NULL) {
  1144. dprintf(idx, "Invalid channel name.\n");
  1145. return;
  1146. }
  1147. if (Tcl_SplitList(NULL, par, &argc, &argv ) == TCL_ERROR) {
  1148. dprintf(idx, "Invalid channel options.\n");
  1149. return;
  1150. }
  1151. for (i = 0; i < argc; i++) {
  1152. if ((!strncmp(argv[i], "need-", 5) || !strcmp(argv[i] + 1, "static"))
  1153. && (!(u->flags & USER_OWNER) || (!isowner(dcc[idx].nick)
  1154. && must_be_owner))) {
  1155. dprintf(idx, "Due to security concerns, only permanent owners can "
  1156. "set the need-* and +/-static modes.\n");
  1157. Tcl_Free((char *) argv);
  1158. return;
  1159. }
  1160. if (argv[i][0] == '-' || argv[i][0] == '+')
  1161. continue;
  1162. i++;
  1163. }
  1164. Tcl_Free((char *) argv);
  1165. if (tcl_channel_add(0, chname, par) == TCL_ERROR)
  1166. dprintf(idx, "Invalid channel or channel options.\n");
  1167. else
  1168. putlog(LOG_CMDS, "*", "#%s# +chan %s", dcc[idx].nick, chname);
  1169. }
  1170. static void cmd_mns_chan(struct userrec *u, int idx, char *par)
  1171. {
  1172. char *chname;
  1173. struct chanset_t *chan;
  1174. int i;
  1175. if (!par[0]) {
  1176. dprintf(idx, "Usage: -chan [%s]<channel>\n", CHANMETA);
  1177. return;
  1178. }
  1179. chname = newsplit(&par);
  1180. chan = findchan_by_dname(chname);
  1181. if (!chan) {
  1182. if ((chan = findchan(chname)))
  1183. dprintf(idx, "That channel exists with a short name of %s, use that.\n",
  1184. chan->dname);
  1185. else
  1186. dprintf(idx, "That channel doesn't exist!\n");
  1187. return;
  1188. }
  1189. if (channel_static(chan)) {
  1190. dprintf(idx, "Cannot remove %s, it is a static channel!\n", chname);
  1191. return;
  1192. }
  1193. for (i = 0; i < dcc_total; i++)
  1194. if ((dcc[i].type->flags & DCT_CHAT) &&
  1195. !rfc_casecmp(dcc[i].u.chat->con_chan, chan->dname)) {
  1196. dprintf(i, "%s is no longer a valid channel, changing your console "
  1197. "to '*'\n", chname);
  1198. strcpy(dcc[i].u.chat->con_chan, "*");
  1199. }
  1200. remove_channel(chan);
  1201. dprintf(idx, "Channel %s removed from the bot.\n", chname);
  1202. dprintf(idx, "This includes any channel specific bans, invites, exemptions "
  1203. "and user records that you set.\n");
  1204. putlog(LOG_CMDS, "*", "#%s# -chan %s", dcc[idx].nick, chname);
  1205. }
  1206. static void cmd_chaninfo(struct userrec *u, int idx, char *par)
  1207. {
  1208. char *chname, work[512];
  1209. struct chanset_t *chan;
  1210. int ii, tmp;
  1211. struct udef_struct *ul;
  1212. if (!par[0]) {
  1213. chname = dcc[idx].u.chat->con_chan;
  1214. if (chname[0] == '*') {
  1215. dprintf(idx, "Your console channel is invalid.\n");
  1216. return;
  1217. }
  1218. } else {
  1219. chname = newsplit(&par);
  1220. get_user_flagrec(u, &user, chname);
  1221. if (!glob_master(user) && !chan_master(user)) {
  1222. dprintf(idx, "You don't have access to %s.\n", chname);
  1223. return;
  1224. }
  1225. }
  1226. if (!(chan = findchan_by_dname(chname)))
  1227. dprintf(idx, "No such channel defined.\n");
  1228. else {
  1229. dprintf(idx, "Settings for %s channel %s:\n",
  1230. channel_static(chan) ? "static" : "dynamic", chan->dname);
  1231. get_mode_protect(chan, work);
  1232. dprintf(idx, "Protect modes (chanmode): %s\n", work[0] ? work : "None");
  1233. if (chan->idle_kick)
  1234. dprintf(idx, "Idle Kick after (idle-kick): %d\n", chan->idle_kick);
  1235. else
  1236. dprintf(idx, "Idle Kick after (idle-kick): DON'T!\n");
  1237. if (chan->stopnethack_mode)
  1238. dprintf(idx, "stopnethack-mode: %d\n", chan->stopnethack_mode);
  1239. else
  1240. dprintf(idx, "stopnethack: DON'T!\n");
  1241. dprintf(idx, "aop-delay: %d:%d\n", chan->aop_min, chan->aop_max);
  1242. if (chan->revenge_mode)
  1243. dprintf(idx, "revenge-mode: %d\n", chan->revenge_mode);
  1244. else
  1245. dprintf(idx, "revenge-mode: 0\n");
  1246. dprintf(idx, "ban-type: %d\n", chan->ban_type);
  1247. if (chan->ban_time)
  1248. dprintf(idx, "ban-time: %d\n", chan->ban_time);
  1249. else
  1250. dprintf(idx, "ban-time: 0\n");
  1251. if (chan->exempt_time)
  1252. dprintf(idx, "exempt-time: %d\n", chan->exempt_time);
  1253. else
  1254. dprintf(idx, "exempt-time: 0\n");
  1255. if (chan->invite_time)
  1256. dprintf(idx, "invite-time: %d\n", chan->invite_time);
  1257. else
  1258. dprintf(idx, "invite-time: 0\n");
  1259. /* Only bot owners can see/change these (they're TCL commands) */
  1260. if (u->flags & USER_OWNER) {
  1261. if (chan->need_op[0])
  1262. dprintf(idx, "To regain op's (need-op):\n%s\n", chan->need_op);
  1263. if (chan->need_invite[0])
  1264. dprintf(idx, "To get invite (need-invite):\n%s\n", chan->need_invite);
  1265. if (chan->need_key[0])
  1266. dprintf(idx, "To get key (need-key):\n%s\n", chan->need_key);
  1267. if (chan->need_unban[0])
  1268. dprintf(idx, "If I'm banned (need-unban):\n%s\n", chan->need_unban);
  1269. if (chan->need_limit[0])
  1270. dprintf(idx, "When channel full (need-limit):\n%s\n",
  1271. chan->need_limit);
  1272. }
  1273. dprintf(idx, "Other modes:\n");
  1274. dprintf(idx,
  1275. " %cinactive %cstatuslog %csecret "
  1276. "%cshared\n", (chan->status & CHAN_INACTIVE) ? '+' : '-',
  1277. (chan->status & CHAN_LOGSTATUS) ? '+' : '-',
  1278. (chan->status & CHAN_SECRET) ? '+' : '-',
  1279. (chan->status & CHAN_SHARED) ? '+' : '-');
  1280. dprintf(idx,
  1281. " %cgreet %cseen %ccycle "
  1282. "%cdontkickops\n", (chan->status & CHAN_GREET) ? '+' : '-',
  1283. (chan->status & CHAN_SEEN) ? '+' : '-',
  1284. (chan->status & CHAN_CYCLE) ? '+' : '-',
  1285. (chan->status & CHAN_DONTKICKOPS) ? '+' : '-');
  1286. dprintf(idx,
  1287. " %cprotectops %cprotectfriends %crevenge "
  1288. "%crevengebot\n", (chan->status & CHAN_PROTECTOPS) ? '+' : '-',
  1289. (chan->status & CHAN_PROTECTFRIENDS) ? '+' : '-',
  1290. (chan->status & CHAN_REVENGE) ? '+' : '-',
  1291. (chan->status & CHAN_REVENGEBOT) ? '+' : '-');
  1292. dprintf(idx,
  1293. " %cbitch %cautoop %cautovoice "
  1294. "%cnodesynch\n", (chan->status & CHAN_BITCH) ? '+' : '-',
  1295. (chan->status & CHAN_OPONJOIN) ? '+' : '-',
  1296. (chan->status & CHAN_AUTOVOICE) ? '+' : '-',
  1297. (chan->status & CHAN_NODESYNCH) ? '+' : '-');
  1298. dprintf(idx,
  1299. " %cenforcebans %cdynamicbans %cuserbans "
  1300. "%cautohalfop\n", (chan->status & CHAN_ENFORCEBANS) ? '+' : '-',
  1301. (chan->status & CHAN_DYNAMICBANS) ? '+' : '-',
  1302. (chan->status & CHAN_NOUSERBANS) ? '-' : '+',
  1303. (chan->status & CHAN_AUTOHALFOP) ? '+' : '-');
  1304. dprintf(idx, " %cprotecthalfops %cstatic\n",
  1305. (chan->status & CHAN_PROTECTHALFOPS) ? '+' : '-',
  1306. (chan->status & CHAN_STATIC) ? '+' : '-');
  1307. dprintf(idx,
  1308. " %cdynamicexempts %cuserexempts %cdynamicinvites "
  1309. "%cuserinvites\n",
  1310. (chan->ircnet_status & CHAN_DYNAMICEXEMPTS) ? '+' : '-',
  1311. (chan->ircnet_status & CHAN_NOUSEREXEMPTS) ? '-' : '+',
  1312. (chan->ircnet_status & CHAN_DYNAMICINVITES) ? '+' : '-',
  1313. (chan->ircnet_status & CHAN_NOUSERINVITES) ? '-' : '+');
  1314. ii = 1;
  1315. tmp = 0;
  1316. for (ul = udef; ul; ul = ul->next)
  1317. if (ul->defined && ul->type == UDEF_FLAG) {
  1318. int work_len;
  1319. if (!tmp) {
  1320. dprintf(idx, "User defined channel flags:\n");
  1321. tmp = 1;
  1322. }
  1323. if (ii == 1)
  1324. egg_snprintf(work, sizeof work, " ");
  1325. work_len = strlen(work);
  1326. egg_snprintf(work + work_len, sizeof(work) - work_len, " %c%s",
  1327. getudef(ul->values, chan->dname) ? '+' : '-', ul->name);
  1328. ii++;
  1329. if (ii > 4) {
  1330. dprintf(idx, "%s\n", work);
  1331. ii = 1;
  1332. }
  1333. }
  1334. if (ii > 1)
  1335. dprintf(idx, "%s\n", work);
  1336. work[0] = 0;
  1337. ii = 1;
  1338. tmp = 0;
  1339. for (ul = udef; ul; ul = ul->next)
  1340. if (ul->defined && ul->type == UDEF_INT) {
  1341. int work_len = strlen(work);
  1342. if (!tmp) {
  1343. dprintf(idx, "User defined channel settings:\n");
  1344. tmp = 1;
  1345. }
  1346. egg_snprintf(work + work_len, sizeof(work) - work_len, "%s: %d ",
  1347. ul->name, getudef(ul->values, chan->dname));
  1348. ii++;
  1349. if (ii > 4) {
  1350. dprintf(idx, "%s\n", work);
  1351. work[0] = 0;
  1352. ii = 1;
  1353. }
  1354. }
  1355. if (ii > 1)
  1356. dprintf(idx, "%s\n", work);
  1357. if (u->flags & USER_OWNER) {
  1358. tmp = 0;
  1359. for (ul = udef; ul; ul = ul->next) {
  1360. if (ul->defined && ul->type == UDEF_STR) {
  1361. char *p = (char *) getudef(ul->values, chan->dname);
  1362. if (!p)
  1363. p = "{}";
  1364. if (!tmp) {
  1365. dprintf(idx, "User defined channel strings:\n");
  1366. tmp = 1;
  1367. }
  1368. dprintf(idx, "%s: %s\n", ul->name, p);
  1369. }
  1370. }
  1371. }
  1372. dprintf(idx, "flood settings: chan ctcp join kick deop nick\n");
  1373. dprintf(idx, "number: %3d %3d %3d %3d %3d %3d\n",
  1374. chan->flood_pub_thr, chan->flood_ctcp_thr,
  1375. chan->flood_join_thr, chan->flood_kick_thr,
  1376. chan->flood_deop_thr, chan->flood_nick_thr);
  1377. dprintf(idx, "time : %3d %3d %3d %3d %3d %3d\n",
  1378. chan->flood_pub_time, chan->flood_ctcp_time,
  1379. chan->flood_join_time, chan->flood_kick_time,
  1380. chan->flood_deop_time, chan->flood_nick_time);
  1381. putlog(LOG_CMDS, "*", "#%s# chaninfo %s", dcc[idx].nick, chname);
  1382. }
  1383. }
  1384. static void cmd_chanset(struct userrec *u, int idx, char *par)
  1385. {
  1386. char *chname = NULL, answers[512], *parcpy;
  1387. char *list[2], *bak, *buf;
  1388. struct chanset_t *chan = NULL;
  1389. int all = 0;
  1390. if (!par[0])
  1391. dprintf(idx, "Usage: chanset [%schannel] <settings>\n", CHANMETA);
  1392. else {
  1393. if (strlen(par) > 2 && par[0] == '*' && par[1] == ' ') {
  1394. all = 1;
  1395. get_user_flagrec(u, &user, chanset ? chanset->dname : "");
  1396. if (!glob_master(user)) {
  1397. dprintf(idx, "You need to be a global master to use .chanset *.\n");
  1398. return;
  1399. }
  1400. newsplit(&par);
  1401. } else {
  1402. if (strchr(CHANMETA, par[0])) {
  1403. chname = newsplit(&par);
  1404. get_user_flagrec(u, &user, chname);
  1405. if (!glob_master(user) && !chan_master(user)) {
  1406. dprintf(idx, "You don't have access to %s. \n", chname);
  1407. return;
  1408. } else if (!(chan = findchan_by_dname(chname)) && (chname[0] != '+')) {
  1409. dprintf(idx, "That channel doesn't exist!\n");
  1410. return;
  1411. }
  1412. if (!chan) {
  1413. if (par[0])
  1414. *--par = ' ';
  1415. par = chname;
  1416. }
  1417. }
  1418. if (!par[0] || par[0] == '*') {
  1419. dprintf(idx, "Usage: chanset [%schannel] <settings>\n", CHANMETA);
  1420. return;
  1421. }
  1422. if (!chan &&
  1423. !(chan = findchan_by_dname(chname = dcc[idx].u.chat->con_chan))) {
  1424. dprintf(idx, "Invalid console channel.\n");
  1425. return;
  1426. }
  1427. }
  1428. if (all)
  1429. chan = chanset;
  1430. bak = par;
  1431. buf = nmalloc(strlen(par) + 1);
  1432. while (chan) {
  1433. chname = chan->dname;
  1434. strcpy(buf, bak);
  1435. par = buf;
  1436. list[0] = newsplit(&par);
  1437. answers[0] = 0;
  1438. while (list[0][0]) {
  1439. if (list[0][0] == '+' || list[0][0] == '-' ||
  1440. (!strcmp(list[0], "dont-idle-kick"))) {
  1441. if (!strcmp(list[0] + 1, "static") && must_be_owner &&
  1442. !(isowner(dcc[idx].nick))) {
  1443. dprintf(idx, "Only permanent owners can modify the static flag.\n");
  1444. nfree(buf);
  1445. return;
  1446. }
  1447. if (tcl_channel_modify(0, chan, 1, list) == TCL_OK) {
  1448. strcat(answers, list[0]);
  1449. strcat(answers, " ");
  1450. } else if (!all || !chan->next)
  1451. dprintf(idx, "Error trying to set %s for %s, invalid mode.\n",
  1452. list[0], all ? "all channels" : chname);
  1453. list[0] = newsplit(&par);
  1454. continue;
  1455. }
  1456. /* The rest have an unknown amount of args, so assume the rest of the
  1457. * line is args. Woops nearly made a nasty little hole her…

Large files files are truncated, but you can click here to view the full file