cmdsirc.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938
  1. /*
  2. * chancmds.c -- part of irc.mod
  3. * handles commands direclty relating to channel interaction
  4. *
  5. * $Id: cmdsirc.c,v 1.19 2000/01/08 21:23:16 per Exp $
  6. */
  7. /*
  8. * Copyright (C) 1997 Robey Pointer
  9. * Copyright (C) 1999, 2000 Eggheads
  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. /* Do we have any flags that will allow us ops on a channel? */
  26. static struct chanset_t *has_op(int idx, char *chname)
  27. {
  28. struct chanset_t *chan;
  29. Context;
  30. if (chname && chname[0]) {
  31. chan = findchan(chname);
  32. if (!chan) {
  33. dprintf(idx, "No such channel.\n");
  34. return 0;
  35. }
  36. } else {
  37. chname = dcc[idx].u.chat->con_chan;
  38. chan = findchan(chname);
  39. if (!chan) {
  40. dprintf(idx, "Invalid console channel.\n");
  41. return 0;
  42. }
  43. }
  44. get_user_flagrec(dcc[idx].user, &user, chname);
  45. if (chan_op(user) || (glob_op(user) && !chan_deop(user)))
  46. return chan;
  47. dprintf(idx, "You are not a channel op on %s.\n", chan->name);
  48. return 0;
  49. }
  50. static void cmd_act(struct userrec *u, int idx, char *par)
  51. {
  52. char *chname;
  53. struct chanset_t *chan;
  54. memberlist *m;
  55. if (!par[0]) {
  56. dprintf(idx, "Usage: act [channel] <action>\n");
  57. return;
  58. }
  59. if (strchr(CHANMETA, par[0]) != NULL)
  60. chname = newsplit(&par);
  61. else
  62. chname = 0;
  63. if (!(chan = has_op(idx, chname)))
  64. return;
  65. m = ismember(chan, botname);
  66. if (!m) {
  67. dprintf(idx, "Cannot say to %s: I'm not on that channel.\n", chan->name);
  68. return;
  69. }
  70. if ((chan->channel.mode & CHANMODER) && !(m->flags & (CHANOP | CHANVOICE))) {
  71. dprintf(idx, "Cannot say to %s, it is moderated.\n", chan->name);
  72. return;
  73. }
  74. putlog(LOG_CMDS, "*", "#%s# (%s) act %s", dcc[idx].nick,
  75. chan->name, par);
  76. dprintf(DP_HELP, "PRIVMSG %s :\001ACTION %s\001\n",
  77. chan->name, par);
  78. dprintf(idx, "Action to %s: %s\n", chan->name, par);
  79. }
  80. static void cmd_msg(struct userrec *u, int idx, char *par)
  81. {
  82. char *nick;
  83. if (!par[0]) {
  84. dprintf(idx, "Usage: msg <nick> <message>\n");
  85. } else {
  86. nick = newsplit(&par);
  87. putlog(LOG_CMDS, "*", "#%s# msg %s %s", dcc[idx].nick, nick, par);
  88. dprintf(DP_HELP, "PRIVMSG %s :%s\n", nick, par);
  89. dprintf(idx, "Msg to %s: %s\n", nick, par);
  90. }
  91. }
  92. static void cmd_say(struct userrec *u, int idx, char *par)
  93. {
  94. char *chname;
  95. struct chanset_t *chan;
  96. memberlist *m;
  97. if (!par[0]) {
  98. dprintf(idx, "Usage: say [channel] <message>\n");
  99. return;
  100. }
  101. if (strchr(CHANMETA, par[0]) != NULL)
  102. chname = newsplit(&par);
  103. else
  104. chname = 0;
  105. if (!(chan = has_op(idx, chname)))
  106. return;
  107. m = ismember(chan, botname);
  108. if (!m) {
  109. dprintf(idx, "Cannot say to %s: I'm not on that channel.\n", chan->name);
  110. return;
  111. }
  112. if ((chan->channel.mode & CHANMODER) && !(m->flags & (CHANOP | CHANVOICE))) {
  113. dprintf(idx, "Cannot say to %s, it is moderated.\n", chan->name);
  114. return;
  115. }
  116. putlog(LOG_CMDS, "*", "#%s# (%s) say %s", dcc[idx].nick, chan->name, par);
  117. dprintf(DP_HELP, "PRIVMSG %s :%s\n", chan->name, par);
  118. dprintf(idx, "Said to %s: %s\n", chan->name, par);
  119. }
  120. static void cmd_kickban(struct userrec *u, int idx, char *par)
  121. {
  122. struct chanset_t *chan;
  123. char *chname, *nick, *s1;
  124. memberlist *m;
  125. char s[1024];
  126. char bantype = 0;
  127. if (!par[0]) {
  128. dprintf(idx, "Usage: kickban [channel] [-|@]<nick> [reason]\n");
  129. return;
  130. }
  131. if (strchr(CHANMETA, par[0]) != NULL)
  132. chname = newsplit(&par);
  133. else
  134. chname = 0;
  135. if (!(chan = has_op(idx, chname)))
  136. return;
  137. if (!me_op(chan)) {
  138. dprintf(idx, "I can't help you now because I'm not a channel op on %s.\n",
  139. chan->name);
  140. return;
  141. }
  142. putlog(LOG_CMDS, "*", "#%s# (%s) kickban %s", dcc[idx].nick,
  143. chan->name, par);
  144. nick = newsplit(&par);
  145. if ((nick[0] == '@') || (nick[0] == '-')) {
  146. bantype = nick[0];
  147. nick++;
  148. }
  149. if (match_my_nick(nick)) {
  150. dprintf(idx, "You're trying to pull a Run?\n");
  151. return;
  152. } else {
  153. m = ismember(chan, nick);
  154. if (!m) {
  155. dprintf(idx, "%s is not on %s\n", nick, chan->name);
  156. } else {
  157. simple_sprintf(s, "%s!%s", m->nick, m->userhost);
  158. u = get_user_by_host(s);
  159. get_user_flagrec(u, &victim, chan->name);
  160. if ((chan_op(victim) || (glob_op(victim) && !chan_deop(victim))) &&
  161. !(chan_master(user) || glob_master(user))) {
  162. dprintf(idx, "%s is a legal op.\n", nick);
  163. return;
  164. }
  165. if ((chan_master(victim) || glob_master(victim)) &&
  166. !(glob_owner(user) || chan_owner(user))) {
  167. dprintf(idx, "%s is a %s master.\n", nick, chan->name);
  168. return;
  169. }
  170. if (glob_bot(victim) && !(glob_owner(victim) || chan_owner(victim))) {
  171. dprintf(idx, "%s is another channel bot!\n", nick);
  172. return;
  173. }
  174. if (m->flags & CHANOP)
  175. add_mode(chan, '-', 'o', m->nick);
  176. switch (bantype) {
  177. case '@':
  178. s1 = strchr(s, '@');
  179. s1 -= 3;
  180. s1[0] = '*';
  181. s1[1] = '!';
  182. s1[2] = '*';
  183. break;
  184. case '!':
  185. s1 = strchr(s, '-');
  186. s1[1] = '*';
  187. s1--;
  188. s1[0] = '*';
  189. break;
  190. default:
  191. s1 = quickban(chan, m->userhost);
  192. break;
  193. }
  194. if (bantype == '@' || bantype == '-')
  195. do_mask(chan, chan->channel.ban, s1, 'b');
  196. if (!par[0])
  197. par = "requested";
  198. dprintf(DP_SERVER, "KICK %s %s :%s\n", chan->name, m->nick, par);
  199. m->flags |= SENTKICK;
  200. u_addban(chan, s1, dcc[idx].nick, par, now + (60 * ban_time), 0);
  201. dprintf(idx, "Okay, done.\n");
  202. }
  203. }
  204. }
  205. static void cmd_voice(struct userrec *u, int idx, char *par)
  206. {
  207. struct chanset_t *chan;
  208. char *nick;
  209. memberlist *m;
  210. char s[1024];
  211. if (!par[0]) {
  212. dprintf(idx, "Usage: voice <nick> [channel]\n");
  213. return;
  214. }
  215. nick = newsplit(&par);
  216. if (!(chan = has_op(idx, par)))
  217. return;
  218. if (!me_op(chan)) {
  219. dprintf(idx, "I can't help you now because I'm not a chan op on %s.\n",
  220. chan->name);
  221. return;
  222. }
  223. putlog(LOG_CMDS, "*", "#%s# (%s) voice %s %s", dcc[idx].nick,
  224. dcc[idx].u.chat->con_chan, nick, par);
  225. m = ismember(chan, nick);
  226. if (!m) {
  227. dprintf(idx, "%s is not on %s.\n", nick, chan->name);
  228. return;
  229. }
  230. simple_sprintf(s, "%s!%s", m->nick, m->userhost);
  231. add_mode(chan, '+', 'v', nick);
  232. dprintf(idx, "Gave voice to %s on %s\n", nick, chan->name);
  233. }
  234. static void cmd_devoice(struct userrec *u, int idx, char *par)
  235. {
  236. struct chanset_t *chan;
  237. char *nick;
  238. memberlist *m;
  239. char s[1024];
  240. if (!par[0]) {
  241. dprintf(idx, "Usage: devoice <nick> [channel]\n");
  242. return;
  243. }
  244. nick = newsplit(&par);
  245. if (!(chan = has_op(idx, par)))
  246. return;
  247. if (!me_op(chan)) {
  248. dprintf(idx, "I can't do that right now I'm not a chan op on %s.\n",
  249. chan->name);
  250. return;
  251. }
  252. putlog(LOG_CMDS, "*", "#%s# (%s) devoice %s %s", dcc[idx].nick,
  253. dcc[idx].u.chat->con_chan, nick, par);
  254. m = ismember(chan, nick);
  255. if (!m) {
  256. dprintf(idx, "%s is not on %s.\n", nick, chan->name);
  257. return;
  258. }
  259. simple_sprintf(s, "%s!%s", m->nick, m->userhost);
  260. add_mode(chan, '-', 'v', nick);
  261. dprintf(idx, "Devoiced %s on %s\n", nick, chan->name);
  262. }
  263. static void cmd_op(struct userrec *u, int idx, char *par)
  264. {
  265. struct chanset_t *chan;
  266. char *nick;
  267. memberlist *m;
  268. char s[1024];
  269. if (!par[0]) {
  270. dprintf(idx, "Usage: op <nick> [channel]\n");
  271. return;
  272. }
  273. nick = newsplit(&par);
  274. if (!(chan = has_op(idx, par)))
  275. return;
  276. if (!me_op(chan)) {
  277. dprintf(idx, "I can't help you now because I'm not a chan op on %s.\n",
  278. chan->name);
  279. return;
  280. }
  281. putlog(LOG_CMDS, "*", "#%s# (%s) op %s %s", dcc[idx].nick,
  282. dcc[idx].u.chat->con_chan, nick, par);
  283. m = ismember(chan, nick);
  284. if (!m) {
  285. dprintf(idx, "%s is not on %s.\n", nick, chan->name);
  286. return;
  287. }
  288. simple_sprintf(s, "%s!%s", m->nick, m->userhost);
  289. u = get_user_by_host(s);
  290. get_user_flagrec(u, &victim, chan->name);
  291. if (chan_deop(victim) || (glob_deop(victim) && !glob_op(victim))) {
  292. dprintf(idx, "%s is currently being auto-deopped.\n", m->nick);
  293. return;
  294. }
  295. if (channel_bitch(chan)
  296. && !(chan_op(victim) || (glob_op(victim) && !chan_deop(victim)))) {
  297. dprintf(idx, "%s is not a registered op.\n", m->nick);
  298. return;
  299. }
  300. add_mode(chan, '+', 'o', nick);
  301. dprintf(idx, "Gave op to %s on %s\n", nick, chan->name);
  302. }
  303. static void cmd_deop(struct userrec *u, int idx, char *par)
  304. {
  305. struct chanset_t *chan;
  306. char *nick;
  307. memberlist *m;
  308. char s[121];
  309. if (!par[0]) {
  310. dprintf(idx, "Usage: deop <nick> [channel]\n");
  311. return;
  312. }
  313. nick = newsplit(&par);
  314. if (!(chan = has_op(idx, par)))
  315. return;
  316. if (!me_op(chan)) {
  317. dprintf(idx, "I can't help you now because I'm not a chan op on %s.\n",
  318. chan->name);
  319. return;
  320. }
  321. putlog(LOG_CMDS, "*", "#%s# (%s) deop %s %s", dcc[idx].nick,
  322. dcc[idx].u.chat->con_chan, nick, par);
  323. m = ismember(chan, nick);
  324. if (!m) {
  325. dprintf(idx, "%s is not on %s.\n", nick, chan->name);
  326. return;
  327. }
  328. if (match_my_nick(nick)) {
  329. dprintf(idx, "I'm not going to deop myself.\n");
  330. return;
  331. }
  332. simple_sprintf(s, "%s!%s", m->nick, m->userhost);
  333. u = get_user_by_host(s);
  334. get_user_flagrec(u, &victim, chan->name);
  335. if ((chan_master(victim) || glob_master(victim)) &&
  336. !(chan_owner(user) || glob_owner(user))) {
  337. dprintf(idx, "%s is a master for %s\n", m->nick, chan->name);
  338. return;
  339. }
  340. if ((chan_op(victim) || (glob_op(victim) && !chan_deop(victim))) &&
  341. !(chan_master(user) || glob_master(user))) {
  342. dprintf(idx, "%s has the op flag for %s\n", m->nick, chan->name);
  343. return;
  344. }
  345. add_mode(chan, '-', 'o', nick);
  346. dprintf(idx, "Took op from %s on %s\n", nick, chan->name);
  347. }
  348. static void cmd_kick(struct userrec *u, int idx, char *par)
  349. {
  350. struct chanset_t *chan;
  351. char *chname, *nick;
  352. memberlist *m;
  353. char s[121];
  354. if (!par[0]) {
  355. dprintf(idx, "Usage: kick [channel] <nick> [reason]\n");
  356. return;
  357. }
  358. if (strchr(CHANMETA, par[0]) != NULL)
  359. chname = newsplit(&par);
  360. else
  361. chname = 0;
  362. if (!(chan = has_op(idx, chname)))
  363. return;
  364. if (!me_op(chan)) {
  365. dprintf(idx, "I can't help you now because I'm not a channel op on %s.\n",
  366. chan->name);
  367. return;
  368. }
  369. putlog(LOG_CMDS, "*", "#%s# (%s) kick %s", dcc[idx].nick,
  370. chan->name, par);
  371. nick = newsplit(&par);
  372. if (!par[0])
  373. par = "request";
  374. if (match_my_nick(nick)) {
  375. dprintf(idx, "But I don't WANT to kick myself!\n");
  376. return;
  377. }
  378. m = ismember(chan, nick);
  379. if (!m) {
  380. dprintf(idx, "%s is not on %s\n", nick, chan->name);
  381. return;
  382. }
  383. simple_sprintf(s, "%s!%s", m->nick, m->userhost);
  384. u = get_user_by_host(s);
  385. get_user_flagrec(u, &victim, chan->name);
  386. if ((chan_op(victim) || (glob_op(victim) && !chan_deop(victim))) &&
  387. !(chan_master(user) || glob_master(user))) {
  388. dprintf(idx, "%s is a legal op.\n", nick);
  389. return;
  390. }
  391. if ((chan_master(victim) || glob_master(victim)) &&
  392. !(glob_owner(user) || chan_owner(user))) {
  393. dprintf(idx, "%s is a %s master.\n", nick, chan->name);
  394. return;
  395. }
  396. if (glob_bot(victim) && !(glob_owner(victim) || chan_owner(victim))) {
  397. dprintf(idx, "%s is another channel bot!\n", nick);
  398. return;
  399. }
  400. dprintf(DP_SERVER, "KICK %s %s :%s\n", chan->name, m->nick, par);
  401. m->flags |= SENTKICK;
  402. dprintf(idx, "Okay, done.\n");
  403. }
  404. static void cmd_invite(struct userrec *u, int idx, char *par)
  405. {
  406. struct chanset_t *chan;
  407. memberlist *m;
  408. char *nick;
  409. if (!par[0])
  410. par = dcc[idx].nick; /* doh, it's been without this since .9 ! */
  411. /* (1.2.0+pop3) - poptix */
  412. nick = newsplit(&par);
  413. if (!(chan = has_op(idx, par)))
  414. return;
  415. putlog(LOG_CMDS, "*", "#%s# (%s) invite %s", dcc[idx].nick, chan->name, nick);
  416. if (!me_op(chan)) {
  417. if (chan->channel.mode & CHANINV) {
  418. dprintf(idx, "I'm not chop on %s, so I can't invite anyone.\n",
  419. chan->name);
  420. return;
  421. }
  422. if (!channel_active(chan)) {
  423. dprintf(idx, "I'm not on %s right now!\n", chan->name);
  424. return;
  425. }
  426. }
  427. m = ismember(chan, nick);
  428. if (m && !chan_issplit(m)) {
  429. dprintf(idx, "%s is already on %s!\n", nick, chan->name);
  430. return;
  431. }
  432. dprintf(DP_SERVER, "INVITE %s %s\n", nick, chan->name);
  433. dprintf(idx, "Inviting %s to %s.\n", nick, chan->name);
  434. }
  435. static void cmd_channel(struct userrec *u, int idx, char *par)
  436. {
  437. char handle[20], s[121], s1[121], atrflag, chanflag, *chname;
  438. struct chanset_t *chan;
  439. int i;
  440. memberlist *m;
  441. static char spaces[33] = " ";
  442. static char spaces2[33] = " ";
  443. int len, len2;
  444. if (!has_op(idx, par))
  445. return;
  446. chname = newsplit(&par);
  447. putlog(LOG_CMDS, "*", "#%s# (%s) channel %s", dcc[idx].nick,
  448. dcc[idx].u.chat->con_chan, chname);
  449. if (!chname[0])
  450. chan = findchan(dcc[idx].u.chat->con_chan);
  451. else
  452. chan = findchan(chname);
  453. if (chan == NULL) {
  454. dprintf(idx, "%s %s\n", IRC_NOTACTIVECHAN, chname);
  455. return;
  456. }
  457. strcpy(s, getchanmode(chan));
  458. if (channel_pending(chan))
  459. sprintf(s1, "%s %s", IRC_PROCESSINGCHAN, chan->name);
  460. else if (channel_active(chan))
  461. sprintf(s1, "%s %s", IRC_CHANNEL, chan->name);
  462. else
  463. sprintf(s1, "%s %s", IRC_DESIRINGCHAN, chan->name);
  464. dprintf(idx, "%s, %d member%s, mode %s:\n", s1, chan->channel.members,
  465. chan->channel.members == 1 ? "" : "s", s);
  466. if (chan->channel.topic)
  467. dprintf(idx, "%s: %s\n", IRC_CHANNELTOPIC, chan->channel.topic);
  468. m = chan->channel.member;
  469. i = 0;
  470. if (channel_active(chan)) {
  471. dprintf(idx, "(n = owner, m = master, o = op, d = deop, b = bot)\n");
  472. spaces[NICKMAX - 9] = 0;
  473. spaces2[HANDLEN - 9] = 0;
  474. dprintf(idx, " NICKNAME %s HANDLE %s JOIN IDLE USER@HOST\n",
  475. spaces, spaces2);
  476. spaces[NICKMAX - 9] = ' ';
  477. spaces2[HANDLEN - 9] = ' ';
  478. while (m && m->nick[0]) {
  479. if (m->joined > 0) {
  480. strcpy(s, ctime(&(m->joined)));
  481. if ((now - (m->joined)) > 86400) {
  482. strcpy(s1, &s[4]);
  483. strcpy(s, &s[8]);
  484. strcpy(&s[2], s1);
  485. s[5] = 0;
  486. } else {
  487. strcpy(s, &s[11]);
  488. s[5] = 0;
  489. }
  490. } else
  491. strcpy(s, " --- ");
  492. if (m->user == NULL) {
  493. sprintf(s1, "%s!%s", m->nick, m->userhost);
  494. m->user = get_user_by_host(s1);
  495. }
  496. if (m->user == NULL) {
  497. strcpy(handle, "*");
  498. } else {
  499. strcpy(handle, m->user->handle);
  500. }
  501. get_user_flagrec(m->user, &user, chan->name);
  502. /* determine status char to use */
  503. if (glob_bot(user))
  504. atrflag = 'b';
  505. else if (glob_owner(user))
  506. atrflag = 'N';
  507. else if (chan_owner(user))
  508. atrflag = 'n';
  509. else if (glob_master(user))
  510. atrflag = 'M';
  511. else if (chan_master(user))
  512. atrflag = 'm';
  513. else if (glob_deop(user))
  514. atrflag = 'D';
  515. else if (chan_deop(user))
  516. atrflag = 'd';
  517. else if (glob_autoop(user))
  518. atrflag = 'A';
  519. else if (chan_autoop(user))
  520. atrflag = 'a';
  521. else if (glob_op(user))
  522. atrflag = 'O';
  523. else if (chan_op(user))
  524. atrflag = 'o';
  525. else if (glob_quiet(user))
  526. atrflag = 'Q';
  527. else if (chan_quiet(user))
  528. atrflag = 'q';
  529. else if (glob_gvoice(user))
  530. atrflag = 'G';
  531. else if (chan_gvoice(user))
  532. atrflag = 'g';
  533. else if (glob_voice(user))
  534. atrflag = 'V';
  535. else if (chan_voice(user))
  536. atrflag = 'v';
  537. else
  538. atrflag = ' ';
  539. if (chan_hasop(m))
  540. chanflag = '@';
  541. else if (chan_hasvoice(m))
  542. chanflag = '+';
  543. else
  544. chanflag = ' ';
  545. spaces[len = (NICKMAX - strlen(m->nick))] = 0;
  546. spaces2[len2 = (HANDLEN - strlen(handle))] = 0;
  547. if (chan_issplit(m))
  548. dprintf(idx, "%c%s%s %s%s %s %c <- netsplit, %lus\n", chanflag,
  549. m->nick, spaces, handle, spaces2, s, atrflag,
  550. now - (m->split));
  551. else if (!rfc_casecmp(m->nick, botname))
  552. dprintf(idx, "%c%s%s %s%s %s %c <- it's me!\n", chanflag, m->nick,
  553. spaces, handle, spaces2, s, atrflag);
  554. else {
  555. /* determine idle time */
  556. if (now - (m->last) > 86400)
  557. sprintf(s1, "%2lud", ((now - (m->last)) / 86400));
  558. else if (now - (m->last) > 3600)
  559. sprintf(s1, "%2luh", ((now - (m->last)) / 3600));
  560. else if (now - (m->last) > 180)
  561. sprintf(s1, "%2lum", ((now - (m->last)) / 60));
  562. else
  563. strcpy(s1, " ");
  564. dprintf(idx, "%c%s%s %s%s %s %c %s %s\n", chanflag, m->nick,
  565. spaces, handle, spaces2, s, atrflag, s1, m->userhost);
  566. }
  567. spaces[len] = ' ';
  568. spaces2[len2] = ' ';
  569. if (chan_fakeop(m))
  570. dprintf(idx, " (%s)\n", IRC_FAKECHANOP);
  571. if (chan_sentop(m))
  572. dprintf(idx, " (%s)\n", IRC_PENDINGOP);
  573. if (chan_sentdeop(m))
  574. dprintf(idx, " (%s)\n", IRC_PENDINGDEOP);
  575. if (chan_sentkick(m))
  576. dprintf(idx, " (%s)\n", IRC_PENDINGKICK);
  577. m = m->next;
  578. }
  579. }
  580. dprintf(idx, "%s\n", IRC_ENDCHANINFO);
  581. }
  582. static void cmd_topic(struct userrec *u, int idx, char *par)
  583. {
  584. struct chanset_t *chan;
  585. if (par[0] && (strchr(CHANMETA, par[0]) != NULL)) {
  586. char *chname = newsplit(&par);
  587. chan = has_op(idx, chname);
  588. } else
  589. chan = has_op(idx, "");
  590. if (chan) {
  591. if (!par[0]) {
  592. if (chan->channel.topic) {
  593. dprintf(idx, "The topic for %s is: %s\n", chan->name,
  594. chan->channel.topic);
  595. } else {
  596. dprintf(idx, "No topic is set for %s\n", chan->name);
  597. }
  598. } else if (channel_optopic(chan) && !me_op(chan)) {
  599. dprintf(idx, "I'm not a channel op on %s and the channel is +t.\n",
  600. chan->name);
  601. } else {
  602. dprintf(DP_SERVER, "TOPIC %s :%s\n", chan->name, par);
  603. dprintf(idx, "Changing topic...\n");
  604. putlog(LOG_CMDS, "*", "#%s# (%s) topic %s", dcc[idx].nick,
  605. chan->name, par);
  606. }
  607. }
  608. }
  609. static void cmd_resetbans(struct userrec *u, int idx, char *par)
  610. {
  611. char *chname;
  612. struct chanset_t *chan;
  613. chname = newsplit(&par);
  614. rmspace(chname);
  615. if (chname[0]) {
  616. chan = findchan(chname);
  617. if (!chan) {
  618. dprintf(idx, "That channel doesnt exist!\n");
  619. return;
  620. }
  621. get_user_flagrec(u, &user, chname);
  622. } else {
  623. chan = findchan(dcc[idx].u.chat->con_chan);
  624. if (!chan) {
  625. dprintf(idx, "Invalid console channel.\n");
  626. return;
  627. }
  628. get_user_flagrec(u, &user, dcc[idx].u.chat->con_chan);
  629. }
  630. if (glob_op(user) || chan_op(user)) {
  631. putlog(LOG_CMDS, "*", "#%s# (%s) resetbans", dcc[idx].nick, chan->name);
  632. dprintf(idx, "Resetting bans on %s...\n", chan->name);
  633. resetbans(chan);
  634. }
  635. }
  636. static void cmd_resetexempts(struct userrec *u, int idx, char *par)
  637. {
  638. char *chname;
  639. struct chanset_t *chan;
  640. chname = newsplit(&par);
  641. rmspace(chname);
  642. if (chname[0]) {
  643. chan = findchan(chname);
  644. if (!chan) {
  645. dprintf(idx, "That channel doesnt exist!\n");
  646. return;
  647. }
  648. get_user_flagrec(u, &user, chname);
  649. } else {
  650. chan = findchan(dcc[idx].u.chat->con_chan);
  651. if (!chan) {
  652. dprintf(idx, "Invalid console channel.\n");
  653. return;
  654. }
  655. get_user_flagrec(u, &user, dcc[idx].u.chat->con_chan);
  656. }
  657. if (glob_op(user) || chan_op(user)) {
  658. putlog(LOG_CMDS, "*", "#%s# (%s) resetexempts", dcc[idx].nick, chan->name);
  659. dprintf(idx, "Resetting exemptions on %s...\n", chan->name);
  660. resetexempts(chan);
  661. }
  662. }
  663. static void cmd_resetinvites(struct userrec *u, int idx, char *par)
  664. {
  665. char *chname;
  666. struct chanset_t *chan;
  667. chname = newsplit(&par);
  668. rmspace(chname);
  669. if (chname[0]) {
  670. chan = findchan(chname);
  671. if (!chan) {
  672. dprintf(idx, "That channel doesnt exist!\n");
  673. return;
  674. }
  675. get_user_flagrec(u, &user, chname);
  676. } else {
  677. chan = findchan(dcc[idx].u.chat->con_chan);
  678. if (!chan) {
  679. dprintf(idx, "Invalid console channel.\n");
  680. return;
  681. }
  682. get_user_flagrec(u, &user, dcc[idx].u.chat->con_chan);
  683. }
  684. if (glob_op(user) || chan_op(user)) {
  685. putlog(LOG_CMDS, "*", "#%s# (%s) resetinvites", dcc[idx].nick, chan->name);
  686. dprintf(idx, "Resetting invitations on %s...\n", chan->name);
  687. resetinvites(chan);
  688. }
  689. }
  690. static void cmd_adduser(struct userrec *u, int idx, char *par)
  691. {
  692. char *nick, *hand;
  693. struct chanset_t *chan;
  694. memberlist *m = 0;
  695. char s[121], s1[121];
  696. int atr = u ? u->flags : 0;
  697. int statichost = 0;
  698. char *p1 = s1;
  699. Context;
  700. if ((!par[0]) || ((par[0]=='!') && (!par[1]))) {
  701. dprintf(idx, "Usage: adduser <nick> [handle]\n");
  702. return;
  703. }
  704. nick = newsplit(&par);
  705. /* patch that allow to create users with static host (drummer,20Apr99) */
  706. if (nick[0] == '!') {
  707. statichost = 1;
  708. nick++;
  709. }
  710. if (!par[0]) {
  711. hand = nick;
  712. } else {
  713. char *p;
  714. int ok = 1;
  715. for (p = par; *p; p++)
  716. if ((*p <= 32) || (*p >= 127))
  717. ok = 0;
  718. if (!ok) {
  719. dprintf(idx, "You can't have strange characters in a nick.\n");
  720. return;
  721. } else if (strchr("-,+*=:!.@#;$", par[0]) != NULL) {
  722. dprintf(idx, "You can't start a nick with '%c'.\n", par[0]);
  723. return;
  724. }
  725. hand = par;
  726. }
  727. Context;
  728. chan = chanset;
  729. while (chan != NULL) {
  730. m = ismember(chan, nick);
  731. if (m)
  732. break;
  733. chan=chan->next;
  734. }
  735. if (!m) {
  736. dprintf(idx, "%s is not on any channels I monitor\n", nick);
  737. return;
  738. } /* else
  739. dprintf(idx,"I found %s on %s as %s\n", nick, chan->name, m->userhost);
  740. */
  741. if (strlen(hand) > HANDLEN)
  742. hand[HANDLEN] = 0;
  743. simple_sprintf(s, "%s!%s", m->nick, m->userhost);
  744. u = get_user_by_host(s);
  745. if (u) {
  746. dprintf(idx, "%s is already known as %s.\n", nick, u->handle);
  747. return;
  748. }
  749. u = get_user_by_handle(userlist, hand);
  750. if (u && (u->flags & USER_OWNER) &&
  751. !(atr & USER_OWNER) && !strcasecmp(dcc[idx].nick, hand)) {
  752. dprintf(idx, "You can't add hostmasks to the bot owner.\n");
  753. return;
  754. }
  755. if (!statichost)
  756. maskhost(s, s1);
  757. else {
  758. strcpy(s1,s);
  759. p1 = strchr(s1,'!');
  760. if (strchr("~^+=-",p1[1]))
  761. p1[1] = '*';
  762. p1--;
  763. p1[0] = '*';
  764. }
  765. if (!u) {
  766. dprintf(idx, "Added [%s]%s with no password.\n", hand, p1);
  767. userlist = adduser(userlist, hand, p1, "-", USER_DEFAULT);
  768. } else {
  769. dprintf(idx, "Added hostmask %s to %s.\n", p1, u->handle);
  770. addhost_by_handle(hand,p1);
  771. get_user_flagrec(u, &user, chan->name);
  772. if ((chan_op(user) || (glob_op(user) && !chan_deop(user))) &&
  773. (channel_autoop(chan) || glob_autoop(user) || chan_autoop(user)))
  774. add_mode(chan, '+', 'o', m->nick);
  775. }
  776. putlog(LOG_CMDS, "*", "#%s# adduser %s %s", dcc[idx].nick, nick,
  777. hand == nick ? "" : hand);
  778. }
  779. static void cmd_deluser(struct userrec *u, int idx, char *par)
  780. {
  781. char *nick, s[1024];
  782. struct chanset_t *chan;
  783. memberlist *m;
  784. struct flag_record victim = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
  785. if (!par[0]) {
  786. dprintf(idx, "Usage: deluser <nick>\n");
  787. return;
  788. }
  789. chan = findchan(dcc[idx].u.chat->con_chan);
  790. if (!chan) {
  791. dprintf(idx, "Your console channel is invalid.\n");
  792. return;
  793. }
  794. if (!channel_active(chan)) {
  795. dprintf(idx, "I'm not on %s!\n", chan->name);
  796. return;
  797. }
  798. nick = newsplit(&par);
  799. m = ismember(chan, nick);
  800. if (!m) {
  801. dprintf(idx, "%s is not on %s.\n", nick, chan->name);
  802. return;
  803. }
  804. get_user_flagrec(u, &user, chan->name);
  805. simple_sprintf(s, "%s!%s", m->nick, m->userhost);
  806. u = get_user_by_host(s);
  807. if (!u) {
  808. dprintf(idx, "%s is not in a valid user.\n", nick);
  809. return;
  810. }
  811. get_user_flagrec(u, &victim, NULL);
  812. /* this maybe should allow glob +n's to deluser glob +n's but I don't
  813. * like that - beldin */
  814. /* checks vs channel owner/master ANYWHERE now -
  815. * so deluser on a channel they're not on should work */
  816. /* Shouldn't allow people to remove permanent owners (guppy 9Jan1999) */
  817. if ((glob_owner(victim) && strcasecmp(dcc[idx].nick, nick)) ||
  818. isowner(u->handle)) {
  819. dprintf(idx, "Can't remove the bot owner!\n");
  820. } else if (glob_botmast(victim) && !glob_owner(user)) {
  821. dprintf(idx, "Can't delete a master!\n");
  822. } else if (chan_owner(victim) && !glob_owner(user)) {
  823. dprintf(idx, "Can't remove a channel owner!\n");
  824. } else if (chan_master(victim) && !(glob_owner(user) || chan_owner(user))) {
  825. dprintf(idx, "Can't delete a channel master!\n");
  826. } else if (glob_bot(victim) && !glob_owner(user)) {
  827. dprintf(idx, "Can't delete a bot!\n");
  828. } else {
  829. char buf[HANDLEN + 1];
  830. strncpy(buf, u->handle, HANDLEN);
  831. buf[HANDLEN] = 0;
  832. if (deluser(u->handle)) {
  833. dprintf(idx, "Deleted %s.\n", buf); /* ?!?! :) */
  834. putlog(LOG_CMDS, "*", "#%s# deluser %s [%s]", dcc[idx].nick, nick, buf);
  835. } else {
  836. dprintf(idx, "Failed.\n");
  837. }
  838. }
  839. }
  840. static void cmd_reset(struct userrec *u, int idx, char *par)
  841. {
  842. struct chanset_t *chan;
  843. if (par[0]) {
  844. chan = findchan(par);
  845. if (!chan)
  846. dprintf(idx, "%s\n", IRC_NOMONITOR);
  847. else {
  848. get_user_flagrec(u, &user, par);
  849. if (!glob_master(user) && !chan_master(user)) {
  850. dprintf(idx, "You are not a master on %s.\n", chan->name);
  851. } else if (!channel_active(chan)) {
  852. dprintf(idx, "Im not on %s at the moment!\n", chan->name);
  853. } else {
  854. putlog(LOG_CMDS, "*", "#%s# reset %s", dcc[idx].nick, par);
  855. dprintf(idx, "Resetting channel info for %s...\n", par);
  856. reset_chan_info(chan);
  857. }
  858. }
  859. } else if (!(u->flags & USER_MASTER)) {
  860. dprintf(idx, "You are not a Bot Master.\n");
  861. } else {
  862. putlog(LOG_CMDS, "*", "#%s# reset all", dcc[idx].nick);
  863. dprintf(idx, "Resetting channel info for all channels...\n");
  864. chan = chanset;
  865. while (chan != NULL) {
  866. if (channel_active(chan))
  867. reset_chan_info(chan);
  868. chan = chan->next;
  869. }
  870. }
  871. }
  872. /* update the add/rem_builtins in irc.c if you add to this list!! */
  873. static cmd_t irc_dcc[] =
  874. {
  875. {"adduser", "m|m", (Function) cmd_adduser, NULL},
  876. {"deluser", "m|m", (Function) cmd_deluser, NULL},
  877. {"reset", "m|m", (Function) cmd_reset, NULL},
  878. {"resetbans", "o|o", (Function) cmd_resetbans, NULL},
  879. {"resetexempts", "o|o", (Function) cmd_resetexempts, NULL},
  880. {"resetinvites", "o|o", (Function) cmd_resetinvites, NULL},
  881. {"act", "o|o", (Function) cmd_act, NULL},
  882. {"channel", "o|o", (Function) cmd_channel, NULL},
  883. {"deop", "o|o", (Function) cmd_deop, NULL},
  884. {"invite", "o|o", (Function) cmd_invite, NULL},
  885. {"kick", "o|o", (Function) cmd_kick, NULL},
  886. {"kickban", "o|o", (Function) cmd_kickban, NULL},
  887. {"msg", "o", (Function) cmd_msg, NULL},
  888. {"voice", "o|o", (Function) cmd_voice, NULL},
  889. {"devoice", "o|o", (Function) cmd_devoice, NULL},
  890. {"op", "o|o", (Function) cmd_op, NULL},
  891. {"say", "o|o", (Function) cmd_say, NULL},
  892. {"topic", "o|o", (Function) cmd_topic, NULL},
  893. {0, 0, 0, 0}
  894. };