m_chansno.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. #include "unrealircd.h"
  2. typedef struct _conf_operflag OperFlag;
  3. typedef struct _chansnoflag ChanSnoFlag;
  4. struct _conf_operflag {
  5. long flag;
  6. char *name;
  7. };
  8. struct _chansnoflag {
  9. ChanSnoFlag *prev, *next;
  10. char *channel;
  11. long flags;
  12. };
  13. extern OperFlag *config_binary_flags_search(OperFlag *table, char *cmd, int size);
  14. #define MSG_CHANSNO "CHANSNO"
  15. #define CHSNO_TABLESIZE sizeof(_ChanSnoFlags) / sizeof(_ChanSnoFlags[0])
  16. #define MaxSize(x) (sizeof(x) - strlen(x) - 1)
  17. #define ircstrdup(x,y) if(x) MyFree(x); if(!y) x = NULL; else x = strdup(y)
  18. #define IsParam(x) (parc > (x) && !BadPtr(parv[(x)]))
  19. #define IsNotParam(x) (parc <= (x) || BadPtr(parv[(x)]))
  20. /* Some helpful abbreviations */
  21. #define UserName(cptr) ((cptr)->user->username)
  22. #define RealHost(cptr) ((cptr)->user->realhost)
  23. /* Messages types */
  24. #define MT_PRIVMSG 0x00
  25. #define MT_NOTICE 0x01
  26. #define MsgType (msgtype == MT_PRIVMSG ? "PRIVMSG" : "NOTICE")
  27. /* Channel server notice masks */
  28. #define CHSNO_CONNECT 0x0001
  29. #define CHSNO_DISCONNECT 0x0002
  30. #define CHSNO_NICKCHANGE 0x0004
  31. #define CHSNO_JOIN 0x0008
  32. #define CHSNO_PART 0x0010
  33. #define CHSNO_KICK 0x0020
  34. #define CHSNO_CHANMODE 0x0040
  35. #define CHSNO_SCONNECT 0x0080
  36. #define CHSNO_SQUIT 0x0100
  37. #define CHSNO_TOPIC 0x0200
  38. #define CHSNO_UNKUSER_QUIT 0x0400
  39. #define CHSNO_CHANNEL_CREATE 0x0800
  40. #define CHSNO_CHANNEL_DESTROY 0x1000
  41. #define CHSNO_OPER 0x2000
  42. #define CHSNO_SPAMFILTER 0x4000
  43. #define CHSNO_TKL_ADD 0x8000
  44. /* This MUST be alphabetized */
  45. OperFlag _ChanSnoFlags[] = {
  46. { CHSNO_CHANNEL_CREATE, "channel-creations" },
  47. { CHSNO_CHANNEL_DESTROY, "channel-destructions" },
  48. { CHSNO_CONNECT, "connects" },
  49. { CHSNO_DISCONNECT, "disconnects" },
  50. { CHSNO_JOIN, "joins" },
  51. { CHSNO_KICK, "kicks" },
  52. { CHSNO_CHANMODE, "mode-changes" },
  53. { CHSNO_NICKCHANGE, "nickchanges" },
  54. { CHSNO_OPER, "oper-ups" },
  55. { CHSNO_PART, "parts" },
  56. { CHSNO_SCONNECT, "server-connects" },
  57. { CHSNO_SPAMFILTER, "spamfilter-hits" },
  58. { CHSNO_SQUIT, "squits" },
  59. { CHSNO_TKL_ADD, "tkl-add" },
  60. { CHSNO_TOPIC, "topics" },
  61. { CHSNO_UNKUSER_QUIT, "unknown-users" }
  62. };
  63. CMD_FUNC(m_chansno);
  64. int chansno_configtest(ConfigFile *, ConfigEntry *, int, int *);
  65. int chansno_configrun(ConfigFile *, ConfigEntry *, int);
  66. int chansno_rehash(void);
  67. int chansno_hook_chanmode(aClient *cptr, aClient *sptr, aChannel *chptr, char *modebuf, char *parabuf, time_t sendts, int samode);
  68. int chansno_hook_connect(aClient *sptr);
  69. int chansno_hook_quit(aClient *sptr, char *comment);
  70. int chansno_hook_join(aClient *cptr, aClient *sptr, aChannel *chptr, char *parv[]);
  71. int chansno_hook_kick(aClient *cptr, aClient *sptr, aClient *victim, aChannel *chptr, char *comment);
  72. int chansno_hook_nickchange(aClient *sptr, char *newnick);
  73. int chansno_hook_part(aClient *cptr, aClient *sptr, aChannel *chptr, char *comment);
  74. int chansno_hook_serverconnect(aClient *sptr);
  75. int chansno_hook_serverquit(aClient *sptr);
  76. int chansno_hook_topic(aClient *cptr, aClient *sptr, aChannel *chptr, char *topic);
  77. int chansno_hook_unkuserquit(aClient *sptr, char *comment);
  78. int chansno_hook_channelcreate(aClient *sptr, aChannel *chptr);
  79. int chansno_hook_channeldestroy(aChannel *chptr, int *should_destroy);
  80. int chansno_hook_spamfilter(aClient *acptr, char *str, char *str_in, int type, char *target, aTKline *tkl);
  81. static int chansno_override_oper(Cmdoverride *ovr, aClient *cptr, aClient *sptr, int parc, char *parv[]);
  82. int chansno_hook_tkladd(aClient *cptr, aClient *sptr, aTKline *tkl, int parc, char *parv[]);
  83. static void InitConf(void);
  84. static void FreeConf(void);
  85. static char *get_flag_names(long flags);
  86. static void stats_chansno_channels(aClient *sptr);
  87. static void stats_chansno_config(aClient *sptr);
  88. static u_int find_sno_channel(aChannel *chptr);
  89. static void SendNotice_simple(long type, int local);
  90. static void SendNotice_channel(aChannel *chptr, long type, int local);
  91. Command *CmdChanSno = NULL;
  92. Cmdoverride *OvrOper = NULL;
  93. ChanSnoFlag *ConfChanSno;
  94. Hook *HookConfTest, *HookConfRun, *HookConfRehash;
  95. Hook *HookMode = NULL, *HookConnect = NULL, *HookQuit = NULL;
  96. Hook *HookJoin = NULL, *HookKick = NULL, *HookTopic = NULL;
  97. Hook *HookPart = NULL, *HookServerConnect = NULL;
  98. Hook *HookServerQuit = NULL, *HookNickChange = NULL;
  99. Hook *HookUnkUserQuit = NULL, *HookChannelCreate = NULL;
  100. Hook *HookChannelDestroy = NULL;
  101. Hook *HookSpamfilter = NULL;
  102. Hook *HookTKLAdd = NULL;
  103. u_int msgtype = MT_PRIVMSG;
  104. static ModuleInfo *chansnoMI;
  105. char msgbuf[BUFSIZE + 1];
  106. ModuleHeader MOD_HEADER(chansno) = {
  107. "m_chansno",
  108. "$Id: v1.04 2018/05/31 Gottem$",
  109. "Allows you to assign channels for specific server notifications (sort of like snomasks)",
  110. "3.2-b8-1",
  111. NULL
  112. };
  113. // =================================================================
  114. // Module functions
  115. // =================================================================
  116. MOD_TEST(m_chansno) {
  117. chansnoMI = modinfo;
  118. HookConfTest = HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, chansno_configtest);
  119. return MOD_SUCCESS;
  120. }
  121. MOD_INIT(m_chansno) {
  122. chansnoMI = modinfo;
  123. InitConf();
  124. CmdChanSno = CommandAdd(modinfo->handle, MSG_CHANSNO, m_chansno, MAXPARA, M_USER);
  125. HookConfRun = HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, chansno_configrun);
  126. HookConfRehash = HookAdd(modinfo->handle, HOOKTYPE_REHASH, 0, chansno_rehash);
  127. HookMode = HookAdd(modinfo->handle, HOOKTYPE_LOCAL_CHANMODE, 0, chansno_hook_chanmode);
  128. HookConnect = HookAdd(modinfo->handle, HOOKTYPE_LOCAL_CONNECT, 0, chansno_hook_connect);
  129. HookQuit = HookAdd(modinfo->handle, HOOKTYPE_LOCAL_QUIT, 0, chansno_hook_quit);
  130. HookJoin = HookAdd(modinfo->handle, HOOKTYPE_LOCAL_JOIN, 0, chansno_hook_join);
  131. HookKick = HookAdd(modinfo->handle, HOOKTYPE_LOCAL_KICK, 0, chansno_hook_kick);
  132. HookNickChange = HookAdd(modinfo->handle, HOOKTYPE_LOCAL_NICKCHANGE, 0, chansno_hook_nickchange);
  133. HookPart = HookAdd(modinfo->handle, HOOKTYPE_LOCAL_PART, 0, chansno_hook_part);
  134. HookServerConnect = HookAdd(modinfo->handle, HOOKTYPE_SERVER_CONNECT, 0, chansno_hook_serverconnect);
  135. HookServerQuit = HookAdd(modinfo->handle, HOOKTYPE_SERVER_QUIT, 0, chansno_hook_serverquit);
  136. HookTopic = HookAdd(modinfo->handle, HOOKTYPE_LOCAL_TOPIC, 0, chansno_hook_topic);
  137. HookUnkUserQuit = HookAdd(modinfo->handle, HOOKTYPE_UNKUSER_QUIT, 0, chansno_hook_unkuserquit);
  138. HookChannelCreate = HookAdd(modinfo->handle, HOOKTYPE_CHANNEL_CREATE, 0, chansno_hook_channelcreate);
  139. HookChannelDestroy = HookAdd(modinfo->handle, HOOKTYPE_CHANNEL_DESTROY, 0, chansno_hook_channeldestroy);
  140. HookSpamfilter = HookAdd(modinfo->handle, HOOKTYPE_LOCAL_SPAMFILTER, 0, chansno_hook_spamfilter);
  141. HookTKLAdd = HookAdd(modinfo->handle, HOOKTYPE_TKL_ADD, 0, chansno_hook_tkladd);
  142. return MOD_SUCCESS;
  143. }
  144. MOD_LOAD(m_chansno) {
  145. OvrOper = CmdoverrideAdd(chansnoMI->handle, "OPER", chansno_override_oper);
  146. if(ModuleGetError(chansnoMI->handle) != MODERR_NOERROR || !OvrOper || !CmdChanSno) {
  147. config_error("A critical error occurred when loading module %s: %s", MOD_HEADER(m_chansno).name, ModuleGetErrorStr(chansnoMI->handle));
  148. return MOD_FAILED;
  149. }
  150. return MOD_SUCCESS;
  151. }
  152. MOD_UNLOAD(m_chansno) {
  153. FreeConf();
  154. return MOD_SUCCESS;
  155. }
  156. // =================================================================
  157. // Functions related to loading/unloading configuration
  158. // =================================================================
  159. static void InitConf(void) {
  160. ConfChanSno = NULL;
  161. msgtype = MT_PRIVMSG;
  162. }
  163. static void FreeConf(void) {
  164. ChanSnoFlag *c;
  165. ListStruct *next;
  166. for(c = ConfChanSno; c; c = (ChanSnoFlag *) next) {
  167. next = (ListStruct *)c->next;
  168. DelListItem(c, ConfChanSno);
  169. MyFree(c->channel);
  170. MyFree(c);
  171. }
  172. }
  173. // =================================================================
  174. // Config file interfacing
  175. // =================================================================
  176. int chansno_rehash(void) {
  177. FreeConf();
  178. InitConf();
  179. return HOOK_CONTINUE;
  180. }
  181. int chansno_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) {
  182. ConfigEntry *cep, *cep2;
  183. int errors = 0;
  184. if(type != CONFIG_MAIN)
  185. return 0;
  186. if(!ce->ce_varname || strcmp(ce->ce_varname, "chansno"))
  187. return 0;
  188. for(cep = ce->ce_entries; cep; cep = cep->ce_next) {
  189. if(!cep->ce_varname) {
  190. config_error("%s:%i: blank chansno item", cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
  191. errors++;
  192. continue;
  193. }
  194. if(!cep->ce_vardata) {
  195. config_error("%s:%i: chansno::%s item without value", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
  196. errors++;
  197. continue;
  198. }
  199. if(!strcmp(cep->ce_varname, "channel")) {
  200. if(!cep->ce_entries) {
  201. config_error("%s:%i: chansno::channel without contents", cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
  202. errors++;
  203. continue;
  204. }
  205. for(cep2 = cep->ce_entries; cep2; cep2 = cep2->ce_next) {
  206. if(!cep2->ce_varname) {
  207. config_error("%s:%i: chansno::channel item without variable name", cep2->ce_fileptr->cf_filename, cep2->ce_varlinenum);
  208. errors++;
  209. continue;
  210. }
  211. if(!config_binary_flags_search(_ChanSnoFlags, cep2->ce_varname, CHSNO_TABLESIZE)) {
  212. config_error("%s:%i: unknown chansno::channel flag '%s'", cep2->ce_fileptr->cf_filename, cep2->ce_varlinenum, cep2->ce_varname);
  213. errors++;
  214. }
  215. }
  216. }
  217. else if(!strcmp(cep->ce_varname, "msgtype")) {
  218. if(strcmp(cep->ce_vardata, "privmsg") && strcmp(cep->ce_vardata, "notice")) {
  219. config_error("%s:%i: unknown chansno::msgtype '%s'", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_vardata);
  220. errors++;
  221. }
  222. }
  223. else {
  224. config_error("%s:%i: unknown directive chansno::%s", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
  225. errors++;
  226. }
  227. }
  228. *errs = errors;
  229. return errors ? -1 : 1;
  230. }
  231. int chansno_configrun(ConfigFile *cf, ConfigEntry *ce, int type) {
  232. ConfigEntry *cep, *cep2;
  233. OperFlag *ofp;
  234. ChanSnoFlag *ca;
  235. if(type != CONFIG_MAIN)
  236. return 0;
  237. if(!ce->ce_varname || strcmp(ce->ce_varname, "chansno"))
  238. return 0;
  239. for(cep = ce->ce_entries; cep; cep = cep->ce_next) {
  240. if(!strcmp(cep->ce_varname, "channel")) {
  241. ca = MyMallocEx(sizeof(ChanSnoFlag));
  242. ircstrdup(ca->channel, cep->ce_vardata);
  243. for(cep2 = cep->ce_entries; cep2; cep2 = cep2->ce_next) {
  244. if((ofp = config_binary_flags_search(_ChanSnoFlags, cep2->ce_varname, CHSNO_TABLESIZE)))
  245. ca->flags |= ofp->flag;
  246. }
  247. AddListItem(ca, ConfChanSno);
  248. }
  249. else if(!strcmp(cep->ce_varname, "msgtype")) {
  250. if(!strcmp(cep->ce_vardata, "privmsg"))
  251. msgtype = MT_PRIVMSG;
  252. else if(!strcmp(cep->ce_vardata, "notice"))
  253. msgtype = MT_NOTICE;
  254. }
  255. }
  256. return 1;
  257. }
  258. // ===============================================================
  259. // Functions used by m_chansno
  260. // ===============================================================
  261. static char *get_flag_names(long flags) {
  262. u_int i, found = 0;
  263. memset(&msgbuf, 0, sizeof(msgbuf));
  264. for(i = 0; i < CHSNO_TABLESIZE; i++) {
  265. if(flags & _ChanSnoFlags[i].flag) {
  266. if(found)
  267. strncat(msgbuf, ", ", MaxSize(msgbuf));
  268. else
  269. found = 1;
  270. strncat(msgbuf, _ChanSnoFlags[i].name, MaxSize(msgbuf));
  271. }
  272. }
  273. if(!strlen(msgbuf))
  274. strcpy(msgbuf, "<None>");
  275. return msgbuf;
  276. }
  277. static void stats_chansno_channels(aClient *sptr) {
  278. ChanSnoFlag *c;
  279. for(c = ConfChanSno; c; c = c->next)
  280. sendto_one(sptr, ":%s %i %s :channel %s: %s", me.name, RPL_TEXT, sptr->name, c->channel, get_flag_names(c->flags));
  281. sendto_one(sptr, rpl_str(RPL_ENDOFSTATS), me.name, sptr->name, 'S');
  282. }
  283. static void stats_chansno_config(aClient *sptr) {
  284. sendto_one(sptr, ":%s %i %s :msgtype: %s", me.name, RPL_TEXT, sptr->name, MsgType);
  285. sendto_one(sptr, rpl_str(RPL_ENDOFSTATS), me.name, sptr->name, 'S');
  286. }
  287. // ===============================================================
  288. // m_chansno
  289. // parv[0]: sender prefix
  290. // parv[1]: option
  291. // parv[2]: server name (optional)
  292. // ===============================================================
  293. CMD_FUNC(m_chansno) {
  294. if(!IsPerson(sptr))
  295. return -1;
  296. if(!IsOper(sptr)) {
  297. sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  298. return -1;
  299. }
  300. if(!IsParam(1)) {
  301. sendto_one(sptr, ":%s NOTICE %s :Usage:", me.name, sptr->name);
  302. sendto_one(sptr, ":%s NOTICE %s : /chansno <option> [<servername>]", me.name, sptr->name);
  303. sendto_one(sptr, ":%s NOTICE %s :Options:", me.name, sptr->name);
  304. sendto_one(sptr, ":%s NOTICE %s : list: displays the chansno::channel block list", me.name, sptr->name);
  305. sendto_one(sptr, ":%s NOTICE %s : config: shows the rest of chansno configuration", me.name, sptr->name);
  306. return 0;
  307. }
  308. if(IsParam(2)) {
  309. if(hunt_server(cptr, sptr, ":%s CHANSNO %s %s", 2, parc, parv) != HUNTED_ISME)
  310. return 0;
  311. }
  312. if(!strcasecmp(parv[1], "list"))
  313. stats_chansno_channels(sptr);
  314. else if(!strcasecmp(parv[1], "config"))
  315. stats_chansno_config(sptr);
  316. else {
  317. sendto_one(sptr, ":%s NOTICE %s :Unknown option %s." " Valid options are: list, config", me.name, sptr->name, parv[1]);
  318. return -1;
  319. }
  320. return 0;
  321. }
  322. // ===============================================================
  323. // Interface for sending notifications
  324. // ===============================================================
  325. static u_int find_sno_channel(aChannel *chptr) {
  326. ChanSnoFlag *c;
  327. for(c = ConfChanSno; c; c = c->next) {
  328. if(!strcasecmp(chptr->chname, c->channel))
  329. return 1;
  330. }
  331. return 0;
  332. }
  333. static void SendNotice_simple(long type, int local) {
  334. ChanSnoFlag *c;
  335. aChannel *chptr;
  336. for(c = ConfChanSno; c; c = c->next) {
  337. if(c->flags & type) {
  338. if((chptr = find_channel(c->channel, NULL)) && msgbuf[1]) {
  339. if(local) {
  340. // The following call sends the message to locally connected users in the channel only ;]
  341. // Currently only applies to channel destructions, as every server keeps track of that themselves
  342. sendto_channel_butserv(chptr, &me, ":%s %s %s :%s", me.name, MsgType, chptr->chname, msgbuf);
  343. }
  344. else {
  345. // This call sends the message to all clients in the particular channel ;]
  346. sendto_channelprefix_butone(NULL, &me, chptr, 0, ":%s %s %s :%s", me.name, MsgType, chptr->chname, msgbuf);
  347. }
  348. }
  349. }
  350. }
  351. }
  352. static void SendNotice_channel(aChannel *chptr, long type, int local) {
  353. ChanSnoFlag *c;
  354. aChannel *chptr2;
  355. for(c = ConfChanSno; c; c = c->next) {
  356. if(c->flags & type) {
  357. if(chptr && !find_sno_channel(chptr) && (chptr2 = find_channel(c->channel, NULL)) && msgbuf[1]) {
  358. if(local) {
  359. // The following call sends the message to locally connected users in the channel only ;]
  360. // Currently only applies to channel destructions, as every server keeps track of that themselves
  361. sendto_channel_butserv(chptr2, &me, ":%s %s %s :[%s] %s", me.name, MsgType, chptr2->chname, chptr->chname, msgbuf);
  362. }
  363. else {
  364. // This call sends the message to all clients in the particular channel ;]
  365. sendto_channelprefix_butone(NULL, &me, chptr2, 0, ":%s %s %s :[%s] %s", me.name, MsgType, chptr2->chname, chptr->chname, msgbuf);
  366. }
  367. }
  368. }
  369. }
  370. }
  371. int chansno_hook_chanmode(aClient *cptr, aClient *sptr, aChannel *chptr, char *modebuf, char *parabuf, time_t sendts, int samode) {
  372. snprintf(msgbuf, BUFSIZE, "%s sets mode: %s%s%s", sptr->name, modebuf, BadPtr(parabuf) ? "" : " ", BadPtr(parabuf) ? "" : parabuf);
  373. SendNotice_channel(chptr, CHSNO_CHANMODE, 0);
  374. return HOOK_CONTINUE;
  375. }
  376. int chansno_hook_connect(aClient *sptr) {
  377. snprintf(msgbuf, BUFSIZE, "Client connecting on port %d: %s (%s@%s) [%s] %s%s%s",
  378. sptr->local->listener->port, sptr->name, UserName(sptr), RealHost(sptr),
  379. sptr->local->class ? sptr->local->class->name : "",
  380. IsSecure(sptr) ? "[secure " : "",
  381. IsSecure(sptr) ? SSL_get_cipher(sptr->local->ssl) : "",
  382. IsSecure(sptr) ? "]" : "");
  383. SendNotice_simple(CHSNO_CONNECT, 0);
  384. return HOOK_CONTINUE;
  385. }
  386. int chansno_hook_quit(aClient *sptr, char *comment) {
  387. snprintf(msgbuf, BUFSIZE, "Client exiting: %s!%s@%s (%s)", sptr->name, UserName(sptr), RealHost(sptr), comment);
  388. SendNotice_simple(CHSNO_DISCONNECT, 0);
  389. return HOOK_CONTINUE;
  390. }
  391. int chansno_hook_unkuserquit(aClient *sptr, char *comment) {
  392. if(BadPtr(comment))
  393. snprintf(msgbuf, BUFSIZE, "Unknown client exiting: %s", sptr->ip);
  394. else
  395. snprintf(msgbuf, BUFSIZE, "Unknown client exiting: %s (%s)", sptr->ip, comment);
  396. SendNotice_simple(CHSNO_UNKUSER_QUIT, 0);
  397. return HOOK_CONTINUE;
  398. }
  399. int chansno_hook_join(aClient *cptr, aClient *sptr, aChannel *chptr, char *parv[]) {
  400. snprintf(msgbuf, BUFSIZE, "%s (%s@%s) has joined %s", sptr->name, UserName(sptr), RealHost(sptr), chptr->chname);
  401. SendNotice_channel(chptr, CHSNO_JOIN, 0);
  402. return HOOK_CONTINUE;
  403. }
  404. int chansno_hook_kick(aClient *cptr, aClient *sptr, aClient *victim, aChannel *chptr, char *comment) {
  405. snprintf(msgbuf, BUFSIZE, "%s has kicked %s (%s)", sptr->name, victim->name, comment);
  406. SendNotice_channel(chptr, CHSNO_KICK, 0);
  407. return HOOK_CONTINUE;
  408. }
  409. int chansno_hook_nickchange(aClient *sptr, char *newnick) {
  410. snprintf(msgbuf, BUFSIZE, "%s (%s@%s) has changed their nickname to %s", sptr->name, UserName(sptr), RealHost(sptr), newnick);
  411. SendNotice_simple(CHSNO_NICKCHANGE, 0);
  412. return HOOK_CONTINUE;
  413. }
  414. int chansno_hook_part(aClient *cptr, aClient *sptr, aChannel *chptr, char *comment) {
  415. snprintf(msgbuf, BUFSIZE, "%s (%s@%s) has left %s (%s)", sptr->name, UserName(sptr), RealHost(sptr), chptr->chname, comment ? comment : sptr->name);
  416. SendNotice_channel(chptr, CHSNO_PART, 0);
  417. return HOOK_CONTINUE;
  418. }
  419. int chansno_hook_serverconnect(aClient *sptr) {
  420. if(!sptr || !sptr->local || !sptr->local->listener) return HOOK_CONTINUE;
  421. snprintf(msgbuf, BUFSIZE, "Server connecting on port %d: %s (%s) [%s] %s%s%s",
  422. sptr->local->listener->port, sptr->name, sptr->info,
  423. sptr->local->class ? sptr->local->class->name : "",
  424. IsSecure(sptr) ? "[secure " : "",
  425. IsSecure(sptr) ? SSL_get_cipher(sptr->local->ssl) : "",
  426. IsSecure(sptr) ? "]" : "");
  427. SendNotice_simple(CHSNO_SCONNECT, 0);
  428. return HOOK_CONTINUE;
  429. }
  430. int chansno_hook_serverquit(aClient *sptr) {
  431. /* The hook supports no reason :-( */
  432. snprintf(msgbuf, BUFSIZE, "Server exiting: %s", sptr->name);
  433. SendNotice_simple(CHSNO_SQUIT, 0);
  434. return HOOK_CONTINUE;
  435. }
  436. int chansno_hook_topic(aClient *cptr, aClient *sptr, aChannel *chptr, char *topic) {
  437. snprintf(msgbuf, BUFSIZE, "%s changes topic to: %s", sptr->name, topic);
  438. SendNotice_channel(chptr, CHSNO_TOPIC, 0);
  439. return HOOK_CONTINUE;
  440. }
  441. int chansno_hook_channelcreate(aClient *cptr, aChannel *chptr) {
  442. if(!IsServer(cptr) && !find_sno_channel(chptr)) {
  443. snprintf(msgbuf, BUFSIZE, "%s created channel %s", cptr->name, chptr->chname);
  444. SendNotice_simple(CHSNO_CHANNEL_CREATE, 0);
  445. }
  446. return HOOK_CONTINUE;
  447. }
  448. int chansno_hook_channeldestroy(aChannel *chptr, int *should_destroy) {
  449. if(!find_sno_channel(chptr)) {
  450. snprintf(msgbuf, BUFSIZE, "Channel %s has been destroyed", chptr->chname);
  451. SendNotice_simple(CHSNO_CHANNEL_DESTROY, 1);
  452. }
  453. return HOOK_CONTINUE;
  454. }
  455. int chansno_hook_spamfilter(aClient *acptr, char *str, char *str_in, int type, char *target, aTKline *tkl) {
  456. snprintf(msgbuf, BUFSIZE, "%s!%s@%s matched spamfilter '%s': [%s%s: '%s'] [%s]",
  457. acptr->name, acptr->user->username, acptr->user->realhost, tkl->reason, cmdname_by_spamftarget(type),
  458. target, str_in, unreal_decodespace(tkl->ptr.spamf->tkl_reason));
  459. SendNotice_simple(CHSNO_SPAMFILTER, 0);
  460. return HOOK_CONTINUE;
  461. }
  462. static int chansno_override_oper(Cmdoverride *ovr, aClient *cptr, aClient *sptr, int parc, char *parv[]) {
  463. int ret, i;
  464. char *operclass;
  465. ConfigItem_oper *oper;
  466. if(!IsPerson(sptr) || !MyClient(sptr) || IsOper(sptr))
  467. return CallCmdoverride(ovr, cptr, sptr, parc, parv);
  468. ret = CallCmdoverride(ovr, cptr, sptr, parc, parv);
  469. if(IsOper(sptr)) {
  470. oper = Find_oper(sptr->user->operlogin);
  471. if(oper && oper->operclass)
  472. operclass = oper->operclass;
  473. snprintf(msgbuf, BUFSIZE, "Oper-up by %s (%s@%s) [%s] (operclass: %s)", sptr->name, UserName(sptr), RealHost(sptr), parv[1], operclass);
  474. SendNotice_simple(CHSNO_OPER, 0);
  475. }
  476. return ret;
  477. }
  478. // Added by jesopo
  479. int chansno_hook_tkladd(aClient *cptr, aClient *sptr, aTKline *tkl, int parc, char *parv[]) {
  480. char setby[NICKLEN + USERLEN + HOSTLEN + 6];
  481. char *name;
  482. aClient *setter;
  483. char txt[256];
  484. char set_at[256];
  485. char expire_at[256];
  486. char *timeret;
  487. strncpy(setby, tkl->setby, sizeof(setby));
  488. name = strtok(setby, "!");
  489. setter = find_client(name, NULL);
  490. if(setter == NULL || (!IsMe(setter) && !MyClient(setter)))
  491. {
  492. return HOOK_CONTINUE;
  493. }
  494. switch (tkl->type)
  495. {
  496. case TKL_KILL:
  497. strlcpy(txt, "K:Line", sizeof(txt));
  498. break;
  499. case TKL_ZAP:
  500. strlcpy(txt, "Z:Line", sizeof(txt));
  501. break;
  502. case TKL_KILL | TKL_GLOBAL:
  503. strlcpy(txt, "G:Line", sizeof(txt));
  504. break;
  505. case TKL_ZAP | TKL_GLOBAL:
  506. strlcpy(txt, "Global Z:line", sizeof(txt));
  507. break;
  508. case TKL_SHUN | TKL_GLOBAL:
  509. strlcpy(txt, "Shun", sizeof(txt));
  510. break;
  511. case TKL_NICK | TKL_GLOBAL:
  512. strlcpy(txt, "Global Q:line", sizeof(txt));
  513. break;
  514. case TKL_NICK:
  515. strlcpy(txt, "Q:line", sizeof(txt));
  516. break;
  517. default:
  518. strlcpy(txt, "Unknown *:Line", sizeof(txt));
  519. }
  520. timeret = asctime(gmtime((TS *)&tkl->set_at));
  521. strlcpy(set_at, timeret, sizeof(set_at));
  522. timeret = asctime(gmtime((TS *)&tkl->expire_at));
  523. strlcpy(expire_at, timeret, sizeof(expire_at));
  524. iCstrip(set_at);
  525. iCstrip(expire_at);
  526. if (tkl->expire_at != 0)
  527. {
  528. if (tkl->type & TKL_NICK)
  529. {
  530. if (*tkl->usermask != 'H')
  531. {
  532. snprintf(msgbuf, BUFSIZE, "%s added for %s on %s GMT (from %s to expire at %s GMT: %s)",
  533. txt, tkl->hostmask, set_at, tkl->setby, expire_at, tkl->reason);
  534. }
  535. }
  536. else
  537. {
  538. snprintf(msgbuf, BUFSIZE, "%s added for %s@%s on %s GMT (from %s to expire at %s GMT: %s)",
  539. txt, tkl->usermask, tkl->hostmask, set_at, tkl->setby, expire_at, tkl->reason);
  540. }
  541. }
  542. else
  543. {
  544. if (tkl->type & TKL_NICK)
  545. {
  546. if (*tkl->usermask != 'H')
  547. {
  548. snprintf(msgbuf, BUFSIZE, "Permanent %s added for %s on %s GMT (from %s: %s)",
  549. txt, tkl->hostmask, set_at, tkl->setby, tkl->reason);
  550. }
  551. }
  552. else {
  553. snprintf(msgbuf, BUFSIZE, "Permanent %s added for %s on %s GMT (from %s: %s)",
  554. txt, tkl->usermask, tkl->hostmask, set_at, tkl->setby, tkl->reason);
  555. }
  556. }
  557. SendNotice_simple(CHSNO_TKL_ADD, 0);
  558. return HOOK_CONTINUE;
  559. }