irc.c 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523
  1. /*
  2. * irc.c -- part of irc.mod
  3. * support for channels within the bot
  4. *
  5. */
  6. #include "src/common.h"
  7. #define MAKING_IRC
  8. #include "irc.h"
  9. #include "src/match.h"
  10. #include "src/settings.h"
  11. #include "src/tandem.h"
  12. #include "src/net.h"
  13. #include "src/botnet.h"
  14. #include "src/botmsg.h"
  15. #include "src/main.h"
  16. #include "src/response.h"
  17. #include "src/cfg.h"
  18. #include "src/userrec.h"
  19. #include "src/misc.h"
  20. #include "src/rfc1459.h"
  21. #include "src/chanprog.h"
  22. #include "src/auth.h"
  23. #include "src/userrec.h"
  24. #include "src/tclhash.h"
  25. #include "src/userent.h"
  26. #include "src/egg_timer.h"
  27. #include "src/mod/share.mod/share.h"
  28. #include "src/mod/server.mod/server.h"
  29. #include "src/mod/channels.mod/channels.h"
  30. #include "src/mod/ctcp.mod/ctcp.h"
  31. #include <stdarg.h>
  32. #define PRIO_DEOP 1
  33. #define PRIO_KICK 2
  34. #ifdef CACHE
  35. static cache_t *irccache = NULL;
  36. #endif /* CACHE */
  37. static int net_type = 0;
  38. static time_t wait_split = 300; /* Time to wait for user to return from
  39. * net-split. */
  40. int max_bans; /* Modified by net-type 1-4 */
  41. int max_exempts;
  42. int max_invites;
  43. int max_modes; /* Modified by net-type 1-4 */
  44. static bool bounce_bans = 0;
  45. static bool bounce_exempts = 0;
  46. static bool bounce_invites = 0;
  47. static bool bounce_modes = 0;
  48. unsigned int modesperline; /* Number of modes per line to send. */
  49. static size_t mode_buf_len = 200; /* Maximum bytes to send in 1 mode. */
  50. bool use_354 = 0; /* Use ircu's short 354 /who
  51. * responses. */
  52. static bool kick_fun = 0;
  53. static bool ban_fun = 1;
  54. static bool keepnick = 1; /* Keep nick */
  55. static bool prevent_mixing = 1; /* To prevent mixing old/new modes */
  56. static bool include_lk = 1; /* For correct calculation
  57. * in real_add_mode. */
  58. #include "chan.c"
  59. #include "mode.c"
  60. #include "cmdsirc.c"
  61. #include "msgcmds.c"
  62. static void
  63. detect_autokick(char *nick, char *uhost, struct chanset_t *chan, char *msg)
  64. {
  65. if (!nick || !nick[0] || !uhost || !uhost[0] || !chan || !msg || !msg[0])
  66. return;
  67. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  68. struct userrec *u = get_user_by_host(uhost);
  69. int i = 0;
  70. //size_t tot = strlen(msg);
  71. get_user_flagrec(u, &fr, chan->dname);
  72. for (; *msg; ++msg) {
  73. if (egg_isupper(*msg))
  74. i++;
  75. }
  76. /* if ((chan->capslimit)) { */
  77. while (((msg) && *msg)) {
  78. if (egg_isupper(*msg))
  79. i++;
  80. msg++;
  81. }
  82. /*
  83. if (chan->capslimit && ((i / tot) >= chan->capslimit)) {
  84. dprintf(DP_MODE, "PRIVMSG %s :flood stats for %s: %d/%d are CAP, percentage: %d\n", chan->name, nick, i, tot, (i/tot)*100);
  85. if ((((i / tot) * 100) >= 50)) {
  86. dprintf(DP_HELP, "PRIVMSG %s :cap flood.\n", chan->dname);
  87. }
  88. */
  89. }
  90. void notice_invite(struct chanset_t *chan, char *handle, char *nick, char *uhost, bool op) {
  91. char fhandle[21] = "";
  92. const char *ops = " (auto-op)";
  93. if (handle)
  94. sprintf(fhandle, "\002%s\002 ", handle);
  95. putlog(LOG_MISC, "*", "Invited %s%s(%s%s%s) to %s.", handle ? handle : "", handle ? " " : "", nick, uhost ? "!" : "", uhost ? uhost : "", chan->dname);
  96. dprintf(DP_MODE, "PRIVMSG %s :\001ACTION has invited %s(%s%s%s) to %s.%s\001\n",
  97. chan->name, fhandle, nick, uhost ? "!" : "", uhost ? uhost : "", chan->dname, op ? ops : "");
  98. }
  99. #ifdef CACHE
  100. static cache_t *cache_new(char *nick)
  101. {
  102. cache_t *cache = (cache_t *) my_calloc(1, sizeof(cache_t));
  103. cache->next = NULL;
  104. strcpy(cache->nick, nick);
  105. cache->uhost[0] = 0;
  106. cache->handle[0] = 0;
  107. // cache->user = NULL;
  108. cache->timeval = now;
  109. cache->cchan = NULL;
  110. list_append((struct list_type **) &irccache, (struct list_type *) cache);
  111. return cache;
  112. }
  113. static cache_chan_t *cache_chan_add(cache_t *cache, char *chname)
  114. {
  115. cache_chan_t *cchan = (cache_chan_t *) my_calloc(1, sizeof(cache_chan_t));
  116. cchan->next = NULL;
  117. strcpy(cchan->dname, chname);
  118. cchan->ban = 0;
  119. cchan->invite = 0;
  120. cchan->invited = 0;
  121. list_append((struct list_type **) &(cache->cchan), (struct list_type *) cchan);
  122. return cchan;
  123. }
  124. static void cache_chan_find(cache_t *cache, cache_chan_t *cchan, char *nick, char *chname)
  125. {
  126. if (!cache)
  127. cache = cache_find(nick);
  128. if (cache) {
  129. for (cchan = cache->cchan; cchan && cchan->dname[0]; cchan = cchan->next) {
  130. if (!rfc_casecmp(cchan->dname, chname)) {
  131. return;
  132. }
  133. }
  134. }
  135. return;
  136. }
  137. static void cache_chan_del(char *nick, char *chname) {
  138. cache_t *cache = NULL;
  139. cache_chan_t *cchan = NULL;
  140. cache_chan_find(cache, cchan, nick, chname);
  141. if (cchan) {
  142. list_delete((struct list_type **) &cache->cchan, (struct list_type *) cchan);
  143. free(cache);
  144. }
  145. }
  146. static cache_t *cache_find(char *nick)
  147. {
  148. cache_t *cache = NULL;
  149. for (cache = irccache; cache && cache->nick[0]; cache = cache->next)
  150. if (!rfc_casecmp(cache->nick, nick))
  151. break;
  152. return cache;
  153. }
  154. static void cache_del(char *nick, cache_t *cache)
  155. {
  156. if (!cache)
  157. cache = cache_find(nick);
  158. if (cache) {
  159. list_delete((struct list_type **) &irccache, (struct list_type *) cache);
  160. free(cache);
  161. }
  162. }
  163. static void cache_debug(void)
  164. {
  165. cache_t *cache = NULL;
  166. cache_chan_t *cchan = NULL;
  167. for (cache = irccache; cache && cache->nick[0]; cache = cache->next) {
  168. dprintf(DP_MODE, "PRIVMSG #wraith :%s!%s (%s)\n", cache->nick, cache->uhost, cache->handle);
  169. for (cchan = cache->cchan; cchan && cchan->dname[0]; cchan = cchan->next)
  170. dprintf(DP_MODE, "PRIVMSG #wraith :%s %d %d %d\n", cchan->dname, cchan->ban, cchan->invite, cchan->invited);
  171. }
  172. }
  173. #endif /* CACHE */
  174. static void cache_invite(struct chanset_t *chan, char *nick, char *host, char *handle, bool op, bool bot)
  175. {
  176. #ifdef CACHE
  177. cache_t *cache = NULL;
  178. if ((cache = cache_find(nick)) == NULL)
  179. cache = cache_new(nick);
  180. cache->bot = bot;
  181. /* if we find they have a host but it doesnt match the new host, wipe it */
  182. if (host && cache->uhost[0] && egg_strcasecmp(cache->uhost, host))
  183. cache->uhost[0] = 0;
  184. if (host && !cache->uhost[0])
  185. strcpy(cache->uhost, host);
  186. /* if we find they have a handle but it doesnt match the new handle, wipe it */
  187. if (handle && cache->handle[0] && egg_strcasecmp(cache->handle, handle))
  188. cache->handle[0] = 0;
  189. if (handle && !cache->handle[0])
  190. strcpy(cache->handle, handle);
  191. cache_chan_t *cchan = cache_chan_add(cache, chan->dname);
  192. cchan->op = op;
  193. if (!host) {
  194. cchan->invite = 1;
  195. dprintf(DP_MODE, "USERHOST %s\n", nick);
  196. return;
  197. }
  198. /* if we have a uhost already, it's safe to invite them */
  199. cchan->invited = 1;
  200. cchan->invite = 0;
  201. #endif /* CACHE */
  202. dprintf(DP_SERVER, "INVITE %s %s\n", nick, chan->name);
  203. }
  204. static char *
  205. makecookie(char *chn, char *bnick)
  206. {
  207. char *buf = NULL, randstring[5] = "", ts[11] = "", *chname = NULL, *hash = NULL, tohash[50] = "";
  208. chname = strdup(chn);
  209. make_rand_str(randstring, 4);
  210. /* &ts[4] is now last 6 digits of time */
  211. sprintf(ts, "%010li", now + timesync);
  212. /* Only use first 3 chars of chan */
  213. if (strlen(chname) > 2)
  214. chname[3] = 0;
  215. strtoupper(chname);
  216. sprintf(tohash, "%c%s%s%s%s%c", settings.salt2[0], bnick, chname, &ts[4], randstring, settings.salt2[15]);
  217. hash = MD5(tohash);
  218. buf = (char *) my_calloc(1, 20);
  219. sprintf(buf, "%c%c%c!%s@%s", hash[8], hash[16], hash[18], randstring, ts);
  220. /* sprintf(buf, "%c/%s!%s@%X", hash[16], randstring, ts, BIT31); */
  221. free(chname);
  222. return buf;
  223. }
  224. static int
  225. checkcookie(char *chn, char *bnick, char *cookie)
  226. {
  227. char randstring[5] = "", ts[11] = "", *chname = NULL, *hash = NULL, tohash[50] = "", *p = NULL;
  228. time_t optime = 0;
  229. chname = strdup(chn);
  230. p = cookie;
  231. p += 4; /* has! */
  232. strlcpy(randstring, p, sizeof(randstring));
  233. p += 5; /* rand@ */
  234. /* &ts[4] is now last 6 digits of time */
  235. strlcpy(ts, p, sizeof(ts));
  236. optime = atol(ts);
  237. /* Only use first 3 chars of chan */
  238. if (strlen(chname) > 2)
  239. chname[3] = 0;
  240. strtoupper(chname);
  241. /* hash!rand@ts */
  242. sprintf(tohash, "%c%s%s%s%s%c", settings.salt2[0], bnick, chname, &ts[4], randstring, settings.salt2[15]);
  243. hash = MD5(tohash);
  244. if (!(hash[8] == cookie[0] && hash[16] == cookie[1] && hash[18] == cookie[2]))
  245. return BC_HASH;
  246. if (((now + timesync) - optime) > 600)
  247. return BC_SLACK;
  248. return 0;
  249. }
  250. /*
  251. opreq = o #chan nick
  252. inreq = i #chan nick uhost
  253. inreq keyreply = K #chan key
  254. */
  255. void
  256. getin_request(char *botnick, char *code, char *par)
  257. {
  258. if (!server_online)
  259. return;
  260. if (!par[0] || !par)
  261. return;
  262. struct chanset_t *chan = NULL;
  263. char *what = newsplit(&par), *chname = newsplit(&par);
  264. if (!chname[0] || !chname)
  265. return;
  266. if (!(chan = findchan_by_dname(chname))) {
  267. putlog(LOG_GETIN, "*", "getin req from %s for %s which is not a valid channel!", botnick, chname);
  268. return;
  269. }
  270. char *nck = newsplit(&par);
  271. if (!nck[0])
  272. return;
  273. struct userrec *u = NULL;
  274. memberlist *mem = NULL;
  275. char *hst = newsplit(&par), *ip = NULL, *tmp = NULL;
  276. char nick[NICKLEN] = "", uhost[UHOSTLEN] = "", uip[UHOSTLEN];
  277. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  278. if (nck[0]) {
  279. strlcpy(nick, nck, sizeof(nick));
  280. } else
  281. nick[0] = 0;
  282. if (hst[0]) {
  283. strlcpy(uhost, hst, sizeof(uhost));
  284. ip = newsplit(&par);
  285. if (ip[0]) {
  286. char *tmp2 = NULL;
  287. tmp = strdup(uhost);
  288. tmp2 = strtok(tmp, "@");
  289. egg_snprintf(uip, sizeof uip, "%s@%s", strtok(tmp2, "@"), ip);
  290. free(tmp);
  291. } else {
  292. uip[0] = 0;
  293. }
  294. } else
  295. uhost[0] = 0;
  296. /*
  297. * if (!ismember(chan, botname)) {
  298. * putlog(LOG_GETIN, "*", "getin req from %s for %s - I'm not on %s!", botnick, chname, chname);
  299. * return;
  300. * }
  301. */
  302. u = get_user_by_handle(userlist, botnick);
  303. if (nick[0])
  304. mem = ismember(chan, nick);
  305. if (what[0] == 'o') {
  306. if (!nick[0]) {
  307. putlog(LOG_GETIN, "*", "opreq from %s/??? on %s - No nick specified - SHOULD NOT HAPPEN", botnick,
  308. chname);
  309. return;
  310. }
  311. if (!chan) {
  312. putlog(LOG_GETIN, "*", "opreq from %s/%s on %s - Channel %s doesn't exist", botnick, nick, chname,
  313. chname);
  314. return;
  315. }
  316. if (!mem) {
  317. putlog(LOG_GETIN, "*", "opreq from %s/%s on %s - %s isn't on %s", botnick, nick, chan->dname, nick,
  318. chan->dname);
  319. return;
  320. }
  321. if (!u) {
  322. putlog(LOG_GETIN, "*", "opreq from %s/%s on %s - No user called %s in userlist", botnick, nick,
  323. chan->dname, botnick);
  324. return;
  325. }
  326. if (mem->user != u) {
  327. putlog(LOG_GETIN, "*", "opreq from %s/%s on %s - %s doesn't match %s", botnick, nick, chan->dname, nick,
  328. botnick);
  329. return;
  330. }
  331. get_user_flagrec(u, &fr, chan->dname);
  332. if (!chk_op(fr, chan)) {
  333. putlog(LOG_GETIN, "*", "opreq from %s/%s on %s - %s doesnt have +o for chan.", botnick, nick,
  334. chan->dname, botnick);
  335. return;
  336. }
  337. if (chan_kick(fr) || glob_kick(fr)) {
  338. putlog(LOG_GETIN, "*", "opreq from %s/%s on %s - %s is set to auto kickban.", botnick, nick, chan->dname, botnick);
  339. return;
  340. }
  341. if (chan_hasop(mem)) {
  342. putlog(LOG_GETIN, "*", "opreq from %s/%s on %s - %s already has ops", botnick, nick, chan->dname, nick);
  343. return;
  344. }
  345. if (chan_issplit(mem)) {
  346. putlog(LOG_GETIN, "*", "opreq from %s/%s on %s - %s is split", botnick, nick, chan->dname, nick);
  347. return;
  348. }
  349. if (!me_op(chan)) {
  350. putlog(LOG_GETIN, "*", "opreq from %s/%s on %s - I haven't got ops", botnick, nick, chan->dname);
  351. return;
  352. }
  353. if (chan_sentop(mem)) {
  354. putlog(LOG_GETIN, "*", "opreq from %s/%s on %s - Already sent a +o", botnick, nick, chan->dname);
  355. return;
  356. }
  357. if (server_lag > LAG_THRESHOLD) {
  358. putlog(LOG_GETIN, "*", "opreq from %s/%s on %s - I'm too lagged", botnick, nick, chan->dname);
  359. return;
  360. }
  361. if (chan->channel.no_op) {
  362. if (chan->channel.no_op > now) /* dont op until this time has passed */
  363. return;
  364. else
  365. chan->channel.no_op = 0;
  366. }
  367. do_op(nick, chan, 0, 1);
  368. putlog(LOG_GETIN, "*", "opreq from %s/%s on %s - Opped", botnick, nick, chan->dname);
  369. } else if (what[0] == 'i') {
  370. if (!nick[0]) {
  371. putlog(LOG_GETIN, "*", "inreq from %s/??? for %s - No nick specified - SHOULD NOT HAPPEN", botnick,
  372. chname);
  373. return;
  374. }
  375. if (!chan) {
  376. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - Channel %s doesn't exist", botnick, nick, chname,
  377. chname);
  378. return;
  379. }
  380. if (mem) {
  381. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - %s is already on %s", botnick, nick, chan->dname,
  382. nick, chan->dname);
  383. return;
  384. }
  385. if (!u) {
  386. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - No user called %s in userlist", botnick, nick,
  387. chan->dname, botnick);
  388. return;
  389. }
  390. get_user_flagrec(u, &fr, chan->dname);
  391. if (!chk_op(fr, chan)) {
  392. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - %s doesn't have acces for chan.", botnick, nick,
  393. chan->dname, botnick);
  394. return;
  395. }
  396. if (server_lag > LAG_THRESHOLD) {
  397. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - I'm too lagged", botnick, nick, chan->dname);
  398. return;
  399. }
  400. if (!(channel_pending(chan) || channel_active(chan))) {
  401. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - I'm not on %s now", botnick, nick, chan->dname,
  402. chan->dname);
  403. return;
  404. }
  405. char s[256] = "", *p = NULL, *p2 = NULL, *p3 = NULL;
  406. bool sendi = 0;
  407. strcpy(s, getchanmode(chan));
  408. p = (char *) &s;
  409. p2 = newsplit(&p);
  410. p3 = newsplit(&p);
  411. if (strchr(p2, 'l')) {
  412. if (!me_op(chan)) {
  413. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - I haven't got ops", botnick, nick, chan->dname);
  414. return;
  415. } else {
  416. int lim = chan->channel.members + 5, curlim;
  417. if (!*p)
  418. curlim = atoi(p3);
  419. else
  420. curlim = atoi(p);
  421. if (curlim > 0 && curlim < lim) {
  422. char s2[16] = "";
  423. sendi = 1;
  424. simple_sprintf(s2, "%d", lim);
  425. add_mode(chan, '+', 'l', s2);
  426. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - Raised limit to %d", botnick, nick, chan->dname,
  427. lim);
  428. }
  429. }
  430. }
  431. struct maskrec **mr = NULL, *tmr = NULL;
  432. mr = &global_bans;
  433. while (*mr) {
  434. if (wild_match((*mr)->mask, uhost) ||
  435. wild_match((*mr)->mask, uip) ||
  436. match_cidr((*mr)->mask, uip)) {
  437. if (!noshare) {
  438. shareout("-m b %s\n", (*mr)->mask);
  439. }
  440. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - Removed permanent global ban %s", botnick, nick,
  441. chan->dname, (*mr)->mask);
  442. /*gban_total--; */
  443. free((*mr)->mask);
  444. if ((*mr)->desc)
  445. free((*mr)->desc);
  446. if ((*mr)->user)
  447. free((*mr)->user);
  448. tmr = *mr;
  449. *mr = (*mr)->next;
  450. free(tmr);
  451. } else {
  452. mr = &((*mr)->next);
  453. }
  454. }
  455. mr = &chan->bans;
  456. while (*mr) {
  457. if (wild_match((*mr)->mask, uhost) ||
  458. wild_match((*mr)->mask, uip) ||
  459. match_cidr((*mr)->mask, uip)) {
  460. if (!noshare) {
  461. shareout("-mc b %s %s\n", chan->dname, (*mr)->mask);
  462. }
  463. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - Removed permanent channel ban %s", botnick, nick,
  464. chan->dname, (*mr)->mask);
  465. free((*mr)->mask);
  466. if ((*mr)->desc)
  467. free((*mr)->desc);
  468. if ((*mr)->user)
  469. free((*mr)->user);
  470. tmr = *mr;
  471. *mr = (*mr)->next;
  472. free(tmr);
  473. } else {
  474. mr = &((*mr)->next);
  475. }
  476. }
  477. for (struct maskstruct *b = chan->channel.ban; b->mask[0]; b = b->next) {
  478. if (wild_match(b->mask, uhost) ||
  479. wild_match(b->mask, uip) ||
  480. match_cidr(b->mask, uip)) {
  481. add_mode(chan, '-', 'b', b->mask);
  482. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - Removed active ban %s", botnick, nick, chan->dname,
  483. b->mask);
  484. sendi = 1;
  485. }
  486. }
  487. if (strchr(p2, 'k')) {
  488. sendi = 0;
  489. tmp = (char *) my_calloc(1, strlen(chan->dname) + strlen(p3) + 7);
  490. sprintf(tmp, "gi K %s %s", chan->dname, p3);
  491. botnet_send_zapf(nextbot(botnick), conf.bot->nick, botnick, tmp);
  492. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - Sent key (%s)", botnick, nick, chan->dname, p3);
  493. free(tmp);
  494. }
  495. if (strchr(p2, 'i')) {
  496. if (!me_op(chan)) {
  497. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - I haven't got ops", botnick, nick, chan->dname);
  498. return;
  499. } else {
  500. sendi = 1;
  501. putlog(LOG_GETIN, "*", "inreq from %s/%s for %s - Invited", botnick, nick, chan->dname);
  502. }
  503. }
  504. if (sendi && me_op(chan))
  505. dprintf(DP_MODE, "INVITE %s %s\n", nick, chan->name);
  506. } else if (what[0] == 'K') {
  507. if (!chan) {
  508. putlog(LOG_GETIN, "*", "Got key for nonexistant channel %s from %s", chname, botnick);
  509. return;
  510. }
  511. if (!shouldjoin(chan)) {
  512. putlog(LOG_GETIN, "*", "Got key for %s from %s - I shouldn't be on that chan?!?", chan->dname, botnick);
  513. } else {
  514. if (!(channel_pending(chan) || channel_active(chan))) {
  515. putlog(LOG_GETIN, "*", "Got key for %s from %s (%s) - Joining", chan->dname, botnick, nick);
  516. dprintf(DP_MODE, "JOIN %s %s\n", chan->dname, nick);
  517. chan->status |= CHAN_JOINING;
  518. } else {
  519. putlog(LOG_GETIN, "*", "Got key for %s from %s - I'm already in the channel", chan->dname, botnick);
  520. }
  521. }
  522. }
  523. }
  524. static void
  525. request_op(struct chanset_t *chan)
  526. {
  527. if (!chan || (chan && (channel_pending(chan) || !shouldjoin(chan) || !channel_active(chan) || me_op(chan))))
  528. return;
  529. if (chan->channel.no_op) {
  530. if (chan->channel.no_op > now) /* dont op until this time has passed */
  531. return;
  532. else
  533. chan->channel.no_op = 0;
  534. }
  535. chan->channel.do_opreq = 0;
  536. /* check server lag */
  537. if (server_lag > LAG_THRESHOLD) {
  538. putlog(LOG_GETIN, "*", "Not asking for ops on %s - I'm too lagged", chan->dname);
  539. return;
  540. }
  541. int i = 0, my_exp = 0, first = 100;
  542. time_t n = now;
  543. /* max OPREQ_COUNT requests per OPREQ_SECONDS sec */
  544. while (i < 5) {
  545. if (n - chan->opreqtime[i] > OPREQ_SECONDS) {
  546. if (first > i)
  547. first = i;
  548. my_exp++;
  549. chan->opreqtime[i] = 0;
  550. }
  551. i++;
  552. }
  553. if ((5 - my_exp) >= OPREQ_COUNT) {
  554. putlog(LOG_GETIN, "*", "Delaying opreq for %s - Maximum of %d:%d reached", chan->dname, OPREQ_COUNT,
  555. OPREQ_SECONDS);
  556. return;
  557. }
  558. int cnt = OP_BOTS, i2;
  559. memberlist *ml = NULL;
  560. memberlist *botops[MAX_BOTS];
  561. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  562. char s[UHOSTLEN] = "";
  563. for (i = 0, ml = chan->channel.member; (i < MAX_BOTS) && ml && ml->nick[0]; ml = ml->next) {
  564. /* If bot, linked, global op & !split & chanop & (chan is reserver | bot isn't +a) ->
  565. * add to temp list */
  566. if (!ml->user && !ml->tried_getuser) {
  567. simple_sprintf(s, "%s!%s", ml->nick, ml->userhost);
  568. ml->user = get_user_by_host(s);
  569. ml->tried_getuser = 1;
  570. }
  571. if ((i < MAX_BOTS) && ml->user && ml->user->bot &&
  572. findbot(ml->user->handle) && chan_hasop(ml) && !chan_issplit(ml)) {
  573. get_user_flagrec(ml->user, &fr, NULL);
  574. if (chk_op(fr, chan))
  575. botops[i++] = ml;
  576. }
  577. }
  578. if (!i) {
  579. if (channel_active(chan) && !channel_pending(chan))
  580. putlog(LOG_GETIN, "*", "No one to ask for ops on %s", chan->dname);
  581. return;
  582. }
  583. char *l = (char *) my_calloc(1, cnt * 50);
  584. /* first scan for bots on my server, ask first found for ops */
  585. simple_sprintf(s, "gi o %s %s", chan->dname, botname);
  586. /* look for bots 0-1 hops away */
  587. for (i2 = 0; i2 < i; i2++) {
  588. if (botops[i2]->hops < 2) {
  589. putbot(botops[i2]->user->handle, s);
  590. chan->opreqtime[first] = n;
  591. if (l[0]) {
  592. strcat(l, ", ");
  593. strcat(l, botops[i2]->user->handle);
  594. } else {
  595. strcpy(l, botops[i2]->user->handle);
  596. }
  597. strcat(l, "/");
  598. strcat(l, botops[i2]->nick);
  599. botops[i2] = NULL;
  600. cnt--;
  601. break;
  602. }
  603. }
  604. /* Pick random op and ask for ops */
  605. while (cnt) {
  606. i2 = randint(i);
  607. if (botops[i2]) {
  608. putbot(botops[i2]->user->handle, s);
  609. chan->opreqtime[first] = n;
  610. if (l[0]) {
  611. strcat(l, ", ");
  612. strcat(l, botops[i2]->user->handle);
  613. } else {
  614. strcpy(l, botops[i2]->user->handle);
  615. }
  616. strcat(l, "/");
  617. strcat(l, botops[i2]->nick);
  618. cnt--;
  619. botops[i2] = NULL;
  620. } else {
  621. if (i < OP_BOTS)
  622. cnt--;
  623. }
  624. }
  625. putlog(LOG_GETIN, "*", "Requested ops on %s from %s", chan->dname, l);
  626. free(l);
  627. }
  628. static void
  629. request_in(struct chanset_t *chan)
  630. {
  631. int i = 0;
  632. struct userrec *botops[MAX_BOTS];
  633. struct flag_record fr = { FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0 };
  634. for (struct userrec *u = userlist; u && (i < MAX_BOTS); u = u->next) {
  635. get_user_flagrec(u, &fr, NULL);
  636. if (bot_hublevel(u) == 999 && glob_bot(fr) && chk_op(fr, chan)
  637. #ifdef G_BACKUP
  638. && (!glob_backupbot(fr) || channel_backup(chan))
  639. #endif
  640. /* G_BACKUP */
  641. && nextbot(u->handle) >= 0)
  642. botops[i++] = u;
  643. }
  644. if (!i) {
  645. putlog(LOG_GETIN, "*", "No bots linked, can't request help to join %s", chan->dname);
  646. return;
  647. }
  648. char s[255] = "", *l = (char *) my_calloc(1, IN_BOTS * 30);
  649. int cnt = IN_BOTS, n;
  650. sprintf(s, "gi i %s %s %s!%s %s", chan->dname, botname, botname, botuserhost, botuserip);
  651. while (cnt) {
  652. n = randint(i);
  653. if (botops[n]) {
  654. putbot(botops[n]->handle, s);
  655. if (l[0]) {
  656. strcat(l, ", ");
  657. strcat(l, botops[n]->handle);
  658. } else {
  659. strcpy(l, botops[n]->handle);
  660. }
  661. botops[n] = NULL;
  662. cnt--;
  663. } else {
  664. if (i < IN_BOTS)
  665. cnt--;
  666. }
  667. }
  668. putlog(LOG_GETIN, "*", "Requesting help to join %s from %s", chan->dname, l);
  669. free(l);
  670. }
  671. /* Contains the logic to decide wether we want to punish someone. Returns
  672. * true (1) if we want to, false (0) if not.
  673. */
  674. static bool
  675. want_to_revenge(struct chanset_t *chan, struct userrec *u,
  676. struct userrec *u2, char *badnick, char *victimstr, bool mevictim)
  677. {
  678. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  679. /* Do not take revenge upon ourselves. */
  680. if (match_my_nick(badnick))
  681. return 0;
  682. get_user_flagrec(u, &fr, chan->dname);
  683. /* Kickee didn't kick themself? */
  684. if (rfc_casecmp(badnick, victimstr)) {
  685. /* They kicked me? */
  686. if (mevictim) {
  687. /* ... and I'm allowed to take revenge? <snicker> */
  688. if (channel_revengebot(chan))
  689. return 1;
  690. /* Do we revenge for our users ... and do we actually know the victim? */
  691. } else if (channel_revenge(chan) && u2) {
  692. struct flag_record fr2 = { FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  693. get_user_flagrec(u2, &fr2, chan->dname);
  694. /* Protecting friends? */
  695. /* Protecting ops? */
  696. if ((channel_protectops(chan) &&
  697. /* ... and kicked is valid op? */
  698. (chan_op(fr2) || (glob_op(fr2) && !chan_deop(fr2)))))
  699. return 1;
  700. }
  701. }
  702. return 0;
  703. }
  704. /* Dependant on revenge_mode, punish the offender.
  705. */
  706. static void
  707. punish_badguy(struct chanset_t *chan, char *whobad,
  708. struct userrec *u, char *badnick, char *victimstr, bool mevictim, int type)
  709. {
  710. memberlist *m = ismember(chan, badnick);
  711. if (!m)
  712. return;
  713. char reason[1024] = "", ct[81] = "", *kick_msg = NULL;
  714. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  715. get_user_flagrec(u, &fr, chan->dname);
  716. /* Get current time into a string */
  717. egg_strftime(ct, sizeof ct, "%d %b %Z", gmtime(&now));
  718. /* Put together log and kick messages */
  719. reason[0] = 0;
  720. switch (type) {
  721. case REVENGE_KICK:
  722. kick_msg = IRC_KICK_PROTECT;
  723. simple_sprintf(reason, "kicked %s off %s", victimstr, chan->dname);
  724. break;
  725. case REVENGE_DEOP:
  726. simple_sprintf(reason, "deopped %s on %s", victimstr, chan->dname);
  727. kick_msg = IRC_DEOP_PROTECT;
  728. break;
  729. default:
  730. kick_msg = "revenge!";
  731. }
  732. putlog(LOG_MISC, chan->dname, "Punishing %s (%s)", badnick, reason);
  733. /* Set the offender +d */
  734. if ((chan->revenge_mode > 0) &&
  735. /* ... unless there's no more to do */
  736. !(chan_deop(fr) || glob_deop(fr))) {
  737. char s[UHOSTLEN], s1[UHOSTLEN];
  738. memberlist *mx = NULL;
  739. /* Removing op */
  740. if (chan_op(fr) || (glob_op(fr) && !chan_deop(fr))) {
  741. fr.match = FR_CHAN;
  742. if (chan_op(fr)) {
  743. fr.chan &= ~USER_OP;
  744. } else {
  745. fr.chan |= USER_DEOP;
  746. }
  747. set_user_flagrec(u, &fr, chan->dname);
  748. putlog(LOG_MISC, "*", "No longer opping %s[%s] (%s)", u->handle, whobad, reason);
  749. }
  750. /* ... or just setting to deop */
  751. else if (u) {
  752. /* In the user list already, cool :) */
  753. fr.match = FR_CHAN;
  754. fr.chan |= USER_DEOP;
  755. set_user_flagrec(u, &fr, chan->dname);
  756. simple_sprintf(s, "(%s) %s", ct, reason);
  757. putlog(LOG_MISC, "*", "Now deopping %s[%s] (%s)", u->handle, whobad, s);
  758. }
  759. /* ... or creating new user and setting that to deop */
  760. else {
  761. strcpy(s1, whobad);
  762. maskhost(s1, s);
  763. strcpy(s1, badnick);
  764. /* If that handle exists use "badX" (where X is an increasing number)
  765. * instead.
  766. */
  767. while (get_user_by_handle(userlist, s1)) {
  768. if (!strncmp(s1, "bad", 3)) {
  769. int i;
  770. i = atoi(s1 + 3);
  771. simple_sprintf(s1 + 3, "%d", i + 1);
  772. } else
  773. strcpy(s1, "bad1"); /* Start with '1' */
  774. }
  775. userlist = adduser(userlist, s1, s, "-", 0, 0);
  776. fr.match = FR_CHAN;
  777. fr.chan = USER_DEOP;
  778. u = get_user_by_handle(userlist, s1);
  779. if ((mx = ismember(chan, badnick)))
  780. mx->user = u;
  781. set_user_flagrec(u, &fr, chan->dname);
  782. simple_sprintf(s, "(%s) %s (%s)", ct, reason, whobad);
  783. set_user(&USERENTRY_COMMENT, u, (void *) s);
  784. putlog(LOG_MISC, "*", "Now deopping %s (%s)", whobad, reason);
  785. }
  786. }
  787. /* Always try to deop the offender */
  788. if (!mevictim)
  789. add_mode(chan, '-', 'o', badnick);
  790. /* Ban. Should be done before kicking. */
  791. if (chan->revenge_mode > 2) {
  792. char s[UHOSTLEN] = "", s1[UHOSTLEN] = "";
  793. splitnick(&whobad);
  794. maskhost(whobad, s1);
  795. simple_sprintf(s, "(%s) %s", ct, reason);
  796. u_addmask('b', chan, s1, conf.bot->nick, s, now + (60 * chan->ban_time), 0);
  797. if (!mevictim && me_op(chan)) {
  798. add_mode(chan, '+', 'b', s1);
  799. flush_mode(chan, QUICK);
  800. }
  801. }
  802. /* Kick the offender */
  803. if ((chan->revenge_mode > 1) && !chan_sentkick(m) &&
  804. /* ... and can I actually do anything about it? */
  805. me_op(chan) && !mevictim) {
  806. dprintf(DP_MODE, "KICK %s %s :%s%s\n", chan->name, m->nick, bankickprefix, response(RES_MEAN));
  807. m->flags |= SENTKICK;
  808. }
  809. }
  810. /* Punishes bad guys under certain circumstances using methods as defined
  811. * by the revenge_mode flag.
  812. */
  813. static void
  814. maybe_revenge(struct chanset_t *chan, char *whobad, char *whovictim, int type)
  815. {
  816. if (!chan || (type < 0))
  817. return;
  818. /* Get info about offender */
  819. struct userrec *u = get_user_by_host(whobad), *u2 = NULL;
  820. char *badnick = splitnick(&whobad), *victimstr = NULL;
  821. bool mevictim;
  822. /* Get info about victim */
  823. u2 = get_user_by_host(whovictim);
  824. victimstr = splitnick(&whovictim);
  825. mevictim = match_my_nick(victimstr);
  826. /* Do we want to revenge? */
  827. if (!want_to_revenge(chan, u, u2, badnick, victimstr, mevictim))
  828. return; /* No, leave them alone ... */
  829. /* Haha! Do the vengeful thing ... */
  830. punish_badguy(chan, whobad, u, badnick, victimstr, mevictim, type);
  831. }
  832. /* Set the key.
  833. */
  834. static void
  835. my_setkey(struct chanset_t *chan, char *k)
  836. {
  837. free(chan->channel.key);
  838. if (k == NULL) {
  839. chan->channel.key = (char *) my_calloc(1, 1);
  840. return;
  841. }
  842. chan->channel.key = (char *) my_calloc(1, strlen(k) + 1);
  843. strcpy(chan->channel.key, k);
  844. }
  845. /* Adds a ban, exempt or invite mask to the list
  846. * m should be chan->channel.(exempt|invite|ban)
  847. */
  848. static void
  849. new_mask(masklist *m, char *s, char *who)
  850. {
  851. for (; m && m->mask[0] && rfc_casecmp(m->mask, s); m = m->next) ;
  852. if (m->mask[0])
  853. return; /* Already existent mask */
  854. m->next = (masklist *) my_calloc(1, sizeof(masklist));
  855. m->next->next = NULL;
  856. m->next->mask = (char *) my_calloc(1, 1);
  857. free(m->mask);
  858. m->mask = (char *) my_calloc(1, strlen(s) + 1);
  859. strcpy(m->mask, s);
  860. m->who = (char *) my_calloc(1, strlen(who) + 1);
  861. strcpy(m->who, who);
  862. m->timer = now;
  863. }
  864. /* Removes a nick from the channel member list (returns 1 if successful)
  865. */
  866. static bool
  867. killmember(struct chanset_t *chan, char *nick)
  868. {
  869. memberlist *x = NULL, *old = NULL;
  870. for (x = chan->channel.member; x && x->nick[0]; old = x, x = x->next)
  871. if (!rfc_casecmp(x->nick, nick))
  872. break;
  873. if (!x || !x->nick[0]) {
  874. if (!channel_pending(chan))
  875. putlog(LOG_MISC, "*", "(!) killmember(%s, %s) -> nonexistent", chan->dname, nick);
  876. return 0;
  877. }
  878. if (old)
  879. old->next = x->next;
  880. else
  881. chan->channel.member = x->next;
  882. free(x);
  883. chan->channel.members--;
  884. /* The following two errors should NEVER happen. We will try to correct
  885. * them though, to keep the bot from crashing.
  886. */
  887. if (chan->channel.members < 0) {
  888. chan->channel.members = 0;
  889. for (x = chan->channel.member; x && x->nick[0]; x = x->next)
  890. chan->channel.members++;
  891. putlog(LOG_MISC, "*", "(!) actually I know of %d members.", chan->channel.members);
  892. }
  893. if (!chan->channel.member) {
  894. chan->channel.member = (memberlist *) my_calloc(1, sizeof(memberlist));
  895. chan->channel.member->nick[0] = 0;
  896. chan->channel.member->next = NULL;
  897. }
  898. return 1;
  899. }
  900. /* Check if I am a chanop. Returns boolean 1 or 0.
  901. */
  902. bool
  903. me_op(struct chanset_t *chan)
  904. {
  905. memberlist *mx = ismember(chan, botname);
  906. if (!mx)
  907. return 0;
  908. if (chan_hasop(mx))
  909. return 1;
  910. else
  911. return 0;
  912. }
  913. /* Check whether I'm voice. Returns boolean 1 or 0.
  914. */
  915. static bool
  916. me_voice(struct chanset_t *chan)
  917. {
  918. memberlist *mx = ismember(chan, botname);
  919. if (!mx)
  920. return 0;
  921. if (chan_hasvoice(mx))
  922. return 1;
  923. else
  924. return 0;
  925. }
  926. /* Check if there are any ops on the channel. Returns boolean 1 or 0.
  927. */
  928. static bool
  929. any_ops(struct chanset_t *chan)
  930. {
  931. memberlist *x = NULL;
  932. for (x = chan->channel.member; x && x->nick[0]; x = x->next)
  933. if (chan_hasop(x))
  934. break;
  935. if (!x || !x->nick[0])
  936. return 0;
  937. return 1;
  938. }
  939. /* Reset the channel information.
  940. */
  941. static void
  942. reset_chan_info(struct chanset_t *chan)
  943. {
  944. /* Don't reset the channel if we're already resetting it */
  945. if (!shouldjoin(chan)) {
  946. dprintf(DP_MODE, "PART %s\n", chan->name);
  947. return;
  948. }
  949. if (!channel_pending(chan)) {
  950. bool opped = 0;
  951. if (me_op(chan))
  952. opped = 1;
  953. free(chan->channel.key);
  954. chan->channel.key = (char *) my_calloc(1, 1);
  955. clear_channel(chan, 1);
  956. chan->status |= CHAN_PEND;
  957. chan->status &= ~(CHAN_ACTIVE | CHAN_ASKEDMODES | CHAN_JOINING);
  958. if (!(chan->status & CHAN_ASKEDBANS)) {
  959. chan->status |= CHAN_ASKEDBANS;
  960. dprintf(DP_MODE, "MODE %s +b\n", chan->name);
  961. }
  962. if (opped && !channel_take(chan)) {
  963. if (!(chan->ircnet_status & CHAN_ASKED_EXEMPTS) && use_exempts == 1) {
  964. chan->ircnet_status |= CHAN_ASKED_EXEMPTS;
  965. dprintf(DP_MODE, "MODE %s +e\n", chan->name);
  966. }
  967. if (!(chan->ircnet_status & CHAN_ASKED_INVITES) && use_invites == 1) {
  968. chan->ircnet_status |= CHAN_ASKED_INVITES;
  969. dprintf(DP_MODE, "MODE %s +I\n", chan->name);
  970. }
  971. }
  972. /* These 2 need to get out asap, so into the mode queue */
  973. dprintf(DP_MODE, "MODE %s\n", chan->name);
  974. if (use_354)
  975. dprintf(DP_MODE, "WHO %s %%c%%h%%n%%u%%f\n", chan->name);
  976. else
  977. dprintf(DP_MODE, "WHO %s\n", chan->name);
  978. /* clear_channel nuked the data...so */
  979. }
  980. }
  981. /* If i'm the only person on the channel, and i'm not op'd,
  982. * might as well leave and rejoin. If i'm NOT the only person
  983. * on the channel, but i'm still not op'd, demand ops.
  984. */
  985. static void
  986. check_lonely_channel(struct chanset_t *chan)
  987. {
  988. if (channel_pending(chan) || !channel_active(chan) || me_op(chan) ||
  989. !shouldjoin(chan) || (chan->channel.mode & CHANANON))
  990. return;
  991. memberlist *m = NULL;
  992. char s[UHOSTLEN] = "";
  993. int i = 0;
  994. static int whined = 0;
  995. /* Count non-split channel members */
  996. for (m = chan->channel.member; m && m->nick[0]; m = m->next)
  997. if (!chan_issplit(m))
  998. i++;
  999. if (i == 1 && channel_cycle(chan) && !channel_stop_cycle(chan)) {
  1000. if (chan->name[0] != '+') { /* Its pointless to cycle + chans for ops */
  1001. putlog(LOG_MISC, "*", "Trying to cycle %s to regain ops.", chan->dname);
  1002. dprintf(DP_MODE, "PART %s\n", chan->name);
  1003. /* If it's a !chan, we need to recreate the channel with !!chan <cybah> */
  1004. dprintf(DP_MODE, "JOIN %s%s %s\n", (chan->dname[0] == '!') ? "!" : "", chan->dname, chan->key_prot);
  1005. chan->status |= CHAN_JOINING;
  1006. whined = 0;
  1007. }
  1008. } else if (any_ops(chan)) {
  1009. whined = 0;
  1010. request_op(chan);
  1011. /* need: op */
  1012. } else {
  1013. /* Other people here, but none are ops. If there are other bots make
  1014. * them LEAVE!
  1015. */
  1016. bool ok = 1;
  1017. struct userrec *u = NULL;
  1018. if (!whined) {
  1019. /* + is opless. Complaining about no ops when without special
  1020. * help(services), we cant get them - Raist
  1021. */
  1022. if (chan->name[0] != '+')
  1023. putlog(LOG_MISC, "*", "%s is active but has no ops :(", chan->dname);
  1024. whined = 1;
  1025. }
  1026. for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
  1027. sprintf(s, "%s!%s", m->nick, m->userhost);
  1028. u = get_user_by_host(s);
  1029. if (!match_my_nick(m->nick) && (!u || !u->bot)) {
  1030. ok = 0;
  1031. break;
  1032. }
  1033. }
  1034. if (ok && channel_cycle(chan)) {
  1035. /* ALL bots! make them LEAVE!!! */
  1036. /*
  1037. for (m = chan->channel.member; m && m->nick[0]; m = m->next)
  1038. if (!match_my_nick(m->nick))
  1039. dprintf(DP_SERVER, "PRIVMSG %s :go %s\n", m->nick, chan->dname);
  1040. */
  1041. } else {
  1042. /* Some humans on channel, but still op-less */
  1043. request_op(chan);
  1044. /* need: op */
  1045. }
  1046. }
  1047. }
  1048. static void
  1049. warn_pls_take(struct chanset_t *chan)
  1050. {
  1051. if (channel_take(chan) && me_op(chan))
  1052. putlog(LOG_WARN, "*", "%s is set +take, and I'm already opped! +take is insecure, try +bitch instead",
  1053. chan->dname);
  1054. }
  1055. /* FIXME: max sendq will occur. */
  1056. static void
  1057. check_servers(struct chanset_t *chan)
  1058. {
  1059. for (memberlist *m = chan->channel.member; m && m->nick[0]; m = m->next) {
  1060. if (!match_my_nick(m->nick) && chan_hasop(m) && (m->hops == -1)) {
  1061. putlog(LOG_DEBUG, "*", "Updating WHO for '%s' because '%s' is missing data.", chan->dname, m->nick);
  1062. dprintf(DP_HELP, "WHO %s\n", chan->name);
  1063. break; /* lets just do one chan at a time to save from flooding */
  1064. }
  1065. }
  1066. }
  1067. static void
  1068. check_netfight(struct chanset_t *chan)
  1069. {
  1070. int limit = atoi(CFG_FIGHTTHRESHOLD.gdata ? CFG_FIGHTTHRESHOLD.gdata : "0");
  1071. if (limit) {
  1072. if ((chan->channel.fighting) && (chan->channel.fighting > limit)) {
  1073. if (!chan_bitch(chan) || !channel_closed(chan)) {
  1074. putlog(LOG_WARN, "*", "Auto-closed %s - channel fight", chan->dname);
  1075. do_chanset(NULL, chan, "+bitch +closed +backup", DO_LOCAL | DO_NET);
  1076. enforce_closed(chan);
  1077. dprintf(DP_MODE, "TOPIC %s :Auto-closed - channel fight\n", chan->name);
  1078. }
  1079. }
  1080. }
  1081. chan->channel.fighting = 0; /* we put this here because we need to clear it once per min */
  1082. }
  1083. void
  1084. raise_limit(struct chanset_t *chan)
  1085. {
  1086. if (!chan || !me_op(chan))
  1087. return;
  1088. int nl = chan->channel.members + chan->limitraise; /* new limit */
  1089. int i = chan->limitraise >> 2; /* DIV 4 */
  1090. /* if the newlimit will be in the range made by these vars, dont change. */
  1091. int ul = nl + i; /* upper limit */
  1092. int ll = nl - i; /* lower limit */
  1093. if ((chan->channel.maxmembers > ll) && (chan->channel.maxmembers < ul))
  1094. return; /* the current limit is in the range, so leave it. */
  1095. if (nl != chan->channel.maxmembers) {
  1096. char s[5] = "";
  1097. sprintf(s, "%d", nl);
  1098. add_mode(chan, '+', 'l', s);
  1099. }
  1100. }
  1101. static void
  1102. check_expired_chanstuff(struct chanset_t *chan)
  1103. {
  1104. if (channel_active(chan)) {
  1105. masklist *b = NULL, *e = NULL;
  1106. memberlist *m = NULL, *n = NULL;
  1107. char s[UHOSTLEN] = "";
  1108. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  1109. if (me_op(chan)) {
  1110. if (channel_dynamicbans(chan) && chan->ban_time)
  1111. for (b = chan->channel.ban; b->mask[0]; b = b->next)
  1112. if (now - b->timer > 60 * chan->ban_time &&
  1113. !u_sticky_mask(chan->bans, b->mask) &&
  1114. !u_sticky_mask(global_bans, b->mask) && expired_mask(chan, b->who)) {
  1115. putlog(LOG_MODES, chan->dname, "(%s) Channel ban on %s expired.", chan->dname, b->mask);
  1116. add_mode(chan, '-', 'b', b->mask);
  1117. b->timer = now;
  1118. }
  1119. if (use_exempts && channel_dynamicexempts(chan) && chan->exempt_time)
  1120. for (e = chan->channel.exempt; e->mask[0]; e = e->next)
  1121. if (now - e->timer > 60 * chan->exempt_time &&
  1122. !u_sticky_mask(chan->exempts, e->mask) &&
  1123. !u_sticky_mask(global_exempts, e->mask) && expired_mask(chan, e->who)) {
  1124. /* Check to see if it matches a ban */
  1125. int match = 0;
  1126. for (b = chan->channel.ban; b->mask[0]; b = b->next)
  1127. if (wild_match(b->mask, e->mask) || wild_match(e->mask, b->mask)) {
  1128. match = 1;
  1129. break;
  1130. }
  1131. /* Leave this extra logging in for now. Can be removed later
  1132. * Jason
  1133. */
  1134. if (match) {
  1135. putlog(LOG_MODES, chan->dname,
  1136. "(%s) Channel exemption %s NOT expired. Exempt still set!", chan->dname, e->mask);
  1137. } else {
  1138. putlog(LOG_MODES, chan->dname, "(%s) Channel exemption on %s expired.", chan->dname, e->mask);
  1139. add_mode(chan, '-', 'e', e->mask);
  1140. }
  1141. e->timer = now;
  1142. }
  1143. if (use_invites && channel_dynamicinvites(chan) && chan->invite_time && !(chan->channel.mode & CHANINV)) {
  1144. for (b = chan->channel.invite; b->mask[0]; b = b->next) {
  1145. if (now - b->timer > 60 * chan->invite_time &&
  1146. !u_sticky_mask(chan->invites, b->mask) &&
  1147. !u_sticky_mask(global_invites, b->mask) && expired_mask(chan, b->who)) {
  1148. putlog(LOG_MODES, chan->dname, "(%s) Channel invitation on %s expired.", chan->dname, b->mask);
  1149. add_mode(chan, '-', 'I', b->mask);
  1150. b->timer = now;
  1151. }
  1152. }
  1153. }
  1154. } /* me_op */
  1155. // for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
  1156. for (m = chan->channel.member; m && m->nick[0]; m = n) {
  1157. n = m->next;
  1158. if (m->split && now - m->split > wait_split) {
  1159. sprintf(s, "%s!%s", m->nick, m->userhost);
  1160. putlog(LOG_JOIN, chan->dname, "%s (%s) got lost in the net-split.", m->nick, m->userhost);
  1161. killmember(chan, m->nick);
  1162. continue;
  1163. }
  1164. if (me_op(chan)) {
  1165. if (chan->idle_kick) {
  1166. if (now - m->last >= chan->idle_kick * 60 && !match_my_nick(m->nick) && !chan_issplit(m)) {
  1167. sprintf(s, "%s!%s", m->nick, m->userhost);
  1168. get_user_flagrec(m->user ? m->user : get_user_by_host(s), &fr, chan->dname);
  1169. if (!(glob_bot(fr) || (glob_op(fr) && !glob_deop(fr)) || chan_op(fr))) {
  1170. dprintf(DP_SERVER, "KICK %s %s :%sidle %d min\n", chan->name, m->nick, kickprefix, chan->idle_kick);
  1171. m->flags |= SENTKICK;
  1172. }
  1173. }
  1174. } else if (dovoice(chan) && !loading) { /* autovoice of +v users if bot is +y */
  1175. if (!chan_hasop(m) && !chan_hasvoice(m)) {
  1176. if (!m->user) {
  1177. sprintf(s, "%s!%s", m->nick, m->userhost);
  1178. m->user = get_user_by_host(s);
  1179. }
  1180. if (m->user) {
  1181. get_user_flagrec(m->user, &fr, chan->dname);
  1182. if (!glob_bot(fr)) {
  1183. if (!(m->flags & EVOICE) && !privchan(fr, chan, PRIV_VOICE) &&
  1184. ((channel_voice(chan) && !chk_devoice(fr)) ||
  1185. (!channel_voice(chan) && chk_voice(fr, chan)))) {
  1186. add_mode(chan, '+', 'v', m->nick);
  1187. } else if ((chk_devoice(fr) || (m->flags & EVOICE))) {
  1188. add_mode(chan, '-', 'v', m->nick);
  1189. }
  1190. }
  1191. } else if (!m->user && !(m->flags & EVOICE) && channel_voice(chan)) {
  1192. add_mode(chan, '+', 'v', m->nick);
  1193. }
  1194. }
  1195. }
  1196. }
  1197. m = n;
  1198. }
  1199. check_lonely_channel(chan);
  1200. } else if (shouldjoin(chan) && !channel_pending(chan) && !channel_joining(chan)) {
  1201. dprintf(DP_MODE, "JOIN %s %s\n",
  1202. (chan->name[0]) ? chan->name : chan->dname,
  1203. chan->channel.key[0] ? chan->channel.key : chan->key_prot);
  1204. chan->status |= CHAN_JOINING;
  1205. }
  1206. }
  1207. void
  1208. irc_minutely()
  1209. {
  1210. for (register struct chanset_t *chan = chanset; chan; chan = chan->next) {
  1211. warn_pls_take(chan);
  1212. if (server_online) {
  1213. check_netfight(chan);
  1214. check_servers(chan);
  1215. check_expired_chanstuff(chan);
  1216. }
  1217. }
  1218. }
  1219. int check_bind_authc(char *cmd, Auth *auth, char *chname, char *args)
  1220. {
  1221. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  1222. int x = 0;
  1223. get_user_flagrec(auth->user, &fr, chname);
  1224. x = check_bind(BT_msgc, cmd, &fr, auth, chname, args);
  1225. if (x & BIND_RET_LOG) {
  1226. if (chname)
  1227. putlog(LOG_CMDS, "*", "(%s!%s) !%s! %s %c%s %s", auth->nick, auth->host,
  1228. auth->handle, chname, cmdprefix, cmd, args);
  1229. else
  1230. putlog(LOG_CMDS, "*", "(%s!%s) !%s! %c%s %s", auth->nick, auth->host, auth->handle, cmdprefix, cmd, args);
  1231. }
  1232. if (x & BIND_RET_BREAK)
  1233. return (1);
  1234. return (0);
  1235. }
  1236. /* Flush the modes for EVERY channel.
  1237. */
  1238. void
  1239. flush_modes()
  1240. {
  1241. if (!modesperline) /* Haven't received 005 yet :) */
  1242. return;
  1243. memberlist *m = NULL;
  1244. for (register struct chanset_t *chan = chanset; chan; chan = chan->next) {
  1245. for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
  1246. if (m->delay && m->delay <= now) {
  1247. m->delay = 0L;
  1248. m->flags &= ~FULL_DELAY;
  1249. if (chan_sentop(m)) {
  1250. m->flags &= ~SENTOP;
  1251. do_op(m->nick, chan, 0, 0);
  1252. }
  1253. if (chan_sentvoice(m)) {
  1254. m->flags &= ~SENTVOICE;
  1255. add_mode(chan, '+', 'v', m->nick);
  1256. }
  1257. }
  1258. }
  1259. flush_mode(chan, NORMAL);
  1260. }
  1261. }
  1262. void
  1263. irc_report(int idx, int details)
  1264. {
  1265. struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  1266. char ch[1024] = "", q[160] = "", *p = NULL;
  1267. int k = 10;
  1268. size_t len;
  1269. strcpy(q, "Channels: ");
  1270. for (struct chanset_t *chan = chanset; chan; chan = chan->next) {
  1271. if (idx != DP_STDOUT)
  1272. get_user_flagrec(dcc[idx].user, &fr, chan->dname);
  1273. if (!privchan(fr, chan, PRIV_OP) && (idx == DP_STDOUT || glob_master(fr) || chan_master(fr))) {
  1274. p = NULL;
  1275. if (shouldjoin(chan)) {
  1276. if (chan->status & CHAN_JUPED)
  1277. p = MISC_JUPED;
  1278. else if (channel_joining(chan))
  1279. p = MISC_JOINING;
  1280. else if (!(chan->status & CHAN_ACTIVE))
  1281. p = MISC_TRYING;
  1282. else if (chan->status & CHAN_PEND)
  1283. p = MISC_PENDING;
  1284. else if ((chan->dname[0] != '+') && !me_op(chan))
  1285. p = MISC_WANTOPS;
  1286. }
  1287. len = simple_sprintf(ch, "%s%s%s%s, ", chan->dname, p ? "(" : "", p ? p : "", p ? ")" : "");
  1288. if ((k + len) > 70) {
  1289. dprintf(idx, " %s\n", q);
  1290. strcpy(q, " ");
  1291. k = 10;
  1292. }
  1293. k += my_strcpy(q + k, ch);
  1294. }
  1295. }
  1296. if (k > 10) {
  1297. q[k - 2] = 0;
  1298. dprintf(idx, " %s\n", q);
  1299. }
  1300. }
  1301. static void
  1302. do_nettype()
  1303. {
  1304. switch (net_type) {
  1305. case 0: /* Efnet */
  1306. include_lk = 0;
  1307. break;
  1308. case 1: /* Ircnet */
  1309. include_lk = 1;
  1310. break;
  1311. case 2: /* Undernet */
  1312. include_lk = 1;
  1313. break;
  1314. case 3: /* Dalnet */
  1315. include_lk = 1;
  1316. break;
  1317. case 4: /* hybrid-6+ */
  1318. include_lk = 0;
  1319. break;
  1320. default:
  1321. break;
  1322. }
  1323. }
  1324. static cmd_t irc_bot[] = {
  1325. {"dp", "", (Function) mdop_request, NULL, LEAF},
  1326. {"gi", "", (Function) getin_request, NULL, LEAF},
  1327. {NULL, NULL, NULL, NULL, 0}
  1328. };
  1329. static void
  1330. getin_5secondly()
  1331. {
  1332. if (!server_online)
  1333. return;
  1334. for (register struct chanset_t *chan = chanset; chan; chan = chan->next) {
  1335. if ((!channel_pending(chan) && channel_active(chan)) && !me_op(chan))
  1336. request_op(chan);
  1337. }
  1338. }
  1339. void
  1340. irc_init()
  1341. {
  1342. timer_create_secs(60, "irc_minutely", (Function) irc_minutely);
  1343. timer_create_secs(5, "getin_5secondly", (Function) getin_5secondly);
  1344. /* Add our commands to the imported tables. */
  1345. add_builtins("dcc", irc_dcc);
  1346. add_builtins("bot", irc_bot);
  1347. add_builtins("raw", irc_raw);
  1348. add_builtins("msg", C_msg);
  1349. add_builtins("msgc", C_msgc);
  1350. do_nettype();
  1351. }