cmdschan.c 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844
  1. /*
  2. * cmdschan.c -- part of channels.mod
  3. * commands from a user via dcc that cause server interaction
  4. *
  5. */
  6. #include <ctype.h>
  7. static struct flag_record user = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
  8. static struct flag_record victim = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
  9. static void cmd_pls_ban(struct userrec *u, int idx, char *par)
  10. {
  11. char *chname, *who, s[UHOSTLEN], s1[UHOSTLEN], *p, *p_expire;
  12. unsigned long int expire_time = 0, expire_foo;
  13. int sticky = 0;
  14. struct chanset_t *chan = NULL;
  15. module_entry *me;
  16. if (!par[0]) {
  17. dprintf(idx, "Usage: +ban <hostmask> [channel] [%%<XdXhXm>] [reason]\n");
  18. } else {
  19. who = newsplit(&par);
  20. if (par[0] && strchr(CHANMETA, par[0]))
  21. chname = newsplit(&par);
  22. else
  23. chname = 0;
  24. if (chname || !(u->flags & USER_MASTER)) {
  25. if (!chname)
  26. chname = dcc[idx].u.chat->con_chan;
  27. get_user_flagrec(u, &user, chname);
  28. chan = findchan_by_dname(chname);
  29. /* *shrug* ??? (guppy:10Feb1999) */
  30. if (!chan) {
  31. dprintf(idx, "That channel doesn't exist!\n");
  32. return;
  33. } else if (private(user, chan, PRIV_OP)) {
  34. dprintf(idx, "No such channel.\n");
  35. return;
  36. } else if (!((glob_op(user) && !chan_deop(user)) || chan_op(user))) {
  37. dprintf(idx, "You don't have access to set bans on %s.\n", chname);
  38. return;
  39. }
  40. } else
  41. chan = 0;
  42. /* Added by Q and Solal -- Requested by Arty2, special thanx :) */
  43. if (par[0] == '%') {
  44. p = newsplit(&par);
  45. p_expire = p + 1;
  46. while (*(++p) != 0) {
  47. switch (tolower(*p)) {
  48. case 'd':
  49. *p = 0;
  50. expire_foo = strtol(p_expire, NULL, 10);
  51. if (expire_foo > 365)
  52. expire_foo = 365;
  53. expire_time += 86400 * expire_foo;
  54. p_expire = p + 1;
  55. break;
  56. case 'h':
  57. *p = 0;
  58. expire_foo = strtol(p_expire, NULL, 10);
  59. if (expire_foo > 8760)
  60. expire_foo = 8760;
  61. expire_time += 3600 * expire_foo;
  62. p_expire = p + 1;
  63. break;
  64. case 'm':
  65. *p = 0;
  66. expire_foo = strtol(p_expire, NULL, 10);
  67. if (expire_foo > 525600)
  68. expire_foo = 525600;
  69. expire_time += 60 * expire_foo;
  70. p_expire = p + 1;
  71. }
  72. }
  73. }
  74. if (!par[0])
  75. par = "requested";
  76. else if (strlen(par) > MASKREASON_MAX)
  77. par[MASKREASON_MAX] = 0;
  78. if (strlen(who) > UHOSTMAX - 4)
  79. who[UHOSTMAX - 4] = 0;
  80. /* Fix missing ! or @ BEFORE checking against myself */
  81. if (!strchr(who, '!')) {
  82. if (!strchr(who, '@'))
  83. egg_snprintf(s, sizeof s, "%s!*@*", who); /* Lame nick ban */
  84. else
  85. egg_snprintf(s, sizeof s, "*!%s", who);
  86. } else if (!strchr(who, '@'))
  87. egg_snprintf(s, sizeof s, "%s@*", who); /* brain-dead? */
  88. else
  89. strncpyz(s, who, sizeof s);
  90. if ((me = module_find("server", 0, 0)) && me->funcs)
  91. egg_snprintf(s1, sizeof s1, "%s!%s", me->funcs[SERVER_BOTNAME],
  92. me->funcs[SERVER_BOTUSERHOST]);
  93. else
  94. egg_snprintf(s1, sizeof s1, "%s!%s@%s", origbotname, botuser, hostname);
  95. if (wild_match(s, s1)) {
  96. dprintf(idx, "I'm not going to ban myself.\n");
  97. putlog(LOG_CMDS, "*", "#%s# attempted +ban %s", dcc[idx].nick, s);
  98. } else {
  99. /* IRC can't understand bans longer than 70 characters */
  100. if (strlen(s) > 70) {
  101. s[69] = '*';
  102. s[70] = 0;
  103. }
  104. if (chan) {
  105. u_addban(chan, s, dcc[idx].nick, par,
  106. expire_time ? now + expire_time : 0, 0);
  107. if (par[0] == '*') {
  108. sticky = 1;
  109. par++;
  110. putlog(LOG_CMDS, "*", "#%s# (%s) +ban %s %s (%s) (sticky)",
  111. dcc[idx].nick, dcc[idx].u.chat->con_chan, s, chan->dname, par);
  112. dprintf(idx, "New %s sticky ban: %s (%s)\n", chan->dname, s, par);
  113. } else {
  114. putlog(LOG_CMDS, "*", "#%s# (%s) +ban %s %s (%s)", dcc[idx].nick,
  115. dcc[idx].u.chat->con_chan, s, chan->dname, par);
  116. dprintf(idx, "New %s ban: %s (%s)\n", chan->dname, s, par);
  117. }
  118. /* Avoid unnesessary modes if you got +dynamicbans, and there is
  119. * no reason to set mode if irc.mod aint loaded. (dw 001120)
  120. */
  121. if ((me = module_find("irc", 0, 0)))
  122. (me->funcs[IRC_CHECK_THIS_BAN])(chan, s, sticky);
  123. } else {
  124. u_addban(NULL, s, dcc[idx].nick, par,
  125. expire_time ? now + expire_time : 0, 0);
  126. if (par[0] == '*') {
  127. sticky = 1;
  128. par++;
  129. putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +ban %s (%s) (sticky)",
  130. dcc[idx].nick, s, par);
  131. dprintf(idx, "New sticky ban: %s (%s)\n", s, par);
  132. } else {
  133. putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +ban %s (%s)", dcc[idx].nick,
  134. s, par);
  135. dprintf(idx, "New ban: %s (%s)\n", s, par);
  136. }
  137. if ((me = module_find("irc", 0, 0)))
  138. for (chan = chanset; chan != NULL; chan = chan->next)
  139. (me->funcs[IRC_CHECK_THIS_BAN])(chan, s, sticky);
  140. }
  141. }
  142. }
  143. }
  144. #ifdef S_IRCNET
  145. static void cmd_pls_exempt(struct userrec *u, int idx, char *par)
  146. {
  147. char *chname, *who, s[UHOSTLEN], s1[UHOSTLEN], *p, *p_expire;
  148. unsigned long int expire_time = 0, expire_foo;
  149. struct chanset_t *chan = NULL;
  150. module_entry *me;
  151. if (!use_exempts) {
  152. dprintf(idx, "This command can only be used with use-exempts enabled.\n");
  153. return;
  154. }
  155. if (!par[0]) {
  156. dprintf(idx, "Usage: +exempt <hostmask> [channel] [%%<XdXhXm>] [reason]\n");
  157. } else {
  158. who = newsplit(&par);
  159. if (par[0] && strchr(CHANMETA, par[0]))
  160. chname = newsplit(&par);
  161. else
  162. chname = 0;
  163. if (chname || !(u->flags & USER_MASTER)) {
  164. if (!chname)
  165. chname = dcc[idx].u.chat->con_chan;
  166. get_user_flagrec(u,&user,chname);
  167. chan = findchan_by_dname(chname);
  168. /* *shrug* ??? (guppy:10Feb99) */
  169. if (!chan) {
  170. dprintf(idx, "That channel doesn't exist!\n");
  171. return;
  172. } else if (private(user, chan, PRIV_OP)) {
  173. dprintf(idx, "No such channel.\n");
  174. return;
  175. } else if (!((glob_op(user) && !chan_deop(user)) || chan_op(user))) {
  176. dprintf(idx, "You don't have access to set exempts on %s.\n", chname);
  177. return;
  178. }
  179. } else
  180. chan = 0;
  181. /* Added by Q and Solal - Requested by Arty2, special thanx :) */
  182. if (par[0] == '%') {
  183. p = newsplit (&par);
  184. p_expire = p + 1;
  185. while (*(++p) != 0) {
  186. switch (tolower(*p)) {
  187. case 'd':
  188. *p = 0;
  189. expire_foo = strtol (p_expire, NULL, 10);
  190. if (expire_foo > 365)
  191. expire_foo = 365;
  192. expire_time += 86400 * expire_foo;
  193. p_expire = p + 1;
  194. break;
  195. case 'h':
  196. *p = 0;
  197. expire_foo = strtol (p_expire, NULL, 10);
  198. if (expire_foo > 8760)
  199. expire_foo = 8760;
  200. expire_time += 3600 * expire_foo;
  201. p_expire = p + 1;
  202. break;
  203. case 'm':
  204. *p = 0;
  205. expire_foo = strtol (p_expire, NULL, 10);
  206. if (expire_foo > 525600)
  207. expire_foo = 525600;
  208. expire_time += 60 * expire_foo;
  209. p_expire = p + 1;
  210. }
  211. }
  212. }
  213. if (!par[0])
  214. par = "requested";
  215. else if (strlen(par) > MASKREASON_MAX)
  216. par[MASKREASON_MAX] = 0;
  217. if (strlen(who) > UHOSTMAX - 4)
  218. who[UHOSTMAX - 4] = 0;
  219. /* Fix missing ! or @ BEFORE checking against myself */
  220. if (!strchr(who, '!')) {
  221. if (!strchr(who, '@'))
  222. egg_snprintf(s, sizeof s, "%s!*@*", who); /* Lame nick exempt */
  223. else
  224. egg_snprintf(s, sizeof s, "*!%s", who);
  225. } else if (!strchr(who, '@'))
  226. egg_snprintf(s, sizeof s, "%s@*", who); /* brain-dead? */
  227. else
  228. strncpyz(s, who, sizeof s);
  229. if ((me = module_find("server",0,0)) && me->funcs)
  230. egg_snprintf(s1, sizeof s1, "%s!%s", me->funcs[SERVER_BOTNAME],
  231. me->funcs[SERVER_BOTUSERHOST]);
  232. else
  233. egg_snprintf(s1, sizeof s1, "%s!%s@%s", origbotname, botuser, hostname);
  234. /* IRC can't understand exempts longer than 70 characters */
  235. if (strlen(s) > 70) {
  236. s[69] = '*';
  237. s[70] = 0;
  238. }
  239. if (chan) {
  240. u_addexempt(chan, s, dcc[idx].nick, par,
  241. expire_time ? now + expire_time : 0, 0);
  242. if (par[0] == '*') {
  243. par++;
  244. putlog(LOG_CMDS, "*", "#%s# (%s) +exempt %s %s (%s) (sticky)",
  245. dcc[idx].nick, dcc[idx].u.chat->con_chan, s, chan->dname, par);
  246. dprintf(idx, "New %s sticky exempt: %s (%s)\n", chan->dname, s, par);
  247. } else {
  248. putlog(LOG_CMDS, "*", "#%s# (%s) +exempt %s %s (%s)", dcc[idx].nick,
  249. dcc[idx].u.chat->con_chan, s, chan->dname, par);
  250. dprintf(idx, "New %s exempt: %s (%s)\n", chan->dname, s, par);
  251. }
  252. add_mode(chan, '+', 'e', s);
  253. } else {
  254. u_addexempt(NULL, s, dcc[idx].nick, par,
  255. expire_time ? now + expire_time : 0, 0);
  256. if (par[0] == '*') {
  257. par++;
  258. putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +exempt %s (%s) (sticky)",
  259. dcc[idx].nick, s, par);
  260. dprintf(idx, "New sticky exempt: %s (%s)\n", s, par);
  261. } else {
  262. putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +exempt %s (%s)", dcc[idx].nick,
  263. s, par);
  264. dprintf(idx, "New exempt: %s (%s)\n", s, par);
  265. }
  266. for (chan = chanset; chan != NULL; chan = chan->next)
  267. add_mode(chan, '+', 'e', s);
  268. }
  269. }
  270. }
  271. static void cmd_pls_invite(struct userrec *u, int idx, char *par)
  272. {
  273. char *chname, *who, s[UHOSTLEN], s1[UHOSTLEN], *p, *p_expire;
  274. unsigned long int expire_time = 0, expire_foo;
  275. struct chanset_t *chan = NULL;
  276. module_entry *me;
  277. if (!use_invites) {
  278. dprintf(idx, "This command can only be used with use-invites enabled.\n");
  279. return;
  280. }
  281. if (!par[0]) {
  282. dprintf(idx, "Usage: +invite <hostmask> [channel] [%%<XdXhXm>] [reason]\n");
  283. } else {
  284. who = newsplit(&par);
  285. if (par[0] && strchr(CHANMETA, par[0]))
  286. chname = newsplit(&par);
  287. else
  288. chname = 0;
  289. if (chname || !(u->flags & USER_MASTER)) {
  290. if (!chname)
  291. chname = dcc[idx].u.chat->con_chan;
  292. get_user_flagrec(u,&user,chname);
  293. chan = findchan_by_dname(chname);
  294. /* *shrug* ??? (guppy:10Feb99) */
  295. if (!chan) {
  296. dprintf(idx, "That channel doesn't exist!\n");
  297. return;
  298. } else if (private(user, chan, PRIV_OP)) {
  299. dprintf(idx, "No such channel.\n");
  300. return;
  301. } else if (!((glob_op(user) && !chan_deop(user)) || chan_op(user))) {
  302. dprintf(idx, "You don't have access to set invites on %s.\n", chname);
  303. return;
  304. }
  305. } else
  306. chan = 0;
  307. /* Added by Q and Solal - Requested by Arty2, special thanx :) */
  308. if (par[0] == '%') {
  309. p = newsplit (&par);
  310. p_expire = p + 1;
  311. while (*(++p) != 0) {
  312. switch (tolower(*p)) {
  313. case 'd':
  314. *p = 0;
  315. expire_foo = strtol (p_expire, NULL, 10);
  316. if (expire_foo > 365)
  317. expire_foo = 365;
  318. expire_time += 86400 * expire_foo;
  319. p_expire = p + 1;
  320. break;
  321. case 'h':
  322. *p = 0;
  323. expire_foo = strtol (p_expire, NULL, 10);
  324. if (expire_foo > 8760)
  325. expire_foo = 8760;
  326. expire_time += 3600 * expire_foo;
  327. p_expire = p + 1;
  328. break;
  329. case 'm':
  330. *p = 0;
  331. expire_foo = strtol (p_expire, NULL, 10);
  332. if (expire_foo > 525600)
  333. expire_foo = 525600;
  334. expire_time += 60 * expire_foo;
  335. p_expire = p + 1;
  336. }
  337. }
  338. }
  339. if (!par[0])
  340. par = "requested";
  341. else if (strlen(par) > MASKREASON_MAX)
  342. par[MASKREASON_MAX] = 0;
  343. if (strlen(who) > UHOSTMAX - 4)
  344. who[UHOSTMAX - 4] = 0;
  345. /* Fix missing ! or @ BEFORE checking against myself */
  346. if (!strchr(who, '!')) {
  347. if (!strchr(who, '@'))
  348. egg_snprintf(s, sizeof s, "%s!*@*", who); /* Lame nick invite */
  349. else
  350. egg_snprintf(s, sizeof s, "*!%s", who);
  351. } else if (!strchr(who, '@'))
  352. egg_snprintf(s, sizeof s, "%s@*", who); /* brain-dead? */
  353. else
  354. strncpyz(s, who, sizeof s);
  355. if ((me = module_find("server",0,0)) && me->funcs)
  356. egg_snprintf(s1, sizeof s1, "%s!%s", me->funcs[SERVER_BOTNAME],
  357. me->funcs[SERVER_BOTUSERHOST]);
  358. else
  359. egg_snprintf(s1, sizeof s1, "%s!%s@%s", origbotname, botuser, hostname);
  360. /* IRC can't understand invites longer than 70 characters */
  361. if (strlen(s) > 70) {
  362. s[69] = '*';
  363. s[70] = 0;
  364. }
  365. if (chan) {
  366. u_addinvite(chan, s, dcc[idx].nick, par,
  367. expire_time ? now + expire_time : 0, 0);
  368. if (par[0] == '*') {
  369. par++;
  370. putlog(LOG_CMDS, "*", "#%s# (%s) +invite %s %s (%s) (sticky)",
  371. dcc[idx].nick, dcc[idx].u.chat->con_chan, s, chan->dname, par);
  372. dprintf(idx, "New %s sticky invite: %s (%s)\n", chan->dname, s, par);
  373. } else {
  374. putlog(LOG_CMDS, "*", "#%s# (%s) +invite %s %s (%s)", dcc[idx].nick,
  375. dcc[idx].u.chat->con_chan, s, chan->dname, par);
  376. dprintf(idx, "New %s invite: %s (%s)\n", chan->dname, s, par);
  377. }
  378. add_mode(chan, '+', 'I', s);
  379. } else {
  380. u_addinvite(NULL, s, dcc[idx].nick, par,
  381. expire_time ? now + expire_time : 0, 0);
  382. if (par[0] == '*') {
  383. par++;
  384. putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +invite %s (%s) (sticky)",
  385. dcc[idx].nick, s, par);
  386. dprintf(idx, "New sticky invite: %s (%s)\n", s, par);
  387. } else {
  388. putlog(LOG_CMDS, "*", "#%s# (GLOBAL) +invite %s (%s)", dcc[idx].nick,
  389. s, par);
  390. dprintf(idx, "New invite: %s (%s)\n", s, par);
  391. }
  392. for (chan = chanset; chan != NULL; chan = chan->next)
  393. add_mode(chan, '+', 'I', s);
  394. }
  395. }
  396. }
  397. #endif /* S_IRCNET */
  398. static void cmd_mns_ban(struct userrec *u, int idx, char *par)
  399. {
  400. int console = 0, i = 0, j;
  401. struct chanset_t *chan = NULL;
  402. char s[UHOSTLEN], *ban, *chname, *mask;
  403. masklist *b;
  404. if (!par[0]) {
  405. dprintf(idx, "Usage: -ban <hostmask|ban #> [channel]\n");
  406. return;
  407. }
  408. ban = newsplit(&par);
  409. if (par[0] && strchr(CHANMETA, par[0]))
  410. chname = newsplit(&par);
  411. else {
  412. chname = dcc[idx].u.chat->con_chan;
  413. console = 1;
  414. }
  415. if (chname || !(u->flags & USER_MASTER)) {
  416. if (!chname)
  417. chname = dcc[idx].u.chat->con_chan;
  418. get_user_flagrec(u, &user, chname);
  419. if (private(user, findchan_by_dname(chname), PRIV_OP)) {
  420. dprintf(idx, "No such channel.\n");
  421. return;
  422. }
  423. if ((!chan_op(user) && (!glob_op(user) || chan_deop(user)))) {
  424. dprintf(idx, "You don't have access to remove bans on %s.\n", chname);
  425. return;
  426. }
  427. }
  428. strncpyz(s, ban, sizeof s);
  429. if (console) {
  430. i = u_delban(NULL, s, (u->flags & USER_MASTER));
  431. if (i > 0) {
  432. if (lastdeletedmask)
  433. mask = lastdeletedmask;
  434. else
  435. mask = s;
  436. putlog(LOG_CMDS, "*", "#%s# -ban %s", dcc[idx].nick, mask);
  437. dprintf(idx, "%s: %s\n", IRC_REMOVEDBAN, mask);
  438. for (chan = chanset; chan != NULL; chan = chan->next)
  439. add_mode(chan, '-', 'b', mask);
  440. return;
  441. }
  442. }
  443. /* Channel-specific ban? */
  444. if (chname)
  445. chan = findchan_by_dname(chname);
  446. if (!chan) {
  447. dprintf(idx, "Invalid channel.\n");
  448. return;
  449. }
  450. if (str_isdigit(ban)) {
  451. i = atoi(ban);
  452. /* substract the numer of global bans to get the number of the channel ban */
  453. egg_snprintf(s, sizeof s, "%d", i);
  454. j = u_delban(0, s, 0);
  455. if (j < 0) {
  456. egg_snprintf(s, sizeof s, "%d", -j);
  457. j = u_delban(chan, s, 1);
  458. if (j > 0) {
  459. if (lastdeletedmask)
  460. mask = lastdeletedmask;
  461. else
  462. mask = s;
  463. putlog(LOG_CMDS, "*", "#%s# (%s) -ban %s", dcc[idx].nick, chan->dname,
  464. mask);
  465. dprintf(idx, "Removed %s channel ban: %s\n", chan->dname, mask);
  466. add_mode(chan, '-', 'b', mask);
  467. return;
  468. }
  469. }
  470. i = 0;
  471. for (b = chan->channel.ban; b && b->mask && b->mask[0]; b = b->next) {
  472. if ((!u_equals_mask(global_bans, b->mask)) &&
  473. (!u_equals_mask(chan->bans, b->mask))) {
  474. i++;
  475. if (i == -j) {
  476. add_mode(chan, '-', 'b', b->mask);
  477. dprintf(idx, "%s '%s' on %s.\n", IRC_REMOVEDBAN,
  478. b->mask, chan->dname);
  479. putlog(LOG_CMDS, "*", "#%s# (%s) -ban %s [on channel]",
  480. dcc[idx].nick, dcc[idx].u.chat->con_chan, ban);
  481. return;
  482. }
  483. }
  484. }
  485. } else {
  486. j = u_delban(chan, ban, 1);
  487. if (j > 0) {
  488. putlog(LOG_CMDS, "*", "#%s# (%s) -ban %s", dcc[idx].nick,
  489. dcc[idx].u.chat->con_chan, ban);
  490. dprintf(idx, "Removed %s channel ban: %s\n", chname, ban);
  491. add_mode(chan, '-', 'b', ban);
  492. return;
  493. }
  494. for (b = chan->channel.ban; b && b->mask && b->mask[0]; b = b->next) {
  495. if (!rfc_casecmp(b->mask, ban)) {
  496. add_mode(chan, '-', 'b', b->mask);
  497. dprintf(idx, "%s '%s' on %s.\n", IRC_REMOVEDBAN, b->mask, chan->dname);
  498. putlog(LOG_CMDS, "*", "#%s# (%s) -ban %s [on channel]",
  499. dcc[idx].nick, dcc[idx].u.chat->con_chan, ban);
  500. return;
  501. }
  502. }
  503. }
  504. dprintf(idx, "No such ban.\n");
  505. }
  506. #ifdef S_IRCNET
  507. static void cmd_mns_exempt(struct userrec *u, int idx, char *par)
  508. {
  509. int console = 0, i = 0, j;
  510. struct chanset_t *chan = NULL;
  511. char s[UHOSTLEN], *exempt, *chname, *mask;
  512. masklist *e;
  513. if (!use_exempts) {
  514. dprintf(idx, "This command can only be used with use-exempts enabled.\n");
  515. return;
  516. }
  517. if (!par[0]) {
  518. dprintf(idx, "Usage: -exempt <hostmask|exempt #> [channel]\n");
  519. return;
  520. }
  521. exempt = newsplit(&par);
  522. if (par[0] && strchr(CHANMETA, par[0]))
  523. chname = newsplit(&par);
  524. else {
  525. chname = dcc[idx].u.chat->con_chan;
  526. console = 1;
  527. }
  528. if (chname || !(u->flags & USER_MASTER)) {
  529. if (!chname)
  530. chname = dcc[idx].u.chat->con_chan;
  531. get_user_flagrec(u, &user, chname);
  532. if (private(user, findchan_by_dname(chname), PRIV_OP)) {
  533. dprintf(idx, "No such channel.\n");
  534. return;
  535. }
  536. if ((!chan_op(user) && (!glob_op(user) || chan_deop(user)))) {
  537. dprintf(idx, "You don't have access to remove exempts on %s.\n", chname);
  538. return;
  539. }
  540. }
  541. strncpyz(s, exempt, sizeof s);
  542. if (console) {
  543. i = u_delexempt(NULL, s, (u->flags & USER_MASTER));
  544. if (i > 0) {
  545. if (lastdeletedmask)
  546. mask = lastdeletedmask;
  547. else
  548. mask = s;
  549. putlog(LOG_CMDS, "*", "#%s# -exempt %s", dcc[idx].nick, mask);
  550. dprintf(idx, "%s: %s\n", IRC_REMOVEDEXEMPT, mask);
  551. for (chan = chanset; chan != NULL; chan = chan->next)
  552. add_mode(chan, '-', 'e', mask);
  553. return;
  554. }
  555. }
  556. /* Channel-specific exempt? */
  557. if (chname)
  558. chan = findchan_by_dname(chname);
  559. if (!chan) {
  560. dprintf(idx, "Invalid channel.\n");
  561. return;
  562. }
  563. if (str_isdigit(exempt)) {
  564. i = atoi(exempt);
  565. /* substract the numer of global exempts to get the number of the channel exempt */
  566. egg_snprintf(s, sizeof s, "%d", i);
  567. j = u_delexempt(0, s, 0);
  568. if (j < 0) {
  569. egg_snprintf(s, sizeof s, "%d", -j);
  570. j = u_delexempt(chan, s, 1);
  571. if (j > 0) {
  572. if (lastdeletedmask)
  573. mask = lastdeletedmask;
  574. else
  575. mask = s;
  576. putlog(LOG_CMDS, "*", "#%s# (%s) -exempt %s", dcc[idx].nick,
  577. chan->dname, mask);
  578. dprintf(idx, "Removed %s channel exempt: %s\n", chan->dname, mask);
  579. add_mode(chan, '-', 'e', mask);
  580. return;
  581. }
  582. }
  583. i = 0;
  584. for (e = chan->channel.exempt; e && e->mask && e->mask[0]; e = e->next) {
  585. if (!u_equals_mask(global_exempts, e->mask) &&
  586. !u_equals_mask(chan->exempts, e->mask)) {
  587. i++;
  588. if (i == -j) {
  589. add_mode(chan, '-', 'e', e->mask);
  590. dprintf(idx, "%s '%s' on %s.\n", IRC_REMOVEDEXEMPT,
  591. e->mask, chan->dname);
  592. putlog(LOG_CMDS, "*", "#%s# (%s) -exempt %s [on channel]",
  593. dcc[idx].nick, dcc[idx].u.chat->con_chan, exempt);
  594. return;
  595. }
  596. }
  597. }
  598. } else {
  599. j = u_delexempt(chan, exempt, 1);
  600. if (j > 0) {
  601. putlog(LOG_CMDS, "*", "#%s# (%s) -exempt %s", dcc[idx].nick,
  602. dcc[idx].u.chat->con_chan, exempt);
  603. dprintf(idx, "Removed %s channel exempt: %s\n", chname, exempt);
  604. add_mode(chan, '-', 'e', exempt);
  605. return;
  606. }
  607. for (e = chan->channel.exempt; e && e->mask && e->mask[0]; e = e->next) {
  608. if (!rfc_casecmp(e->mask, exempt)) {
  609. add_mode(chan, '-', 'e', e->mask);
  610. dprintf(idx, "%s '%s' on %s.\n",
  611. IRC_REMOVEDEXEMPT, e->mask, chan->dname);
  612. putlog(LOG_CMDS, "*", "#%s# (%s) -exempt %s [on channel]",
  613. dcc[idx].nick, dcc[idx].u.chat->con_chan, exempt);
  614. return;
  615. }
  616. }
  617. }
  618. dprintf(idx, "No such exemption.\n");
  619. }
  620. static void cmd_mns_invite(struct userrec *u, int idx, char *par)
  621. {
  622. int console = 0, i = 0, j;
  623. struct chanset_t *chan = NULL;
  624. char s[UHOSTLEN], *invite, *chname, *mask;
  625. masklist *inv;
  626. if (!use_invites) {
  627. dprintf(idx, "This command can only be used with use-invites enabled.\n");
  628. return;
  629. }
  630. if (!par[0]) {
  631. dprintf(idx, "Usage: -invite <hostmask|invite #> [channel]\n");
  632. return;
  633. }
  634. invite = newsplit(&par);
  635. if (par[0] && strchr(CHANMETA, par[0]))
  636. chname = newsplit(&par);
  637. else {
  638. chname = dcc[idx].u.chat->con_chan;
  639. console = 1;
  640. }
  641. if (chname || !(u->flags & USER_MASTER)) {
  642. if (!chname)
  643. chname = dcc[idx].u.chat->con_chan;
  644. get_user_flagrec(u, &user, chname);
  645. if (private(user, findchan_by_dname(chname), PRIV_OP)) {
  646. dprintf(idx, "No such channel.\n");
  647. return;
  648. }
  649. if ((!chan_op(user) && (!glob_op(user) || chan_deop(user)))) {
  650. dprintf(idx, "You don't have access to remove invites on %s.\n", chname);
  651. return;
  652. }
  653. }
  654. strncpyz(s, invite, sizeof s);
  655. if (console) {
  656. i = u_delinvite(NULL, s, (u->flags & USER_MASTER));
  657. if (i > 0) {
  658. if (lastdeletedmask)
  659. mask = lastdeletedmask;
  660. else
  661. mask = s;
  662. putlog(LOG_CMDS, "*", "#%s# -invite %s", dcc[idx].nick, mask);
  663. dprintf(idx, "%s: %s\n", IRC_REMOVEDINVITE, mask);
  664. for (chan = chanset; chan != NULL; chan = chan->next)
  665. add_mode(chan, '-', 'I', mask);
  666. return;
  667. }
  668. }
  669. /* Channel-specific invite? */
  670. if (chname)
  671. chan = findchan_by_dname(chname);
  672. if (!chan) {
  673. dprintf(idx, "Invalid channel.\n");
  674. return;
  675. }
  676. if (str_isdigit(invite)) {
  677. i = atoi(invite);
  678. /* substract the numer of global invites to get the number of the channel invite */
  679. egg_snprintf(s, sizeof s, "%d", i);
  680. j = u_delinvite(0, s, 0);
  681. if (j < 0) {
  682. egg_snprintf(s, sizeof s, "%d", -j);
  683. j = u_delinvite(chan, s, 1);
  684. if (j > 0) {
  685. if (lastdeletedmask)
  686. mask = lastdeletedmask;
  687. else
  688. mask = s;
  689. putlog(LOG_CMDS, "*", "#%s# (%s) -invite %s", dcc[idx].nick,
  690. chan->dname, mask);
  691. dprintf(idx, "Removed %s channel invite: %s\n", chan->dname, mask);
  692. add_mode(chan, '-', 'I', mask);
  693. return;
  694. }
  695. }
  696. i = 0;
  697. for (inv = chan->channel.invite; inv && inv->mask && inv->mask[0];
  698. inv = inv->next) {
  699. if (!u_equals_mask(global_invites, inv->mask) &&
  700. !u_equals_mask(chan->invites, inv->mask)) {
  701. i++;
  702. if (i == -j) {
  703. add_mode(chan, '-', 'I', inv->mask);
  704. dprintf(idx, "%s '%s' on %s.\n", IRC_REMOVEDINVITE,
  705. inv->mask, chan->dname);
  706. putlog(LOG_CMDS, "*", "#%s# (%s) -invite %s [on channel]",
  707. dcc[idx].nick, dcc[idx].u.chat->con_chan, invite);
  708. return;
  709. }
  710. }
  711. }
  712. } else {
  713. j = u_delinvite(chan, invite, 1);
  714. if (j > 0) {
  715. putlog(LOG_CMDS, "*", "#%s# (%s) -invite %s", dcc[idx].nick,
  716. dcc[idx].u.chat->con_chan, invite);
  717. dprintf(idx, "Removed %s channel invite: %s\n", chname, invite);
  718. add_mode(chan, '-', 'I', invite);
  719. return;
  720. }
  721. for (inv = chan->channel.invite; inv && inv->mask && inv->mask[0];
  722. inv = inv->next) {
  723. if (!rfc_casecmp(inv->mask, invite)) {
  724. add_mode(chan, '-', 'I', inv->mask);
  725. dprintf(idx, "%s '%s' on %s.\n",
  726. IRC_REMOVEDINVITE, inv->mask, chan->dname);
  727. putlog(LOG_CMDS, "*", "#%s# (%s) -invite %s [on channel]",
  728. dcc[idx].nick, dcc[idx].u.chat->con_chan, invite);
  729. return;
  730. }
  731. }
  732. }
  733. dprintf(idx, "No such invite.\n");
  734. }
  735. #endif /* S_IRCNET */
  736. static void cmd_bans(struct userrec *u, int idx, char *par)
  737. {
  738. if (!egg_strcasecmp(par, "all")) {
  739. putlog(LOG_CMDS, "*", "#%s# bans all", dcc[idx].nick);
  740. tell_bans(idx, 1, "");
  741. } else {
  742. putlog(LOG_CMDS, "*", "#%s# bans %s", dcc[idx].nick, par);
  743. tell_bans(idx, 0, par);
  744. }
  745. }
  746. #ifdef S_IRCNET
  747. static void cmd_exempts(struct userrec *u, int idx, char *par)
  748. {
  749. if (!use_exempts) {
  750. dprintf(idx, "This command can only be used with use-exempts enabled.\n");
  751. return;
  752. }
  753. if (!egg_strcasecmp(par, "all")) {
  754. putlog(LOG_CMDS, "*", "#%s# exempts all", dcc[idx].nick);
  755. tell_exempts(idx, 1, "");
  756. } else {
  757. putlog(LOG_CMDS, "*", "#%s# exempts %s", dcc[idx].nick, par);
  758. tell_exempts(idx, 0, par);
  759. }
  760. }
  761. static void cmd_invites(struct userrec *u, int idx, char *par)
  762. {
  763. if (!use_invites) {
  764. dprintf(idx, "This command can only be used with use-invites enabled.\n");
  765. return;
  766. }
  767. if (!egg_strcasecmp(par, "all")) {
  768. putlog(LOG_CMDS, "*", "#%s# invites all", dcc[idx].nick);
  769. tell_invites(idx, 1, "");
  770. } else {
  771. putlog(LOG_CMDS, "*", "#%s# invites %s", dcc[idx].nick, par);
  772. tell_invites(idx, 0, par);
  773. }
  774. }
  775. #endif /* S_IRCNET */
  776. static void cmd_info(struct userrec *u, int idx, char *par)
  777. {
  778. char s[512], *chname, *s1;
  779. int locked = 0;
  780. if (!use_info) {
  781. dprintf(idx, "Info storage is turned off.\n");
  782. return;
  783. }
  784. s1 = get_user(&USERENTRY_INFO, u);
  785. if (s1 && s1[0] == '@')
  786. locked = 1;
  787. if (par[0] && strchr(CHANMETA, par[0])) {
  788. chname = newsplit(&par);
  789. if (!findchan_by_dname(chname)) {
  790. dprintf(idx, "No such channel.\n");
  791. return;
  792. }
  793. get_handle_chaninfo(dcc[idx].nick, chname, s);
  794. if (s[0] == '@')
  795. locked = 1;
  796. s1 = s;
  797. } else
  798. chname = 0;
  799. if (!par[0]) {
  800. if (s1 && s1[0] == '@')
  801. s1++;
  802. if (s1 && s1[0]) {
  803. if (chname) {
  804. dprintf(idx, "Info on %s: %s\n", chname, s1);
  805. dprintf(idx, "Use 'info %s none' to remove it.\n", chname);
  806. } else {
  807. dprintf(idx, "Default info: %s\n", s1);
  808. dprintf(idx, "Use 'info none' to remove it.\n");
  809. }
  810. } else
  811. dprintf(idx, "No info has been set for you.\n");
  812. putlog(LOG_CMDS, "*", "#%s# info %s", dcc[idx].nick, chname ? chname : "");
  813. return;
  814. }
  815. if (locked && !(u && (u->flags & USER_MASTER))) {
  816. dprintf(idx, "Your info line is locked. Sorry.\n");
  817. return;
  818. }
  819. if (!egg_strcasecmp(par, "none")) {
  820. if (chname) {
  821. par[0] = 0;
  822. set_handle_chaninfo(userlist, dcc[idx].nick, chname, NULL);
  823. dprintf(idx, "Removed your info line on %s.\n", chname);
  824. putlog(LOG_CMDS, "*", "#%s# info %s none", dcc[idx].nick, chname);
  825. } else {
  826. set_user(&USERENTRY_INFO, u, NULL);
  827. dprintf(idx, "Removed your default info line.\n");
  828. putlog(LOG_CMDS, "*", "#%s# info none", dcc[idx].nick);
  829. }
  830. return;
  831. }
  832. /* if (par[0] == '@') This is stupid, and prevents a users info from being locked */
  833. /* par++; without .tcl, or a tcl script, aka, 'half-assed' -poptix 4Jun01 */
  834. if (chname) {
  835. set_handle_chaninfo(userlist, dcc[idx].nick, chname, par);
  836. dprintf(idx, "Your info on %s is now: %s\n", chname, par);
  837. putlog(LOG_CMDS, "*", "#%s# info %s ...", dcc[idx].nick, chname);
  838. } else {
  839. set_user(&USERENTRY_INFO, u, par);
  840. dprintf(idx, "Your default info is now: %s\n", par);
  841. putlog(LOG_CMDS, "*", "#%s# info ...", dcc[idx].nick);
  842. }
  843. }
  844. static void cmd_chinfo(struct userrec *u, int idx, char *par)
  845. {
  846. char *handle, *chname;
  847. struct userrec *u1;
  848. if (!use_info) {
  849. dprintf(idx, "Info storage is turned off.\n");
  850. return;
  851. }
  852. handle = newsplit(&par);
  853. if (!handle[0]) {
  854. dprintf(idx, "Usage: chinfo <handle> [channel] <new-info>\n");
  855. return;
  856. }
  857. u1 = get_user_by_handle(userlist, handle);
  858. if (!u1) {
  859. dprintf(idx, "No such user.\n");
  860. return;
  861. }
  862. if (par[0] && strchr(CHANMETA, par[0])) {
  863. chname = newsplit(&par);
  864. if (!findchan_by_dname(chname)) {
  865. dprintf(idx, "No such channel.\n");
  866. return;
  867. }
  868. } else
  869. chname = 0;
  870. if ((u1->flags & USER_BOT) && !(u->flags & USER_MASTER)) {
  871. dprintf(idx, "You have to be master to change bots info.\n");
  872. return;
  873. }
  874. if ((u1->flags & USER_OWNER) && !(u->flags & USER_OWNER)) {
  875. dprintf(idx, "You can't change info for the bot owner.\n");
  876. return;
  877. }
  878. if (chname) {
  879. get_user_flagrec(u, &user, chname);
  880. get_user_flagrec(u1, &victim, chname);
  881. if ((chan_owner(victim) || glob_owner(victim)) &&
  882. !(glob_owner(user) || chan_owner(user))) {
  883. dprintf(idx, "You can't change info for the channel owner.\n");
  884. return;
  885. }
  886. }
  887. putlog(LOG_CMDS, "*", "#%s# chinfo %s %s %s", dcc[idx].nick, handle,
  888. chname ? chname : par, chname ? par : "");
  889. if (!egg_strcasecmp(par, "none"))
  890. par[0] = 0;
  891. if (chname) {
  892. set_handle_chaninfo(userlist, handle, chname, par);
  893. if (par[0] == '@')
  894. dprintf(idx, "New info (LOCKED) for %s on %s: %s\n", handle, chname,
  895. &par[1]);
  896. else if (par[0])
  897. dprintf(idx, "New info for %s on %s: %s\n", handle, chname, par);
  898. else
  899. dprintf(idx, "Wiped info for %s on %s\n", handle, chname);
  900. } else {
  901. set_user(&USERENTRY_INFO, u1, par[0] ? par : NULL);
  902. if (par[0] == '@')
  903. dprintf(idx, "New default info (LOCKED) for %s: %s\n", handle, &par[1]);
  904. else if (par[0])
  905. dprintf(idx, "New default info for %s: %s\n", handle, par);
  906. else
  907. dprintf(idx, "Wiped default info for %s\n", handle);
  908. }
  909. }
  910. static void cmd_slowjoin(struct userrec *u, int idx, char *par)
  911. {
  912. int intvl = 0, delay = 0, count = 1;
  913. char *chname;
  914. char buf[2048], buf2[1048];
  915. struct chanset_t *chan;
  916. tand_t *bot;
  917. char *p;
  918. /* slowjoin #chan 60 */
  919. putlog(LOG_CMDS, "*", "#%s# slowjoin %s", dcc[idx].nick, par);
  920. chname = newsplit(&par);
  921. p = newsplit(&par);
  922. intvl = atoi(p);
  923. if (!chname[0] || !p[0]) {
  924. dprintf(idx, "Usage: slowjoin channel interval-seconds [channel options]\n");
  925. return;
  926. }
  927. if (intvl < 10) {
  928. dprintf(idx, "Interval must be at least 10 seconds\n");
  929. return;
  930. }
  931. if ((chan = findchan_by_dname(chname))) {
  932. dprintf(idx, "Already on %s\n", chan->dname);
  933. return;
  934. }
  935. if (!strchr(CHANMETA, chname[0])) {
  936. dprintf(idx, "Invalid channel name\n");
  937. return;
  938. }
  939. strcpy(buf, "+inactive ");
  940. if (par[0])
  941. strncat(buf, par, sizeof(buf));
  942. if (tcl_channel_add(0, chname, buf) == TCL_ERROR) {
  943. dprintf(idx, "Invalid channel.\n");
  944. return;
  945. }
  946. chan = findchan_by_dname(chname);
  947. if (!chan) {
  948. dprintf(idx, "Hmmm... Channel didn't get added. Weird *shrug*\n");
  949. return;
  950. }
  951. sprintf(buf2, "cjoin %s %s", chan->dname, buf);
  952. putallbots(buf2);
  953. #ifdef HUB
  954. count=0;
  955. #else /* !HUB */
  956. count=1;
  957. #endif /* HUB */
  958. for (bot = tandbot; bot; bot = bot->next) {
  959. struct userrec *ubot;
  960. char tmp[100];
  961. ubot = get_user_by_handle(userlist, bot->bot);
  962. if (ubot) {
  963. /* Variation: 60 secs intvl should be 60 +/- 15 */
  964. if (bot_hublevel(ubot) < 999) {
  965. sprintf(tmp, "sj %s 0\n", chan->dname);
  966. } else {
  967. int v = (random() % (intvl / 2)) - (intvl / 4);
  968. delay += intvl;
  969. sprintf(tmp, "sj %s %i\n", chan->dname, delay + v);
  970. count++;
  971. }
  972. putbot(ubot->handle, tmp);
  973. }
  974. }
  975. dprintf(idx, "%i bots joining %s during the next %i seconds\n", count, chan->dname, delay);
  976. chan->status &= ~CHAN_INACTIVE;
  977. #ifdef LEAF
  978. if (shouldjoin(chan))
  979. dprintf(DP_MODE, "JOIN %s %s\n", chan->name, chan->key_prot);
  980. #endif /* LEAF */
  981. }
  982. static void cmd_slowpart(struct userrec *u, int idx, char *par)
  983. {
  984. int intvl = 0, delay = 0, count = 1;
  985. char *chname;
  986. struct chanset_t *chan;
  987. tand_t *bot;
  988. char *p;
  989. /* slowpart #chan 60 */
  990. putlog(LOG_CMDS, "*", "#%s# slowpart %s", dcc[idx].nick, par);
  991. chname = newsplit(&par);
  992. p = newsplit(&par);
  993. intvl = atoi(p);
  994. if (!chname[0] || !p[0]) {
  995. dprintf(idx, "Usage: slowpart channel interval-seconds\n");
  996. return;
  997. }
  998. if (intvl < 10) {
  999. dprintf(idx, "Interval must be at least 10 seconds\n");
  1000. return;
  1001. }
  1002. if (!(chan = findchan_by_dname(chname))) {
  1003. dprintf(idx, "Not on %s\n", chan->dname);
  1004. return;
  1005. }
  1006. remove_channel(chan);
  1007. #ifdef HUB
  1008. write_userfile(-1);
  1009. #endif /* HUB */
  1010. dprintf(idx, "Channel %s removed from the bot.\n", chname);
  1011. dprintf(idx, "This includes any channel specific bans, invites, exemptions and user records that you set.\n");
  1012. if (findchan_by_dname(chname)) {
  1013. dprintf(idx, "Hmmm... Channel didn't get removed. Weird *shrug*\n");
  1014. return;
  1015. }
  1016. #ifdef HUB
  1017. count=0;
  1018. #else /* !HUB */
  1019. count=1;
  1020. #endif /* HUB */
  1021. for (bot = tandbot; bot; bot = bot->next) {
  1022. char tmp[100];
  1023. struct userrec *ubot;
  1024. ubot = get_user_by_handle(userlist, bot->bot);
  1025. /* Variation: 60 secs intvl should be 60 +/- 15 */
  1026. if (ubot) {
  1027. if (bot_hublevel(ubot) < 999) {
  1028. sprintf(tmp, "sp %s 0\n", chname);
  1029. } else {
  1030. int v = (random() % (intvl / 2)) - (intvl / 4);
  1031. delay += intvl;
  1032. sprintf(tmp, "sp %s %i\n", chname, delay + v);
  1033. count++;
  1034. }
  1035. putbot(ubot->handle, tmp);
  1036. }
  1037. }
  1038. dprintf(idx, "%i bots parting %s during the next %i seconds\n", count, chname, delay);
  1039. #ifdef LEAF
  1040. dprintf(DP_MODE, "PART %s\n", chname);
  1041. #endif /* LEAF */
  1042. }
  1043. static void cmd_stick_yn(int idx, char *par, int yn)
  1044. {
  1045. int i = 0, j;
  1046. struct chanset_t *chan, *achan;
  1047. char *stick_type, s[UHOSTLEN], chname[81];
  1048. module_entry *me;
  1049. stick_type = newsplit(&par);
  1050. strncpyz(s, newsplit(&par), sizeof s);
  1051. strncpyz(chname, newsplit(&par), sizeof chname);
  1052. #ifdef S_IRCNET
  1053. if (egg_strcasecmp(stick_type, "exempt") &&
  1054. egg_strcasecmp(stick_type, "invite") &&
  1055. egg_strcasecmp(stick_type, "ban")) {
  1056. #else
  1057. if (egg_strcasecmp(stick_type, "ban")) {
  1058. #endif
  1059. strncpyz(chname, s, sizeof chname);
  1060. strncpyz(s, stick_type, sizeof s);
  1061. }
  1062. if (!s[0]) {
  1063. #ifdef S_IRCNET
  1064. dprintf(idx, "Usage: %sstick [ban/exempt/invite] <hostmask or number> [channel]\n",
  1065. #else
  1066. dprintf(idx, "Usage: %sstick [ban] <hostmask or number> [channel]\n",
  1067. #endif
  1068. yn ? "" : "un");
  1069. return;
  1070. }
  1071. /* Now deal with exemptions */
  1072. #ifdef S_IRCNET
  1073. if (!egg_strcasecmp(stick_type, "exempt")) {
  1074. if (!use_exempts) {
  1075. dprintf(idx, "This command can only be used with use-exempts enabled.\n");
  1076. return;
  1077. }
  1078. if (!chname[0]) {
  1079. i = u_setsticky_exempt(NULL, s,
  1080. (dcc[idx].user->flags & USER_MASTER) ? yn : -1);
  1081. if (i > 0) {
  1082. putlog(LOG_CMDS, "*", "#%s# %sstick exempt %s",
  1083. dcc[idx].nick, yn ? "" : "un", s);
  1084. dprintf(idx, "%stuck exempt: %s\n", yn ? "S" : "Uns", s);
  1085. return;
  1086. }
  1087. strncpyz(chname, dcc[idx].u.chat->con_chan, sizeof chname);
  1088. }
  1089. /* Channel-specific exempt? */
  1090. if (!(chan = findchan_by_dname(chname))) {
  1091. dprintf(idx, "No such channel.\n");
  1092. return;
  1093. }
  1094. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1095. if (private(user, chan, PRIV_OP)) {
  1096. dprintf(idx, "No such channel.\n");
  1097. return;
  1098. }
  1099. if (str_isdigit(s)) {
  1100. /* substract the numer of global exempts to get the number of the channel exempt */
  1101. j = u_setsticky_exempt(NULL, s, -1);
  1102. if (j < 0)
  1103. egg_snprintf(s, sizeof s, "%d", -j);
  1104. }
  1105. j = u_setsticky_exempt(chan, s, yn);
  1106. if (j > 0) {
  1107. putlog(LOG_CMDS, "*", "#%s# %sstick exempt %s %s", dcc[idx].nick,
  1108. yn ? "" : "un", s, chname);
  1109. dprintf(idx, "%stuck %s exempt: %s\n", yn ? "S" : "Uns", chname, s);
  1110. return;
  1111. }
  1112. dprintf(idx, "No such exempt.\n");
  1113. return;
  1114. /* Now the invites */
  1115. } else if (!egg_strcasecmp(stick_type, "invite")) {
  1116. if (!use_invites) {
  1117. dprintf(idx, "This command can only be used with use-invites enabled.\n");
  1118. return;
  1119. }
  1120. if (!chname[0]) {
  1121. i = u_setsticky_invite(NULL, s,
  1122. (dcc[idx].user->flags & USER_MASTER) ? yn : -1);
  1123. if (i > 0) {
  1124. putlog(LOG_CMDS, "*", "#%s# %sstick invite %s",
  1125. dcc[idx].nick, yn ? "" : "un", s);
  1126. dprintf(idx, "%stuck invite: %s\n", yn ? "S" : "Uns", s);
  1127. return;
  1128. }
  1129. strncpyz(chname, dcc[idx].u.chat->con_chan, sizeof chname);
  1130. }
  1131. /* Channel-specific invite? */
  1132. if (!(chan = findchan_by_dname(chname))) {
  1133. dprintf(idx, "No such channel.\n");
  1134. return;
  1135. }
  1136. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1137. if (private(user, chan, PRIV_OP)) {
  1138. dprintf(idx, "No such channel.\n");
  1139. return;
  1140. }
  1141. if (str_isdigit(s)) {
  1142. /* substract the numer of global invites to get the number of the channel invite */
  1143. j = u_setsticky_invite(NULL, s, -1);
  1144. if (j < 0)
  1145. egg_snprintf(s, sizeof s, "%d", -j);
  1146. }
  1147. j = u_setsticky_invite(chan, s, yn);
  1148. if (j > 0) {
  1149. putlog(LOG_CMDS, "*", "#%s# %sstick invite %s %s", dcc[idx].nick,
  1150. yn ? "" : "un", s, chname);
  1151. dprintf(idx, "%stuck %s invite: %s\n", yn ? "S" : "Uns", chname, s);
  1152. return;
  1153. }
  1154. dprintf(idx, "No such invite.\n");
  1155. return;
  1156. }
  1157. #endif /* S_IRCNET */
  1158. if (!chname[0]) {
  1159. i = u_setsticky_ban(NULL, s,
  1160. (dcc[idx].user->flags & USER_MASTER) ? yn : -1);
  1161. if (i > 0) {
  1162. putlog(LOG_CMDS, "*", "#%s# %sstick ban %s",
  1163. dcc[idx].nick, yn ? "" : "un", s);
  1164. dprintf(idx, "%stuck ban: %s\n", yn ? "S" : "Uns", s);
  1165. if ((me = module_find("irc", 0, 0)))
  1166. for (achan = chanset; achan != NULL; achan = achan->next)
  1167. (me->funcs[IRC_CHECK_THIS_BAN])(achan, s, yn);
  1168. return;
  1169. }
  1170. strncpyz(chname, dcc[idx].u.chat->con_chan, sizeof chname);
  1171. }
  1172. /* Channel-specific ban? */
  1173. if (!(chan = findchan_by_dname(chname))) {
  1174. dprintf(idx, "No such channel.\n");
  1175. return;
  1176. }
  1177. get_user_flagrec(dcc[idx].user, &user, chan->dname);
  1178. if (private(user, chan, PRIV_OP)) {
  1179. dprintf(idx, "No such channel.\n");
  1180. return;
  1181. }
  1182. if (str_isdigit(s)) {
  1183. /* substract the numer of global bans to get the number of the channel ban */
  1184. j = u_setsticky_ban(NULL, s, -1);
  1185. if (j < 0)
  1186. egg_snprintf(s, sizeof s, "%d", -j);
  1187. }
  1188. j = u_setsticky_ban(chan, s, yn);
  1189. if (j > 0) {
  1190. putlog(LOG_CMDS, "*", "#%s# %sstick ban %s %s", dcc[idx].nick,
  1191. yn ? "" : "un", s, chname);
  1192. dprintf(idx, "%stuck %s ban: %s\n", yn ? "S" : "Uns", chname, s);
  1193. if ((me = module_find("irc", 0, 0)))
  1194. (me->funcs[IRC_CHECK_THIS_BAN])(chan, s, yn);
  1195. return;
  1196. }
  1197. dprintf(idx, "No such ban.\n");
  1198. }
  1199. static void cmd_stick(struct userrec *u, int idx, char *par)
  1200. {
  1201. cmd_stick_yn(idx, par, 1);
  1202. }
  1203. static void cmd_unstick(struct userrec *u, int idx, char *par)
  1204. {
  1205. cmd_stick_yn(idx, par, 0);
  1206. }
  1207. static void cmd_pls_chrec(struct userrec *u, int idx, char *par)
  1208. {
  1209. char *nick, *chn;
  1210. struct chanset_t *chan;
  1211. struct userrec *u1;
  1212. struct chanuserrec *chanrec;
  1213. if (!par[0]) {
  1214. dprintf(idx, "Usage: +chrec <user> [channel]\n");
  1215. return;
  1216. }
  1217. nick = newsplit(&par);
  1218. u1 = get_user_by_handle(userlist, nick);
  1219. if (!u1) {
  1220. dprintf(idx, "No such user.\n");
  1221. return;
  1222. }
  1223. if (!par[0])
  1224. chan = findchan_by_dname(dcc[idx].u.chat->con_chan);
  1225. else {
  1226. chn = newsplit(&par);
  1227. chan = findchan_by_dname(chn);
  1228. }
  1229. if (!chan) {
  1230. dprintf(idx, "No such channel.\n");
  1231. return;
  1232. }
  1233. get_user_flagrec(u, &user, chan->dname);
  1234. get_user_flagrec(u1, &victim, chan->dname);
  1235. if (private(user, chan, PRIV_OP)) {
  1236. dprintf(idx, "No such channel.\n");
  1237. return;
  1238. }
  1239. if ((!glob_master(user) && !chan_master(user)) || /* drummer */
  1240. (chan_owner(victim) && !chan_owner(user) && !glob_owner(user)) ||
  1241. (glob_owner(victim) && !glob_owner(user))) {
  1242. dprintf(idx, "You have no permission to do that.\n");
  1243. return;
  1244. }
  1245. chanrec = get_chanrec(u1, chan->dname);
  1246. if (chanrec) {
  1247. dprintf(idx, "User %s already has a channel record for %s.\n",
  1248. nick, chan->dname);
  1249. return;
  1250. }
  1251. putlog(LOG_CMDS, "*", "#%s# +chrec %s %s", dcc[idx].nick,
  1252. nick, chan->dname);
  1253. add_chanrec(u1, chan->dname);
  1254. dprintf(idx, "Added %s channel record for %s.\n", chan->dname, nick);
  1255. }
  1256. static void cmd_mns_chrec(struct userrec *u, int idx, char *par)
  1257. {
  1258. char *nick, *chn = NULL;
  1259. struct userrec *u1;
  1260. struct chanuserrec *chanrec;
  1261. if (!par[0]) {
  1262. dprintf(idx, "Usage: -chrec <user> [channel]\n");
  1263. return;
  1264. }
  1265. nick = newsplit(&par);
  1266. u1 = get_user_by_handle(userlist, nick);
  1267. if (!u1) {
  1268. dprintf(idx, "No such user.\n");
  1269. return;
  1270. }
  1271. if (!par[0]) {
  1272. struct chanset_t *chan;
  1273. chan = findchan_by_dname(dcc[idx].u.chat->con_chan);
  1274. if (chan)
  1275. chn = chan->dname;
  1276. else {
  1277. dprintf(idx, "Invalid console channel.\n");
  1278. return;
  1279. }
  1280. } else
  1281. chn = newsplit(&par);
  1282. get_user_flagrec(u, &user, chn);
  1283. get_user_flagrec(u1, &victim, chn);
  1284. if (private(user, findchan_by_dname(chn), PRIV_OP)) {
  1285. dprintf(idx, "No such channel.\n");
  1286. return;
  1287. }
  1288. if ((!glob_master(user) && !chan_master(user)) || /* drummer */
  1289. (chan_owner(victim) && !chan_owner(user) && !glob_owner(user)) ||
  1290. (glob_owner(victim) && !glob_owner(user))) {
  1291. dprintf(idx, "You have no permission to do that.\n");
  1292. return;
  1293. }
  1294. chanrec = get_chanrec(u1, chn);
  1295. if (!chanrec) {
  1296. dprintf(idx, "User %s doesn't have a channel record for %s.\n", nick, chn);
  1297. return;
  1298. }
  1299. putlog(LOG_CMDS, "*", "#%s# -chrec %s %s", dcc[idx].nick, nick, chn);
  1300. del_chanrec(u1, chn);
  1301. dprintf(idx, "Removed %s channel record from %s.\n", chn, nick);
  1302. }
  1303. static void cmd_cycle(struct userrec *u, int idx, char *par)
  1304. {
  1305. char *chname;
  1306. char buf2[1024];
  1307. int delay = 10;
  1308. struct chanset_t *chan;
  1309. putlog(LOG_CMDS, "*", "#%s# cycle %s", dcc[idx].nick, par);
  1310. if (!par[0]) {
  1311. dprintf(idx, "Usage: cycle [%s]<channel> [delay]\n", CHANMETA);
  1312. dprintf(idx, "rejoin delay defaults to '10'\n");
  1313. return;
  1314. }
  1315. chname = newsplit(&par);
  1316. chan = findchan_by_dname(chname);
  1317. if (!chan) {
  1318. dprintf(idx, "%s it not a valid channel.\n", chname);
  1319. return;
  1320. }
  1321. if (par[0])
  1322. delay = atoi(newsplit(&par));
  1323. sprintf(buf2, "cycle %s %d", chname, delay); //this just makes the bot PART
  1324. putallbots(buf2);
  1325. #ifdef LEAF
  1326. do_chanset(chan, "+inactive", 2);
  1327. dprintf(DP_SERVER, "PART %s\n", chan->name);
  1328. chan->channel.jointime = ((now + delay) - server_lag);
  1329. #endif /* LEAF */
  1330. }
  1331. static void cmd_down(struct userrec *u, int idx, char *par)
  1332. {
  1333. char *chname;
  1334. char buf2[1024];
  1335. struct chanset_t *chan;
  1336. putlog(LOG_CMDS, "*", "#%s# down %s", dcc[idx].nick, par);
  1337. if (!par[0]) {
  1338. dprintf(idx, "Usage: down [%s]<channel>\n", CHANMETA);
  1339. return;
  1340. }
  1341. chname = newsplit(&par);
  1342. chan = findchan_by_dname(chname);
  1343. if (!chan) {
  1344. dprintf(idx, "%s it not a valid channel.\n", chname);
  1345. return;
  1346. }
  1347. sprintf(buf2, "down %s", chan->dname);
  1348. putallbots(buf2);
  1349. #ifdef LEAF
  1350. add_mode(chan, '-', 'o', botname);
  1351. chan->channel.no_op = (now + 10);
  1352. #endif /* LEAF */
  1353. }
  1354. static void cmd_pls_chan(struct userrec *u, int idx, char *par)
  1355. {
  1356. char *chname;
  1357. char buf2[1024];
  1358. struct chanset_t *chan;
  1359. putlog(LOG_CMDS, "*", "#%s# +chan %s", dcc[idx].nick, par);
  1360. if (!par[0]) {
  1361. dprintf(idx, "Usage: +chan [%s]<channel> [options]\n", CHANMETA);
  1362. return;
  1363. }
  1364. chname = newsplit(&par);
  1365. sprintf(buf2, "cjoin %s %s", chname, par);
  1366. putallbots(buf2);
  1367. if (findchan_by_dname(chname)) {
  1368. dprintf(idx, "That channel already exists!\n");
  1369. return;
  1370. } else if ((chan = findchan(chname))) {
  1371. /* This prevents someone adding a channel by it's unique server
  1372. * name <cybah>
  1373. */
  1374. dprintf(idx, "That channel already exists as %s!\n", chan->dname);
  1375. return;
  1376. }
  1377. if (tcl_channel_add(0, chname, par) == TCL_ERROR) /* drummer */
  1378. dprintf(idx, "Invalid channel or channel options.\n");
  1379. else {
  1380. #ifdef HUB
  1381. write_userfile(-1);
  1382. #endif /* HUB */
  1383. }
  1384. }
  1385. static void cmd_mns_chan(struct userrec *u, int idx, char *par)
  1386. {
  1387. char *chname;
  1388. char buf2[1024];
  1389. struct chanset_t *chan;
  1390. int i;
  1391. putlog(LOG_CMDS, "*", "#%s# -chan %s", dcc[idx].nick, par);
  1392. if (!par[0]) {
  1393. dprintf(idx, "Usage: -chan [%s]<channel>\n", CHANMETA);
  1394. return;
  1395. }
  1396. chname = newsplit(&par);
  1397. sprintf(buf2, "cpart %s", chname);
  1398. putallbots(buf2);
  1399. chan = findchan_by_dname(chname);
  1400. if (!chan) {
  1401. if ((chan = findchan(chname)))
  1402. dprintf(idx, "That channel exists with a short name of %s, use that.\n",
  1403. chan->dname);
  1404. else
  1405. dprintf(idx, "That channel doesn't exist!\n");
  1406. return;
  1407. }
  1408. for (i = 0; i < dcc_total; i++)
  1409. if ((dcc[i].type->flags & DCT_CHAT) &&
  1410. !rfc_casecmp(dcc[i].u.chat->con_chan, chan->dname)) {
  1411. dprintf(i, "%s is no longer a valid channel, changing your console to '*'\n",
  1412. chname);
  1413. strcpy(dcc[i].u.chat->con_chan, "*");
  1414. }
  1415. remove_channel(chan);
  1416. #ifdef HUB
  1417. write_userfile(-1);
  1418. #endif /* HUB */
  1419. dprintf(idx, "Channel %s removed from the bot.\n", chname);
  1420. dprintf(idx, "This includes any channel specific bans, invites, exemptions and user records that you set.\n");
  1421. }
  1422. /* thanks Excelsior */
  1423. void modesetting(int idx, char *work, int *cnt, char *name, int state)
  1424. {
  1425. char tmp[100];
  1426. if (((*cnt) < 3) && (!name || (name && !name[0]))) (*cnt) = 3; /* empty buffer if no (char *) name */
  1427. (*cnt)++;
  1428. if (*cnt > 4) {
  1429. *cnt = 1;
  1430. work[0] = 0;
  1431. }
  1432. if (!work[0])
  1433. sprintf(work, " ");
  1434. if (name && name[0]) {
  1435. snprintf(tmp, sizeof tmp, "%s%-17s", state ? "\002+\002" : "\002-\002", name);
  1436. strcat(work, tmp);
  1437. }
  1438. if (*cnt >= 4)
  1439. dprintf(idx, "%s\n", work);
  1440. }
  1441. #define MSET(name, state) modesetting(idx, work, &cnt, name, state)
  1442. static void cmd_chaninfo(struct userrec *u, int idx, char *par)
  1443. {
  1444. char *chname, work[512];
  1445. struct chanset_t *chan;
  1446. int ii, tmp, cnt = 0;
  1447. struct udef_struct *ul;
  1448. if (!par[0]) {
  1449. chname = dcc[idx].u.chat->con_chan;
  1450. if (chname[0] == '*') {
  1451. dprintf(idx, "Your console channel is invalid.\n");
  1452. return;
  1453. }
  1454. } else {
  1455. chname = newsplit(&par);
  1456. get_user_flagrec(u, &user, chname);
  1457. if (!glob_master(user) && !chan_master(user)) {
  1458. dprintf(idx, "You don't have access to %s.\n", chname);
  1459. return;
  1460. }
  1461. }
  1462. if (!(chan = findchan_by_dname(chname)))
  1463. dprintf(idx, "No such channel defined.\n");
  1464. else {
  1465. dprintf(idx, "Settings for dynamic channel %s:\n", chan->dname);
  1466. get_mode_protect(chan, work);
  1467. dprintf(idx, "Protect modes (chanmode): %s\n", work[0] ? work : "None");
  1468. /* Chanchar template
  1469. * dprintf(idx, "String temp: %s\n", chan->temp[0] ? chan->temp : "NULL");
  1470. */
  1471. if (chan->idle_kick)
  1472. dprintf(idx, "Idle Kick after (idle-kick): %d\n", chan->idle_kick);
  1473. else
  1474. dprintf(idx, "Idle Kick after (idle-kick): DON'T!\n");
  1475. if (chan->limitraise)
  1476. dprintf(idx, "Limit raise: %d\n", chan->limitraise);
  1477. else
  1478. dprintf(idx, "Limit raise: disabled\n");
  1479. if (chan->stopnethack_mode)
  1480. dprintf(idx, "stopnethack-mode: %d\n", chan->stopnethack_mode);
  1481. else
  1482. dprintf(idx, "stopnethack: DON'T!\n");
  1483. if (chan->revenge_mode)
  1484. dprintf(idx, "revenge-mode: %d\n", chan->revenge_mode);
  1485. else
  1486. dprintf(idx, "revenge-mode: 0\n");
  1487. if (chan->ban_time)
  1488. dprintf(idx, "ban-time: %d\n", chan->ban_time);
  1489. else
  1490. dprintf(idx, "ban-time: 0\n");
  1491. /* Chanint template
  1492. * if (chan->temp)
  1493. * dprintf(idx, "temp: %d\n", chan->temp);
  1494. * else
  1495. * dprintf(idx, temp: 0\n");
  1496. */
  1497. #ifdef S_IRCNET
  1498. if (chan->exempt_time)
  1499. dprintf(idx, "exempt-time: %d\n", chan->exempt_time);
  1500. else
  1501. dprintf(idx, "exempt-time: 0\n");
  1502. if (chan->invite_time)
  1503. dprintf(idx, "invite-time: %d\n", chan->invite_time);
  1504. else
  1505. dprintf(idx, "invite-time: 0\n");
  1506. #endif /* S_IRCNET */
  1507. dprintf(idx, "Other modes:\n");
  1508. work[0] = 0;
  1509. MSET("bitch", channel_bitch(chan));
  1510. MSET("closed", channel_closed(chan));
  1511. MSET("cycle", channel_cycle(chan));
  1512. MSET("dontkickops", channel_dontkickops(chan));
  1513. MSET("enforcebans", channel_enforcebans(chan));
  1514. MSET("fastop", channel_fastop(chan));
  1515. MSET("inactive", channel_inactive(chan));
  1516. MSET("manop", channel_manop(chan));
  1517. MSET("nodesynch", channel_nodesynch(chan));
  1518. MSET("nomop", channel_nomop(chan));
  1519. MSET("private", channel_private(chan));
  1520. MSET("protectops", channel_protectops(chan));
  1521. MSET("revenge", channel_revenge(chan));
  1522. MSET("revengebot", channel_revengebot(chan));
  1523. MSET("take", channel_take(chan));
  1524. MSET("voice", channel_voice(chan));
  1525. MSET("", 0);
  1526. MSET("dynamicbans", channel_dynamicbans(chan));
  1527. MSET("userbans", !channel_nouserbans(chan));
  1528. #ifdef S_IRCNET
  1529. MSET("dynamicexempts", channel_dynamicexempts(chan));
  1530. MSET("userexempts", !channel_nouserexempts(chan));
  1531. MSET("dynamicinvites", channel_dynamicinvites(chan));
  1532. MSET("userinvites", !channel_nouserinvites(chan));
  1533. #endif /* S_IRCNET */
  1534. MSET("", 0);
  1535. work[0] = 0;
  1536. /* Chanflag template
  1537. * (chan->status & CHAN_TEMP) ? '+' : '-',
  1538. * also include %ctemp in dprintf.
  1539. */
  1540. ii = 1;
  1541. tmp = 0;
  1542. for (ul = udef; ul; ul = ul->next)
  1543. if (ul->defined && ul->type == UDEF_FLAG) {
  1544. int work_len;
  1545. if (!tmp) {
  1546. dprintf(idx, "User defined channel flags:\n");
  1547. tmp = 1;
  1548. }
  1549. if (ii == 1)
  1550. egg_snprintf(work, sizeof work, " ");
  1551. work_len = strlen(work);
  1552. egg_snprintf(work + work_len, sizeof(work) - work_len, " %c%s",
  1553. getudef(ul->values, chan->dname) ? '+' : '-', ul->name);
  1554. ii++;
  1555. if (ii > 4) {
  1556. dprintf(idx, "%s\n", work);
  1557. ii = 1;
  1558. }
  1559. }
  1560. if (ii > 1)
  1561. dprintf(idx, "%s\n", work);
  1562. work[0] = 0;
  1563. ii = 1;
  1564. tmp = 0;
  1565. for (ul = udef; ul; ul = ul->next)
  1566. if (ul->defined && ul->type == UDEF_INT) {
  1567. int work_len = strlen(work);
  1568. if (!tmp) {
  1569. dprintf(idx, "User defined channel settings:\n");
  1570. tmp = 1;
  1571. }
  1572. egg_snprintf(work + work_len, sizeof(work) - work_len, "%s: %d ",
  1573. ul->name, getudef(ul->values, chan->dname));
  1574. ii++;
  1575. if (ii > 4) {
  1576. dprintf(idx, "%s\n", work);
  1577. work[0] = 0;
  1578. ii = 1;
  1579. }
  1580. }
  1581. if (ii > 1)
  1582. dprintf(idx, "%s\n", work);
  1583. dprintf(idx, "flood settings: chan ctcp join kick deop nick\n");
  1584. dprintf(idx, "number: %3d %3d %3d %3d %3d %3d\n",
  1585. chan->flood_pub_thr, chan->flood_ctcp_thr,
  1586. chan->flood_join_thr, chan->flood_kick_thr,
  1587. chan->flood_deop_thr, chan->flood_nick_thr);
  1588. dprintf(idx, "time : %3d %3d %3d %3d %3d %3d\n",
  1589. chan->flood_pub_time, chan->flood_ctcp_time,
  1590. chan->flood_join_time, chan->flood_kick_time,
  1591. chan->flood_deop_time, chan->flood_nick_time);
  1592. putlog(LOG_CMDS, "*", "#%s# chaninfo %s", dcc[idx].nick, chname);
  1593. }
  1594. }
  1595. static void cmd_chanset(struct userrec *u, int idx, char *par)
  1596. {
  1597. char *chname = NULL, answers[512], *parcpy;
  1598. char *list[2], *bak, *buf;
  1599. struct chanset_t *chan = NULL;
  1600. int all = 0, items = 0;
  1601. putlog(LOG_CMDS, "*", "#%s# chanset %s", dcc[idx].nick, par);
  1602. if (!par[0])
  1603. dprintf(idx, "Usage: chanset [%schannel] <settings>\n", CHANMETA);
  1604. else {
  1605. if (strlen(par) > 2 && par[0] == '*' && par[1] == ' ') {
  1606. dprintf(idx, "currently chanset * does not work. use %stcl foreach chan [channels] { channel set $chan +mode }\n", dcc_prefix);
  1607. return;
  1608. all = 1;
  1609. get_user_flagrec(u, &user, chanset ? chanset->dname : "");
  1610. if (!glob_master(user)) {
  1611. dprintf(idx, "You need to be a global master to use %schanset *.\n", dcc_prefix);
  1612. return;
  1613. }
  1614. newsplit(&par);
  1615. } else {
  1616. if (strchr(CHANMETA, par[0])) {
  1617. chname = newsplit(&par);
  1618. get_user_flagrec(u, &user, chname);
  1619. if (!glob_master(user) && !chan_master(user)) {
  1620. dprintf(idx, "You don't have access to %s. \n", chname);
  1621. return;
  1622. } else if (!(chan = findchan_by_dname(chname)) && (chname[0] != '+')) {
  1623. dprintf(idx, "That channel doesn't exist!\n");
  1624. return;
  1625. } else if ((strstr(par, "+private") || strstr(par, "-private")) && (!glob_owner(user))) {
  1626. dprintf(idx, "You don't have access to set +/-private on %s (halting command due to lazy coder).\n", chname);
  1627. return;
  1628. }
  1629. if (!chan) {
  1630. if (par[0])
  1631. *--par = ' ';
  1632. par = chname;
  1633. }
  1634. }
  1635. if (!par[0] || par[0] == '*') {
  1636. dprintf(idx, "Usage: chanset [%schannel] <settings>\n", CHANMETA);
  1637. return;
  1638. }
  1639. if (!chan &&
  1640. !(chan = findchan_by_dname(chname = dcc[idx].u.chat->con_chan))) {
  1641. dprintf(idx, "Invalid console channel.\n");
  1642. return;
  1643. }
  1644. }
  1645. if (all)
  1646. chan = chanset;
  1647. bak = par;
  1648. buf = nmalloc(strlen(par) + 1);
  1649. while (chan) {
  1650. chname = chan->dname;
  1651. strcpy(buf, bak);
  1652. par = buf;
  1653. list[0] = newsplit(&par);
  1654. answers[0] = 0;
  1655. while (list[0][0]) {
  1656. if (list[0][0] == '+' || list[0][0] == '-' ||
  1657. (!strcmp(list[0], "dont-idle-kick"))) {
  1658. if (tcl_channel_modify(0, chan, 1, list) == TCL_OK) {
  1659. strcat(answers, list[0]);
  1660. strcat(answers, " ");
  1661. items++;
  1662. } else if (!all || !chan->next)
  1663. dprintf(idx, "Error trying to set %s for %s, invalid mode.\n",
  1664. list[0], all ? "all channels" : chname);
  1665. list[0] = newsplit(&par);
  1666. continue;
  1667. }
  1668. /* The rest have an unknown amount of args, so assume the rest of the
  1669. * line is args. Woops nearly made a nasty little hole here :) we'll
  1670. * just ignore any non global +n's trying to set the need-commands.
  1671. */
  1672. if (strncmp(list[0], "need-", 5) || (u->flags & USER_OWNER)) {
  1673. list[1] = par;
  1674. /* Par gets modified in tcl channel_modify under some
  1675. * circumstances, so save it now.
  1676. */
  1677. parcpy = nmalloc(strlen(par) + 1);
  1678. strcpy(parcpy, par);
  1679. if (tcl_channel_modify(0, chan, 2, list) == TCL_OK) {
  1680. strcat(answers, list[0]);
  1681. strcat(answers, " { ");
  1682. strcat(answers, parcpy);
  1683. strcat(answers, " }");
  1684. } else if (!all || !chan->next)
  1685. dprintf(idx, "Error trying to set %s for %s, invalid option\n",
  1686. list[0], all ? "all channels" : chname);
  1687. nfree(parcpy);
  1688. }
  1689. break;
  1690. }
  1691. if (!all && answers[0]) {
  1692. struct chanset_t *my_chan;
  1693. my_chan = findchan_by_dname(chname);
  1694. if (my_chan)
  1695. do_chanset(my_chan, bak, 0);
  1696. dprintf(idx, "Successfully set modes { %s } on %s.\n",
  1697. answers, chname);
  1698. #ifdef HUB
  1699. write_userfile(-1);
  1700. #endif /* HUB */
  1701. }
  1702. if (!all)
  1703. chan = NULL;
  1704. else
  1705. chan = chan->next;
  1706. }
  1707. if (all && answers[0]) {
  1708. do_chanset(NULL, bak, 0); /* NULL does all */
  1709. dprintf(idx, "Successfully set modes { %s } on all channels.\n",
  1710. answers);
  1711. #ifdef HUB
  1712. write_userfile(-1);
  1713. #endif /* HUB */
  1714. }
  1715. nfree(buf);
  1716. }
  1717. }
  1718. /* DCC CHAT COMMANDS
  1719. *
  1720. * Function call should be:
  1721. * int cmd_whatever(idx,"parameters");
  1722. *
  1723. * NOTE: As with msg commands, the function is responsible for any logging.
  1724. */
  1725. static cmd_t C_dcc_irc[] =
  1726. {
  1727. {"+ban", "o|o", (Function) cmd_pls_ban, NULL},
  1728. #ifdef S_IRCNET
  1729. {"+exempt", "o|o", (Function) cmd_pls_exempt, NULL},
  1730. {"+invite", "o|o", (Function) cmd_pls_invite, NULL},
  1731. #endif /* S_IRCNET */
  1732. {"+chan", "n", (Function) cmd_pls_chan, NULL},
  1733. {"+chrec", "m|m", (Function) cmd_pls_chrec, NULL},
  1734. {"-ban", "o|o", (Function) cmd_mns_ban, NULL},
  1735. {"-chan", "n", (Function) cmd_mns_chan, NULL},
  1736. {"-chrec", "m|m", (Function) cmd_mns_chrec, NULL},
  1737. #ifdef S_IRCNET
  1738. {"-exempt", "o|o", (Function) cmd_mns_exempt, NULL},
  1739. {"-invite", "o|o", (Function) cmd_mns_invite, NULL},
  1740. #endif /* S_IRCNET */
  1741. {"bans", "o|o", (Function) cmd_bans, NULL},
  1742. #ifdef S_IRCNET
  1743. {"exempts", "o|o", (Function) cmd_exempts, NULL},
  1744. {"invites", "o|o", (Function) cmd_invites, NULL},
  1745. #endif /* S_IRCNET */
  1746. {"chaninfo", "m|m", (Function) cmd_chaninfo, NULL},
  1747. {"chanset", "m|m", (Function) cmd_chanset, NULL},
  1748. {"chinfo", "m|m", (Function) cmd_chinfo, NULL},
  1749. {"cycle", "n|n", (Function) cmd_cycle, NULL},
  1750. {"down", "n|n", (Function) cmd_down, NULL},
  1751. {"info", "", (Function) cmd_info, NULL},
  1752. {"slowjoin", "n", (Function) cmd_slowjoin, NULL},
  1753. {"slowpart", "n|n", (Function) cmd_slowpart, NULL},
  1754. {"stick", "o|o", (Function) cmd_stick, NULL},
  1755. {"unstick", "o|o", (Function) cmd_unstick, NULL},
  1756. {NULL, NULL, NULL, NULL}
  1757. };