Anope IRC Services  Version 1.8
chanserv.c
Go to the documentation of this file.
1 /* ChanServ functions.
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  *
11  *
12  */
13 
14 /*************************************************************************/
15 
16 #include "services.h"
17 #include "pseudo.h"
18 
19 /*************************************************************************/
20 /* *INDENT-OFF* */
21 
23 
24 static int def_levels[][2] = {
25  { CA_AUTOOP, 5 },
26  { CA_AUTOVOICE, 3 },
27  { CA_AUTODEOP, -1 },
28  { CA_NOJOIN, -2 },
29  { CA_INVITE, 5 },
30  { CA_AKICK, 10 },
33  { CA_UNBAN, 5 },
34  { CA_OPDEOP, 5 },
35  { CA_ACCESS_LIST, 1 },
36  { CA_ACCESS_CHANGE, 10 },
37  { CA_MEMO, 10 },
39  { CA_BADWORDS, 10 },
40  { CA_NOKICK, 1 },
41  { CA_FANTASIA, 3 },
42  { CA_SAY, 5 },
43  { CA_GREET, 5 },
44  { CA_VOICEME, 3 },
45  { CA_VOICE, 5 },
46  { CA_GETKEY, 5 },
47  { CA_AUTOHALFOP, 4 },
48  { CA_AUTOPROTECT, 10 },
49  { CA_OPDEOPME, 5 },
50  { CA_HALFOPME, 4 },
51  { CA_HALFOP, 5 },
52  { CA_PROTECTME, 10 },
54  { CA_KICKME, 5 },
55  { CA_KICK, 5 },
57  { CA_BANME, 5 },
58  { CA_BAN, 5 },
61  { -1 }
62 };
63 
64 
66  { CA_AUTODEOP, "AUTODEOP", CHAN_LEVEL_AUTODEOP },
67  { CA_AUTOHALFOP, "AUTOHALFOP", CHAN_LEVEL_AUTOHALFOP },
68  { CA_AUTOOP, "AUTOOP", CHAN_LEVEL_AUTOOP },
69  { CA_AUTOPROTECT, "", CHAN_LEVEL_AUTOPROTECT },
70  { CA_AUTOVOICE, "AUTOVOICE", CHAN_LEVEL_AUTOVOICE },
71  { CA_NOJOIN, "NOJOIN", CHAN_LEVEL_NOJOIN },
72  { CA_SIGNKICK, "SIGNKICK", CHAN_LEVEL_SIGNKICK },
73  { CA_ACCESS_LIST, "ACC-LIST", CHAN_LEVEL_ACCESS_LIST },
74  { CA_ACCESS_CHANGE, "ACC-CHANGE", CHAN_LEVEL_ACCESS_CHANGE },
75  { CA_AKICK, "AKICK", CHAN_LEVEL_AKICK },
76  { CA_SET, "SET", CHAN_LEVEL_SET },
77  { CA_BAN, "BAN", CHAN_LEVEL_BAN },
78  { CA_BANME, "BANME", CHAN_LEVEL_BANME },
79  { CA_CLEAR, "CLEAR", CHAN_LEVEL_CLEAR },
80  { CA_GETKEY, "GETKEY", CHAN_LEVEL_GETKEY },
81  { CA_HALFOP, "HALFOP", CHAN_LEVEL_HALFOP },
82  { CA_HALFOPME, "HALFOPME", CHAN_LEVEL_HALFOPME },
83  { CA_INFO, "INFO", CHAN_LEVEL_INFO },
84  { CA_KICK, "KICK", CHAN_LEVEL_KICK },
85  { CA_KICKME, "KICKME", CHAN_LEVEL_KICKME },
86  { CA_INVITE, "INVITE", CHAN_LEVEL_INVITE },
87  { CA_OPDEOP, "OPDEOP", CHAN_LEVEL_OPDEOP },
88  { CA_OPDEOPME, "OPDEOPME", CHAN_LEVEL_OPDEOPME },
89  { CA_PROTECT, "", CHAN_LEVEL_PROTECT },
90  { CA_PROTECTME, "", CHAN_LEVEL_PROTECTME },
91  { CA_TOPIC, "TOPIC", CHAN_LEVEL_TOPIC },
92  { CA_UNBAN, "UNBAN", CHAN_LEVEL_UNBAN },
93  { CA_VOICE, "VOICE", CHAN_LEVEL_VOICE },
94  { CA_VOICEME, "VOICEME", CHAN_LEVEL_VOICEME },
95  { CA_MEMO, "MEMO", CHAN_LEVEL_MEMO },
96  { CA_ASSIGN, "ASSIGN", CHAN_LEVEL_ASSIGN },
97  { CA_BADWORDS, "BADWORDS", CHAN_LEVEL_BADWORDS },
98  { CA_FANTASIA, "FANTASIA", CHAN_LEVEL_FANTASIA },
99  { CA_GREET, "GREET", CHAN_LEVEL_GREET },
100  { CA_NOKICK, "NOKICK", CHAN_LEVEL_NOKICK },
101  { CA_SAY, "SAY", CHAN_LEVEL_SAY },
102  { -1 }
103 };
105 
107  { "DEOP", "deop", "-o", CI_OPNOTICE, CA_OPDEOP, CA_OPDEOPME },
108  { "OP", "op", "+o", CI_OPNOTICE, CA_OPDEOP, CA_OPDEOPME },
109  { "DEVOICE", "devoice", "-v", 0, CA_VOICE, CA_VOICEME },
110  { "VOICE", "voice", "+v", 0, CA_VOICE, CA_VOICEME },
111  { "DEHALFOP", "dehalfop", "-h", 0, CA_HALFOP, CA_HALFOPME },
112  { "HALFOP", "halfop", "+h", 0, CA_HALFOP, CA_HALFOPME },
113  { "DEPROTECT", "", "", 0, CA_PROTECT, CA_PROTECTME },
114  { "PROTECT", "", "", 0, CA_PROTECT, CA_PROTECTME },
115  { NULL }
116 };
117 
118 /*************************************************************************/
119 
122 }
123 
124 /* *INDENT-ON* */
125 /*************************************************************************/
126 /*************************************************************************/
127 
128 /* Returns modes for mlock in a nice way. */
129 
130 char *get_mlock_modes(ChannelInfo * ci, int complete)
131 {
132  static char res[BUFSIZE];
133 
134  char *end = res;
135 
136  if (ci->mlock_on || ci->mlock_off) {
137  int n = 0;
138  CBModeInfo *cbmi = cbmodeinfos;
139 
140  if (ci->mlock_on) {
141  *end++ = '+';
142  n++;
143 
144  do {
145  if (ci->mlock_on & cbmi->flag)
146  *end++ = cbmi->mode;
147  } while ((++cbmi)->mode != 0 && ++n < sizeof(res) - 1);
148 
149  cbmi = cbmodeinfos;
150  }
151 
152  if (ci->mlock_off) {
153  *end++ = '-';
154  n++;
155 
156  do {
157  if (ci->mlock_off & cbmi->flag)
158  *end++ = cbmi->mode;
159  } while ((++cbmi)->mode != 0 && ++n < sizeof(res) - 1);
160 
161  cbmi = cbmodeinfos;
162  }
163 
164  if (ci->mlock_on && complete) {
165  do {
166  if (cbmi->csgetvalue && (ci->mlock_on & cbmi->flag)) {
167  char *value = cbmi->csgetvalue(ci);
168 
169  if (value) {
170  *end++ = ' ';
171  while (*value)
172  *end++ = *value++;
173  }
174  }
175  } while ((++cbmi)->mode != 0 && ++n < sizeof(res) - 1);
176  }
177  }
178 
179  *end = 0;
180 
181  return res;
182 }
183 
184 /* Display total number of registered channels and info about each; or, if
185  * a specific channel is given, display information about that channel
186  * (like /msg ChanServ INFO <channel>). If count_only != 0, then only
187  * display the number of registered channels (the channel parameter is
188  * ignored).
189  */
190 
191 void listchans(int count_only, const char *chan)
192 {
193  int count = 0;
194  ChannelInfo *ci;
195  int i;
196 
197  if (count_only) {
198 
199  for (i = 0; i < 256; i++) {
200  for (ci = chanlists[i]; ci; ci = ci->next)
201  count++;
202  }
203  printf("%d channels registered.\n", count);
204 
205  } else if (chan) {
206 
207  struct tm *tm;
208  char buf[BUFSIZE];
209 
210  if (!(ci = cs_findchan(chan))) {
211  printf("Channel %s not registered.\n", chan);
212  return;
213  }
214  if (ci->flags & CI_VERBOTEN) {
215  printf("Channel %s is FORBIDden.\n", ci->name);
216  } else {
217  printf("Information about channel %s:\n", ci->name);
218  printf(" Founder: %s\n", ci->founder->display);
219  printf(" Description: %s\n", ci->desc);
220  tm = localtime(&ci->time_registered);
221  strftime(buf, sizeof(buf),
222  getstring(NULL, STRFTIME_DATE_TIME_FORMAT), tm);
223  printf(" Registered: %s\n", buf);
224  tm = localtime(&ci->last_used);
225  strftime(buf, sizeof(buf),
226  getstring(NULL, STRFTIME_DATE_TIME_FORMAT), tm);
227  printf(" Last used: %s\n", buf);
228  if (ci->last_topic) {
229  printf(" Last topic: %s\n", ci->last_topic);
230  printf(" Topic set by: %s\n", ci->last_topic_setter);
231  }
232  if (ci->url)
233  printf(" URL: %s\n", ci->url);
234  if (ci->email)
235  printf(" E-mail address: %s\n", ci->email);
236  printf(" Options: ");
237  if (!ci->flags) {
238  printf("None\n");
239  } else {
240  int need_comma = 0;
241  static const char commastr[] = ", ";
242  if (ci->flags & CI_PRIVATE) {
243  printf("Private");
244  need_comma = 1;
245  }
246  if (ci->flags & CI_KEEPTOPIC) {
247  printf("%sTopic Retention",
248  need_comma ? commastr : "");
249  need_comma = 1;
250  }
251  if (ci->flags & CI_TOPICLOCK) {
252  printf("%sTopic Lock", need_comma ? commastr : "");
253  need_comma = 1;
254  }
255  if (ci->flags & CI_SECUREOPS) {
256  printf("%sSecure Ops", need_comma ? commastr : "");
257  need_comma = 1;
258  }
259  if (ci->flags & CI_RESTRICTED) {
260  printf("%sRestricted Access",
261  need_comma ? commastr : "");
262  need_comma = 1;
263  }
264  if (ci->flags & CI_SECURE) {
265  printf("%sSecure", need_comma ? commastr : "");
266  need_comma = 1;
267  }
268  if (ci->flags & CI_NO_EXPIRE) {
269  printf("%sNo Expire", need_comma ? commastr : "");
270  need_comma = 1;
271  }
272  printf("\n");
273  }
274  if (ci->mlock_on || ci->mlock_off) {
275  printf(" Mode lock: %s\n", get_mlock_modes(ci, 1));
276  }
277  if (ci->flags & CI_SUSPENDED) {
278  printf
279  ("This channel is currently suspended by %s, reason: %s\n",
280  ci->forbidby,
281  (ci->forbidreason ? ci->forbidreason : "No reason"));
282  }
283  }
284 
285  } else {
286 
287  for (i = 0; i < 256; i++) {
288  for (ci = chanlists[i]; ci; ci = ci->next) {
289  printf(" %s %-20s %s\n",
290  ci->flags & CI_NO_EXPIRE ? "!" : " ", ci->name,
291  ci->flags & CI_VERBOTEN ?
292  "Disallowed (FORBID)" : (ci->flags & CI_SUSPENDED ?
293  "Disallowed (SUSPENDED)" :
294  ci->desc));
295  count++;
296  }
297  }
298  printf("%d channels registered.\n", count);
299 
300  }
301 }
302 
303 /*************************************************************************/
304 
305 /* Return information on memory use. Assumes pointers are valid. */
306 
307 void get_chanserv_stats(long *nrec, long *memuse)
308 {
309  long count = 0, mem = 0;
310  int i, j;
311  ChannelInfo *ci;
312 
313  for (i = 0; i < 256; i++) {
314  for (ci = chanlists[i]; ci; ci = ci->next) {
315  count++;
316  mem += sizeof(*ci);
317  if (ci->desc)
318  mem += strlen(ci->desc) + 1;
319  if (ci->url)
320  mem += strlen(ci->url) + 1;
321  if (ci->email)
322  mem += strlen(ci->email) + 1;
323  mem += ci->accesscount * sizeof(ChanAccess);
324  mem += ci->akickcount * sizeof(AutoKick);
325  for (j = 0; j < ci->akickcount; j++) {
326  if (!(ci->akick[j].flags & AK_ISNICK)
327  && ci->akick[j].u.mask)
328  mem += strlen(ci->akick[j].u.mask) + 1;
329  if (ci->akick[j].reason)
330  mem += strlen(ci->akick[j].reason) + 1;
331  if (ci->akick[j].creator)
332  mem += strlen(ci->akick[j].creator) + 1;
333  }
334  if (ci->mlock_key)
335  mem += strlen(ci->mlock_key) + 1;
336  if (ircd->fmode) {
337  if (ci->mlock_flood)
338  mem += strlen(ci->mlock_flood) + 1;
339  }
340  if (ircd->Lmode) {
341  if (ci->mlock_redirect)
342  mem += strlen(ci->mlock_redirect) + 1;
343  }
344  if (ircd->jmode) {
345  if (ci->mlock_throttle)
346  mem += strlen(ci->mlock_throttle) + 1;
347  }
348  if (ci->last_topic)
349  mem += strlen(ci->last_topic) + 1;
350  if (ci->entry_message)
351  mem += strlen(ci->entry_message) + 1;
352  if (ci->forbidby)
353  mem += strlen(ci->forbidby) + 1;
354  if (ci->forbidreason)
355  mem += strlen(ci->forbidreason) + 1;
356  if (ci->levels)
357  mem += sizeof(*ci->levels) * CA_SIZE;
358  mem += ci->memos.memocount * sizeof(Memo);
359  for (j = 0; j < ci->memos.memocount; j++) {
360  if (ci->memos.memos[j].text)
361  mem += strlen(ci->memos.memos[j].text) + 1;
362  }
363  if (ci->ttb)
364  mem += sizeof(*ci->ttb) * TTB_SIZE;
365  mem += ci->bwcount * sizeof(BadWord);
366  for (j = 0; j < ci->bwcount; j++)
367  if (ci->badwords[j].word)
368  mem += strlen(ci->badwords[j].word) + 1;
369  }
370  }
371  *nrec = count;
372  *memuse = mem;
373 }
374 
375 /*************************************************************************/
376 /*************************************************************************/
377 
378 /* ChanServ initialization. */
379 
380 void cs_init(void)
381 {
383 }
384 
385 /*************************************************************************/
386 
387 /* Main ChanServ routine. */
388 
389 void chanserv(User * u, char *buf)
390 {
391  char *cmd, *s;
392 
393  cmd = strtok(buf, " ");
394 
395  if (!cmd) {
396  return;
397  } else if (stricmp(cmd, "\1PING") == 0) {
398  if (!(s = strtok(NULL, ""))) {
399  s = "";
400  }
401  anope_cmd_ctcp(s_ChanServ, u->nick, "PING %s", s);
402  } else if (skeleton) {
403  notice_lang(s_ChanServ, u, SERVICE_OFFLINE, s_ChanServ);
404  } else {
405  mod_run_cmd(s_ChanServ, u, CHANSERV, cmd);
406  }
407 }
408 
409 /*************************************************************************/
410 
411 /* Load/save data files. */
412 
413 
414 #define SAFE(x) do { \
415  if ((x) < 0) { \
416  if (!forceload) \
417  fatal("Read error on %s", ChanDBName); \
418  failed = 1; \
419  break; \
420  } \
421 } while (0)
422 
423 void load_cs_dbase(void)
424 {
425  dbFILE *f;
426  int ver, i, j, c;
427  ChannelInfo *ci, **last, *prev;
428  int failed = 0;
429 
430  if (!(f = open_db(s_ChanServ, ChanDBName, "r", CHAN_VERSION)))
431  return;
432 
433  ver = get_file_version(f);
434 
435  for (i = 0; i < 256 && !failed; i++) {
436  uint16 tmp16;
437  uint32 tmp32;
438  int n_levels;
439  char *s;
440  NickAlias *na;
441 
442  last = &chanlists[i];
443  prev = NULL;
444  while ((c = getc_db(f)) != 0) {
445  if (c != 1)
446  fatal("Invalid format in %s", ChanDBName);
447  ci = scalloc(sizeof(ChannelInfo), 1);
448  *last = ci;
449  last = &ci->next;
450  ci->prev = prev;
451  prev = ci;
452  SAFE(read_buffer(ci->name, f));
453  SAFE(read_string(&s, f));
454  if (s) {
455  if (ver >= 13)
456  ci->founder = findcore(s);
457  else {
458  na = findnick(s);
459  if (na)
460  ci->founder = na->nc;
461  else
462  ci->founder = NULL;
463  }
464  free(s);
465  } else
466  ci->founder = NULL;
467  if (ver >= 7) {
468  SAFE(read_string(&s, f));
469  if (s) {
470  if (ver >= 13)
471  ci->successor = findcore(s);
472  else {
473  na = findnick(s);
474  if (na)
475  ci->successor = na->nc;
476  else
477  ci->successor = NULL;
478  }
479  free(s);
480  } else
481  ci->successor = NULL;
482  } else {
483  ci->successor = NULL;
484  }
485  SAFE(read_buffer(ci->founderpass, f));
486  SAFE(read_string(&ci->desc, f));
487  if (!ci->desc)
488  ci->desc = sstrdup("");
489  SAFE(read_string(&ci->url, f));
490  SAFE(read_string(&ci->email, f));
491  SAFE(read_int32(&tmp32, f));
492  ci->time_registered = tmp32;
493  SAFE(read_int32(&tmp32, f));
494  ci->last_used = tmp32;
495  SAFE(read_string(&ci->last_topic, f));
497  SAFE(read_int32(&tmp32, f));
498  ci->last_topic_time = tmp32;
499  SAFE(read_int32(&ci->flags, f));
500 
501  /* Leaveops cleanup */
502  if (ver <= 13 && (ci->flags & 0x00000020))
503  ci->flags &= ~0x00000020;
504  /* Temporary flags cleanup */
505  ci->flags &= ~CI_INHABIT;
506 
507  if (ver >= 9) {
508  SAFE(read_string(&ci->forbidby, f));
509  SAFE(read_string(&ci->forbidreason, f));
510  } else {
511  ci->forbidreason = NULL;
512  ci->forbidby = NULL;
513  }
514  if (ver >= 9)
515  SAFE(read_int16(&tmp16, f));
516  else
517  tmp16 = CSDefBantype;
518  ci->bantype = tmp16;
519  SAFE(read_int16(&tmp16, f));
520  n_levels = tmp16;
521  ci->levels = scalloc(2 * CA_SIZE, 1);
522  reset_levels(ci);
523  for (j = 0; j < n_levels; j++) {
524  SAFE(read_int16(&tmp16, f));
525  if (j < CA_SIZE)
526  ci->levels[j] = (int16) tmp16;
527  }
528  /* To avoid levels list silly hacks */
529  if (ver < 10)
530  ci->levels[CA_OPDEOPME] = ci->levels[CA_OPDEOP];
531  if (ver < 11) {
532  ci->levels[CA_KICKME] = ci->levels[CA_OPDEOP];
533  ci->levels[CA_KICK] = ci->levels[CA_OPDEOP];
534  }
535  if (ver < 15) {
536 
537  /* Old Ultimate levels import */
538  /* We now conveniently use PROTECT internals for Ultimate's ADMIN support - ShadowMaster */
539  /* Doh, must of course be done before we change the values were trying to import - ShadowMaster */
540  ci->levels[CA_AUTOPROTECT] = ci->levels[32];
541  ci->levels[CA_PROTECTME] = ci->levels[33];
542  ci->levels[CA_PROTECT] = ci->levels[34];
543 
544  ci->levels[CA_BANME] = ci->levels[CA_OPDEOP];
545  ci->levels[CA_BAN] = ci->levels[CA_OPDEOP];
547 
548 
549  }
550 
551  SAFE(read_int16(&ci->accesscount, f));
552  if (ci->accesscount) {
553  ci->access = scalloc(ci->accesscount, sizeof(ChanAccess));
554  for (j = 0; j < ci->accesscount; j++) {
555  SAFE(read_int16(&ci->access[j].in_use, f));
556  if (ci->access[j].in_use) {
557  SAFE(read_int16(&tmp16, f));
558  ci->access[j].level = (int16) tmp16;
559  SAFE(read_string(&s, f));
560  if (s) {
561  if (ver >= 13)
562  ci->access[j].nc = findcore(s);
563  else {
564  na = findnick(s);
565  if (na)
566  ci->access[j].nc = na->nc;
567  else
568  ci->access[j].nc = NULL;
569  }
570  free(s);
571  }
572  if (ci->access[j].nc == NULL)
573  ci->access[j].in_use = 0;
574  if (ver >= 11) {
575  SAFE(read_int32(&tmp32, f));
576  ci->access[j].last_seen = tmp32;
577  } else {
578  ci->access[j].last_seen = 0; /* Means we have never seen the user */
579  }
580  }
581  }
582  } else {
583  ci->access = NULL;
584  }
585 
586  SAFE(read_int16(&ci->akickcount, f));
587  if (ci->akickcount) {
588  ci->akick = scalloc(ci->akickcount, sizeof(AutoKick));
589  for (j = 0; j < ci->akickcount; j++) {
590  if (ver >= 15) {
591  SAFE(read_int16(&ci->akick[j].flags, f));
592  } else {
593  SAFE(read_int16(&tmp16, f));
594  if (tmp16)
595  ci->akick[j].flags |= AK_USED;
596  }
597  if (ci->akick[j].flags & AK_USED) {
598  if (ver < 15) {
599  SAFE(read_int16(&tmp16, f));
600  if (tmp16)
601  ci->akick[j].flags |= AK_ISNICK;
602  }
603  SAFE(read_string(&s, f));
604  if (ci->akick[j].flags & AK_ISNICK) {
605  if (ver >= 13) {
606  ci->akick[j].u.nc = findcore(s);
607  } else {
608  na = findnick(s);
609  if (na)
610  ci->akick[j].u.nc = na->nc;
611  else
612  ci->akick[j].u.nc = NULL;
613  }
614  if (!ci->akick[j].u.nc)
615  ci->akick[j].flags &= ~AK_USED;
616  free(s);
617  } else {
618  ci->akick[j].u.mask = s;
619  }
620  SAFE(read_string(&s, f));
621  if (ci->akick[j].flags & AK_USED)
622  ci->akick[j].reason = s;
623  else if (s)
624  free(s);
625  if (ver >= 9) {
626  SAFE(read_string(&s, f));
627  if (ci->akick[j].flags & AK_USED) {
628  ci->akick[j].creator = s;
629  } else if (s) {
630  free(s);
631  }
632  SAFE(read_int32(&tmp32, f));
633  if (ci->akick[j].flags & AK_USED)
634  ci->akick[j].addtime = tmp32;
635  } else {
636  ci->akick[j].creator = NULL;
637  ci->akick[j].addtime = 0;
638  }
639  }
640 
641  /* Bugfix */
642  if ((ver == 15) && ci->akick[j].flags > 8) {
643  ci->akick[j].flags = 0;
644  ci->akick[j].u.nc = NULL;
645  ci->akick[j].u.nc = NULL;
646  ci->akick[j].addtime = 0;
647  ci->akick[j].creator = NULL;
648  ci->akick[j].reason = NULL;
649  }
650  }
651  } else {
652  ci->akick = NULL;
653  }
654 
655  if (ver >= 10) {
656  SAFE(read_int32(&ci->mlock_on, f));
657  SAFE(read_int32(&ci->mlock_off, f));
658  } else {
659  SAFE(read_int16(&tmp16, f));
660  ci->mlock_on = tmp16;
661  SAFE(read_int16(&tmp16, f));
662  ci->mlock_off = tmp16;
663  }
664  SAFE(read_int32(&ci->mlock_limit, f));
665  SAFE(read_string(&ci->mlock_key, f));
666  if (ver >= 10) {
667  SAFE(read_string(&ci->mlock_flood, f));
668  SAFE(read_string(&ci->mlock_redirect, f));
669  /* We added support for channelmode +j tracking,
670  * however unless for some other reason we need to
671  * change the DB format, it is being saved to DB. ~ Viper
672  SAFE(read_string(&ci->mlock_throttle, f));*/
673  }
674 
675  SAFE(read_int16(&tmp16, f));
676  ci->memos.memocount = (int16) tmp16;
677  SAFE(read_int16(&tmp16, f));
678  ci->memos.memomax = (int16) tmp16;
679  if (ci->memos.memocount) {
680  Memo *memos;
681  memos = scalloc(sizeof(Memo) * ci->memos.memocount, 1);
682  ci->memos.memos = memos;
683  for (j = 0; j < ci->memos.memocount; j++, memos++) {
684  SAFE(read_int32(&memos->number, f));
685  SAFE(read_int16(&memos->flags, f));
686  SAFE(read_int32(&tmp32, f));
687  memos->time = tmp32;
688  SAFE(read_buffer(memos->sender, f));
689  SAFE(read_string(&memos->text, f));
690  memos->moduleData = NULL;
691  }
692  }
693 
694  SAFE(read_string(&ci->entry_message, f));
695 
696  ci->c = NULL;
697 
698  /* Some cleanup */
699  if (ver <= 11) {
700  /* Cleanup: Founder must be != than successor */
701  if (!(ci->flags & CI_VERBOTEN)
702  && ci->successor == ci->founder) {
703  alog("Warning: founder and successor of %s are equal. Cleaning up.", ci->name);
704  ci->successor = NULL;
705  }
706  }
707 
708  /* BotServ options */
709 
710  if (ver >= 8) {
711  int n_ttb;
712 
713  SAFE(read_string(&s, f));
714  if (s) {
715  ci->bi = findbot(s);
716  free(s);
717  } else
718  ci->bi = NULL;
719 
720  SAFE(read_int32(&tmp32, f));
721  ci->botflags = tmp32;
722  SAFE(read_int16(&tmp16, f));
723  n_ttb = tmp16;
724  ci->ttb = scalloc(2 * TTB_SIZE, 1);
725  for (j = 0; j < n_ttb; j++) {
726  SAFE(read_int16(&tmp16, f));
727  if (j < TTB_SIZE)
728  ci->ttb[j] = (int16) tmp16;
729  }
730  for (j = n_ttb; j < TTB_SIZE; j++)
731  ci->ttb[j] = 0;
732  SAFE(read_int16(&tmp16, f));
733  ci->capsmin = tmp16;
734  SAFE(read_int16(&tmp16, f));
735  ci->capspercent = tmp16;
736  SAFE(read_int16(&tmp16, f));
737  ci->floodlines = tmp16;
738  SAFE(read_int16(&tmp16, f));
739  ci->floodsecs = tmp16;
740  SAFE(read_int16(&tmp16, f));
741  ci->repeattimes = tmp16;
742 
743  SAFE(read_int16(&ci->bwcount, f));
744  if (ci->bwcount) {
745  ci->badwords = scalloc(ci->bwcount, sizeof(BadWord));
746  for (j = 0; j < ci->bwcount; j++) {
747  SAFE(read_int16(&ci->badwords[j].in_use, f));
748  if (ci->badwords[j].in_use) {
749  SAFE(read_string(&ci->badwords[j].word, f));
750  SAFE(read_int16(&ci->badwords[j].type, f));
751  }
752  }
753  } else {
754  ci->badwords = NULL;
755  }
756  } else {
757  ci->bi = NULL;
758  ci->botflags = 0;
759  ci->ttb = scalloc(2 * TTB_SIZE, 1);
760  for (j = 0; j < TTB_SIZE; j++)
761  ci->ttb[j] = 0;
762  ci->bwcount = 0;
763  ci->badwords = NULL;
764  }
765 
766  } /* while (getc_db(f) != 0) */
767 
768  *last = NULL;
769 
770  } /* for (i) */
771 
772  close_db(f);
773 
774  /* Check for non-forbidden channels with no founder.
775  Makes also other essential tasks. */
776  for (i = 0; i < 256; i++) {
777  ChannelInfo *next;
778  for (ci = chanlists[i]; ci; ci = next) {
779  next = ci->next;
780  if (!(ci->flags & CI_VERBOTEN) && !ci->founder) {
781  alog("%s: database load: Deleting founderless channel %s",
782  s_ChanServ, ci->name);
783  delchan(ci);
784  continue;
785  }
786  if (ver < 13) {
787  ChanAccess *access, *access2;
788  AutoKick *akick, *akick2;
789  int k;
790 
791  if (ci->flags & CI_VERBOTEN)
792  continue;
793  /* Need to regenerate the channel count for the founder */
794  ci->founder->channelcount++;
795  /* Check for eventual double entries in access/akick lists. */
796  for (j = 0, access = ci->access; j < ci->accesscount;
797  j++, access++) {
798  if (!access->in_use)
799  continue;
800  for (k = 0, access2 = ci->access; k < j;
801  k++, access2++) {
802  if (access2->in_use && access2->nc == access->nc) {
803  alog("%s: deleting %s channel access entry of %s because it is already in the list (this is OK).", s_ChanServ, access->nc->display, ci->name);
804  memset(access, 0, sizeof(ChanAccess));
805  break;
806  }
807  }
808  }
809  for (j = 0, akick = ci->akick; j < ci->akickcount;
810  j++, akick++) {
811  if (!(akick->flags & AK_USED)
812  || !(akick->flags & AK_ISNICK))
813  continue;
814  for (k = 0, akick2 = ci->akick; k < j; k++, akick2++) {
815  if ((akick2->flags & AK_USED)
816  && (akick2->flags & AK_ISNICK)
817  && akick2->u.nc == akick->u.nc) {
818  alog("%s: deleting %s channel akick entry of %s because it is already in the list (this is OK).", s_ChanServ, akick->u.nc->display, ci->name);
819  if (akick->reason)
820  free(akick->reason);
821  if (akick->creator)
822  free(akick->creator);
823  memset(akick, 0, sizeof(AutoKick));
824  break;
825  }
826  }
827  }
828  }
829  }
830  }
831 }
832 
833 #undef SAFE
834 
835 /*************************************************************************/
836 
837 #define SAFE(x) do { \
838  if ((x) < 0) { \
839  restore_db(f); \
840  log_perror("Write error on %s", ChanDBName); \
841  if (time(NULL) - lastwarn > WarningTimeout) { \
842  anope_cmd_global(NULL, "Write error on %s: %s", ChanDBName, \
843  strerror(errno)); \
844  lastwarn = time(NULL); \
845  } \
846  return; \
847  } \
848 } while (0)
849 
850 void save_cs_dbase(void)
851 {
852  dbFILE *f;
853  int i, j;
854  ChannelInfo *ci;
855  Memo *memos;
856  static time_t lastwarn = 0;
857 
858  if (!(f = open_db(s_ChanServ, ChanDBName, "w", CHAN_VERSION)))
859  return;
860 
861  for (i = 0; i < 256; i++) {
862  int16 tmp16;
863 
864  for (ci = chanlists[i]; ci; ci = ci->next) {
865  SAFE(write_int8(1, f));
866  SAFE(write_buffer(ci->name, f));
867  if (ci->founder)
868  SAFE(write_string(ci->founder->display, f));
869  else
870  SAFE(write_string(NULL, f));
871  if (ci->successor)
873  else
874  SAFE(write_string(NULL, f));
875  SAFE(write_buffer(ci->founderpass, f));
876  SAFE(write_string(ci->desc, f));
877  SAFE(write_string(ci->url, f));
878  SAFE(write_string(ci->email, f));
880  SAFE(write_int32(ci->last_used, f));
881  SAFE(write_string(ci->last_topic, f));
884  SAFE(write_int32(ci->flags, f));
885  SAFE(write_string(ci->forbidby, f));
886  SAFE(write_string(ci->forbidreason, f));
887  SAFE(write_int16(ci->bantype, f));
888 
889  tmp16 = CA_SIZE;
890  SAFE(write_int16(tmp16, f));
891  for (j = 0; j < CA_SIZE; j++)
892  SAFE(write_int16(ci->levels[j], f));
893 
894  SAFE(write_int16(ci->accesscount, f));
895  for (j = 0; j < ci->accesscount; j++) {
896  SAFE(write_int16(ci->access[j].in_use, f));
897  if (ci->access[j].in_use) {
898  SAFE(write_int16(ci->access[j].level, f));
899  SAFE(write_string(ci->access[j].nc->display, f));
900  SAFE(write_int32(ci->access[j].last_seen, f));
901  }
902  }
903 
904  SAFE(write_int16(ci->akickcount, f));
905  for (j = 0; j < ci->akickcount; j++) {
906  SAFE(write_int16(ci->akick[j].flags, f));
907  if (ci->akick[j].flags & AK_USED) {
908  if (ci->akick[j].flags & AK_ISNICK)
909  SAFE(write_string(ci->akick[j].u.nc->display, f));
910  else
911  SAFE(write_string(ci->akick[j].u.mask, f));
912  SAFE(write_string(ci->akick[j].reason, f));
913  SAFE(write_string(ci->akick[j].creator, f));
914  SAFE(write_int32(ci->akick[j].addtime, f));
915  }
916  }
917 
918  SAFE(write_int32(ci->mlock_on, f));
919  SAFE(write_int32(ci->mlock_off, f));
920  SAFE(write_int32(ci->mlock_limit, f));
921  SAFE(write_string(ci->mlock_key, f));
922  SAFE(write_string(ci->mlock_flood, f));
924  /* Current DB format does not hold +j yet.. ~ Viper
925  SAFE(write_string(ci->mlock_throttle, f));*/
926  SAFE(write_int16(ci->memos.memocount, f));
927  SAFE(write_int16(ci->memos.memomax, f));
928  memos = ci->memos.memos;
929  for (j = 0; j < ci->memos.memocount; j++, memos++) {
930  SAFE(write_int32(memos->number, f));
931  SAFE(write_int16(memos->flags, f));
932  SAFE(write_int32(memos->time, f));
933  SAFE(write_buffer(memos->sender, f));
934  SAFE(write_string(memos->text, f));
935  }
936 
938 
939  if (ci->bi)
940  SAFE(write_string(ci->bi->nick, f));
941  else
942  SAFE(write_string(NULL, f));
943 
944  SAFE(write_int32(ci->botflags, f));
945 
946  tmp16 = TTB_SIZE;
947  SAFE(write_int16(tmp16, f));
948  for (j = 0; j < TTB_SIZE; j++)
949  SAFE(write_int16(ci->ttb[j], f));
950 
951  SAFE(write_int16(ci->capsmin, f));
952  SAFE(write_int16(ci->capspercent, f));
953  SAFE(write_int16(ci->floodlines, f));
954  SAFE(write_int16(ci->floodsecs, f));
955  SAFE(write_int16(ci->repeattimes, f));
956 
957  SAFE(write_int16(ci->bwcount, f));
958  for (j = 0; j < ci->bwcount; j++) {
959  SAFE(write_int16(ci->badwords[j].in_use, f));
960  if (ci->badwords[j].in_use) {
961  SAFE(write_string(ci->badwords[j].word, f));
962  SAFE(write_int16(ci->badwords[j].type, f));
963  }
964  }
965  } /* for (chanlists[i]) */
966 
967  SAFE(write_int8(0, f));
968 
969  } /* for (i) */
970 
971  close_db(f);
972 
973 }
974 
975 #undef SAFE
976 
977 /*************************************************************************/
978 
980 {
981 #ifdef USE_RDB
982  int i;
983  ChannelInfo *ci;
984 
985  if (!rdb_open())
986  return;
987 
988  if (rdb_tag_table("anope_cs_info") == 0) {
989  alog("Unable to tag table 'anope_cs_info' - ChanServ RDB save failed.");
990  rdb_close();
991  return;
992  }
993  if (rdb_tag_table("anope_cs_access") == 0) {
994  alog("Unable to tag table 'anope_cs_access' - ChanServ RDB save failed.");
995  rdb_close();
996  return;
997  }
998  if (rdb_tag_table("anope_cs_levels") == 0) {
999  alog("Unable to tag table 'anope_cs_levels' - ChanServ RDB save failed.");
1000  rdb_close();
1001  return;
1002  }
1003  if (rdb_tag_table("anope_cs_akicks") == 0) {
1004  alog("Unable to tag table 'anope_cs_akicks' - ChanServ RDB save failed.");
1005  rdb_close();
1006  return;
1007  }
1008  if (rdb_tag_table("anope_cs_badwords") == 0) {
1009  alog("Unable to tag table 'anope_cs_badwords' - ChanServ RDB save failed.");
1010  rdb_close();
1011  return;
1012  }
1013  if (rdb_tag_table("anope_cs_ttb") == 0) {
1014  alog("Unable to tag table 'anope_cs_ttb' - ChanServ RDB save failed.");
1015  rdb_close();
1016  return;
1017  }
1018  if (rdb_tag_table_where("anope_ms_info", "serv='CHAN'") == 0) {
1019  alog("Unable to tag table 'anope_ms_info' - ChanServ RDB save failed.");
1020  rdb_close();
1021  return;
1022  }
1023 
1024  for (i = 0; i < 256; i++) {
1025  for (ci = chanlists[i]; ci; ci = ci->next) {
1026  if (rdb_save_cs_info(ci) == 0) {
1027  alog("Unable to save ChanInfo for %s - ChanServ RDB save failed.", ci->name);
1028  rdb_close();
1029  return;
1030  }
1031  } /* for (chanlists[i]) */
1032  } /* for (i) */
1033 
1034  if (rdb_clean_table("anope_cs_info") == 0) {
1035  alog("Unable to clean table 'anope_cs_info' - ChanServ RDB save failed.");
1036  rdb_close();
1037  return;
1038  }
1039  if (rdb_clean_table("anope_cs_access") == 0) {
1040  alog("Unable to clean table 'anope_cs_access' - ChanServ RDB save failed.");
1041  rdb_close();
1042  return;
1043  }
1044  if (rdb_clean_table("anope_cs_levels") == 0) {
1045  alog("Unable to clean table 'anope_cs_levels' - ChanServ RDB save failed.");
1046  rdb_close();
1047  return;
1048  }
1049  if (rdb_clean_table("anope_cs_akicks") == 0) {
1050  alog("Unable to clean table 'anope_cs_akicks' - ChanServ RDB save failed.");
1051  rdb_close();
1052  return;
1053  }
1054  if (rdb_clean_table("anope_cs_badwords") == 0) {
1055  alog("Unable to clean table 'anope_cs_badwords' - ChanServ RDB save failed.");
1056  rdb_close();
1057  return;
1058  }
1059  if (rdb_clean_table("anope_cs_ttb") == 0) {
1060  alog("Unable to clean table 'anope_cs_ttb' - ChanServ RDB save failed.");
1061  rdb_close();
1062  return;
1063  }
1064  if (rdb_clean_table_where("anope_ms_info", "serv='CHAN'") == 0)
1065  alog("Unable to clean table 'anope_ms_info' - ChanServ RDB save failed.");
1066 
1067  rdb_close();
1068 #endif
1069 }
1070 
1071 /*************************************************************************/
1072 
1073 /* Check the current modes on a channel; if they conflict with a mode lock,
1074  * fix them.
1075  *
1076  * Also check to make sure that every mode set or unset is allowed by the
1077  * defcon mlock settings. This is more important than any normal channel
1078  * mlock'd mode. --gdex (21-04-07)
1079  */
1080 
1082 {
1083  char modebuf[64], argbuf[BUFSIZE], *end = modebuf, *end2 = argbuf;
1084  uint32 modes = 0;
1085  ChannelInfo *ci;
1086  CBModeInfo *cbmi = NULL;
1087  CBMode *cbm = NULL;
1088  boolean DefConOn = DefConLevel != 5;
1089 
1090  if (!c) {
1091  if (debug) {
1092  alog("debug: check_modes called with NULL values");
1093  }
1094  return;
1095  }
1096 
1097  if (c->bouncy_modes)
1098  return;
1099 
1100  /* Check for mode bouncing */
1101  if (c->server_modecount >= 3 && c->chanserv_modecount >= 3) {
1102  anope_cmd_global(NULL,
1103  "Warning: unable to set modes on channel %s. "
1104  "Are your servers' U:lines configured correctly?",
1105  c->name);
1106  alog("%s: Bouncy modes on channel %s", s_ChanServ, c->name);
1107  c->bouncy_modes = 1;
1108  return;
1109  }
1110 
1111  if (c->chanserv_modetime != time(NULL)) {
1112  c->chanserv_modecount = 0;
1113  c->chanserv_modetime = time(NULL);
1114  }
1115  c->chanserv_modecount++;
1116 
1117  /* Check if the channel is registered; if not remove mode -r */
1118  if (!(ci = c->ci)) {
1119  if (ircd->regmode) {
1120  if (c->mode & ircd->regmode) {
1121  c->mode &= ~ircd->regmode;
1122  anope_cmd_mode(whosends(ci), c->name, "-r");
1123  }
1124  }
1125  /* Channels that are not regged also need the defcon modes.. ~ Viper */
1126  /* return; */
1127  }
1128 
1129  /* Initialize the modes-var to set all modes not set yet but which should
1130  * be set as by mlock and defcon.
1131  */
1132  if (ci)
1133  modes = ~c->mode & ci->mlock_on;
1134  if (DefConOn && DefConModesSet)
1135  modes |= (~c->mode & DefConModesOn);
1136 
1137  /* Initialize the buffers */
1138  *end++ = '+';
1139  cbmi = cbmodeinfos;
1140 
1141  do {
1142  if (modes & cbmi->flag) {
1143  *end++ = cbmi->mode;
1144  c->mode |= cbmi->flag;
1145 
1146  /* Add the eventual parameter and modify the Channel structure */
1147  if (cbmi->getvalue && cbmi->csgetvalue) {
1148  char *value;
1149  /* Check if it's a defcon or mlock mode */
1150  if (DefConOn && DefConModesOn & cbmi->flag)
1151  value = cbmi->csgetvalue(&DefConModesCI);
1152  else if (ci)
1153  value = cbmi->csgetvalue(ci);
1154  else {
1155  value = NULL;
1156  if (debug)
1157  alog ("Warning: setting modes with unknown origin.");
1158  }
1159 
1160  cbm = &cbmodes[(int) cbmi->mode];
1161  cbm->setvalue(c, value);
1162 
1163  if (value) {
1164  *end2++ = ' ';
1165  while (*value)
1166  *end2++ = *value++;
1167  }
1168  }
1169  } else if (cbmi->getvalue && cbmi->csgetvalue
1170  && ((ci && (ci->mlock_on & cbmi->flag))
1171  || (DefConOn && DefConModesOn & cbmi->flag))
1172  && (c->mode & cbmi->flag)) {
1173  char *value = cbmi->getvalue(c);
1174  char *csvalue;
1175 
1176  /* Check if it's a defcon or mlock mode */
1177  if (DefConOn && DefConModesOn & cbmi->flag)
1178  csvalue = cbmi->csgetvalue(&DefConModesCI);
1179  else if (ci)
1180  csvalue = cbmi->csgetvalue(ci);
1181  else {
1182  csvalue = NULL;
1183  if (debug)
1184  alog ("Warning: setting modes with unknown origin.");
1185  }
1186 
1187  /* Lock and actual values don't match, so fix the mode */
1188  if (value && csvalue && strcmp(value, csvalue)) {
1189  *end++ = cbmi->mode;
1190 
1191  cbm = &cbmodes[(int) cbmi->mode];
1192  cbm->setvalue(c, csvalue);
1193 
1194  *end2++ = ' ';
1195  while (*csvalue)
1196  *end2++ = *csvalue++;
1197  }
1198  }
1199  } while ((++cbmi)->mode != 0);
1200 
1201  if (*(end - 1) == '+')
1202  end--;
1203 
1204  modes = 0;
1205  if (ci) {
1206  modes = c->mode & ci->mlock_off;
1207  /* Make sure we don't remove a mode just set by defcon.. ~ Viper */
1208  if (DefConOn && DefConModesSet)
1209  modes &= ~(modes & DefConModesOn);
1210  }
1211  if (DefConOn && DefConModesSet)
1212  modes |= c->mode & DefConModesOff;
1213 
1214  if (modes) {
1215  *end++ = '-';
1216  cbmi = cbmodeinfos;
1217 
1218  do {
1219  if (modes & cbmi->flag) {
1220  *end++ = cbmi->mode;
1221  c->mode &= ~cbmi->flag;
1222 
1223  /* Add the eventual parameter and clean up the Channel structure */
1224  if (cbmi->getvalue) {
1225  cbm = &cbmodes[(int) cbmi->mode];
1226 
1227  if (!(cbm->flags & CBM_MINUS_NO_ARG)) {
1228  char *value = cbmi->getvalue(c);
1229 
1230  if (value) {
1231  *end2++ = ' ';
1232  while (*value)
1233  *end2++ = *value++;
1234  }
1235  }
1236 
1237  cbm->setvalue(c, NULL);
1238  }
1239  }
1240  } while ((++cbmi)->mode != 0);
1241  }
1242 
1243  if (end == modebuf)
1244  return;
1245 
1246  *end = 0;
1247  *end2 = 0;
1248 
1249  anope_cmd_mode((ci ? whosends(ci) : s_OperServ), c->name, "%s%s", modebuf,
1250  (end2 == argbuf ? "" : argbuf));
1251 }
1252 
1253 /*************************************************************************/
1254 
1255 int check_valid_admin(User * user, Channel * chan, int servermode)
1256 {
1257  if (!chan || !chan->ci)
1258  return 1;
1259 
1260  if (!ircd->admin) {
1261  return 0;
1262  }
1263 
1264  /* They will be kicked; no need to deop, no need to update our internal struct too */
1265  if (chan->ci->flags & CI_VERBOTEN)
1266  return 0;
1267 
1268  if (servermode && !check_access(user, chan->ci, CA_AUTOPROTECT)) {
1269  notice_lang(s_ChanServ, user, CHAN_IS_REGISTERED, s_ChanServ);
1270  anope_cmd_mode(whosends(chan->ci), chan->name, "%s %s",
1271  ircd->adminunset, GET_USER(user));
1272  return 0;
1273  }
1274 
1275  if (check_access(user, chan->ci, CA_AUTODEOP)) {
1276  anope_cmd_mode(whosends(chan->ci), chan->name, "%s %s",
1277  ircd->adminunset, GET_USER(user));
1278  return 0;
1279  }
1280 
1281  return 1;
1282 }
1283 
1284 /*************************************************************************/
1285 
1286 /* Check whether a user is allowed to be opped on a channel; if they
1287  * aren't, deop them. If serverop is 1, the +o was done by a server.
1288  * Return 1 if the user is allowed to be opped, 0 otherwise. */
1289 
1290 int check_valid_op(User * user, Channel * chan, int servermode)
1291 {
1292  char *tmp;
1293  if (!chan || !chan->ci)
1294  return 1;
1295 
1296  /* They will be kicked; no need to deop, no need to update our internal struct too */
1297  if (chan->ci->flags & CI_VERBOTEN)
1298  return 0;
1299 
1300  if (servermode && !check_access(user, chan->ci, CA_AUTOOP)) {
1301  notice_lang(s_ChanServ, user, CHAN_IS_REGISTERED, s_ChanServ);
1302  if (ircd->halfop) {
1303  if (ircd->owner && ircd->protect) {
1304  if (check_access(user, chan->ci, CA_AUTOHALFOP)) {
1306  anope_cmd_mode(whosends(chan->ci), chan->name,
1307  "%so%s %s %s %s", ircd->adminunset,
1308  tmp, GET_USER(user),
1309  GET_USER(user), GET_USER(user));
1310  free(tmp);
1311  } else {
1313  anope_cmd_mode(whosends(chan->ci), chan->name,
1314  "%sho%s %s %s %s %s",
1315  ircd->adminunset, tmp,
1316  GET_USER(user), GET_USER(user), GET_USER(user),
1317  GET_USER(user));
1318  free(tmp);
1319  }
1320  } else if (!ircd->owner && ircd->protect) {
1321  if (check_access(user, chan->ci, CA_AUTOHALFOP)) {
1322  anope_cmd_mode(whosends(chan->ci), chan->name,
1323  "%so %s %s", ircd->adminunset,
1324  GET_USER(user), GET_USER(user));
1325  } else {
1326  anope_cmd_mode(whosends(chan->ci), chan->name,
1327  "%soh %s %s %s", ircd->adminunset,
1328  GET_USER(user), GET_USER(user), GET_USER(user));
1329  }
1330  } else {
1331  if (check_access(user, chan->ci, CA_AUTOHALFOP)) {
1332  anope_cmd_mode(whosends(chan->ci), chan->name, "-o %s",
1333  GET_USER(user));
1334  } else {
1335  anope_cmd_mode(whosends(chan->ci), chan->name,
1336  "-ho %s %s", GET_USER(user), GET_USER(user));
1337  }
1338  }
1339  } else {
1340  anope_cmd_mode(whosends(chan->ci), chan->name, "-o %s",
1341  GET_USER(user));
1342  }
1343  return 0;
1344  }
1345 
1346  if (check_access(user, chan->ci, CA_AUTODEOP)) {
1347  if (ircd->halfop) {
1348  if (ircd->owner && ircd->protect) {
1350  anope_cmd_mode(whosends(chan->ci), chan->name,
1351  "%sho%s %s %s %s %s", ircd->adminunset,
1352  tmp, GET_USER(user), GET_USER(user),
1353  GET_USER(user), GET_USER(user));
1354  free(tmp);
1355  } else {
1356  anope_cmd_mode(whosends(chan->ci), chan->name, "-ho %s %s",
1357  GET_USER(user), GET_USER(user));
1358  }
1359  } else {
1360  anope_cmd_mode(whosends(chan->ci), chan->name, "-o %s",
1361  GET_USER(user));
1362  }
1363  return 0;
1364  }
1365 
1366  return 1;
1367 }
1368 
1369 /*************************************************************************/
1370 
1371 /* Check whether a user should be opped on a channel, and if so, do it.
1372  * Return 1 if the user was opped, 0 otherwise. (Updates the channel's
1373  * last used time if the user was opped.) */
1374 
1375 int check_should_op(User * user, char *chan)
1376 {
1377  ChannelInfo *ci = cs_findchan(chan);
1378 
1379  if (!ci || (ci->flags & CI_VERBOTEN) || *chan == '+')
1380  return 0;
1381 
1382  if ((ci->flags & CI_SECURE) && !nick_identified(user))
1383  return 0;
1384 
1385  if (check_access(user, ci, CA_AUTOOP)) {
1386  anope_cmd_mode(whosends(ci), chan, "+o %s", GET_USER(user));
1387  return 1;
1388  }
1389 
1390  return 0;
1391 }
1392 
1393 /*************************************************************************/
1394 
1395 /* Check whether a user should be voiced on a channel, and if so, do it.
1396  * Return 1 if the user was voiced, 0 otherwise. */
1397 
1398 int check_should_voice(User * user, char *chan)
1399 {
1400  ChannelInfo *ci = cs_findchan(chan);
1401 
1402  if (!ci || (ci->flags & CI_VERBOTEN) || *chan == '+')
1403  return 0;
1404 
1405  if ((ci->flags & CI_SECURE) && !nick_identified(user))
1406  return 0;
1407 
1408  if (check_access(user, ci, CA_AUTOVOICE)) {
1409  anope_cmd_mode(whosends(ci), chan, "+v %s", GET_USER(user));
1410  return 1;
1411  }
1412 
1413  return 0;
1414 }
1415 
1416 /*************************************************************************/
1417 
1418 int check_should_halfop(User * user, char *chan)
1419 {
1420  ChannelInfo *ci = cs_findchan(chan);
1421 
1422  if (!ci || (ci->flags & CI_VERBOTEN) || *chan == '+')
1423  return 0;
1424 
1425  if (check_access(user, ci, CA_AUTOHALFOP)) {
1426  anope_cmd_mode(whosends(ci), chan, "+h %s", GET_USER(user));
1427  return 1;
1428  }
1429 
1430  return 0;
1431 }
1432 
1433 /*************************************************************************/
1434 
1435 int check_should_owner(User * user, char *chan)
1436 {
1437  char *tmp;
1438  ChannelInfo *ci = cs_findchan(chan);
1439 
1440  if (!ci || (ci->flags & CI_VERBOTEN) || *chan == '+')
1441  return 0;
1442 
1443  if (((ci->flags & CI_SECUREFOUNDER) && is_real_founder(user, ci))
1444  || (!(ci->flags & CI_SECUREFOUNDER) && is_founder(user, ci))) {
1445  tmp = stripModePrefix(ircd->ownerset);
1446  anope_cmd_mode(whosends(ci), chan, "+o%s %s %s", tmp, GET_USER(user),
1447  GET_USER(user));
1448  free(tmp);
1449  return 1;
1450  }
1451 
1452  return 0;
1453 }
1454 
1455 /*************************************************************************/
1456 
1457 int check_should_protect(User * user, char *chan)
1458 {
1459  char *tmp;
1460  ChannelInfo *ci = cs_findchan(chan);
1461 
1462  if (!ci || (ci->flags & CI_VERBOTEN) || *chan == '+')
1463  return 0;
1464 
1465  if (check_access(user, ci, CA_AUTOPROTECT)) {
1466  tmp = stripModePrefix(ircd->adminset);
1467  anope_cmd_mode(whosends(ci), chan, "+o%s %s %s", tmp, GET_USER(user),
1468  GET_USER(user));
1469  free(tmp);
1470  return 1;
1471  }
1472 
1473  return 0;
1474 }
1475 
1476 /*************************************************************************/
1477 
1478 /* Tiny helper routine to get ChanServ out of a channel after it went in. */
1479 
1480 static void timeout_leave(Timeout * to)
1481 {
1482  char *chan = to->data;
1483  ChannelInfo *ci = cs_findchan(chan);
1484 
1485  if (ci) /* Check cos the channel may be dropped in the meantime */
1486  ci->flags &= ~CI_INHABIT;
1487 
1488  anope_cmd_part(s_ChanServ, chan, NULL);
1489  free(to->data);
1490 }
1491 
1492 
1493 /* Check whether a user is permitted to be on a channel. If so, return 0;
1494  * else, kickban the user with an appropriate message (could be either
1495  * AKICK or restricted access) and return 1. Note that this is called
1496  * _before_ the user is added to internal channel lists (so do_kick() is
1497  * not called). The channel TS must be given for a new channel.
1498  */
1499 
1500 int check_kick(User * user, char *chan, time_t chants)
1501 {
1502  ChannelInfo *ci = cs_findchan(chan);
1503  Channel *c;
1504  AutoKick *akick;
1505  int i, set_modes = 0;
1506  NickCore *nc;
1507  char *av[4];
1508  int ac;
1509  char buf[BUFSIZE];
1510  char mask[BUFSIZE];
1511  const char *reason;
1512  Timeout *t;
1513 
1514  if (!ci)
1515  return 0;
1516 
1517  if (user->isSuperAdmin == 1)
1518  return 0;
1519 
1520  /* We don't enforce services restrictions on clients on ulined services
1521  * as this will likely lead to kick/rejoin floods. ~ Viper */
1522  if (is_ulined(user->server->name)) {
1523  return 0;
1524  }
1525 
1526  if (ci->flags & CI_VERBOTEN) {
1527  get_idealban(ci, user, mask, sizeof(mask));
1528  reason =
1529  ci->forbidreason ? ci->forbidreason : getstring(user->na,
1530  CHAN_MAY_NOT_BE_USED);
1531  set_modes = 1;
1532  goto kick;
1533  }
1534 
1535  if (ci->flags & CI_SUSPENDED) {
1536  get_idealban(ci, user, mask, sizeof(mask));
1537  reason =
1538  ci->forbidreason ? ci->forbidreason : getstring(user->na,
1539  CHAN_MAY_NOT_BE_USED);
1540  set_modes = 1;
1541  goto kick;
1542  }
1543 
1544  if (nick_recognized(user))
1545  nc = user->na->nc;
1546  else
1547  nc = NULL;
1548 
1549  /*
1550  * Before we go through akick lists, see if they're excepted FIRST
1551  * We cannot kick excempted users that are akicked or not on the channel access list
1552  * as that will start services <-> server wars which ends up as a DoS against services.
1553  *
1554  * UltimateIRCd 3.x at least informs channel staff when a joining user is matching an exempt.
1555  */
1556  if (ircd->except && is_excepted(ci, user) == 1) {
1557  return 0;
1558  }
1559 
1560  for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
1561  if (!(akick->flags & AK_USED))
1562  continue;
1563  if ((akick->flags & AK_ISNICK && akick->u.nc == nc)
1564  || (!(akick->flags & AK_ISNICK)
1565  && match_usermask(akick->u.mask, user))) {
1566  if (debug >= 2)
1567  alog("debug: %s matched akick %s", user->nick,
1568  (akick->flags & AK_ISNICK) ? akick->u.nc->
1569  display : akick->u.mask);
1570  if (akick->flags & AK_ISNICK)
1571  get_idealban(ci, user, mask, sizeof(mask));
1572  else
1573  strscpy(mask, akick->u.mask, sizeof(mask));
1574  reason = akick->reason ? akick->reason : CSAutokickReason;
1575  goto kick;
1576  }
1577  }
1578 
1579  if (check_access(user, ci, CA_NOJOIN)) {
1580  get_idealban(ci, user, mask, sizeof(mask));
1581  reason = getstring(user->na, CHAN_NOT_ALLOWED_TO_JOIN);
1582  goto kick;
1583  }
1584 
1585  return 0;
1586 
1587  kick:
1588  if (debug)
1589  alog("debug: channel: AutoKicking %s!%s@%s from %s", user->nick,
1590  user->username, user->host, chan);
1591 
1592  /* Remember that the user has not been added to our channel user list
1593  * yet, so we check whether the channel does not exist OR has no user
1594  * on it (before SJOIN would have created the channel structure, while
1595  * JOIN would not). */
1596  /* Don't check for CI_INHABIT before for the Channel record cos else
1597  * c may be NULL even if it exists */
1598  if ((!(c = findchan(chan)) || c->usercount == 0)
1599  && !(ci->flags & CI_INHABIT)) {
1600  anope_cmd_join(s_ChanServ, chan, (c ? c->creation_time : chants));
1601  /* Lets hide the channel from /list just incase someone does /list
1602  * while we are here. - katsklaw
1603  * We don't want to block users from joining a legit chan though.. - Viper
1604  */
1605  if (set_modes)
1606  anope_cmd_mode(s_ChanServ, chan, "+ntsi");
1608  t->data = sstrdup(chan);
1609  ci->flags |= CI_INHABIT;
1610  }
1611 
1612  if (c) {
1613  if (ircdcap->tsmode) {
1614  snprintf(buf, BUFSIZE - 1, "%ld", (long int) time(NULL));
1615  av[0] = chan;
1616  av[1] = buf;
1617  av[2] = sstrdup("+b");
1618  av[3] = mask;
1619  ac = 4;
1620  } else {
1621  av[0] = chan;
1622  av[1] = sstrdup("+b");
1623  av[2] = mask;
1624  ac = 3;
1625  }
1626 
1627  do_cmode(whosends(ci), ac, av);
1628 
1629  if (ircdcap->tsmode)
1630  free(av[2]);
1631  else
1632  free(av[1]);
1633  }
1634 
1635  anope_cmd_mode(whosends(ci), chan, "+b %s", mask);
1636  anope_cmd_kick(whosends(ci), chan, user->nick, "%s", reason);
1637 
1638  return 1;
1639 }
1640 
1641 /*************************************************************************/
1642 
1643 /* Record the current channel topic in the ChannelInfo structure. */
1644 
1645 void record_topic(const char *chan)
1646 {
1647  Channel *c;
1648  ChannelInfo *ci;
1649 
1650  if (readonly)
1651  return;
1652 
1653  c = findchan(chan);
1654  if (!c || !(ci = c->ci))
1655  return;
1656 
1657  if (ci->last_topic)
1658  free(ci->last_topic);
1659 
1660  if (c->topic)
1661  ci->last_topic = sstrdup(c->topic);
1662  else
1663  ci->last_topic = NULL;
1664 
1666  ci->last_topic_time = c->topic_time;
1667 }
1668 
1669 /*************************************************************************/
1670 
1671 /* Restore the topic in a channel when it's created, if we should. */
1672 
1673 void restore_topic(char *chan)
1674 {
1675  Channel *c = findchan(chan);
1676  ChannelInfo *ci;
1677 
1678  if (!c || !(ci = c->ci))
1679  return;
1680  /* We can be sure that the topic will be in sync when we return -GD */
1681  c->topic_sync = 1;
1682  if (!(ci->flags & CI_KEEPTOPIC)) {
1683  /* We need to reset the topic here, since it's currently empty and
1684  * should be updated with a TOPIC from the IRCd soon. -GD
1685  */
1686  ci->last_topic = NULL;
1688  ci->last_topic_time = time(NULL);
1689  return;
1690  }
1691  if (c->topic)
1692  free(c->topic);
1693  if (ci->last_topic) {
1694  c->topic = sstrdup(ci->last_topic);
1696  c->topic_time = ci->last_topic_time;
1697  } else {
1698  c->topic = NULL;
1700  }
1701  if (ircd->join2set) {
1702  if (whosends(ci) == s_ChanServ) {
1704  anope_cmd_mode(NULL, chan, "+o %s", GET_BOT(s_ChanServ));
1705  }
1706  }
1708  c->topic ? c->topic : "", c->topic_time);
1709  if (ircd->join2set) {
1710  if (whosends(ci) == s_ChanServ) {
1711  anope_cmd_part(s_ChanServ, c->name, NULL);
1712  }
1713  }
1714 }
1715 
1716 /*************************************************************************/
1717 
1718 /* See if the topic is locked on the given channel, and return 1 (and fix
1719  * the topic) if so. */
1720 
1721 int check_topiclock(Channel * c, time_t topic_time)
1722 {
1723  ChannelInfo *ci;
1724 
1725  if (!c) {
1726  if (debug) {
1727  alog("debug: check_topiclock called with NULL values");
1728  }
1729  return 0;
1730  }
1731 
1732  if (!(ci = c->ci) || !(ci->flags & CI_TOPICLOCK))
1733  return 0;
1734 
1735  if (c->topic)
1736  free(c->topic);
1737  if (ci->last_topic) {
1738  c->topic = sstrdup(ci->last_topic);
1740  } else {
1741  c->topic = NULL;
1742  /* Bot assigned & Symbiosis ON?, the bot will set the topic - doc */
1743  /* Altough whosends() also checks for BSMinUsers -GD */
1745  }
1746 
1747  if (ircd->topictsforward) {
1748  /* Because older timestamps are rejected */
1749  /* Some how the topic_time from do_topic is 0 set it to current + 1 */
1750  if (!topic_time) {
1751  c->topic_time = time(NULL) + 1;
1752  } else {
1753  c->topic_time = topic_time + 1;
1754  }
1755  } else {
1756  /* If no last topic, we can't use last topic time! - doc */
1757  if (ci->last_topic)
1758  c->topic_time = ci->last_topic_time;
1759  else
1760  c->topic_time = time(NULL) + 1;
1761  }
1762 
1763  if (ircd->join2set) {
1764  if (whosends(ci) == s_ChanServ) {
1766  anope_cmd_mode(NULL, c->name, "+o %s", GET_BOT(s_ChanServ));
1767  }
1768  }
1769 
1771  c->topic ? c->topic : "", c->topic_time);
1772 
1773  if (ircd->join2set) {
1774  if (whosends(ci) == s_ChanServ) {
1775  anope_cmd_part(s_ChanServ, c->ci->name, NULL);
1776  }
1777  }
1778  return 1;
1779 }
1780 
1781 /*************************************************************************/
1782 
1783 /* Remove all channels which have expired. */
1784 
1786 {
1787  ChannelInfo *ci, *next;
1788  int i;
1789  time_t now = time(NULL);
1790 
1791  if (!CSExpire)
1792  return;
1793 
1794  for (i = 0; i < 256; i++) {
1795  for (ci = chanlists[i]; ci; ci = next) {
1796  next = ci->next;
1797  if (!ci->c && now - ci->last_used >= CSExpire
1798  && !(ci->
1799  flags & (CI_VERBOTEN | CI_NO_EXPIRE | CI_SUSPENDED)))
1800  {
1802  alog("Expiring channel %s (founder: %s)", ci->name,
1803  (ci->founder ? ci->founder->display : "(none)"));
1804  delchan(ci);
1805  }
1806  }
1807  }
1808 }
1809 
1810 /*************************************************************************/
1811 
1812 /* Remove a (deleted or expired) nickname from all channel lists. */
1813 
1814 void cs_remove_nick(const NickCore * nc)
1815 {
1816  int i, j, k;
1817  ChannelInfo *ci, *next;
1818  ChanAccess *ca;
1819  AutoKick *akick;
1820 
1821  for (i = 0; i < 256; i++) {
1822  for (ci = chanlists[i]; ci; ci = next) {
1823  next = ci->next;
1824  if (ci->founder == nc) {
1825  if (ci->successor) {
1826  NickCore *nc2 = ci->successor;
1827  if (!nick_is_services_admin(nc2) && nc2->channelmax > 0
1828  && nc2->channelcount >= nc2->channelmax) {
1829  alog("%s: Successor (%s) of %s owns too many channels, " "deleting channel", s_ChanServ, nc2->display, ci->name);
1830  delchan(ci);
1831  continue;
1832  } else {
1833  alog("%s: Transferring foundership of %s from deleted " "nick %s to successor %s", s_ChanServ, ci->name, nc->display, nc2->display);
1834  ci->founder = nc2;
1835  ci->successor = NULL;
1836  nc2->channelcount++;
1837  }
1838  } else {
1839  alog("%s: Deleting channel %s owned by deleted nick %s", s_ChanServ, ci->name, nc->display);
1840  if (ircd->regmode) {
1841  /* Maybe move this to delchan() ? */
1842  if ((ci->c) && (ci->c->mode & ircd->regmode)) {
1843  ci->c->mode &= ~ircd->regmode;
1844  anope_cmd_mode(whosends(ci), ci->name, "-r");
1845  }
1846  }
1847 
1848  delchan(ci);
1849  continue;
1850  }
1851  }
1852 
1853  if (ci->successor == nc)
1854  ci->successor = NULL;
1855 
1856  for (ca = ci->access, j = ci->accesscount; j > 0; ca++, j--) {
1857  if (ca->in_use && ca->nc == nc) {
1858  ca->in_use = 0;
1859  ca->nc = NULL;
1860  }
1861  }
1862  CleanAccess(ci);
1863 
1864  for (akick = ci->akick, j = 0; j < ci->akickcount; akick++, j++) {
1865  if ((akick->flags & AK_USED) && (akick->flags & AK_ISNICK)
1866  && akick->u.nc == nc) {
1867  if (akick->creator) {
1868  free(akick->creator);
1869  akick->creator = NULL;
1870  }
1871  if (akick->reason) {
1872  free(akick->reason);
1873  akick->reason = NULL;
1874  }
1875  akick->flags = 0;
1876  akick->addtime = 0;
1877  akick->u.nc = NULL;
1878 
1879  /* Only one occurance can exist in every akick list.. ~ Viper */
1880  break;
1881  }
1882  }
1883 
1884  /* Are there any akicks behind us?
1885  * If so, move all following akicks.. ~ Viper */
1886  if (j < ci->akickcount - 1) {
1887  for (k = j + 1; k < ci->akickcount; j++, k++) {
1888  if (ci->akick[k].flags & AK_USED) {
1889  /* Move the akick one place ahead and clear the original */
1890  if (ci->akick[k].flags & AK_ISNICK) {
1891  ci->akick[j].u.nc = ci->akick[k].u.nc;
1892  ci->akick[k].u.nc = NULL;
1893  } else {
1894  ci->akick[j].u.mask = sstrdup(ci->akick[k].u.mask);
1895  free(ci->akick[k].u.mask);
1896  ci->akick[k].u.mask = NULL;
1897  }
1898 
1899  if (ci->akick[k].reason) {
1900  ci->akick[j].reason = sstrdup(ci->akick[k].reason);
1901  free(ci->akick[k].reason);
1902  ci->akick[k].reason = NULL;
1903  } else
1904  ci->akick[j].reason = NULL;
1905 
1906  ci->akick[j].creator = sstrdup(ci->akick[k].creator);
1907  free(ci->akick[k].creator);
1908  ci->akick[k].creator = NULL;
1909 
1910  ci->akick[j].flags = ci->akick[k].flags;
1911  ci->akick[k].flags = 0;
1912 
1913  ci->akick[j].addtime = ci->akick[k].addtime;
1914  ci->akick[k].addtime = 0;
1915  }
1916  }
1917  }
1918 
1919  /* After moving only the last entry should still be empty.
1920  * Free the place no longer in use... ~ Viper */
1921  ci->akickcount = j;
1922  ci->akick = srealloc(ci->akick,sizeof(AutoKick) * ci->akickcount);
1923  }
1924  }
1925 }
1926 
1927 /*************************************************************************/
1928 
1929 /* Removes any reference to a bot */
1930 
1931 void cs_remove_bot(const BotInfo * bi)
1932 {
1933  int i;
1934  ChannelInfo *ci;
1935 
1936  for (i = 0; i < 256; i++)
1937  for (ci = chanlists[i]; ci; ci = ci->next)
1938  if (ci->bi == bi)
1939  ci->bi = NULL;
1940 }
1941 
1942 /*************************************************************************/
1943 
1944 /* Return the ChannelInfo structure for the given channel, or NULL if the
1945  * channel isn't registered. */
1946 
1947 ChannelInfo *cs_findchan(const char *chan)
1948 {
1949  ChannelInfo *ci;
1950 
1951  if (!chan || !*chan) {
1952  if (debug) {
1953  alog("debug: cs_findchan() called with NULL values");
1954  }
1955  return NULL;
1956  }
1957 
1958  for (ci = chanlists[(unsigned char) tolower(chan[1])]; ci;
1959  ci = ci->next) {
1960  if (stricmp(ci->name, chan) == 0)
1961  return ci;
1962  }
1963  return NULL;
1964 }
1965 
1966 /*************************************************************************/
1967 
1968 /* Return 1 if the user's access level on the given channel falls into the
1969  * given category, 0 otherwise. Note that this may seem slightly confusing
1970  * in some cases: for example, check_access(..., CA_NOJOIN) returns true if
1971  * the user does _not_ have access to the channel (i.e. matches the NOJOIN
1972  * criterion). */
1973 
1974 int check_access(User * user, ChannelInfo * ci, int what)
1975 {
1976  int level;
1977  int limit;
1978 
1979  if (!user || !ci) {
1980  return 0;
1981  }
1982 
1983  level = get_access(user, ci);
1984  limit = ci->levels[what];
1985 
1986  /* Resetting the last used time */
1987  if (level > 0)
1988  ci->last_used = time(NULL);
1989 
1990  if (level >= ACCESS_FOUNDER)
1991  return (what == CA_AUTODEOP || what == CA_NOJOIN) ? 0 : 1;
1992  /* Hacks to make flags work */
1993  if (what == CA_AUTODEOP && (ci->flags & CI_SECUREOPS) && level == 0)
1994  return 1;
1995  if (limit == ACCESS_INVALID)
1996  return 0;
1997  if (what == CA_AUTODEOP || what == CA_NOJOIN)
1998  return level <= ci->levels[what];
1999  else
2000  return level >= ci->levels[what];
2001 }
2002 
2003 /*************************************************************************/
2004 /*********************** ChanServ private routines ***********************/
2005 /*************************************************************************/
2006 
2007 /* Insert a channel alphabetically into the database. */
2008 
2010 {
2011  ChannelInfo *ptr, *prev;
2012  char *chan;
2013 
2014  if (!ci) {
2015  if (debug) {
2016  alog("debug: alpha_insert_chan called with NULL values");
2017  }
2018  return;
2019  }
2020 
2021  chan = ci->name;
2022 
2023  for (prev = NULL, ptr = chanlists[(unsigned char) tolower(chan[1])];
2024  ptr != NULL && stricmp(ptr->name, chan) < 0;
2025  prev = ptr, ptr = ptr->next);
2026  ci->prev = prev;
2027  ci->next = ptr;
2028  if (!prev)
2029  chanlists[(unsigned char) tolower(chan[1])] = ci;
2030  else
2031  prev->next = ci;
2032  if (ptr)
2033  ptr->prev = ci;
2034 }
2035 
2036 /*************************************************************************/
2037 
2038 /* Add a channel to the database. Returns a pointer to the new ChannelInfo
2039  * structure if the channel was successfully registered, NULL otherwise.
2040  * Assumes channel does not already exist. */
2041 
2042 ChannelInfo *makechan(const char *chan)
2043 {
2044  int i;
2045  ChannelInfo *ci;
2046 
2047  ci = scalloc(sizeof(ChannelInfo), 1);
2048  strscpy(ci->name, chan, CHANMAX);
2049  ci->time_registered = time(NULL);
2050  reset_levels(ci);
2051  ci->ttb = scalloc(2 * TTB_SIZE, 1);
2052  for (i = 0; i < TTB_SIZE; i++)
2053  ci->ttb[i] = 0;
2054  alpha_insert_chan(ci);
2055  return ci;
2056 }
2057 
2058 /*************************************************************************/
2059 
2060 /* Remove a channel from the ChanServ database. Return 1 on success, 0
2061  * otherwise. */
2062 
2064 {
2065  int i;
2066  NickCore *nc;
2067  User *u;
2068  struct u_chaninfolist *cilist, *cilist_next;
2069 
2070  if (!ci) {
2071  if (debug) {
2072  alog("debug: delchan called with NULL values");
2073  }
2074  return 0;
2075  }
2076 
2077  nc = ci->founder;
2078 
2079  if (debug >= 2) {
2080  alog("debug: delchan removing %s", ci->name);
2081  }
2082 
2083  if (ci->bi) {
2084  ci->bi->chancount--;
2085  }
2086 
2087  if (debug >= 2) {
2088  alog("debug: delchan top of removing the bot");
2089  }
2090  if (ci->c) {
2091  if (ci->bi && ci->c->usercount >= BSMinUsers) {
2092  anope_cmd_part(ci->bi->nick, ci->c->name, NULL);
2093  }
2094  ci->c->ci = NULL;
2095  }
2096  if (debug >= 2) {
2097  alog("debug: delchan() Bot has been removed moving on");
2098  }
2099 
2100  if (debug >= 2) {
2101  alog("debug: delchan() founder cleanup");
2102  }
2103  for (i = 0; i < 1024; i++) {
2104  for (u = userlist[i]; u; u = u->next) {
2105  cilist = u->founder_chans;
2106  while (cilist) {
2107  cilist_next = cilist->next;
2108  if (cilist->chan == ci) {
2109  if (debug)
2110  alog("debug: Dropping founder login of %s for %s",
2111  u->nick, ci->name);
2112  if (cilist->next)
2113  cilist->next->prev = cilist->prev;
2114  if (cilist->prev)
2115  cilist->prev->next = cilist->next;
2116  else
2117  u->founder_chans = cilist->next;
2118  free(cilist);
2119  }
2120  cilist = cilist_next;
2121  }
2122  }
2123  }
2124  if (debug >= 2) {
2125  alog("debug: delchan() founder cleanup done");
2126  }
2127 
2128  if (ci->next)
2129  ci->next->prev = ci->prev;
2130  if (ci->prev)
2131  ci->prev->next = ci->next;
2132  else
2133  chanlists[(unsigned char) tolower(ci->name[1])] = ci->next;
2134  if (ci->desc)
2135  free(ci->desc);
2136  if (ci->url)
2137  free(ci->url);
2138  if (ci->email)
2139  free(ci->email);
2140  if (ci->entry_message)
2141  free(ci->entry_message);
2142 
2143  if (ci->mlock_key)
2144  free(ci->mlock_key);
2145  if (ircd->fmode) {
2146  if (ci->mlock_flood)
2147  free(ci->mlock_flood);
2148  }
2149  if (ircd->Lmode) {
2150  if (ci->mlock_redirect)
2151  free(ci->mlock_redirect);
2152  }
2153  if (ircd->jmode) {
2154  if (ci->mlock_throttle)
2155  free(ci->mlock_throttle);
2156  }
2157  if (ci->last_topic)
2158  free(ci->last_topic);
2159  if (ci->forbidby)
2160  free(ci->forbidby);
2161  if (ci->forbidreason)
2162  free(ci->forbidreason);
2163  if (ci->access)
2164  free(ci->access);
2165  if (debug >= 2) {
2166  alog("debug: delchan() top of the akick list");
2167  }
2168  for (i = 0; i < ci->akickcount; i++) {
2169  if (!(ci->akick[i].flags & AK_ISNICK) && ci->akick[i].u.mask)
2170  free(ci->akick[i].u.mask);
2171  if (ci->akick[i].reason)
2172  free(ci->akick[i].reason);
2173  if (ci->akick[i].creator)
2174  free(ci->akick[i].creator);
2175  }
2176  if (debug >= 2) {
2177  alog("debug: delchan() done with the akick list");
2178  }
2179  if (ci->akick)
2180  free(ci->akick);
2181  if (ci->levels)
2182  free(ci->levels);
2183  if (debug >= 2) {
2184  alog("debug: delchan() top of the memo list");
2185  }
2186  if (ci->memos.memos) {
2187  for (i = 0; i < ci->memos.memocount; i++) {
2188  if (ci->memos.memos[i].text)
2189  free(ci->memos.memos[i].text);
2191  }
2192  free(ci->memos.memos);
2193  }
2194  if (debug >= 2) {
2195  alog("debug: delchan() done with the memo list");
2196  }
2197  if (ci->ttb)
2198  free(ci->ttb);
2199 
2200  if (debug >= 2) {
2201  alog("debug: delchan() top of the badword list");
2202  }
2203  for (i = 0; i < ci->bwcount; i++) {
2204  if (ci->badwords[i].word)
2205  free(ci->badwords[i].word);
2206  }
2207  if (ci->badwords)
2208  free(ci->badwords);
2209  if (debug >= 2) {
2210  alog("debug: delchan() done with the badword list");
2211  }
2212 
2213 
2214  if (debug >= 2) {
2215  alog("debug: delchan() calling on moduleCleanStruct()");
2216  }
2218 
2219  free(ci);
2220  if (nc)
2221  nc->channelcount--;
2222 
2223  if (debug >= 2) {
2224  alog("debug: delchan() all done");
2225  }
2226  return 1;
2227 }
2228 
2229 /*************************************************************************/
2230 
2231 /* Reset channel access level values to their default state. */
2232 
2234 {
2235  int i;
2236 
2237  if (!ci) {
2238  if (debug) {
2239  alog("debug: reset_levels called with NULL values");
2240  }
2241  return;
2242  }
2243 
2244  if (ci->levels)
2245  free(ci->levels);
2246  ci->levels = scalloc(CA_SIZE * sizeof(*ci->levels), 1);
2247  for (i = 0; def_levels[i][0] >= 0; i++)
2248  ci->levels[def_levels[i][0]] = def_levels[i][1];
2249 }
2250 
2251 /*************************************************************************/
2252 
2253 /* Does the given user have founder access to the channel? */
2254 
2255 int is_founder(User * user, ChannelInfo * ci)
2256 {
2257  if (!user || !ci) {
2258  return 0;
2259  }
2260 
2261  if (user->isSuperAdmin) {
2262  return 1;
2263  }
2264 
2265  if (user->na && user->na->nc == ci->founder) {
2266  if ((nick_identified(user)
2267  || (nick_recognized(user) && !(ci->flags & CI_SECURE))))
2268  return 1;
2269  }
2270  if (is_identified(user, ci))
2271  return 1;
2272  return 0;
2273 }
2274 
2275 /*************************************************************************/
2276 
2278 {
2279  if (user->isSuperAdmin) {
2280  return 1;
2281  }
2282 
2283  if (user->na && user->na->nc == ci->founder) {
2284  if ((nick_identified(user)
2285  || (nick_recognized(user) && !(ci->flags & CI_SECURE))))
2286  return 1;
2287  }
2288  return 0;
2289 }
2290 
2291 /*************************************************************************/
2292 
2293 /* Has the given user password-identified as founder for the channel? */
2294 
2295 int is_identified(User * user, ChannelInfo * ci)
2296 {
2297  struct u_chaninfolist *c;
2298 
2299  for (c = user->founder_chans; c; c = c->next) {
2300  if (c->chan == ci)
2301  return 1;
2302  }
2303  return 0;
2304 }
2305 
2306 /*************************************************************************/
2307 
2308 /* Returns the ChanAccess entry for an user */
2309 
2311 {
2312  ChanAccess *access;
2313  int i;
2314 
2315  if (!ci || !nc) {
2316  return NULL;
2317  }
2318 
2319  for (access = ci->access, i = 0; i < ci->accesscount; access++, i++)
2320  if (access->in_use && access->nc == nc)
2321  return access;
2322 
2323  return NULL;
2324 }
2325 
2326 /*************************************************************************/
2327 
2328 /* Return the access level the given user has on the channel. If the
2329  * channel doesn't exist, the user isn't on the access list, or the channel
2330  * is CS_SECURE and the user hasn't IDENTIFY'd with NickServ, return 0. */
2331 
2332 int get_access(User * user, ChannelInfo * ci)
2333 {
2334  ChanAccess *access;
2335 
2336  if (!ci || !user)
2337  return 0;
2338 
2339  /* SuperAdmin always has highest level */
2340  if (user->isSuperAdmin)
2341  return ACCESS_SUPERADMIN;
2342 
2343  if (is_founder(user, ci))
2344  return ACCESS_FOUNDER;
2345 
2346  if (!user->na)
2347  return 0;
2348 
2349  if (nick_identified(user)
2350  || (nick_recognized(user) && !(ci->flags & CI_SECURE)))
2351  if ((access = get_access_entry(user->na->nc, ci)))
2352  return access->level;
2353 
2354  if (nick_identified(user))
2355  return 0;
2356 
2357  return 0;
2358 }
2359 
2360 /*************************************************************************/
2361 
2363 {
2364  ChanAccess *access;
2365 
2366  if (!ci || !user || !user->na)
2367  return;
2368 
2369  if (is_founder(user, ci) || nick_identified(user)
2370  || (nick_recognized(user) && !(ci->flags & CI_SECURE)))
2371  if ((access = get_access_entry(user->na->nc, ci)))
2372  access->last_seen = time(NULL);
2373 }
2374 
2375 /*************************************************************************/
2376 
2377 /* Returns the best ban possible for an user depending of the bantype
2378  value. */
2379 
2380 int get_idealban(ChannelInfo * ci, User * u, char *ret, int retlen)
2381 {
2382  char *mask;
2383 
2384  if (!ci || !u || !ret || retlen == 0)
2385  return 0;
2386 
2387  switch (ci->bantype) {
2388  case 0:
2389  snprintf(ret, retlen, "*!%s@%s", common_get_vident(u),
2390  common_get_vhost(u));
2391  return 1;
2392  case 1:
2393  snprintf(ret, retlen, "*!%s%s@%s",
2394  (strlen(common_get_vident(u)) <
2395  (*(common_get_vident(u)) ==
2396  '~' ? USERMAX + 1 : USERMAX) ? "*" : ""),
2397  (*(common_get_vident(u)) ==
2398  '~' ? common_get_vident(u) + 1 : common_get_vident(u)),
2399  common_get_vhost(u));
2400  return 1;
2401  case 2:
2402  snprintf(ret, retlen, "*!*@%s", common_get_vhost(u));
2403  return 1;
2404  case 3:
2405  mask = create_mask(u);
2406  snprintf(ret, retlen, "*!%s", mask);
2407  free(mask);
2408  return 1;
2409 
2410  default:
2411  return 0;
2412  }
2413 }
2414 
2415 /*************************************************************************/
2416 
2418 {
2419  if (!ci) {
2420  return NULL;
2421  } else {
2422  if (ircd->fmode) {
2423  return ci->mlock_flood;
2424  } else {
2425  return NULL;
2426  }
2427  }
2428 }
2429 
2430 /*************************************************************************/
2431 
2433 {
2434  if (!ci) {
2435  return NULL;
2436  } else {
2437  if (ircd->jmode) {
2438  return ci->mlock_throttle;
2439  } else {
2440  return NULL;
2441  }
2442  }
2443 }
2444 
2445 /*************************************************************************/
2446 
2448 {
2449  if (!ci) {
2450  return NULL;
2451  } else {
2452  return ci->mlock_key;
2453  }
2454 }
2455 
2456 /*************************************************************************/
2457 
2459 {
2460  static char limit[16];
2461 
2462  if (!ci) {
2463  return NULL;
2464  }
2465 
2466  if (ci->mlock_limit == 0)
2467  return NULL;
2468 
2469  snprintf(limit, sizeof(limit), "%lu",
2470  (unsigned long int) ci->mlock_limit);
2471  return limit;
2472 }
2473 
2474 /*************************************************************************/
2475 
2477 {
2478  if (!ci) {
2479  return NULL;
2480  } else {
2481  if (ircd->Lmode) {
2482  return ci->mlock_redirect;
2483  } else {
2484  return NULL;
2485  }
2486  }
2487 }
2488 
2489 /*************************************************************************/
2490 
2491 /* This is a dummy function part of making anope accept modes
2492  * it does actively parse.. ~ Viper */
2494 {
2495  return NULL;
2496 }
2497 
2498 /*************************************************************************/
2499 
2500 void cs_set_flood(ChannelInfo * ci, char *value)
2501 {
2502  if (!ci) {
2503  return;
2504  }
2505 
2506  if (ci->mlock_flood)
2507  free(ci->mlock_flood);
2508 
2509  /* This looks ugly, but it works ;) */
2510  if (anope_flood_mode_check(value)) {
2511  ci->mlock_flood = sstrdup(value);
2512  } else {
2513  ci->mlock_on &= ~ircd->chan_fmode;
2514  ci->mlock_flood = NULL;
2515  }
2516 }
2517 
2518 /*************************************************************************/
2519 
2520 void cs_set_throttle(ChannelInfo * ci, char *value)
2521 {
2522  if (!ci)
2523  return;
2524 
2525  if (ci->mlock_throttle)
2526  free(ci->mlock_throttle);
2527 
2528  if (anope_jointhrottle_mode_check(value)) {
2529  ci->mlock_throttle = sstrdup(value);
2530  } else {
2531  ci->mlock_on &= ~ircd->chan_jmode;
2532  ci->mlock_throttle = NULL;
2533  }
2534 }
2535 
2536 /*************************************************************************/
2537 
2538 void cs_set_key(ChannelInfo * ci, char *value)
2539 {
2540  if (!ci) {
2541  return;
2542  }
2543 
2544  if (ci->mlock_key)
2545  free(ci->mlock_key);
2546 
2547  /* Don't allow keys with a coma */
2548  if (value && *value != ':' && !strchr(value, ',')) {
2549  ci->mlock_key = sstrdup(value);
2550  } else {
2551  ci->mlock_on &= ~anope_get_key_mode();
2552  ci->mlock_key = NULL;
2553  }
2554 }
2555 
2556 /*************************************************************************/
2557 
2558 void cs_set_limit(ChannelInfo * ci, char *value)
2559 {
2560  if (!ci) {
2561  return;
2562  }
2563 
2564  ci->mlock_limit = value ? strtoul(value, NULL, 10) : 0;
2565 
2566  if (ci->mlock_limit <= 0)
2567  ci->mlock_on &= ~anope_get_limit_mode();
2568 }
2569 
2570 /*************************************************************************/
2571 
2572 void cs_set_redirect(ChannelInfo * ci, char *value)
2573 {
2574  if (!ci) {
2575  return;
2576  }
2577 
2578  if (ci->mlock_redirect)
2579  free(ci->mlock_redirect);
2580 
2581  /* Don't allow keys with a coma */
2582  if (value && *value == '#') {
2583  ci->mlock_redirect = sstrdup(value);
2584  } else {
2585  ci->mlock_on &= ~ircd->chan_lmode;
2586  ci->mlock_redirect = NULL;
2587  }
2588 }
2589 
2590 /*************************************************************************/
2591 
2592 /* This is a dummy function to make anope parse a param for a mode,
2593  * yet we don't use that param internally.. ~ Viper */
2594 void cs_set_unkwn(ChannelInfo * ci, char *value)
2595 {
2596  /* Do nothing.. */
2597 }
2598 
2599 /*************************************************************************/
2600 
2602 {
2603  ChanAccess *access;
2604  int num;
2605 
2606  if (!ci || !na) {
2607  return 0;
2608  }
2609 
2610  if (na->nc == ci->founder) {
2611  return ACCESS_FOUNDER;
2612  }
2613 
2614  for (num = 0; num < ci->accesscount; num++) {
2615 
2616  access = &ci->access[num];
2617 
2618  if (access->nc && access->nc == na->nc && access->in_use) {
2619  return access->level;
2620  }
2621 
2622  }
2623 
2624  return 0;
2625 
2626 }
2627 
2628 const char *get_xop_level(int level)
2629 {
2630  if (level < ACCESS_VOP) {
2631  return "Err";
2632  } else if (ircd->halfop && level < ACCESS_HOP) {
2633  return "VOP";
2634  } else if (!ircd->halfop && level < ACCESS_AOP) {
2635  return "VOP";
2636  } else if (ircd->halfop && level < ACCESS_AOP) {
2637  return "HOP";
2638  } else if (level < ACCESS_SOP) {
2639  return "AOP";
2640  } else if (level < ACCESS_FOUNDER) {
2641  return "SOP";
2642  } else {
2643  return "Founder";
2644  }
2645 
2646 }
2647 
2648 /*************************************************************************/
2649 /*********************** ChanServ command routines ***********************/
2650 /*************************************************************************/
2651 
2652 /*************************************************************************/
2653 
2654 
2655 /*************************************************************************/
2656 
2657 /* `last' is set to the last index this routine was called with
2658  * `perm' is incremented whenever a permission-denied error occurs
2659  */
2660 
2661 
2662 /*************************************************************************/
2663 
2664 /* Is the mask stuck? */
2665 
2666 AutoKick *is_stuck(ChannelInfo * ci, char *mask)
2667 {
2668  int i;
2669  AutoKick *akick;
2670 
2671  if (!ci) {
2672  return NULL;
2673  }
2674 
2675  for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
2676  if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK)
2677  || !(akick->flags & AK_STUCK))
2678  continue;
2679  /* Example: mask = *!*@*.org and akick->u.mask = *!*@*.anope.org */
2680  if (match_wild_nocase(mask, akick->u.mask))
2681  return akick;
2682  if (ircd->reversekickcheck) {
2683  /* Example: mask = *!*@irc.anope.org and akick->u.mask = *!*@*.anope.org */
2684  if (match_wild_nocase(akick->u.mask, mask))
2685  return akick;
2686  }
2687  }
2688 
2689  return NULL;
2690 }
2691 
2692 /* Ban the stuck mask in a safe manner. */
2693 
2694 void stick_mask(ChannelInfo * ci, AutoKick * akick)
2695 {
2696  char *av[2];
2697  Entry *ban;
2698 
2699  if (!ci) {
2700  return;
2701  }
2702 
2703  if (ci->c->bans && ci->c->bans->entries != 0) {
2704  for (ban = ci->c->bans->entries; ban; ban = ban->next) {
2705  /* If akick is already covered by a wider ban.
2706  Example: c->bans[i] = *!*@*.org and akick->u.mask = *!*@*.epona.org */
2707  if (entry_match_mask(ban, sstrdup(akick->u.mask), 0))
2708  return;
2709 
2710  if (ircd->reversekickcheck) {
2711  /* If akick is wider than a ban already in place.
2712  Example: c->bans[i] = *!*@irc.epona.org and akick->u.mask = *!*@*.epona.org */
2713  if (match_wild_nocase(akick->u.mask, ban->mask))
2714  return;
2715  }
2716  }
2717  }
2718 
2719  /* Falling there means set the ban */
2720  av[0] = sstrdup("+b");
2721  av[1] = akick->u.mask;
2722  anope_cmd_mode(whosends(ci), ci->c->name, "+b %s", akick->u.mask);
2723  chan_set_modes(s_ChanServ, ci->c, 2, av, 1);
2724  free(av[0]);
2725 }
2726 
2727 /* Ban the stuck mask in a safe manner. */
2728 
2730 {
2731  int i;
2732  char *av[2];
2733  AutoKick *akick;
2734 
2735  if (!ci) {
2736  return;
2737  }
2738 
2739  for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) {
2740  if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK)
2741  || !(akick->flags & AK_STUCK))
2742  continue;
2743 
2744  av[0] = sstrdup("+b");
2745  av[1] = akick->u.mask;
2746  anope_cmd_mode(whosends(ci), ci->c->name, "+b %s", akick->u.mask);
2747  chan_set_modes(s_ChanServ, ci->c, 2, av, 1);
2748  free(av[0]);
2749  }
2750 }
2751 
2756 {
2757  int a, b;
2758 
2759  if (!ci)
2760  return;
2761 
2762  for (b = 0; b < ci->accesscount; b++)
2763  {
2764  if (ci->access[b].in_use)
2765  {
2766  for (a = 0; a < ci->accesscount; a++)
2767  {
2768  if (a > b)
2769  break;
2770  if (!ci->access[a].in_use)
2771  {
2772  ci->access[a].in_use = 1;
2773  ci->access[a].level = ci->access[b].level;
2774  ci->access[a].nc = ci->access[b].nc;
2775  ci->access[a].last_seen = ci->access[b].last_seen;
2776  ci->access[b].nc = NULL;
2777  ci->access[b].in_use = 0;
2778  break;
2779  }
2780  }
2781  }
2782  }
2783 
2784  /* After reordering, entries on the end of the list may be empty, remove them */
2785  for (b = ci->accesscount - 1; b >= 0; --b)
2786  {
2787  if (ci->access[b].in_use)
2788  break;
2789  ci->accesscount--;
2790  }
2791 
2792  /* Reallocate the access list to only use the memory we need */
2793  ci->access = srealloc(ci->access, sizeof(ChanAccess) * ci->accesscount);
2794 }
2795 
char * url
Definition: services.h:660
ModuleData * moduleData
Definition: services.h:695
#define CA_KICKME
Definition: services.h:778
#define CA_AUTOVOICE
Definition: services.h:755
E CBMode cbmodes[128]
Definition: extern.h:47
#define CI_SUSPENDED
Definition: services.h:743
#define EVENT_CHAN_EXPIRE
Definition: events.h:31
int check_should_op(User *user, char *chan)
Definition: chanserv.c:1375
void CleanAccess(ChannelInfo *ci)
Definition: chanserv.c:2755
int check_should_protect(User *user, char *chan)
Definition: chanserv.c:1457
#define ACCESS_SUPERADMIN
Definition: services.h:610
char * cs_get_redirect(ChannelInfo *ci)
Definition: chanserv.c:2476
E int nick_is_services_admin(NickCore *nc)
Definition: operserv.c:636
E CBModeInfo * cbmodeinfos
Definition: extern.h:48
int16 usercount
Definition: services.h:1020
uint16 akickcount
Definition: services.h:678
void stick_all(ChannelInfo *ci)
Definition: chanserv.c:2729
void check_modes(Channel *c)
Definition: chanserv.c:1081
E int entry_match_mask(Entry *e, char *mask, uint32 ip)
Definition: channels.c:2310
ChannelInfo * makechan(const char *chan)
Definition: chanserv.c:2042
#define CA_GETKEY
Definition: services.h:770
char sender[NICKMAX]
Definition: services.h:494
ChannelInfo * cs_findchan(const char *chan)
Definition: chanserv.c:1947
#define CA_AUTOOP
Definition: services.h:753
E IRCDCAPAB * ircdcap
Definition: extern.h:40
E int CSDefBantype
Definition: extern.h:405
#define CI_INHABIT
Definition: services.h:746
E int readonly
Definition: extern.h:776
#define CA_ACCESS_CHANGE
Definition: services.h:760
E int match_wild_nocase(const char *pattern, const char *str)
Definition: misc.c:268
void moduleAddChanServCmds(void)
Definition: chanserv.c:120
int check_should_halfop(User *user, char *chan)
Definition: chanserv.c:1418
int get_idealban(ChannelInfo *ci, User *u, char *ret, int retlen)
Definition: chanserv.c:2380
char nick[NICKMAX]
Definition: services.h:875
E int snprintf(char *buf, size_t size, const char *fmt,...)
Definition: compat.c:37
E void anope_cmd_part(char *nick, char *chan, const char *fmt,...)
Definition: ircd.c:367
E NickAlias * findnick(const char *nick)
Definition: db-merger.c:1857
#define CI_OPNOTICE
Definition: services.h:733
uint32 botflags
Definition: services.h:700
char * ownerset
Definition: services.h:303
void cs_set_limit(ChannelInfo *ci, char *value)
Definition: chanserv.c:2558
int Lmode
Definition: services.h:350
char * word
Definition: services.h:642
int16 capspercent
Definition: services.h:705
#define CBM_MINUS_NO_ARG
Definition: services.h:928
struct user_::u_chaninfolist * founder_chans
AutoKick * is_stuck(ChannelInfo *ci, char *mask)
Definition: chanserv.c:2666
E IRCDVar * ircd
Definition: extern.h:39
#define CA_FANTASIA
Definition: services.h:765
E char ** ChanServCoreModules
Definition: extern.h:500
#define CI_RESTRICTED
Definition: services.h:719
uint16 type
Definition: services.h:643
char * mlock_redirect
Definition: services.h:685
int rdb_clean_table_where(char *table, char *clause)
Definition: rdb.c:123
void update_cs_lastseen(User *user, ChannelInfo *ci)
Definition: chanserv.c:2362
void cs_init(void)
Definition: chanserv.c:380
#define CA_CLEAR
Definition: services.h:758
uint32 flag
Definition: services.h:934
Timeout * add_timeout(int delay, void(*code)(Timeout *), int repeat)
Definition: timeout.c:93
time_t last_used
Definition: services.h:664
E int anope_flood_mode_check(char *value)
Definition: ircd.c:644
#define CI_NO_EXPIRE
Definition: services.h:729
E int nick_identified(User *u)
Definition: nickserv.c:1111
Entry * next
Definition: services.h:1038
E char * stripModePrefix(const char *str)
Definition: misc.c:1188
#define CA_NOKICK
Definition: services.h:764
E void send_event(const char *name, int argc,...)
Definition: events.c:37
char * mlock_flood
Definition: services.h:684
ChannelInfo * prev
Definition: services.h:653
void get_chanserv_stats(long *nrec, long *memuse)
Definition: chanserv.c:307
uint32 regmode
Definition: services.h:336
#define AK_STUCK
Definition: services.h:636
char * cs_get_key(ChannelInfo *ci)
Definition: chanserv.c:2447
char founderpass[PASSMAX]
Definition: services.h:658
E int is_ulined(char *server)
Definition: servers.c:495
int is_identified(User *user, ChannelInfo *ci)
Definition: chanserv.c:2295
E int stricmp(const char *s1, const char *s2)
Definition: compat.c:58
#define CA_BAN
Definition: services.h:786
char *(* csgetvalue)(ChannelInfo *ci)
Definition: services.h:939
CSModeUtil csmodeutils[]
Definition: chanserv.c:106
E void anope_cmd_join(char *user, char *channel, time_t chantime)
Definition: ircd.c:352
#define read_buffer(buf, f)
Definition: datafiles.h:61
int16 level
Definition: services.h:594
E void modules_core_init(int number, char **list)
Definition: modules.c:127
E void moduleCleanStruct(ModuleData **moduleData)
Definition: modules.c:2439
#define CI_SECURE
Definition: services.h:723
#define CI_VERBOTEN
Definition: services.h:725
uint16 flags
Definition: services.h:921
int16 chancount
Definition: services.h:579
#define CI_SECUREFOUNDER
Definition: services.h:735
#define getstring(na, index)
Definition: extern.h:731
E char * CSAutokickReason
Definition: extern.h:408
E void chan_set_modes(const char *source, Channel *chan, int ac, char **av, int check)
Definition: channels.c:161
char topic_setter[NICKMAX]
Definition: services.h:1004
#define CI_SECUREOPS
Definition: services.h:713
E int BSMinUsers
Definition: extern.h:422
char * host
Definition: services.h:878
E int DefConLevel
Definition: extern.h:561
char * cs_get_unkwn(ChannelInfo *ci)
Definition: chanserv.c:2493
time_t chanserv_modetime
Definition: services.h:1025
int get_access_level(ChannelInfo *ci, NickAlias *na)
Definition: chanserv.c:2601
void cs_set_key(ChannelInfo *ci, char *value)
Definition: chanserv.c:2538
void cs_set_redirect(ChannelInfo *ci, char *value)
Definition: chanserv.c:2572
#define ACCESS_VOP
Definition: services.h:614
#define CA_GREET
Definition: services.h:767
char * get_mlock_modes(ChannelInfo *ci, int complete)
Definition: chanserv.c:130
#define write_int8(val, f)
Definition: datafiles.h:60
char mode
Definition: services.h:933
E int anope_get_limit_mode()
Definition: ircd.c:1241
#define CA_ACCESS_LIST
Definition: services.h:757
#define CA_AKICK
Definition: services.h:750
E char * strscpy(char *d, const char *s, size_t len)
Definition: db-merger.c:1886
char * cs_get_limit(ChannelInfo *ci)
Definition: chanserv.c:2458
#define CA_SIGNKICK
Definition: services.h:780
int16 memocount
Definition: services.h:505
union AutoKick::@1 u
#define CA_PROTECTME
Definition: services.h:776
int isSuperAdmin
Definition: services.h:896
#define AK_USED
Definition: services.h:634
ChannelInfo * ci
Definition: services.h:1001
char name[CHANMAX]
Definition: services.h:654
#define CA_AUTODEOP
Definition: services.h:754
int except
Definition: services.h:320
#define CA_NOJOIN
Definition: services.h:759
#define AK_ISNICK
Definition: services.h:635
E void notice_lang(char *source, User *dest, int message,...)
Definition: send.c:169
int levelinfo_maxwidth
Definition: chanserv.c:104
#define CA_SIZE
Definition: services.h:790
int check_topiclock(Channel *c, time_t topic_time)
Definition: chanserv.c:1721
time_t last_topic_time
Definition: services.h:667
E int nick_recognized(User *u)
Definition: nickserv.c:1131
char last_topic_setter[NICKMAX]
Definition: services.h:666
char * cs_get_flood(ChannelInfo *ci)
Definition: chanserv.c:2417
void cs_remove_nick(const NickCore *nc)
Definition: chanserv.c:1814
char * forbidreason
Definition: services.h:671
char * last_topic
Definition: services.h:665
E int is_excepted(ChannelInfo *ci, User *user)
Definition: users.c:950
#define CA_AUTOHALFOP
Definition: services.h:771
char * ownerunset
Definition: services.h:304
E int read_int16(uint16 *ret, dbFILE *f)
Definition: datafiles.c:405
E Channel * findchan(const char *chan)
Definition: channels.c:394
int16 bouncy_modes
Definition: services.h:1028
E char * sstrdup(const char *s)
Definition: memory.c:105
#define CA_INFO
Definition: services.h:788
#define CA_KICK
Definition: services.h:779
#define CI_PRIVATE
Definition: services.h:715
NickCore * nc
Definition: services.h:533
int rdb_close()
Definition: rdb.c:47
E void * scalloc(long elsize, long els)
Definition: memory.c:55
int16 bantype
Definition: services.h:673
char * email
Definition: services.h:661
E NickCore * findcore(const char *nick)
Definition: nickserv.c:1263
int16 topic_sync
Definition: services.h:1029
time_t last_seen
Definition: services.h:596
#define ACCESS_SOP
Definition: services.h:617
char * mlock_throttle
Definition: services.h:686
char * display
Definition: services.h:542
uint16 flags
Definition: services.h:492
#define ACCESS_FOUNDER
Definition: services.h:604
E void anope_cmd_kick(char *source, char *chan, char *user, const char *fmt,...)
Definition: ircd.c:230
E void anope_cmd_topic(char *whosets, char *chan, char *whosetit, char *topic, time_t when)
Definition: ircd.c:145
void save_cs_dbase(void)
Definition: chanserv.c:850
E void E void E void fatal(const char *fmt,...) FORMAT(printf
struct memo_ Memo
Definition: services.h:224
void expire_chans()
Definition: chanserv.c:1785
#define CA_UNBAN
Definition: services.h:752
E char * s_OperServ
Definition: extern.h:289
BadWord * badwords
Definition: services.h:704
#define ACCESS_INVALID
Definition: services.h:605
#define getc_db(f)
Definition: datafiles.h:48
struct badword_ BadWord
Definition: services.h:230
uint32 flags
Definition: services.h:669
char * entry_message
Definition: services.h:688
E int read_string(char **ret, dbFILE *f)
Definition: db-merger.c:1806
ModuleData * moduleData
Definition: services.h:496
int16 memomax
Definition: services.h:505
int check_kick(User *user, char *chan, time_t chants)
Definition: chanserv.c:1500
char * text
Definition: services.h:495
E int DefConModesSet
Definition: extern.h:974
#define CA_OPDEOP
Definition: services.h:756
#define CA_INVITE
Definition: services.h:749
void listchans(int count_only, const char *chan)
Definition: chanserv.c:191
E int get_file_version(dbFILE *f)
Definition: datafiles.c:30
Definition: services.h:1037
struct u_chaninfolist * next
Definition: services.h:905
uint32 mode
Definition: services.h:1006
E int write_int16(uint16 val, dbFILE *f)
Definition: db-merger.c:1737
uint16 bwcount
Definition: services.h:703
char * cs_get_throttle(ChannelInfo *ci)
Definition: chanserv.c:2432
int delchan(ChannelInfo *ci)
Definition: chanserv.c:2063
ChanAccess * get_access_entry(NickCore *nc, ChannelInfo *ci)
Definition: chanserv.c:2310
int check_valid_op(User *user, Channel *chan, int servermode)
Definition: chanserv.c:1290
E BotInfo * findbot(char *nick)
Definition: db-merger.c:1989
time_t creation_time
Definition: services.h:1002
void(* setvalue)(Channel *chan, char *value)
Definition: services.h:924
char * reason
Definition: services.h:628
E void close_db(dbFILE *f)
Definition: db-merger.c:1706
uint16 channelcount
Definition: services.h:553
uint16 accesscount
Definition: services.h:676
void restore_topic(char *chan)
Definition: chanserv.c:1673
int is_real_founder(User *user, ChannelInfo *ci)
Definition: chanserv.c:2277
char *(* getvalue)(Channel *chan)
Definition: services.h:938
void stick_mask(ChannelInfo *ci, AutoKick *akick)
Definition: chanserv.c:2694
struct channel_ * c
Definition: services.h:692
uint32 mlock_off
Definition: services.h:681
void record_topic(const char *chan)
Definition: chanserv.c:1645
#define CA_PROTECT
Definition: services.h:777
char * name
Definition: services.h:854
#define CI_KEEPTOPIC
Definition: services.h:711
void cs_remove_bot(const BotInfo *bi)
Definition: chanserv.c:1931
Command * c
Definition: ns_recover.c:17
#define CHANSERV
Definition: modules.h:60
int protect
Definition: services.h:333
int check_valid_admin(User *user, Channel *chan, int servermode)
Definition: chanserv.c:1255
User * next
Definition: services.h:873
Server * server
Definition: services.h:884
u_int32_t uint32
Definition: db-merger.c:123
void alpha_insert_chan(ChannelInfo *ci)
Definition: chanserv.c:2009
E dbFILE * open_db(const char *service, const char *filename, const char *mode, uint32 version)
Definition: datafiles.c:295
NickCore * nc
Definition: services.h:626
E void alog(const char *fmt,...) FORMAT(printf
uint32 chan_jmode
Definition: services.h:375
uint32 number
Definition: services.h:491
int check_should_owner(User *user, char *chan)
Definition: chanserv.c:1435
NickCore * nc
Definition: services.h:595
void cs_set_flood(ChannelInfo *ci, char *value)
Definition: chanserv.c:2500
int topictsforward
Definition: services.h:321
uint32 mlock_limit
Definition: services.h:682
int16_t int16
Definition: db-merger.c:120
char * adminset
Definition: services.h:305
void save_cs_rdb_dbase(void)
Definition: chanserv.c:979
#define CA_AUTOPROTECT
Definition: services.h:772
#define CA_BADWORDS
Definition: services.h:763
#define CHANMAX
Definition: config.h:56
E int debug
Definition: extern.h:775
char * mask
Definition: services.h:625
LevelInfo levelinfo[]
Definition: chanserv.c:65
char * adminunset
Definition: services.h:306
const char * get_xop_level(int level)
Definition: chanserv.c:2628
static time_t lastwarn
Definition: datafiles.c:19
int16 floodlines
Definition: services.h:706
#define ACCESS_HOP
Definition: services.h:615
#define whosends(ci)
Definition: extern.h:163
int16 chanserv_modecount
Definition: services.h:1027
char * username
Definition: services.h:877
char * topic
Definition: services.h:1003
uint16 channelmax
Definition: services.h:554
E int skeleton
Definition: extern.h:778
E char * ChanDBName
Definition: extern.h:334
E char * create_mask(User *u)
Definition: users.c:1122
E int anope_get_key_mode()
Definition: ircd.c:1236
#define CA_VOICE
Definition: services.h:769
void reset_levels(ChannelInfo *ci)
Definition: chanserv.c:2233
#define CA_VOICEME
Definition: services.h:768
int rdb_clean_table(char *table)
Definition: rdb.c:113
EList * bans
Definition: services.h:1012
#define tolower
Definition: services.h:190
E void anope_cmd_mode(char *source, char *dest, const char *fmt,...)
Definition: ircd.c:211
E int CSExpire
Definition: extern.h:404
void load_cs_dbase(void)
Definition: chanserv.c:423
E void do_cmode(const char *source, int ac, char **av)
Definition: channels.c:1183
#define CA_MEMO
Definition: services.h:761
int reversekickcheck
Definition: services.h:334
#define NICKMAX
Definition: config.h:62
#define SAFE(x)
Definition: chanserv.c:837
uint32 chan_fmode
Definition: services.h:351
char * mlock_key
Definition: services.h:683
time_t topic_time
Definition: services.h:1005
void cs_set_unkwn(ChannelInfo *ci, char *value)
Definition: chanserv.c:2594
#define CI_TOPICLOCK
Definition: services.h:717
int rdb_open()
Definition: rdb.c:31
#define CA_OPDEOPME
Definition: services.h:773
int join2set
Definition: services.h:318
MemoInfo memos
Definition: services.h:690
int rdb_tag_table_where(char *table, char *clause)
Definition: rdb.c:86
int16 floodsecs
Definition: services.h:706
uint32 tsmode
Definition: services.h:381
int jmode
Definition: services.h:374
Entry * entries
Definition: services.h:1033
int16 * ttb
Definition: services.h:701
char * nick
Definition: services.h:573
int admin
Definition: services.h:324
#define TTB_SIZE
Definition: services.h:819
time_t time_registered
Definition: services.h:663
int get_access(User *user, ChannelInfo *ci)
Definition: chanserv.c:2332
char name[CHANMAX]
Definition: services.h:1000
#define GET_USER(u)
Definition: services.h:270
void * data
Definition: timeout.h:27
#define USERMAX
Definition: config.h:68
E void * srealloc(void *oldptr, long newsize)
Definition: memory.c:80
#define CA_HALFOPME
Definition: services.h:774
time_t addtime
Definition: services.h:631
#define CA_HALFOP
Definition: services.h:775
AutoKick * akick
Definition: services.h:679
int owner
Definition: services.h:302
E ChannelInfo DefConModesCI
Definition: extern.h:977
int rdb_save_cs_info(ChannelInfo *ci)
Definition: rdb.c:289
ChanAccess * access
Definition: services.h:677
int16 capsmin
Definition: services.h:705
int rdb_tag_table(char *table)
Definition: rdb.c:75
char * creator
Definition: services.h:630
E int CSInhabit
Definition: extern.h:409
uint16 in_use
Definition: services.h:641
int16 * levels
Definition: services.h:674
time_t time
Definition: services.h:493
#define CA_SAY
Definition: services.h:766
uint16 flags
Definition: services.h:623
int16 repeattimes
Definition: services.h:707
E char * s_ChanServ
Definition: extern.h:285
E uint32 DefConModesOn
Definition: extern.h:975
char * desc
Definition: services.h:659
ChannelInfo * chanlists[256]
Definition: chanserv.c:22
Memo * memos
Definition: services.h:506
#define GET_BOT(bot)
Definition: services.h:271
int is_founder(User *user, ChannelInfo *ci)
Definition: chanserv.c:2255
char * mask
Definition: services.h:1042
E int read_int32(uint32 *ret, dbFILE *f)
Definition: datafiles.c:444
MDE void mod_run_cmd(char *service, User *u, CommandHash *cmdTable[], const char *cmd)
Definition: commands.c:67
#define CHAN_VERSION
Definition: services.h:462
#define CA_BANME
Definition: services.h:785
E int write_string(const char *s, dbFILE *f)
Definition: db-merger.c:1826
static int def_levels[][2]
Definition: chanserv.c:24
E User * userlist[1024]
Definition: extern.h:1138
uint16 in_use
Definition: services.h:593
E int match_usermask(const char *mask, User *user)
Definition: users.c:1024
BotInfo * bi
Definition: services.h:699
#define CA_ASSIGN
Definition: services.h:762
E void anope_cmd_ctcp(char *source, char *dest, const char *fmt,...)
Definition: ircd.c:672
int halfop
Definition: services.h:316
#define write_buffer(buf, f)
Definition: datafiles.h:62
NickCore * founder
Definition: services.h:655
void chanserv(User *u, char *buf)
Definition: chanserv.c:389
E int ChanServCoreNumber
Definition: extern.h:501
int check_access(User *user, ChannelInfo *ci, int what)
Definition: chanserv.c:1974
E int write_int32(uint32 val, dbFILE *f)
Definition: db-merger.c:1773
E int anope_jointhrottle_mode_check(char *value)
Definition: ircd.c:649
char * forbidby
Definition: services.h:670
ChannelInfo * next
Definition: services.h:653
uint32 chan_lmode
Definition: services.h:352
E char * common_get_vhost(User *u)
Definition: actions.c:251
int16 server_modecount
Definition: services.h:1026
#define ACCESS_AOP
Definition: services.h:616
int check_should_voice(User *user, char *chan)
Definition: chanserv.c:1398
#define BUFSIZE
Definition: config.h:47
void cs_set_throttle(ChannelInfo *ci, char *value)
Definition: chanserv.c:2520
#define CA_SET
Definition: services.h:751
static void timeout_leave(Timeout *to)
Definition: chanserv.c:1480
int fmode
Definition: services.h:349
#define CA_TOPIC
Definition: services.h:787
E char * common_get_vident(User *u)
Definition: actions.c:272
uint32 mlock_on
Definition: services.h:681
NickAlias * na
Definition: services.h:892
E void anope_cmd_global(char *source, const char *fmt,...)
Definition: ircd.c:506
NickCore * successor
Definition: services.h:656
u_int16_t uint16
Definition: db-merger.c:121
E uint32 DefConModesOff
Definition: extern.h:976