irc.c 47 KB

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