cmdsirc.c 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014
  1. /*
  2. * Copyright (C) 1997 Robey Pointer
  3. * Copyright (C) 1999 - 2002 Eggheads Development Team
  4. * Copyright (C) 2002 - 2008 Bryan Drewery
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. /*
  21. * chancmds.c -- part of irc.mod
  22. * handles commands directly relating to channel interaction
  23. *
  24. */
  25. #include <bdlib/src/Stream.h>
  26. #include <bdlib/src/String.h>
  27. #include "src/misc_file.h"
  28. /* Do we have any flags that will allow us ops on a channel?
  29. */
  30. static struct chanset_t *get_channel(int idx, char *chname, bool check_console = 1)
  31. {
  32. struct chanset_t *chan = NULL;
  33. if (chname && chname[0]) {
  34. chan = findchan_by_dname(chname);
  35. if (chan)
  36. return chan;
  37. else
  38. dprintf(idx, "No such channel.\n");
  39. } else if (check_console) {
  40. chname = dcc[idx].u.chat->con_chan;
  41. chan = findchan_by_dname(chname);
  42. if (chan)
  43. return chan;
  44. else
  45. dprintf(idx, "Invalid console channel.\n");
  46. }
  47. return NULL;
  48. }
  49. /* Do we have any flags that will allow us ops on a channel?
  50. */
  51. static int has_op(int idx, struct chanset_t *chan)
  52. {
  53. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  54. if (privchan(user, chan, PRIV_OP)) {
  55. dprintf(idx, "No such channel.\n");
  56. return 0;
  57. }
  58. if (real_chk_op(user, chan, 0))
  59. return 1;
  60. dprintf(idx, "You are not a channel op on %s.\n", chan->dname);
  61. return 0;
  62. }
  63. /* Finds a nick of the handle. Returns m->nick if
  64. * the nick was found, otherwise NULL (Sup 1Nov2000)
  65. */
  66. char *getnick(const char *handle, struct chanset_t *chan)
  67. {
  68. struct userrec *u = NULL;
  69. char s[UHOSTLEN] = "";
  70. for (register memberlist *m = chan->channel.member; m && m->nick[0]; m = m->next) {
  71. simple_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
  72. if ((u = get_user_by_host(s)) && !strcasecmp(u->handle, handle))
  73. return m->nick;
  74. }
  75. return NULL;
  76. }
  77. static void cmd_act(int idx, char *par)
  78. {
  79. if (!par[0]) {
  80. dprintf(idx, "Usage: act [channel] <action>\n");
  81. return;
  82. }
  83. char *chname = NULL;
  84. struct chanset_t *chan = NULL;
  85. if (strchr(CHANMETA, par[0]) != NULL)
  86. chname = newsplit(&par);
  87. else
  88. chname = 0;
  89. chan = get_channel(idx, chname);
  90. if (!chan || !has_op(idx, chan))
  91. return;
  92. memberlist *m = ismember(chan, botname);
  93. if (!m) {
  94. dprintf(idx, "Cannot say to %s: I'm not on that channel.\n", chan->dname);
  95. return;
  96. }
  97. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  98. if ((chan->channel.mode & CHANMODER) && !me_op(chan) && !me_voice(chan)) {
  99. dprintf(idx, "Cannot say to %s: It is moderated.\n", chan->dname);
  100. return;
  101. }
  102. putlog(LOG_CMDS, "*", "#%s# (%s) act %s", dcc[idx].nick,
  103. chan->dname, par);
  104. bd::String msg;
  105. msg.printf("\001ACTION %s\001", par);
  106. privmsg(chan->name, msg.c_str(), DP_HELP);
  107. dprintf(idx, "Action to %s: %s\n", chan->dname, par);
  108. }
  109. static void cmd_msg(int idx, char *par)
  110. {
  111. if (dcc[idx].simul >= 0) {
  112. dprintf(idx, "Sorry, that cmd isn't available over botcmd.\n");
  113. dprintf(idx, "Instead try: %sbotmsg %s %s\n", settings.dcc_prefix, conf.bot->nick, par);
  114. return;
  115. }
  116. if (!par[0]) {
  117. dprintf(idx, "Usage: msg <nick> <message>\n");
  118. return;
  119. }
  120. char *nick = newsplit(&par);
  121. putlog(LOG_CMDS, "*", "#%s# msg %s %s", dcc[idx].nick, nick, par);
  122. privmsg(nick, par, DP_HELP);
  123. dprintf(idx, "Msg to %s: %s\n", nick, par);
  124. }
  125. static void cmd_nick(int idx, char *par)
  126. {
  127. putlog(LOG_CMDS, "*", "#%s# nick", dcc[idx].nick);
  128. botnet_send_cmd(conf.bot->nick, conf.bot->nick, dcc[idx].nick, idx, "curnick");
  129. }
  130. static void cmd_say(int idx, char *par)
  131. {
  132. if (dcc[idx].simul >= 0) {
  133. dprintf(idx, "Sorry, that cmd isn't available over botcmd.\n");
  134. dprintf(idx, "Instead try: %sbotmsg %s %s\n", settings.dcc_prefix, conf.bot->nick, par);
  135. return;
  136. }
  137. if (!par[0]) {
  138. dprintf(idx, "Usage: say [channel] <message>\n");
  139. return;
  140. }
  141. char *chname = NULL;
  142. struct chanset_t *chan = NULL;
  143. if (strchr(CHANMETA, par[0]) != NULL)
  144. chname = newsplit(&par);
  145. else
  146. chname = 0;
  147. chan = get_channel(idx, chname);
  148. if (!chan || !has_op(idx, chan))
  149. return;
  150. memberlist *m = ismember(chan, botname);
  151. if (!m) {
  152. dprintf(idx, "Cannot say to %s: I'm not on that channel.\n", chan->dname);
  153. return;
  154. }
  155. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  156. if ((chan->channel.mode & CHANMODER) && !me_op(chan) && !me_voice(chan)) {
  157. dprintf(idx, "Cannot say to %s: It is moderated.\n", chan->dname);
  158. return;
  159. }
  160. putlog(LOG_CMDS, "*", "#%s# (%s) say %s", dcc[idx].nick, chan->dname, par);
  161. privmsg(chan->name, par, DP_HELP);
  162. dprintf(idx, "Said to %s: %s\n", chan->dname, par);
  163. }
  164. static void cmd_swhois(int idx, char *par)
  165. {
  166. if (!par[0]) {
  167. dprintf(idx, "Usage: swhois [server/nick] nick\n");
  168. return;
  169. }
  170. putlog(LOG_CMDS, "*", "#%s# swhois %s", dcc[idx].nick, par);
  171. if (!server_online) {
  172. dprintf(idx, "I am currently not connected!\n");
  173. return;
  174. }
  175. char *server = newsplit(&par), *nick = NULL;
  176. if (par[0])
  177. nick = newsplit(&par);
  178. strlcpy(dcc[idx].whois, nick ? nick : server, UHOSTLEN);
  179. dprintf(DP_SERVER, "WHOIS %s %s\n", server, nick ? nick : "");
  180. }
  181. static void cmd_kickban(int idx, char *par)
  182. {
  183. if (!par[0]) {
  184. dprintf(idx, "Usage: kickban [channel|*] [-|@]<nick> [reason]\n");
  185. return;
  186. }
  187. struct chanset_t *chan = NULL;
  188. char *chname = NULL;
  189. bool all = 0;
  190. if (par[0] == '*' && par[1] == ' ') {
  191. all = 1;
  192. newsplit(&par);
  193. } else {
  194. if (strchr(CHANMETA, par[0]) != NULL)
  195. chname = newsplit(&par);
  196. else
  197. chname = 0;
  198. chan = get_channel(idx, chname);
  199. if (!chan || !has_op(idx, chan))
  200. return;
  201. }
  202. putlog(LOG_CMDS, "*", "#%s# (%s) kickban %s", dcc[idx].nick, all ? "*" : chan->dname, par);
  203. char *nick = newsplit(&par), bantype = 0;
  204. if ((nick[0] == '@') || (nick[0] == '-')) {
  205. bantype = nick[0];
  206. nick++;
  207. }
  208. if (match_my_nick(nick)) {
  209. dprintf(idx, "I'm not going to kickban myself.\n");
  210. return;
  211. }
  212. memberlist *m = NULL;
  213. char *s1 = NULL, s[UHOSTLEN] = "";
  214. struct userrec *u = NULL;
  215. if (all)
  216. chan = chanset;
  217. while (chan) {
  218. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  219. if (privchan(user, chan, PRIV_OP)) {
  220. if (all) goto next;
  221. dprintf(idx, "No such channel.\n");
  222. return;
  223. }
  224. else if (!real_chk_op(user, chan, 0)) {
  225. if (all) goto next;
  226. dprintf(idx, "You don't have access to %s\n", chan->dname);
  227. return;
  228. }
  229. if (!channel_active(chan)) {
  230. if (all) goto next;
  231. dprintf(idx, "I'm not on %s right now!\n", chan->dname);
  232. return;
  233. }
  234. if (!me_op(chan)) {
  235. if (all) goto next;
  236. dprintf(idx, "I can't help you now because I'm not a channel op"
  237. " on %s.\n", chan->dname);
  238. return;
  239. }
  240. m = ismember(chan, nick);
  241. if (!m) {
  242. if (all) goto next;
  243. dprintf(idx, "%s is not on %s\n", nick, chan->dname);
  244. return;
  245. }
  246. simple_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
  247. u = get_user_by_host(s);
  248. get_user_flagrec(u, &victim, chan->dname);
  249. if ((chan_master(victim) || glob_master(victim)) &&
  250. !(glob_owner(user) || chan_owner(user))) {
  251. if (all) goto next;
  252. dprintf(idx, "%s is a %s master.\n", nick, chan->dname);
  253. return;
  254. }
  255. if (glob_bot(victim) && !(glob_owner(user) || chan_owner(user))) {
  256. if (all) goto next;
  257. dprintf(idx, "%s is another channel bot!\n", nick);
  258. return;
  259. }
  260. if (u_match_mask(global_exempts,s) || u_match_mask(chan->exempts, s)) {
  261. dprintf(idx, "%s is permanently exempted!\n", nick);
  262. return;
  263. }
  264. if (m->flags & CHANOP)
  265. add_mode(chan, '-', 'o', m->nick);
  266. check_exemptlist(chan, s);
  267. switch (bantype) {
  268. case '@':
  269. s1 = strchr(s, '@');
  270. s1 -= 3;
  271. s1[0] = '*';
  272. s1[1] = '!';
  273. s1[2] = '*';
  274. break;
  275. case '-':
  276. s1 = strchr(s, '!');
  277. s1[1] = '*';
  278. s1--;
  279. s1[0] = '*';
  280. break;
  281. default:
  282. s1 = quickban(chan, m->userhost);
  283. break;
  284. }
  285. if (bantype == '@' || bantype == '-')
  286. do_mask(chan, chan->channel.ban, s1, 'b');
  287. if (!par[0])
  288. par = "requested";
  289. dprintf(DP_MODE, "KICK %s %s :%s%s\n", chan->name, m->nick, bankickprefix, par);
  290. m->flags |= SENTKICK;
  291. u_addmask('b', chan, s1, dcc[idx].nick, par, now + (60 * chan->ban_time), 0);
  292. dprintf(idx, "Kick-banned %s on %s.\n", nick, chan->dname);
  293. next:;
  294. if (!all)
  295. chan = NULL;
  296. else
  297. chan = chan->next;
  298. }
  299. }
  300. static void cmd_voice(int idx, char *par)
  301. {
  302. char *nick = newsplit(&par);
  303. struct chanset_t *chan = NULL;
  304. bool all = 0;
  305. if (par[0] == '*' && !par[1]) {
  306. all = 1;
  307. newsplit(&par);
  308. } else {
  309. chan = get_channel(idx, par);
  310. if (!chan || !has_op(idx, chan))
  311. return;
  312. }
  313. memberlist *m = NULL;
  314. if (all)
  315. chan = chanset;
  316. putlog(LOG_CMDS, "*", "#%s# (%s) voice %s", dcc[idx].nick, all ? "*" : chan->dname , nick);
  317. while (chan) {
  318. if (!nick[0] && !(nick = getnick(dcc[idx].nick, chan))) {
  319. if (all) goto next;
  320. dprintf(idx, "Usage: voice <nick> [channel|*]\n");
  321. return;
  322. }
  323. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  324. if (privchan(user, chan, PRIV_VOICE)) {
  325. if (all) goto next;
  326. dprintf(idx, "No such channel.\n");
  327. return;
  328. }
  329. else if (!chk_voice(user, chan) && !chk_op(user, chan)) {
  330. if (all) goto next;
  331. dprintf(idx, "You don't have access to voice on %s\n", chan->dname);
  332. return;
  333. }
  334. if (!channel_active(chan)) {
  335. if (all) goto next;
  336. dprintf(idx, "I'm not on %s right now!\n", chan->dname);
  337. return;
  338. }
  339. if (!me_op(chan)) {
  340. if (all) goto next;
  341. dprintf(idx, "I can't help you now because I'm not a chan op on %s.\n",
  342. chan->dname);
  343. return;
  344. }
  345. m = ismember(chan, nick);
  346. if (!m) {
  347. if (all) goto next;
  348. dprintf(idx, "%s is not on %s.\n", nick, chan->dname);
  349. return;
  350. }
  351. add_mode(chan, '+', 'v', nick);
  352. dprintf(idx, "Gave voice to %s on %s\n", nick, chan->dname);
  353. next:;
  354. if (!all)
  355. chan = NULL;
  356. else
  357. chan = chan->next;
  358. }
  359. }
  360. static void cmd_devoice(int idx, char *par)
  361. {
  362. struct chanset_t *chan = NULL;
  363. char *nick = newsplit(&par);
  364. bool all = 0;
  365. if (par[0] == '*' && !par[1]) {
  366. all = 1;
  367. newsplit(&par);
  368. } else {
  369. chan = get_channel(idx, par);
  370. if (!chan || !has_op(idx, chan))
  371. return;
  372. }
  373. memberlist *m = NULL;
  374. if (all)
  375. chan = chanset;
  376. putlog(LOG_CMDS, "*", "#%s# (%s) devoice %s", dcc[idx].nick, all ? "*" : chan->dname, nick);
  377. while (chan) {
  378. if (!nick[0] && !(nick = getnick(dcc[idx].nick, chan))) {
  379. if (all) goto next;
  380. dprintf(idx, "Usage: devoice <nick> [channel|*]\n");
  381. return;
  382. }
  383. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  384. if (privchan(user, chan, PRIV_VOICE)) {
  385. if (all) goto next;
  386. dprintf(idx, "No such channel.\n");
  387. return;
  388. }
  389. else if (!chk_voice(user, chan) && !chk_op(user, chan)) {
  390. if (all) goto next;
  391. dprintf(idx, "You don't have access to devoice on %s\n", chan->dname);
  392. return;
  393. }
  394. if (!channel_active(chan)) {
  395. if (all) goto next;
  396. dprintf(idx, "I'm not on %s right now!\n", chan->dname);
  397. return;
  398. }
  399. if (!me_op(chan)) {
  400. if (all) goto next;
  401. dprintf(idx, "I can't do that right now I'm not a chan op on %s",
  402. chan->dname);
  403. return;
  404. }
  405. m = ismember(chan, nick);
  406. if (!m) {
  407. if (all) goto next;
  408. dprintf(idx, "%s is not on %s.\n", nick, chan->dname);
  409. return;
  410. }
  411. add_mode(chan, '-', 'v', nick);
  412. dprintf(idx, "Devoiced %s on %s\n", nick, chan->dname);
  413. next:;
  414. if (!all)
  415. chan = NULL;
  416. else
  417. chan = chan->next;
  418. }
  419. }
  420. static void cmd_release(int idx, char *par) {
  421. putlog(LOG_CMDS, "*", "#%s# release", dcc[idx].nick);
  422. release_nick();
  423. }
  424. static void cmd_op(int idx, char *par)
  425. {
  426. struct chanset_t *chan = NULL;
  427. char *nick = newsplit(&par);
  428. bool all = 0;
  429. if (par[0] == '*' && !par[1]) {
  430. all = 1;
  431. newsplit(&par);
  432. } else {
  433. chan = get_channel(idx, par);
  434. if (!chan || !has_op(idx, chan))
  435. return;
  436. }
  437. char s[UHOSTLEN] = "";
  438. memberlist *m = NULL;
  439. struct userrec *u = NULL;
  440. if (all)
  441. chan = chanset;
  442. putlog(LOG_CMDS, "*", "#%s# (%s) op %s", dcc[idx].nick, all ? "*" : chan->dname, nick);
  443. while (chan) {
  444. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  445. if (!nick[0] && !(nick = getnick(dcc[idx].nick, chan))) {
  446. if (all) goto next;
  447. dprintf(idx, "Usage: op <nick> [channel|*]\n");
  448. return;
  449. }
  450. if (privchan(user, chan, PRIV_OP)) {
  451. if (!all)
  452. dprintf(idx, "No such channel.\n");
  453. goto next;
  454. }
  455. else if (!chk_op(user, chan)) {
  456. if (all) goto next;
  457. dprintf(idx, "You don't have access to op on %s\n", chan->dname);
  458. return;
  459. }
  460. if (!channel_active(chan)) {
  461. if (all) goto next;
  462. dprintf(idx, "I'm not on %s right now!\n", chan->dname);
  463. return;
  464. }
  465. if (!me_op(chan)) {
  466. if (all) goto next;
  467. dprintf(idx, "I can't help you now because I'm not a chan op on %s.\n",
  468. chan->dname);
  469. return;
  470. }
  471. m = ismember(chan, nick);
  472. if (!m) {
  473. if (all) goto next;
  474. dprintf(idx, "%s is not on %s.\n", nick, chan->dname);
  475. return;
  476. }
  477. simple_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
  478. u = get_user_by_host(s);
  479. get_user_flagrec(u, &victim, chan->dname);
  480. if (chk_deop(victim, chan)) {
  481. dprintf(idx, "%s is currently being auto-deopped on %s.\n", m->nick, chan->dname);
  482. if (all) goto next;
  483. return;
  484. }
  485. if (chan_bitch(chan) && !chk_op(victim, chan)) {
  486. dprintf(idx, "%s is not a registered op on %s.\n", m->nick, chan->dname);
  487. if (all) goto next;
  488. return;
  489. }
  490. if (do_op(nick, chan, 0, 1)) {
  491. dprintf(idx, "Gave op to %s on %s.\n", nick, chan->dname);
  492. stats_add(u, 0, 1);
  493. }
  494. next:;
  495. if (!all)
  496. chan = NULL;
  497. else
  498. chan = chan->next;
  499. }
  500. }
  501. static void mass_mode(const char* chname, const char* mode, char *par)
  502. {
  503. char list[101] = "", buf[2048] = "";
  504. size_t list_len = 0, buf_len = 0, cnt = 0;
  505. register const unsigned short max_lines = floodless ? 15 : default_alines;
  506. unsigned short lines = 0;
  507. while (par[0]) {
  508. *(buf + buf_len++) = 'M';
  509. *(buf + buf_len++) = 'O';
  510. *(buf + buf_len++) = 'D';
  511. *(buf + buf_len++) = 'E';
  512. *(buf + buf_len++) = ' ';
  513. buf_len += strlcpy(buf + buf_len, chname, sizeof(buf) - buf_len);
  514. *(buf + buf_len++) = ' ';
  515. while ((cnt < modesperline) && par[0]) {
  516. /* add +mode into irc cmd */
  517. buf_len += strlcpy(buf + buf_len, mode, sizeof(buf) - buf_len);
  518. /* Make list of nicks */
  519. const char* nick = newsplit(&par);
  520. list_len += strlcpy(list + list_len, nick, sizeof(list) - list_len);
  521. if ((++cnt < modesperline) && par[0])
  522. *(list + list_len++) = ' ';
  523. }
  524. /* buf is so far: 'MODE #chan +o+o+o+o' */
  525. *(buf + buf_len++) = ' ';
  526. buf_len += strlcpy(buf + buf_len, list, sizeof(buf) - buf_len);
  527. *(buf + buf_len++) = '\r';
  528. *(buf + buf_len++) = '\n';
  529. if (++lines >= max_lines) {
  530. buf[buf_len] = 0;
  531. tputs(serv, buf, buf_len);
  532. buf[0] = buf_len = lines = 0;
  533. }
  534. list[0] = list_len = cnt = 0;
  535. }
  536. if (buf[0]) {
  537. buf[buf_len] = 0;
  538. tputs(serv, buf, buf_len);
  539. }
  540. }
  541. void mass_request(char *botnick, char *code, char *par)
  542. {
  543. char* mode = newsplit(&par);
  544. if (strlen(mode) > 2 || !strchr("+-kb", mode[0]))
  545. return;
  546. char* chname = newsplit(&par);
  547. if (strchr("+-", mode[0]))
  548. mass_mode(chname, mode, par);
  549. }
  550. static void cmd_mmode(int idx, char *par)
  551. {
  552. char *mode = newsplit(&par);
  553. if (strlen(mode) > 2 || !strchr("+-", mode[0]) || !par[0]) {
  554. dprintf(idx, "Usage: mmode <(+|-)MODE> <#channel> <a|o|v|d|r> [bots=n] [alines=n] [slines=n] [overlap=n] [bitch] [simul] [local]\n");
  555. dprintf(idx, "Ie. mmode -o #chan a\n");
  556. return;
  557. }
  558. putlog(LOG_CMDS, "*", "#%s# mmode %s %s", dcc[idx].nick, mode, par);
  559. char *chname = NULL;
  560. if (strchr(CHANMETA, par[0]) != NULL)
  561. chname = newsplit(&par);
  562. else
  563. chname = NULL;
  564. struct chanset_t *chan = get_channel(idx, chname);
  565. if (chan) {
  566. if (!shouldjoin(chan) || !channel_active(chan)) {
  567. dprintf(idx, "I'm not on %s\n", chan->dname);
  568. return;
  569. }
  570. if (channel_pending(chan)) {
  571. dprintf(idx, "Channel pending.\n");
  572. return;
  573. }
  574. get_user_flagrec(dcc[idx].user, &user, chan->dname, chan);
  575. if (!glob_owner(user) && !chan_owner(user)) {
  576. dprintf(idx, "You do not have mass mode access for %s\n", chan->dname);
  577. return;
  578. }
  579. }
  580. if (!chan || !chname || !chname[0]) {
  581. dprintf(idx, "Usage: mmode <(+|-)MODE> <#channel> <a|o|v|d|r> [bots=n] [alines=n] [slines=n] [overlap=n] [bitch] [simul] [local]\n");
  582. dprintf(idx, "Ie. mmode -o #chan a\n");
  583. return;
  584. }
  585. char *who = newsplit(&par);
  586. if (strlen(who) > 1 || !strchr("aovdr", who[0])) {
  587. dprintf(idx, "Usage: mmode <(+|-)MODE> <#channel> <a|o|v|d|r> [bots=n] [alines=n] [slines=n] [overlap=n] [bitch] [simul] [local]\n");
  588. dprintf(idx, "Ie. mmode -o #chan a\n");
  589. dprintf(idx, "a = all.\n");
  590. dprintf(idx, "o = ops.\n");
  591. dprintf(idx, "O = user-op.\n");
  592. dprintf(idx, "v = voices.\n");
  593. dprintf(idx, "d = non-ops.\n");
  594. dprintf(idx, "r = regulars (-ov).\n");
  595. return;
  596. }
  597. if (mode[0] == '+' && mode[1] == 'o' && !channel_fastop(chan) && !cookies_disabled) {
  598. dprintf(idx, STR("Error: This channel is currently set -fastop.\n"));
  599. dprintf(idx, STR("Mass opping would result in missing op cookies.\n"));
  600. dprintf(idx, STR("Please chanset the channel +fastop first.\n"));
  601. return;
  602. }
  603. memberlist** targets = (memberlist**) my_calloc(1, chan->channel.members * sizeof(memberlist *));
  604. int* overlaps = (int *) my_calloc(1, chan->channel.members * sizeof(int *));
  605. memberlist** chanbots = (memberlist **) my_calloc(1, chan->channel.members * sizeof(memberlist *));
  606. memberlist *m = NULL;
  607. int chanbotcount = 0, targetcount = 0;
  608. for (m = chan->channel.member; m; m = m->next) {
  609. if (m->user) {
  610. if ((m->flags & CHANOP) && m->user->bot &&
  611. (!m->is_me) && (nextbot(m->user->handle) >= 0)) {
  612. chanbots[chanbotcount++] = m;
  613. continue;
  614. } else if (m->is_me)
  615. continue;
  616. get_user_flagrec(m->user, &user, chan->dname);
  617. }
  618. bool is_target = 0;
  619. if (who[0] == 'o' && (m->flags & CHANOP))
  620. is_target = 1;
  621. else if (who[0] == 'O' && chk_op(user, chan))
  622. is_target = 1;
  623. else if (who[0] == 'd' && !(m->flags & CHANOP))
  624. is_target = 1;
  625. else if (who[0] == 'v' && !(m->flags & CHANOP) && (m->flags & CHANVOICE))
  626. is_target = 1;
  627. else if (who[0] == 'r' && !(m->flags & CHANOP) && !(m->flags & CHANVOICE))
  628. is_target = 1;
  629. else if (who[0] == 'a')
  630. is_target = 1;
  631. if (is_target)
  632. targets[targetcount++] = m;
  633. }
  634. int force_bots = 0, force_alines = 0, force_slines = 0, force_overlap = 0;
  635. bool bitch = 0, simul = 0, local = 0;
  636. while (par && par[0]) {
  637. char *p = newsplit(&par);
  638. if (!strncasecmp(p, "bots=", 5)) {
  639. p += 5;
  640. force_bots = atoi(p);
  641. if ((force_bots < 1) || (force_bots > chanbotcount)) {
  642. dprintf(idx, "bots must be within 1-%i\n", chanbotcount);
  643. free(targets);
  644. free(overlaps);
  645. free(chanbots);
  646. return;
  647. }
  648. } else if (!strncasecmp(p, "alines=", 7)) {
  649. p += 7;
  650. force_alines = atoi(p);
  651. if (force_alines > 5)
  652. dprintf(idx, "alines >5 will fail without a floodless.\n");
  653. if ((force_alines < 1) || (force_alines > 100)) {
  654. dprintf(idx, "alines must be within 1-100\n");
  655. free(targets);
  656. free(overlaps);
  657. free(chanbots);
  658. return;
  659. }
  660. } else if (!strncasecmp(p, "slines=", 7)) {
  661. p += 7;
  662. force_slines = atoi(p);
  663. if ((force_slines < 1) || (force_slines > 20)) {
  664. dprintf(idx, "slines must be within 1-20\n");
  665. dprintf(idx, ">6 will fail without a floodless.\n");
  666. free(targets);
  667. free(overlaps);
  668. free(chanbots);
  669. return;
  670. }
  671. } else if (!strncasecmp(p, "overlap=", 8)) {
  672. p += 8;
  673. force_overlap = atoi(p);
  674. if ((force_overlap < 1) || (force_overlap > 8)) {
  675. dprintf(idx, "overlap must be within 1-8\n");
  676. free(targets);
  677. free(overlaps);
  678. free(chanbots);
  679. return;
  680. }
  681. } else if (!strncasecmp(p, "bitch", 5)) {
  682. bitch = 1;
  683. } else if (!strncasecmp(p, "simul", 5)) {
  684. simul = 1;
  685. } else if (!strncasecmp(p, "local", 5)) {
  686. local = 1;
  687. } else {
  688. dprintf(idx, "Unrecognized option %s\n", p);
  689. free(targets);
  690. free(overlaps);
  691. free(chanbots);
  692. return;
  693. }
  694. }
  695. if (!targetcount) {
  696. dprintf(idx, "No targets found on %s\n", chan->name);
  697. free(targets);
  698. free(overlaps);
  699. free(chanbots);
  700. return;
  701. }
  702. if ((!chanbotcount && !local) || (local && !me_op(chan))) {
  703. dprintf(idx, "No bots opped on %s\n", chan->name);
  704. free(targets);
  705. free(overlaps);
  706. free(chanbots);
  707. return;
  708. }
  709. if (local)
  710. force_bots = 1;
  711. if (local && floodless)
  712. force_alines = force_slines = 100;
  713. int overlap = (force_overlap ? force_overlap : 1);
  714. int needed_modes = (overlap * targetcount);
  715. int my_max_modes = ((force_bots ? force_bots : chanbotcount) * (force_alines ? force_alines : default_alines) * modesperline);
  716. if (needed_modes > my_max_modes) {
  717. dprintf(idx, "Need to make %d modes, but the max is %d.\n", needed_modes, my_max_modes);
  718. dprintf(idx, "Try increasing [alines] or decreasing [overlap].\n");
  719. if (overlap == 1)
  720. dprintf(idx, "Not enough bots.\n");
  721. else
  722. dprintf(idx, "Not enough bots. Try with overlap=1\n");
  723. free(targets);
  724. free(overlaps);
  725. free(chanbots);
  726. return;
  727. }
  728. double bots = 0;
  729. int amodes = 0;
  730. /* ok it's possible... now let's figure out how */
  731. if (force_bots && force_alines) {
  732. /* not much choice... overlap should not autochange */
  733. bots = force_bots;
  734. amodes = force_alines * modesperline;
  735. } else {
  736. if (force_bots) {
  737. /* calc needed modes per bot */
  738. bots = force_bots;
  739. amodes = (needed_modes + ((int)bots - 1)) / (int)bots;
  740. } else if (force_alines) {
  741. amodes = force_alines * modesperline;
  742. bots = (double) needed_modes / amodes;
  743. if (bots > (int)bots) bots = (int)bots+1; /* ceil(bots) */
  744. } else {
  745. /* Try minimizing alines, 1,2,3,4,5 against bots needed */
  746. amodes = 1 * modesperline;
  747. bots = (double) needed_modes / amodes;
  748. if (bots > (int)bots) bots = (int)bots+1; /* ceil(bots) */
  749. for (int min_alines = 2; min_alines <= 5; ++min_alines) {
  750. if ((int)bots > chanbotcount) {
  751. amodes = min_alines * modesperline;
  752. bots = (double) needed_modes / amodes;
  753. if (bots > (int)bots) bots = (int)bots+1; /* ceil(bots) */
  754. } else
  755. break;
  756. }
  757. force_slines = (amodes / modesperline);
  758. /* lol einride is dumb */
  759. if ((int)bots > chanbotcount) {
  760. putlog(LOG_MISC, "*", "Totally fucked calculations in cmd_mmode. this CAN'T happen.");
  761. dprintf(idx, "Something's wrong... bug the coder\n");
  762. free(targets);
  763. free(overlaps);
  764. free(chanbots);
  765. return;
  766. }
  767. }
  768. }
  769. /* How many modes to send */
  770. int smodes;
  771. if (force_slines)
  772. smodes = force_slines * modesperline;
  773. else
  774. smodes = default_alines * modesperline;
  775. if (smodes < amodes)
  776. smodes = amodes;
  777. dprintf(idx, "Mass %s of %s\n", mode, chan->dname);
  778. dprintf(idx, " %d bots used.\n", (int)bots);
  779. dprintf(idx, " %d targets.\n", targetcount);
  780. dprintf(idx, " %d assumed modes per participating bot.\n", amodes);
  781. dprintf(idx, " %d assumed mode lines per participating bot.\n", amodes / modesperline);
  782. dprintf(idx, " %d max modes per participating bot.\n", smodes);
  783. dprintf(idx, " %d max mode lines per participating bot.\n", smodes / modesperline);
  784. dprintf(idx, " %d assumed modes per target nick.\n", overlap);
  785. int tpos = 0, bpos = 0, i = 0;
  786. char **work_list = (char**) my_calloc((int)bots, sizeof(char**));
  787. char *work = NULL;
  788. size_t work_size = 2048;
  789. /* now use bots/modes to distribute nicks to MODE on */
  790. while (bots) {
  791. work = work_list[bpos] = (char*) my_calloc(1, work_size);
  792. if (local) {
  793. strlcpy(work, mode, work_size);
  794. strlcat(work, " ", work_size);
  795. strlcat(work, chan->dname, work_size);
  796. } else if (!simul)
  797. simple_snprintf(work, work_size, "mr %s %s", mode, chan->dname);
  798. else
  799. work[0] = 0;
  800. /* Make list of assumed lines (alines) */
  801. for (i = 0; i < amodes; ++i) {
  802. if (overlaps[tpos]++ < overlap) {
  803. strlcat(work, " ", work_size);
  804. strlcat(work, targets[tpos]->nick, work_size);
  805. }
  806. if (++tpos >= targetcount)
  807. tpos = 0;
  808. }
  809. /* Now make lines of throttled modes (send lines) (slines) */
  810. if (smodes > amodes) {
  811. int atpos = tpos;
  812. for (i = 0; i < (smodes - amodes); ++i) {
  813. if (overlaps[atpos]++ < overlap) {
  814. strlcat(work, " ", work_size);
  815. strlcat(work, targets[atpos]->nick, work_size);
  816. }
  817. if (++atpos >= targetcount)
  818. atpos = 0;
  819. }
  820. }
  821. --bots;
  822. ++bpos;
  823. }
  824. bots = bpos;
  825. bpos = 0;
  826. /* QUEUE *ALL*, then dump */
  827. while (bots) {
  828. work = work_list[bpos];
  829. if (simul)
  830. dprintf(idx, "%-10s MODE %s %s\n", local ? botname : chanbots[bpos]->nick, mode, work);
  831. else if (local)
  832. mass_request(conf.bot->nick, "mr", work);
  833. else
  834. putbot(chanbots[bpos]->user->handle, work);
  835. free(work_list[bpos]);
  836. --bots;
  837. ++bpos;
  838. }
  839. free(work_list);
  840. if (bitch && !simul) {
  841. chan->status |= CHAN_BITCH;
  842. do_chanset(NULL, chan, "+bitch", DO_LOCAL | DO_NET);
  843. }
  844. free(targets);
  845. free(overlaps);
  846. free(chanbots);
  847. return;
  848. }
  849. static void cmd_deop(int idx, char *par)
  850. {
  851. struct chanset_t *chan = NULL;
  852. char *nick = newsplit(&par);
  853. bool all = 0;
  854. if (par[0] == '*' && !par[1]) {
  855. all = 1;
  856. newsplit(&par);
  857. } else {
  858. chan = get_channel(idx, par);
  859. if (!chan || !has_op(idx, chan))
  860. return;
  861. }
  862. char s[UHOSTLEN] = "";
  863. memberlist *m = NULL;
  864. struct userrec *u = NULL;
  865. if (all)
  866. chan = chanset;
  867. putlog(LOG_CMDS, "*", "#%s# (%s) deop %s", dcc[idx].nick, all ? "*" : chan->dname, nick);
  868. while (chan) {
  869. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  870. if (!nick[0] && !(nick = getnick(dcc[idx].nick, chan))) {
  871. if (all) goto next;
  872. dprintf(idx, "Usage: deop <nick> [channel|*]\n");
  873. return;
  874. }
  875. if (privchan(user, chan, PRIV_OP)) {
  876. if (all) goto next;
  877. dprintf(idx, "No such channel.\n");
  878. }
  879. else if (!real_chk_op(user, chan, 0)) {
  880. if (all) goto next;
  881. dprintf(idx, "You don't have access to deop on %s\n", chan->dname);
  882. return;
  883. }
  884. if (!channel_active(chan)) {
  885. if (all) goto next;
  886. dprintf(idx, "I'm not on %s right now!\n", chan->dname);
  887. return;
  888. }
  889. if (!me_op(chan)) {
  890. if (all) goto next;
  891. dprintf(idx, "I can't help you now because I'm not a chan op on %s.\n",
  892. chan->dname);
  893. return;
  894. }
  895. m = ismember(chan, nick);
  896. if (!m) {
  897. if (all) goto next;
  898. dprintf(idx, "%s is not on %s.\n", nick, chan->dname);
  899. return;
  900. }
  901. if (match_my_nick(nick)) {
  902. if (all) goto next;
  903. dprintf(idx, "I'm not going to deop myself.\n");
  904. return;
  905. }
  906. simple_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
  907. u = get_user_by_host(s);
  908. get_user_flagrec(u, &victim, chan->dname);
  909. if ((chan_master(victim) || glob_master(victim)) &&
  910. !(chan_owner(user) || glob_owner(user))) {
  911. dprintf(idx, "%s is a master for %s.\n", m->nick, chan->dname);
  912. if (all) goto next;
  913. return;
  914. }
  915. if (chk_op(victim, chan) && !(chan_master(user) || glob_master(user))) {
  916. dprintf(idx, "%s has the op flag for %s.\n", m->nick, chan->dname);
  917. if (all) goto next;
  918. return;
  919. }
  920. add_mode(chan, '-', 'o', nick);
  921. dprintf(idx, "Deopped %s on %s.\n", nick, chan->dname);
  922. next:;
  923. if (!all)
  924. chan = NULL;
  925. else
  926. chan = chan->next;
  927. }
  928. }
  929. static void cmd_kick(int idx, char *par)
  930. {
  931. if (!par[0]) {
  932. dprintf(idx, "Usage: kick [channel|*] <nick> [reason]\n");
  933. return;
  934. }
  935. struct chanset_t *chan = NULL;
  936. char *chname = NULL;
  937. bool all = 0;
  938. if (par[0] == '*' && par[1] == ' ') {
  939. all = 1;
  940. newsplit(&par);
  941. } else {
  942. if (strchr(CHANMETA, par[0]) != NULL)
  943. chname = newsplit(&par);
  944. else
  945. chname = 0;
  946. chan = get_channel(idx, chname);
  947. if (!chan || !has_op(idx, chan))
  948. return;
  949. }
  950. putlog(LOG_CMDS, "*", "#%s# (%s) kick %s", dcc[idx].nick, all ? "*" : chan->dname, par);
  951. char *nick = newsplit(&par);
  952. if (!par[0])
  953. par = "request";
  954. if (match_my_nick(nick)) {
  955. dprintf(idx, "I'm not going to kick myself.\n");
  956. return;
  957. }
  958. char s[UHOSTLEN] = "";
  959. memberlist *m = NULL;
  960. struct userrec *u = NULL;
  961. if (all)
  962. chan = chanset;
  963. while (chan) {
  964. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  965. if (privchan(user, chan, PRIV_OP)) {
  966. if (all) goto next;
  967. dprintf(idx, "No such channel.\n");
  968. return;
  969. }
  970. else if (!real_chk_op(user, chan, 0)) {
  971. if (all) goto next;
  972. dprintf(idx, "You don't have access to kick on %s\n", chan->dname);
  973. return;
  974. }
  975. if (!channel_active(chan)) {
  976. if (all) goto next;
  977. dprintf(idx, "I'm not on %s right now!\n", chan->dname);
  978. return;
  979. }
  980. if (!me_op(chan)) {
  981. if (all) goto next;
  982. dprintf(idx, "I can't help you now because I'm not a channel op on %s.\n", chan->dname);
  983. return;
  984. }
  985. m = ismember(chan, nick);
  986. if (!m) {
  987. if (all) goto next;
  988. dprintf(idx, "%s is not on %s\n", nick, chan->dname);
  989. return;
  990. }
  991. simple_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
  992. u = get_user_by_host(s);
  993. get_user_flagrec(u, &victim, chan->dname);
  994. if (chk_op(victim, chan) && !(chan_master(user) || glob_master(user))) {
  995. if (all) goto next;
  996. dprintf(idx, "%s is a legal op.\n", nick);
  997. return;
  998. }
  999. if ((chan_master(victim) || glob_master(victim)) &&
  1000. !(glob_owner(user) || chan_owner(user))) {
  1001. if (all) goto next;
  1002. dprintf(idx, "%s is a %s master.\n", nick, chan->dname);
  1003. return;
  1004. }
  1005. if (glob_bot(victim) && !(glob_owner(user) || chan_owner(user))) {
  1006. dprintf(idx, "%s is another channel bot!\n", nick);
  1007. return;
  1008. }
  1009. dprintf(DP_SERVER, "KICK %s %s :%s%s\n", chan->name, m->nick, kickprefix, par);
  1010. m->flags |= SENTKICK;
  1011. dprintf(idx, "Kicked %s on %s.\n", nick, chan->dname);
  1012. next:;
  1013. if (!all)
  1014. chan = NULL;
  1015. else
  1016. chan = chan->next;
  1017. }
  1018. }
  1019. static void cmd_getkey(int idx, char *par)
  1020. {
  1021. struct chanset_t *chan = NULL;
  1022. chan = get_channel(idx, par);
  1023. if (!chan || !has_op(idx, chan))
  1024. return;
  1025. putlog(LOG_CMDS, "*", "#%s getkey %s", dcc[idx].nick, par);
  1026. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1027. if (privchan(user, chan, PRIV_OP)) {
  1028. dprintf(idx, "No such channel.\n");
  1029. return;
  1030. }
  1031. else if (!real_chk_op(user, chan, 0)) {
  1032. dprintf(idx, "You don't have access for %s\n", chan->dname);
  1033. return;
  1034. }
  1035. if (!(channel_pending(chan) || channel_active(chan))) {
  1036. dprintf(idx, "I'm not on %s right now.\n", chan->dname);
  1037. return;
  1038. }
  1039. char outbuf[201] = "";
  1040. if (!chan->channel.key[0])
  1041. simple_snprintf(outbuf, sizeof(outbuf), "%s has no key set.", chan->dname);
  1042. else
  1043. simple_snprintf(outbuf, sizeof(outbuf), "Key for %s is: %s", chan->dname, chan->channel.key);
  1044. if (chan->key_prot[0]) {
  1045. size_t olen = strlen(outbuf);
  1046. simple_snprintf(&outbuf[olen], sizeof(outbuf) - olen, " (Enforcing +k %s)", chan->key_prot);
  1047. }
  1048. dprintf(idx, "%s\n", outbuf);
  1049. }
  1050. static void cmd_mop(int idx, char *par)
  1051. {
  1052. struct chanset_t *chan = NULL;
  1053. bool found = 0, all = 0;
  1054. char *chname = NULL;
  1055. if (par[0] == '*' && !par[1]) {
  1056. get_user_flagrec(dcc[idx].user, &user, NULL);
  1057. if (!glob_owner(user)) {
  1058. dprintf(idx, "You do not have access to mop '*'\n");
  1059. return;
  1060. }
  1061. all = 1;
  1062. chan = chanset;
  1063. newsplit(&par);
  1064. } else {
  1065. if (par[0] && (strchr(CHANMETA, par[0]) != NULL)) {
  1066. chname = newsplit(&par);
  1067. chan = get_channel(idx, chname, 0);
  1068. } else
  1069. chan = get_channel(idx, "", 0);
  1070. }
  1071. if (!chan && !all && !chname) {
  1072. dprintf(idx, "Usage: mop <channel|*>\n");
  1073. return;
  1074. } else if (!chan)
  1075. return;
  1076. putlog(LOG_CMDS, "*", "#%s# (%s) mop %s", dcc[idx].nick, all ? "*" : chan->dname, par);
  1077. memberlist *m = NULL;
  1078. char s[256] = "";
  1079. while (chan) {
  1080. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1081. if (privchan(user, chan, PRIV_OP)) {
  1082. if (all) goto next;
  1083. dprintf(idx, "No such channel.\n");
  1084. return;
  1085. }
  1086. if (!chk_op(user, chan)) {
  1087. if (all) goto next;
  1088. dprintf(idx, "You are not a channel op on %s.\n", chan->dname);
  1089. return;
  1090. }
  1091. if (!me_op(chan)) {
  1092. if (all) goto next;
  1093. dprintf(idx, "I am not opped on %s.\n", chan->dname);
  1094. return;
  1095. }
  1096. if (channel_active(chan) && !channel_pending(chan)) {
  1097. for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
  1098. if (!m->user) {
  1099. simple_snprintf(s, sizeof(s), "%s!%s", m->nick, m->userhost);
  1100. m->user = get_user_by_host(s);
  1101. if (!m->user && m->userip[0]) {
  1102. simple_snprintf(s, sizeof(s), "%s!%s", m->nick, m->userip);
  1103. m->user = get_user_by_host(s);
  1104. }
  1105. }
  1106. if (m->user && u_pass_match(m->user, "-"))
  1107. continue; /* dont op users without a pass */
  1108. get_user_flagrec(m->user, &victim, chan->dname);
  1109. if (!chan_hasop(m) && !glob_bot(victim) && chk_op(victim, chan)) {
  1110. found = 1;
  1111. dprintf(idx, "Gave op to '%s' as '%s' on %s\n", m->user->handle, m->nick, chan->dname);
  1112. do_op(m->nick, chan, 0, 0);
  1113. }
  1114. }
  1115. } else {
  1116. if (!all)
  1117. dprintf(idx, "Channel %s is not active or is pending.\n", chan->dname);
  1118. return;
  1119. }
  1120. if (!found && !all)
  1121. dprintf(idx, "No one to op on %s\n", chan->dname);
  1122. next:;
  1123. if (!all)
  1124. chan = NULL;
  1125. else
  1126. chan = chan->next;
  1127. }
  1128. }
  1129. static void cmd_find(int idx, char *par)
  1130. {
  1131. if (!par[0]) {
  1132. dprintf(idx, "Usage: find <nick!ident@host.com>|<user> (wildcard * allowed)\n");
  1133. return;
  1134. }
  1135. putlog(LOG_CMDS, "*", "#%s# find %s", dcc[idx].nick, par);
  1136. struct chanset_t *chan = NULL, **cfound = NULL;
  1137. memberlist *m = NULL, **found = NULL;
  1138. int fcount = 0;
  1139. bool tr = 0, lookup_user = 0;
  1140. struct userrec *u = NULL;
  1141. if (!strchr(par, '!')) {
  1142. lookup_user = 1;
  1143. u = get_user_by_handle(userlist, par);
  1144. if (!u) {
  1145. dprintf(idx, "No such user: %s\n", par);
  1146. return;
  1147. }
  1148. }
  1149. /* make a list of members in found[] */
  1150. for (chan = chanset; chan; chan = chan->next) {
  1151. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1152. if (!privchan(user, chan, PRIV_OP)) {
  1153. for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
  1154. member_getuser(m, 1);
  1155. char s[UHOSTLEN] = "";
  1156. simple_snprintf(s, sizeof(s), "%s!%s", m->nick, m->userhost);
  1157. if ((!lookup_user && wild_match(par, s)) || (lookup_user && m->user == u)) {
  1158. fcount++;
  1159. if (!found) {
  1160. found = (memberlist **) my_calloc(1, sizeof(memberlist *) * 100);
  1161. cfound = (struct chanset_t **) my_calloc(1, sizeof(struct chanset_t *) * 100);
  1162. }
  1163. found[fcount - 1] = m;
  1164. cfound[fcount - 1] = chan;
  1165. if (fcount == 100) {
  1166. tr = 1;
  1167. break;
  1168. }
  1169. }
  1170. }
  1171. }
  1172. if (fcount == 100) {
  1173. tr = 1;
  1174. break;
  1175. }
  1176. }
  1177. if (fcount) {
  1178. char tmp[1024] = "";
  1179. int findex, i;
  1180. for (findex = 0; findex < fcount; findex++) {
  1181. if (found[findex]) {
  1182. simple_snprintf(tmp, sizeof(tmp), "%s!%s %s%s%s on %s", found[findex]->nick, found[findex]->userhost,
  1183. found[findex]->user ? "(user:" : "", found[findex]->user ? found[findex]->user->handle : "", found[findex]->user ? ")" : "",
  1184. cfound[findex]->name);
  1185. for (i = findex + 1; i < fcount; i++) {
  1186. if (found[i] && (!strcmp(found[i]->nick, found[findex]->nick))) {
  1187. strlcat(tmp, ", ", sizeof(tmp));
  1188. strlcat(tmp, cfound[i]->name, sizeof(tmp));
  1189. found[i] = NULL;
  1190. }
  1191. }
  1192. dprintf(idx, "%s\n", tmp);
  1193. }
  1194. }
  1195. free(found);
  1196. free(cfound);
  1197. } else {
  1198. dprintf(idx, "No matches for %s on any channels.\n", par);
  1199. }
  1200. if (tr)
  1201. dprintf(idx, "(more than 100 matches; list truncated)\n");
  1202. dprintf(idx, "--- Found %d matches.\n", fcount);
  1203. }
  1204. static void do_invite(int idx, char *par, bool op)
  1205. {
  1206. struct chanset_t *chan = NULL;
  1207. memberlist *m = NULL;
  1208. bool all = 0;
  1209. char *nick = NULL;
  1210. if (!par[0])
  1211. par = dcc[idx].nick;
  1212. nick = newsplit(&par);
  1213. if (par[0] == '*' && !par[1]) {
  1214. all = 1;
  1215. newsplit(&par);
  1216. } else {
  1217. chan = get_channel(idx, par);
  1218. if (!chan || !has_op(idx, chan))
  1219. return;
  1220. }
  1221. if (all)
  1222. chan = chanset;
  1223. putlog(LOG_CMDS, "*", "#%s# (%s) %s %s", dcc[idx].nick, all ? "*" : chan->dname, op ? "iop" : "invite", nick);
  1224. while (chan) {
  1225. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1226. if (privchan(user, chan, PRIV_OP)) {
  1227. if (all) goto next;
  1228. dprintf(idx, "No such channel.\n");
  1229. }
  1230. else if (!real_chk_op(user, chan, 0)) {
  1231. if (all) goto next;
  1232. dprintf(idx, "You don't have access to invite to %s\n", chan->dname);
  1233. return;
  1234. }
  1235. if (!me_op(chan)) {
  1236. if (all) goto next;
  1237. if (chan->channel.mode & CHANINV) {
  1238. dprintf(idx, "I can't help you now because I'm not a channel op on %s", chan->dname);
  1239. return;
  1240. }
  1241. if (!channel_active(chan)) {
  1242. dprintf(idx, "I'm not on %s right now!\n", chan->dname);
  1243. return;
  1244. }
  1245. }
  1246. m = ismember(chan, nick);
  1247. if (m && !chan_issplit(m)) {
  1248. if (all) goto next;
  1249. dprintf(idx, "%s is already on %s!\n", nick, chan->dname);
  1250. return;
  1251. }
  1252. cache_invite(chan, nick, NULL, NULL, op, 0);
  1253. dprintf(idx, "Inviting %s to %s.\n", nick, chan->dname);
  1254. next:;
  1255. if (!all)
  1256. chan = NULL;
  1257. else
  1258. chan = chan->next;
  1259. }
  1260. }
  1261. static void cmd_invite(int idx, char *par)
  1262. {
  1263. do_invite(idx, par, 0);
  1264. }
  1265. #ifdef CACHE
  1266. static void cmd_iop(int idx, char *par)
  1267. {
  1268. do_invite(idx, par, 1);
  1269. }
  1270. #endif /* CACHE */
  1271. static void cmd_authed(int idx, char *par)
  1272. {
  1273. putlog(LOG_CMDS, "*", STR("#%s# authed"), dcc[idx].nick);
  1274. dprintf(idx, STR("Authed:\n"));
  1275. Auth::TellAuthed(idx);
  1276. }
  1277. static void cmd_channel(int idx, char *par)
  1278. {
  1279. struct chanset_t *chan = NULL;
  1280. chan = get_channel(idx, par);
  1281. if (!chan || !has_op(idx, chan))
  1282. return;
  1283. char handle[HANDLEN + 1] = "", s[UHOSTLEN] = "", s1[UHOSTLEN] = "", atrflag = 0, chanflag[2] = "";
  1284. memberlist *m = NULL;
  1285. size_t maxnicklen, maxhandlen;
  1286. char format[81] = "";
  1287. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1288. putlog(LOG_CMDS, "*", "#%s# (%s) channel", dcc[idx].nick, chan->dname);
  1289. strlcpy(s, getchanmode(chan), sizeof s);
  1290. if (channel_pending(chan)) {
  1291. simple_snprintf(s1, sizeof s1, "Processing channel %s", chan->dname);
  1292. } else if (channel_active(chan)) {
  1293. simple_snprintf(s1, sizeof s1, "Channel %s", chan->dname);
  1294. } else {
  1295. simple_snprintf(s1, sizeof s1, "Desiring channel %s", chan->dname);
  1296. }
  1297. dprintf(idx, "%s, %d member%s, mode %s:\n", s1, chan->channel.members,
  1298. chan->channel.members == 1 ? "" : "s", s);
  1299. if (chan->channel.topic)
  1300. dprintf(idx, "%s: %s\n", "Channel Topic", chan->channel.topic);
  1301. if (channel_active(chan)) {
  1302. /* find max nicklen and handlen */
  1303. maxnicklen = maxhandlen = 0;
  1304. for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
  1305. if (strlen(m->nick) > maxnicklen)
  1306. maxnicklen = strlen(m->nick);
  1307. if (m->user)
  1308. if (strlen(m->user->handle) > maxhandlen)
  1309. maxhandlen = strlen(m->user->handle);
  1310. }
  1311. if (maxnicklen < 9) maxnicklen = 9;
  1312. if (maxhandlen < 9) maxhandlen = 9;
  1313. dprintf(idx, "(n = owner, m = master, o = op, d = deop, b = bot) CAP:global\n");
  1314. simple_snprintf(format, sizeof format, " %%-%zus %%-%zus %%-6s %%-4s %%-5s %%s %%s\n",
  1315. maxnicklen, maxhandlen);
  1316. dprintf(idx, format, "NICKNAME", "HANDLE", " JOIN", " HOPS", "IDLE", "USER@HOST", "USER@IP");
  1317. for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
  1318. if (m->joined > 0) {
  1319. if ((now - (m->joined)) > 86400)
  1320. strftime(s, 6, "%d%b", gmtime(&(m->joined)));
  1321. else
  1322. strftime(s, 6, "%H:%M", gmtime(&(m->joined)));
  1323. } else
  1324. strlcpy(s, " --- ", sizeof s);
  1325. // Force +r (re)processing
  1326. if (!m->userip[0] && doresolv(chan)) {
  1327. char host[UHOSTLEN] = "", *p = NULL;
  1328. p = strchr(m->userhost, '@');
  1329. if (p) {
  1330. ++p;
  1331. strlcpy(host, p, strlen(m->userhost) - (p - host));
  1332. resolve_to_member(chan, m->nick, host);
  1333. }
  1334. }
  1335. member_getuser(m, 1);
  1336. if (m->user == NULL)
  1337. strlcpy(handle, "*", sizeof handle);
  1338. else
  1339. strlcpy(handle, m->user->handle, sizeof handle);
  1340. get_user_flagrec(m->user, &user, chan->dname);
  1341. /* Determine status char to use */
  1342. if (glob_bot(user) && chk_op(user, chan))
  1343. atrflag = 'B';
  1344. else if (glob_bot(user))
  1345. atrflag = 'b';
  1346. else if (glob_owner(user))
  1347. atrflag = 'N';
  1348. else if (chan_owner(user))
  1349. atrflag = 'n';
  1350. else if (glob_master(user))
  1351. atrflag = 'M';
  1352. else if (chan_master(user))
  1353. atrflag = 'm';
  1354. else if (glob_deop(user))
  1355. atrflag = 'D';
  1356. else if (chan_deop(user))
  1357. atrflag = 'd';
  1358. else if (glob_autoop(user))
  1359. atrflag = 'A';
  1360. else if (chan_autoop(user))
  1361. atrflag = 'a';
  1362. else if (glob_op(user) && !privchan(user, chan, PRIV_OP))
  1363. atrflag = 'O';
  1364. else if (chan_op(user))
  1365. atrflag = 'o';
  1366. else if (glob_quiet(user))
  1367. atrflag = 'Q';
  1368. else if (chan_quiet(user))
  1369. atrflag = 'q';
  1370. else if (glob_voice(user) && !privchan(user, chan, PRIV_VOICE))
  1371. atrflag = 'V';
  1372. else if (chan_voice(user))
  1373. atrflag = 'v';
  1374. else if (glob_kick(user))
  1375. atrflag = 'K';
  1376. else if (chan_kick(user))
  1377. atrflag = 'k';
  1378. else if (glob_wasoptest(user))
  1379. atrflag = 'W';
  1380. else if (chan_wasoptest(user))
  1381. atrflag = 'w';
  1382. else
  1383. atrflag = ' ';
  1384. if (chan_hasop(m))
  1385. chanflag[1] = '@';
  1386. else if (chan_hasvoice(m))
  1387. chanflag[1] = '+';
  1388. else
  1389. chanflag[1] = ' ';
  1390. if (m->flags & OPER)
  1391. chanflag[0] = 'O';
  1392. else
  1393. chanflag[0] = ' ';
  1394. if (chan_issplit(m)) {
  1395. simple_snprintf(format, sizeof format,
  1396. "%%c%%c%%-%zus %%-%zus %%s %%c <- netsplit, %%lus\n",
  1397. maxnicklen, maxhandlen);
  1398. dprintf(idx, format, chanflag[0],chanflag[1], m->nick, handle, s, atrflag,
  1399. now - (m->split));
  1400. } else if (m->is_me) {
  1401. simple_snprintf(format, sizeof format,
  1402. "%%c%%c%%-%zus %%-%zus %%s %%c <- it's me!\n",
  1403. maxnicklen, maxhandlen);
  1404. dprintf(idx, format, chanflag[0], chanflag[1], m->nick, handle, s, atrflag);
  1405. } else {
  1406. /* Determine idle time */
  1407. if (now - (m->last) > 86400)
  1408. simple_snprintf(s1, sizeof s1, "%2dd", (int) ((now - (m->last)) / 86400));
  1409. else if (now - (m->last) > 3600)
  1410. simple_snprintf(s1, sizeof s1, "%2dh", (int) ((now - (m->last)) / 3600));
  1411. else if (now - (m->last) > 180)
  1412. simple_snprintf(s1, sizeof s1, "%2dm", (int) ((now - (m->last)) / 60));
  1413. else
  1414. strlcpy(s1, " ", sizeof s1);
  1415. simple_snprintf(format, sizeof format, "%%c%%c%%-%zus %%-%zus %%s %%c %%d %%s %%s %%s\n",
  1416. maxnicklen, maxhandlen);
  1417. dprintf(idx, format, chanflag[0], chanflag[1], m->nick, handle, s, atrflag, m->hops,
  1418. s1, m->userhost, m->userip);
  1419. }
  1420. if (chan_fakeop(m))
  1421. dprintf(idx, " (FAKE CHANOP GIVEN BY SERVER)\n");
  1422. if (chan_sentop(m))
  1423. dprintf(idx, " (pending +o -- I'm lagged)\n");
  1424. if (chan_sentdeop(m))
  1425. dprintf(idx, " (pending -o -- I'm lagged)\n");
  1426. if (chan_sentkick(m))
  1427. dprintf(idx, " (pending kick)\n");
  1428. }
  1429. }
  1430. dprintf(idx, "End of channel info.\n");
  1431. }
  1432. static void cmd_topic(int idx, char *par)
  1433. {
  1434. struct chanset_t *chan = NULL;
  1435. if (par[0] && (strchr(CHANMETA, par[0]) != NULL)) {
  1436. chan = get_channel(idx, newsplit(&par));
  1437. } else
  1438. chan = get_channel(idx, "");
  1439. if (!chan || !has_op(idx, chan))
  1440. return;
  1441. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1442. if (!channel_active(chan)) {
  1443. dprintf(idx, "I'm not on %s right now!\n", chan->dname);
  1444. return;
  1445. }
  1446. if (!par[0]) {
  1447. if (chan->channel.topic) {
  1448. dprintf(idx, "The topic for %s is: %s\n", chan->dname,
  1449. chan->channel.topic);
  1450. } else {
  1451. dprintf(idx, "No topic is set for %s\n", chan->dname);
  1452. }
  1453. } else if (channel_optopic(chan) && !me_op(chan)) {
  1454. dprintf(idx, "I'm not a channel op on %s and the channel %s",
  1455. "is +t.\n", chan->dname);
  1456. } else {
  1457. dprintf(DP_SERVER, "TOPIC %s :%s\n", chan->name, par);
  1458. dprintf(idx, "Changing topic...\n");
  1459. putlog(LOG_CMDS, "*", "#%s# (%s) topic %s", dcc[idx].nick,
  1460. chan->dname, par);
  1461. }
  1462. }
  1463. static void cmd_resetbans(int idx, char *par)
  1464. {
  1465. struct chanset_t *chan = get_channel(idx, newsplit(&par));
  1466. if (!chan || !has_op(idx, chan))
  1467. return;
  1468. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1469. putlog(LOG_CMDS, "*", "#%s# (%s) resetbans", dcc[idx].nick, chan->dname);
  1470. dprintf(idx, "Resetting bans on %s...\n", chan->dname);
  1471. resetbans(chan);
  1472. }
  1473. static void cmd_resetexempts(int idx, char *par)
  1474. {
  1475. struct chanset_t *chan = get_channel(idx, newsplit(&par));
  1476. if (!chan || !has_op(idx, chan))
  1477. return;
  1478. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1479. putlog(LOG_CMDS, "*", "#%s# (%s) resetexempts", dcc[idx].nick, chan->dname);
  1480. dprintf(idx, "Resetting exempts on %s...\n", chan->dname);
  1481. resetexempts(chan);
  1482. }
  1483. static void cmd_resetinvites(int idx, char *par)
  1484. {
  1485. struct chanset_t *chan = get_channel(idx, newsplit(&par));
  1486. if (!chan || !has_op(idx, chan))
  1487. return;
  1488. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1489. putlog(LOG_CMDS, "*", "#%s# (%s) resetinvites", dcc[idx].nick, chan->dname);
  1490. dprintf(idx, "Resetting resetinvites on %s...\n", chan->dname);
  1491. resetinvites(chan);
  1492. }
  1493. static void cmd_adduser(int idx, char *par)
  1494. {
  1495. if ((!par[0]) || ((par[0] =='!') && (!par[1]))) {
  1496. dprintf(idx, "Usage: adduser <nick> [handle]\n");
  1497. return;
  1498. }
  1499. char *nick = NULL, *hand = NULL;
  1500. struct chanset_t *chan = NULL;
  1501. struct userrec *u = NULL;
  1502. memberlist *m = NULL;
  1503. char s[UHOSTLEN] = "", s1[UHOSTLEN] = "", s2[MAXPASSLEN + 1] = "", s3[MAXPASSLEN + 1] = "", tmp[50] = "";
  1504. int atr = dcc[idx].user ? dcc[idx].user->flags : 0;
  1505. bool statichost = 0;
  1506. char *p1 = s1;
  1507. putlog(LOG_CMDS, "*", "#%s# adduser %s", dcc[idx].nick, par);
  1508. nick = newsplit(&par);
  1509. /* This flag allows users to have static host (added by drummer, 20Apr99) */
  1510. if (nick[0] == '!') {
  1511. statichost = 1;
  1512. nick++;
  1513. }
  1514. if (!par[0]) {
  1515. hand = nick;
  1516. } else {
  1517. bool ok = 1;
  1518. for (char *p = par; *p; p++)
  1519. if ((*p <= 32) || (*p >= 127))
  1520. ok = 0;
  1521. if (!ok) {
  1522. dprintf(idx, "You can't have strange characters in a nick.\n");
  1523. return;
  1524. } else if (strchr("-,+*=:!.@#;$", par[0]) != NULL) {
  1525. dprintf(idx, "You can't start a nick with '%c'.\n", par[0]);
  1526. return;
  1527. }
  1528. hand = par;
  1529. }
  1530. for (chan = chanset; chan; chan = chan->next) {
  1531. m = ismember(chan, nick);
  1532. if (m)
  1533. break;
  1534. }
  1535. if (!m) {
  1536. dprintf(idx, "%s is not on any channels I monitor\n", nick);
  1537. return;
  1538. }
  1539. if (strlen(hand) > HANDLEN)
  1540. hand[HANDLEN] = 0;
  1541. simple_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
  1542. if ((u = get_user_by_host(s))) {
  1543. dprintf(idx, "%s is already known as %s.\n", nick, u->handle);
  1544. return;
  1545. }
  1546. u = get_user_by_handle(userlist, hand);
  1547. if (u && (u->flags & (USER_OWNER | USER_MASTER)) &&
  1548. !(atr & USER_OWNER) && strcasecmp(dcc[idx].nick, hand)) {
  1549. dprintf(idx, "You can't add hostmasks to the bot owner/master.\n");
  1550. return;
  1551. }
  1552. if (!statichost)
  1553. maskaddr(s, s1, 0); /* *!user@host.com */
  1554. else {
  1555. strlcpy(s1, s, sizeof s1);
  1556. p1 = strchr(s1, '!');
  1557. if (strchr("~^+=-", p1[1]))
  1558. p1[1] = '?';
  1559. p1--;
  1560. p1[0] = '*';
  1561. }
  1562. if (!u) {
  1563. userlist = adduser(userlist, hand, p1, "-", USER_DEFAULT, 0);
  1564. u = get_user_by_handle(userlist, hand);
  1565. simple_snprintf(tmp, sizeof(tmp), "%li %s", (long) now, dcc[idx].nick);
  1566. set_user(&USERENTRY_ADDED, u, tmp);
  1567. make_rand_str(s2, MAXPASSLEN);
  1568. set_user(&USERENTRY_PASS, u, s2);
  1569. make_rand_str(s3, MAXPASSLEN);
  1570. set_user(&USERENTRY_SECPASS, u, s3);
  1571. dprintf(idx, "Added [%s]%s with no flags.\n", hand, p1);
  1572. dprintf(idx, "%s's initial password set to \002%s\002\n", hand, s2);
  1573. dprintf(idx, "%s's initial secpass set to \002%s\002\n", hand, s3);
  1574. bd::String msg;
  1575. msg.printf("*** You've been add to this botnet as '%s' with the host '%s'. Ask a botnet admin for the msg cmds. Your initial password is: %s", hand, p1, s2);
  1576. privmsg(nick, msg.c_str(), DP_HELP);
  1577. } else {
  1578. dprintf(idx, "Added hostmask %s to %s.\n", p1, u->handle);
  1579. addhost_by_handle(hand, p1);
  1580. get_user_flagrec(u, &user, chan->dname);
  1581. check_this_user(hand, 0, NULL);
  1582. }
  1583. }
  1584. static void cmd_deluser(int idx, char *par)
  1585. {
  1586. if (!par[0]) {
  1587. dprintf(idx, "Usage: deluser <nick>\n");
  1588. return;
  1589. }
  1590. char *nick = NULL, s[UHOSTLEN] = "", *added = NULL;
  1591. struct chanset_t *chan = NULL;
  1592. memberlist *m = NULL;
  1593. struct userrec *u = NULL;
  1594. nick = newsplit(&par);
  1595. for (chan = chanset; chan; chan = chan->next) {
  1596. m = ismember(chan, nick);
  1597. if (m)
  1598. break;
  1599. }
  1600. if (!m) {
  1601. dprintf(idx, "%s is not on any channels I monitor\n", nick);
  1602. return;
  1603. }
  1604. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1605. simple_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
  1606. if (!(u = get_user_by_host(s))) {
  1607. dprintf(idx, "%s is not a valid user.\n", nick);
  1608. return;
  1609. }
  1610. added = (char *) get_user(&USERENTRY_ADDED, u);
  1611. newsplit(&added);
  1612. get_user_flagrec(u, &victim, NULL);
  1613. if (isowner(u->handle)) {
  1614. dprintf(idx, "You can't remove a permanent bot owner!\n");
  1615. } else if (glob_admin(victim) && !isowner(dcc[idx].nick)) {
  1616. dprintf(idx, "You can't remove an admin!\n");
  1617. } else if (glob_owner(victim)) {
  1618. dprintf(idx, "You can't remove a bot owner!\n");
  1619. } else if (chan_owner(victim) && !glob_owner(user)) {
  1620. dprintf(idx, "You can't remove a channel owner!\n");
  1621. } else if (chan_master(victim) && !(glob_owner(user) || chan_owner(user))) {
  1622. dprintf(idx, "You can't remove a channel master!\n");
  1623. } else if (glob_bot(victim) && !glob_owner(user)) {
  1624. dprintf(idx, "You can't remove a bot!\n");
  1625. } else if (!glob_master(user) && strcasecmp(dcc[idx].nick, added)) {
  1626. dprintf(idx, "Sorry, you may not delete this user as you did not add them.\n");
  1627. } else {
  1628. char buf[HANDLEN + 1] = "";
  1629. strlcpy(buf, u->handle, sizeof buf);
  1630. if (deluser(u->handle)) {
  1631. dprintf(idx, "Deleted %s.\n", buf); /* ?!?! :) */
  1632. putlog(LOG_CMDS, "*", "#%s# deluser %s [%s]", dcc[idx].nick, nick, buf);
  1633. } else {
  1634. dprintf(idx, "Failed.\n");
  1635. }
  1636. }
  1637. }
  1638. static void cmd_reset(int idx, char *par)
  1639. {
  1640. struct chanset_t *chan = NULL;
  1641. if (par[0]) {
  1642. chan = findchan_by_dname(par);
  1643. if (chan)
  1644. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1645. if (!chan || privchan(user, chan, PRIV_OP)) {
  1646. dprintf(idx, "I don't monitor that channel.\n");
  1647. } else {
  1648. get_user_flagrec(dcc[idx].user, &user, par);
  1649. if (!glob_master(user) && !chan_master(user)) {
  1650. dprintf(idx, "You are not a master on %s.\n", chan->dname);
  1651. } else if (!channel_active(chan)) {
  1652. dprintf(idx, "I'm not on %s at the moment!\n", chan->dname);
  1653. } else {
  1654. putlog(LOG_CMDS, "*", "#%s# reset %s", dcc[idx].nick, par);
  1655. dprintf(idx, "Resetting channel info for %s...\n", chan->dname);
  1656. reset_chan_info(chan);
  1657. }
  1658. }
  1659. } else if (!(dcc[idx].user->flags & USER_MASTER)) {
  1660. dprintf(idx, "You are not a Bot Master.\n");
  1661. } else {
  1662. putlog(LOG_CMDS, "*", "#%s# reset all", dcc[idx].nick);
  1663. dprintf(idx, "Resetting channel info for all channels...\n");
  1664. for (chan = chanset; chan; chan = chan->next) {
  1665. if (channel_active(chan) || (!channel_active(chan) && shouldjoin(chan)))
  1666. reset_chan_info(chan);
  1667. }
  1668. }
  1669. }
  1670. static void cmd_play(int idx, char *par)
  1671. {
  1672. if (!par[0]) {
  1673. dprintf(idx, "Usage: play [channel] <file>\n");
  1674. return;
  1675. }
  1676. char *chname = NULL;
  1677. struct chanset_t *chan = NULL;
  1678. if (strchr(CHANMETA, par[0]) != NULL)
  1679. chname = newsplit(&par);
  1680. else
  1681. chname = 0;
  1682. chan = get_channel(idx, chname);
  1683. if (!chan)
  1684. return;
  1685. if (!par[0]) {
  1686. dprintf(idx, "Usage: play [channel] <file>\n");
  1687. return;
  1688. }
  1689. memberlist *m = ismember(chan, botname);
  1690. if (!m) {
  1691. dprintf(idx, "Cannot play to %s: I'm not on that channel.\n", chan->dname);
  1692. return;
  1693. }
  1694. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1695. if (!me_op(chan) && !isowner(dcc[idx].nick)) {
  1696. dprintf(idx, "Cannot play to %s: I am not opped.\n", chan->dname);
  1697. dprintf(idx, "Only owners may play to a channel the bot is not opped in.\n");
  1698. return;
  1699. }
  1700. if (!me_op(chan) && !me_voice(chan)) {
  1701. dprintf(idx, "Cannot play to %s: I am not voiced or opped.\n", chan->dname);
  1702. return;
  1703. }
  1704. putlog(LOG_CMDS, "*", "#%s# (%s) play %s", dcc[idx].nick, chan->dname, par);
  1705. // Ensure file exists and is within proper path
  1706. bd::String file(par);
  1707. if (file[0] == '/' || file(0, 2) == "..") {
  1708. dprintf(idx, "Cannot play '%s': Illegal path.\n", par);
  1709. return;
  1710. }
  1711. if (!can_stat(par)) {
  1712. dprintf(idx, "Cannot play '%s': Cannot access file.\n", par);
  1713. return;
  1714. }
  1715. bd::String prefix;
  1716. bd::Stream stream;
  1717. stream.loadFile(par);
  1718. bd::String str;
  1719. size_t lines = 0;
  1720. while (stream.tell() < stream.length()) {
  1721. str = stream.getline().chomp();
  1722. if (str.length()) {
  1723. privmsg(chan->name, str.c_str(), DP_PLAY);
  1724. ++lines;
  1725. }
  1726. }
  1727. dprintf(idx, "Playing %zu lines from %s to %s\n", lines, par, chan->dname);
  1728. long time_to_play = 0;
  1729. if (floodless)
  1730. time_to_play = 0;
  1731. else if (lines < 10)
  1732. time_to_play = 3;
  1733. else
  1734. time_to_play = 3 + ((lines - 10) / 2);
  1735. dprintf(idx, "Estimated time-to-play: %li seconds\n", time_to_play);
  1736. }
  1737. static cmd_t irc_dcc[] =
  1738. {
  1739. {"act", "o|o", (Function) cmd_act, NULL, LEAF},
  1740. {"adduser", "m|m", (Function) cmd_adduser, NULL, LEAF|AUTH},
  1741. {"authed", "n", (Function) cmd_authed, NULL, LEAF},
  1742. {"channel", "o|o", (Function) cmd_channel, NULL, LEAF},
  1743. {"deluser", "m|m", (Function) cmd_deluser, NULL, LEAF|AUTH},
  1744. {"deop", "o|o", (Function) cmd_deop, NULL, LEAF|AUTH},
  1745. {"devoice", "o|o", (Function) cmd_devoice, NULL, LEAF|AUTH},
  1746. {"getkey", "o|o", (Function) cmd_getkey, NULL, LEAF|AUTH},
  1747. {"find", "", (Function) cmd_find, NULL, LEAF|AUTH},
  1748. {"invite", "o|o", (Function) cmd_invite, NULL, LEAF|AUTH},
  1749. #ifdef CACHE
  1750. {"iop", "o|o", (Function) cmd_iop, NULL, LEAF|AUTH},
  1751. #endif /* CACHE */
  1752. {"kick", "o|o", (Function) cmd_kick, NULL, LEAF|AUTH},
  1753. {"kickban", "o|o", (Function) cmd_kickban, NULL, LEAF|AUTH},
  1754. {"mmode", "n|n", (Function) cmd_mmode, NULL, LEAF|AUTH},
  1755. {"mop", "n|m", (Function) cmd_mop, NULL, LEAF|AUTH},
  1756. {"msg", "o", (Function) cmd_msg, NULL, LEAF|AUTH},
  1757. {"nick", "m", (Function) cmd_nick, NULL, LEAF},
  1758. {"op", "o|o", (Function) cmd_op, NULL, LEAF|AUTH},
  1759. {"play", "m|m", (Function) cmd_play, NULL, LEAF|AUTH},
  1760. {"release", "m", (Function) cmd_release, NULL, LEAF|AUTH},
  1761. {"reset", "m|m", (Function) cmd_reset, NULL, LEAF|AUTH},
  1762. {"resetbans", "o|o", (Function) cmd_resetbans, NULL, LEAF|AUTH},
  1763. {"resetexempts", "o|o", (Function) cmd_resetexempts, NULL, LEAF|AUTH},
  1764. {"resetinvites", "o|o", (Function) cmd_resetinvites, NULL, LEAF|AUTH},
  1765. {"say", "o|o", (Function) cmd_say, NULL, LEAF},
  1766. {"swhois", "", (Function) cmd_swhois, NULL, LEAF|AUTH},
  1767. {"topic", "o|o", (Function) cmd_topic, NULL, LEAF|AUTH},
  1768. {"voice", "o|o", (Function) cmd_voice, NULL, LEAF|AUTH},
  1769. {NULL, NULL, NULL, NULL, 0}
  1770. };