Anope IRC Services  Version 1.8
channels.c
Go to the documentation of this file.
1 /* Channel-handling routines.
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 #include "services.h"
15 #include "language.h"
16 
18 
19 #define HASH(chan) ((chan)[1] ? ((chan)[1]&31)<<5 | ((chan)[2]&31) : 0)
20 
21 /**************************** External Calls *****************************/
22 /*************************************************************************/
23 
24 void chan_deluser(User * user, Channel * c)
25 {
26  struct c_userlist *u;
27 
28  if (c->ci)
29  update_cs_lastseen(user, c->ci);
30 
31  for (u = c->users; u && u->user != user; u = u->next);
32  if (!u)
33  return;
34 
35  if (u->ud) {
36  if (u->ud->lastline)
37  free(u->ud->lastline);
38  free(u->ud);
39  }
40 
41  if (u->next)
42  u->next->prev = u->prev;
43  if (u->prev)
44  u->prev->next = u->next;
45  else
46  c->users = u->next;
47  free(u);
48  c->usercount--;
49 
50  if (s_BotServ && c->ci && c->ci->bi && c->usercount == BSMinUsers - 1) {
51  anope_cmd_part(c->ci->bi->nick, c->name, NULL);
52  }
53 
54  /* Channel is permament and shouldn't be deleted */
56  return;
57 
58  if (!c->users)
59  chan_delete(c);
60 }
61 
62 /*************************************************************************/
63 
64 /* Returns a fully featured binary modes string. If complete is 0, the
65  * eventual parameters won't be added to the string.
66  */
67 
68 char *chan_get_modes(Channel * chan, int complete, int plus)
69 {
70  static char res[BUFSIZE];
71  char *end = res;
72 
73  if (chan->mode) {
74  int n = 0;
75  CBModeInfo *cbmi = cbmodeinfos;
76 
77  do {
78  if (chan->mode & cbmi->flag)
79  *end++ = cbmi->mode;
80  } while ((++cbmi)->mode != 0 && ++n < sizeof(res) - 1);
81 
82  if (complete) {
83  cbmi = cbmodeinfos;
84 
85  do {
86  if (cbmi->getvalue && (chan->mode & cbmi->flag) &&
87  (plus || !(cbmi->flags & CBM_MINUS_NO_ARG))) {
88  char *value = cbmi->getvalue(chan);
89 
90  if (value) {
91  *end++ = ' ';
92  while (*value)
93  *end++ = *value++;
94  }
95  }
96  } while ((++cbmi)->mode != 0 && ++n < sizeof(res) - 1);
97  }
98  }
99 
100  *end = 0;
101 
102  return res;
103 }
104 
105 /*************************************************************************/
106 
107 /* Retrieves the status of an user on a channel */
108 
109 int chan_get_user_status(Channel * chan, User * user)
110 {
111  struct u_chanlist *uc;
112 
113  for (uc = user->chans; uc; uc = uc->next)
114  if (uc->chan == chan)
115  return uc->status;
116 
117  return 0;
118 }
119 
120 /*************************************************************************/
121 
122 /* Has the given user the given status on the given channel? :p */
123 
124 int chan_has_user_status(Channel * chan, User * user, int16 status)
125 {
126  struct u_chanlist *uc;
127 
128  for (uc = user->chans; uc; uc = uc->next) {
129  if (uc->chan == chan) {
130  if (debug) {
131  alog("debug: chan_has_user_status wanted %d the user is %d", status, uc->status);
132  }
133  return (uc->status & status);
134  }
135  }
136  return 0;
137 }
138 
139 /*************************************************************************/
140 
141 /* Remove the status of an user on a channel */
142 
143 void chan_remove_user_status(Channel * chan, User * user, int16 status)
144 {
145  struct u_chanlist *uc;
146 
147  if (debug >= 2)
148  alog("debug: removing user status (%d) from %s for %s", status,
149  user->nick, chan->name);
150 
151  for (uc = user->chans; uc; uc = uc->next) {
152  if (uc->chan == chan) {
153  uc->status &= ~status;
154  break;
155  }
156  }
157 }
158 
159 /*************************************************************************/
160 
161 void chan_set_modes(const char *source, Channel * chan, int ac, char **av,
162  int check)
163 {
164  int add = 1;
165  char *modes = av[0], mode;
166  CBMode *cbm;
167  CMMode *cmm;
168  CUMode *cum;
169  unsigned char botmode = 0;
170  BotInfo *bi;
171  User *u, *user;
172  int i, real_ac = ac;
173  char **real_av = av;
174 
175  if (debug)
176  alog("debug: Changing modes for %s to %s", chan->name,
177  merge_args(ac, av));
178 
179  if (UseTS6 && ircd->ts6) {
180  u = find_byuid(source);
181  if (!u) u = finduser(source);
182  } else
183  u = finduser(source);
184 
185  if (u && (chan_get_user_status(chan, u) & CUS_DEOPPED)) {
186  char *s;
187 
188  if (debug)
189  alog("debug: Removing instead of setting due to DEOPPED flag");
190 
191  /* Swap adding and removing of the modes */
192  for (s = av[0]; *s; s++) {
193  if (*s == '+')
194  *s = '-';
195  else if (*s == '-')
196  *s = '+';
197  }
198 
199  /* Set the resulting mode buffer */
200  anope_cmd_mode(whosends(chan->ci), chan->name, merge_args(ac, av));
201 
202  chan_set_modes(whosends(chan->ci), chan, ac, av, check);
203 
204  return;
205  }
206 
207  ac--;
208 
209  while ((mode = *modes++)) {
210 
211  switch (mode) {
212  case '+':
213  add = 1;
214  continue;
215  case '-':
216  add = 0;
217  continue;
218  }
219 
220  if (((int) mode) < 0) {
221  if (debug)
222  alog("Debug: Malformed mode detected on %s.", chan->name);
223  continue;
224  }
225 
226  if ((cum = &cumodes[(int) mode])->status != 0) {
227  if (ac == 0) {
228  alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name);
229  continue;
230  }
231  ac--;
232  av++;
233 
234  if ((cum->flags & CUF_PROTECT_BOTSERV) && !add) {
235  if ((bi = findbot(*av))) {
236  if (!botmode || botmode != mode) {
237  anope_cmd_mode(bi->nick, chan->name, "+%c %s",
238  mode, bi->nick);
239  botmode = mode;
240  continue;
241  } else {
242  botmode = mode;
243  continue;
244  }
245  }
246  } else {
247  if ((bi = findbot(*av))) {
248  continue;
249  }
250  }
251 
252  if (UseTS6 && ircd->ts6) {
253  user = find_byuid(*av);
254  if (!user) user = finduser(*av);
255  } else
256  user = finduser(*av);
257  if (!user) {
258  if (debug)
259  alog("debug: MODE %s %c%c for nonexistent user %s",
260  chan->name, (add ? '+' : '-'), mode, *av);
261  continue;
262  }
263 
264  if (debug)
265  alog("debug: Setting %c%c on %s for %s", (add ? '+' : '-'),
266  mode, chan->name, user->nick);
267 
268  if (add) {
269  chan_set_user_status(chan, user, cum->status);
270  /* If this does +o or +h, remove any DEOPPED flag */
271  if (cum->status & CUS_OP || cum->status & CUS_HALFOP)
272  chan_remove_user_status(chan, user, CUS_DEOPPED);
273  } else {
274  chan_remove_user_status(chan, user, cum->status);
275  }
276 
277  } else if ((cbm = &cbmodes[(int) mode])->flag != 0) {
278  if (check >= 0) {
279  if (add)
280  chan->mode |= cbm->flag;
281  else
282  chan->mode &= ~cbm->flag;
283  }
284 
285  if (cbm->setvalue) {
286  if (add || !(cbm->flags & CBM_MINUS_NO_ARG)) {
287  if (ac == 0) {
288  alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name);
289  continue;
290  }
291  ac--;
292  av++;
293  }
294  cbm->setvalue(chan, add ? *av : NULL);
295  }
296 
297  if (check < 0) {
298  if (add)
299  chan->mode |= cbm->flag;
300  else
301  chan->mode &= ~cbm->flag;
302  }
303  } else if ((cmm = &cmmodes[(int) mode])->addmask) {
304  if (ac == 0) {
305  alog("channel: mode %c%c with no parameter (?) for channel %s", add ? '+' : '-', mode, chan->name);
306  continue;
307  }
308 
309  ac--;
310  av++;
311  if (add)
312  cmm->addmask(chan, *av);
313  else
314  cmm->delmask(chan, *av);
315  }
316  }
317 
318  /* Don't bounce modes from u:lined clients or servers, bug #1004. *
319  * We can get UUIDs as well.. don not assume nick ~ Viper */
320  if (UseTS6 && ircd->ts6) {
321  user = find_byuid(source);
322  if (!user) user = finduser(source);
323  } else
324  user = finduser(source);
325 
326  if ((user && is_ulined(user->server->name)) || is_ulined((char *)source))
327  return;
328 
329  if (check > 0) {
330  check_modes(chan);
331 
332  if ((check < 2) || (check == 3)) {
333  /* Walk through all users we've set modes for and see if they are
334  * valid. Invalid modes (like +o with SECUREOPS on) will be removed
335  */
336  real_ac--;
337  real_av++;
338  for (i = 0; i < real_ac; i++) {
339  if (UseTS6 && ircd->ts6) {
340  user = find_byuid(*real_av);
341  if (!user) user = finduser(*real_av);
342  } else
343  user = finduser(*real_av);
344 
345  if (!user && UseTS6 && ircd->ts6) user = find_byuid(*real_av);
346  if (user && is_on_chan(chan, user)) {
347  if (check < 2)
348  chan_set_correct_modes(user, chan, 0);
349  else if ((chan->ci->flags) && (chan->ci->flags & CI_SECUREOPS))
350  chan_set_correct_modes(user, chan, 0);
351  }
352  real_av++;
353  }
354  }
355  }
356 }
357 
358 /*************************************************************************/
359 
360 /* Set the status of an user on a channel */
361 
362 void chan_set_user_status(Channel * chan, User * user, int16 status)
363 {
364  struct u_chanlist *uc;
365 
366  if (debug >= 2)
367  alog("debug: setting user status (%d) on %s for %s", status,
368  user->nick, chan->name);
369 
370  if (HelpChannel && ircd->supporthelper && (status & CUS_OP)
371  && (stricmp(chan->name, HelpChannel) == 0)
372  && (!chan->ci || check_access(user, chan->ci, CA_AUTOOP))) {
373  if (debug) {
374  alog("debug: %s being given +h for having %d status in %s",
375  user->nick, status, chan->name);
376  }
377  common_svsmode(user, "+h", NULL);
378  }
379 
380  for (uc = user->chans; uc; uc = uc->next) {
381  if (uc->chan == chan) {
382  uc->status |= status;
383  break;
384  }
385  }
386 }
387 
388 /*************************************************************************/
389 
390 /* Return the Channel structure corresponding to the named channel, or NULL
391  * if the channel was not found. chan is assumed to be non-NULL and valid
392  * (i.e. pointing to a channel name of 2 or more characters). */
393 
394 Channel *findchan(const char *chan)
395 {
396  Channel *c;
397 
398  if (!chan || !*chan) {
399  if (debug) {
400  alog("debug: findchan() called with NULL values");
401  }
402  return NULL;
403  }
404 
405  if (debug >= 3)
406  alog("debug: findchan(%p)", chan);
407  c = chanlist[HASH(chan)];
408  while (c) {
409  if (stricmp(c->name, chan) == 0) {
410  if (debug >= 3)
411  alog("debug: findchan(%s) -> %p", chan, (void *) c);
412  return c;
413  }
414  c = c->next;
415  }
416  if (debug >= 3)
417  alog("debug: findchan(%s) -> %p", chan, (void *) c);
418  return NULL;
419 }
420 
421 /*************************************************************************/
422 
423 /* Iterate over all channels in the channel list. Return NULL at end of
424  * list.
425  */
426 
427 static Channel *current;
428 static int next_index;
429 
431 {
432  next_index = 0;
433  while (next_index < 1024 && current == NULL)
434  current = chanlist[next_index++];
435  if (debug >= 3)
436  alog("debug: firstchan() returning %s",
437  current ? current->name : "NULL (end of list)");
438  return current;
439 }
440 
442 {
443  if (current)
444  current = current->next;
445  if (!current && next_index < 1024) {
446  while (next_index < 1024 && current == NULL)
447  current = chanlist[next_index++];
448  }
449  if (debug >= 3)
450  alog("debug: nextchan() returning %s",
451  current ? current->name : "NULL (end of list)");
452  return current;
453 }
454 
455 /*************************************************************************/
456 
457 /* Return statistics. Pointers are assumed to be valid. */
458 
459 void get_channel_stats(long *nrec, long *memuse)
460 {
461  long count = 0, mem = 0;
462  Channel *chan;
463  struct c_userlist *cu;
464  BanData *bd;
465  int i;
466 
467  for (i = 0; i < 1024; i++) {
468  for (chan = chanlist[i]; chan; chan = chan->next) {
469  count++;
470  mem += sizeof(*chan);
471  if (chan->topic)
472  mem += strlen(chan->topic) + 1;
473  if (chan->key)
474  mem += strlen(chan->key) + 1;
475  if (ircd->fmode) {
476  if (chan->flood)
477  mem += strlen(chan->flood) + 1;
478  }
479  if (ircd->Lmode) {
480  if (chan->redirect)
481  mem += strlen(chan->redirect) + 1;
482  }
483  if (ircd->jmode) {
484  if (chan->throttle)
485  mem += strlen(chan->throttle) + 1;
486  }
487  mem += get_memuse(chan->bans);
488  if (ircd->except) {
489  mem += get_memuse(chan->excepts);
490  }
491  if (ircd->invitemode) {
492  mem += get_memuse(chan->invites);
493  }
494  for (cu = chan->users; cu; cu = cu->next) {
495  mem += sizeof(*cu);
496  if (cu->ud) {
497  mem += sizeof(*cu->ud);
498  if (cu->ud->lastline)
499  mem += strlen(cu->ud->lastline) + 1;
500  }
501  }
502  for (bd = chan->bd; bd; bd = bd->next) {
503  if (bd->mask)
504  mem += strlen(bd->mask) + 1;
505  mem += sizeof(*bd);
506  }
507  }
508  }
509  *nrec = count;
510  *memuse = mem;
511 }
512 
513 /*************************************************************************/
514 
515 /* Is the given nick on the given channel? */
516 
518 {
519  struct u_chanlist *uc;
520 
521  for (uc = u->chans; uc; uc = uc->next)
522  if (uc->chan == c)
523  return 1;
524 
525  return 0;
526 }
527 
528 /*************************************************************************/
529 
530 /* Is the given nick on the given channel?
531  This function supports links. */
532 
534 {
535  struct c_userlist *u;
536 
537  if (!c || !nc)
538  return NULL;
539 
540  for (u = c->users; u; u = u->next) {
541  if (u->user->na && u->user->na->nc == nc
542  && nick_recognized(u->user))
543  return u->user;
544  }
545  return NULL;
546 }
547 
548 /*************************************************************************/
549 /*************************** Message Handling ****************************/
550 /*************************************************************************/
551 
552 /* Handle a JOIN command.
553  * av[0] = channels to join
554  */
555 
556 void do_join(const char *source, int ac, char **av)
557 {
558  User *user;
559  Channel *chan;
560  char *s, *t;
561  struct u_chanlist *c, *nextc;
562  char *channame;
563  time_t ts = time(NULL);
564 
565  if (UseTS6 && ircd->ts6) {
566  user = find_byuid(source);
567  if (!user)
568  user = finduser(source);
569  } else {
570  user = finduser(source);
571  }
572  if (!user) {
573  if (debug) {
574  alog("debug: JOIN from nonexistent user %s: %s", source,
575  merge_args(ac, av));
576  }
577  return;
578  }
579 
580  t = av[0];
581  while (*(s = t)) {
582  t = s + strcspn(s, ",");
583  if (*t)
584  *t++ = 0;
585 
586  if (*s == '0') {
587  c = user->chans;
588  while (c) {
589  nextc = c->next;
590  channame = sstrdup(c->chan->name);
592  channame);
593  chan_deluser(user, c->chan);
595  channame);
596  free(channame);
597  free(c);
598  c = nextc;
599  }
600  user->chans = NULL;
601  continue;
602  }
603 
604  /* how about not triggering the JOIN event on an actual /part :) -certus */
605  send_event(EVENT_JOIN_CHANNEL, 3, EVENT_START, source, s);
606 
607  /* Make sure check_kick comes before chan_adduser, so banned users
608  * don't get to see things like channel keys. */
609  /* If channel already exists, check_kick() will use correct TS.
610  * Otherwise, we lose. */
611  if (check_kick(user, s, ts))
612  continue;
613 
614  if (ac == 2) {
615  ts = strtoul(av[1], NULL, 10);
616  if (debug) {
617  alog("debug: recieved a new TS for JOIN: %ld",
618  (long int) ts);
619  }
620  }
621 
622  chan = findchan(s);
623  chan = join_user_update(user, chan, s, ts);
624  chan_set_correct_modes(user, chan, 1);
625 
626  send_event(EVENT_JOIN_CHANNEL, 3, EVENT_STOP, source, s);
627  }
628 }
629 
630 /*************************************************************************/
631 
632 /* Handle a KICK command.
633  * av[0] = channel
634  * av[1] = nick(s) being kicked
635  * av[2] = reason
636  */
637 
638 void do_kick(const char *source, int ac, char **av)
639 {
640  BotInfo *bi;
641  ChannelInfo *ci;
642  User *user;
643  char *s, *t;
644  struct u_chanlist *c;
645  Uid *uid;
646 
647  t = av[1];
648  while (*(s = t)) {
649  t = s + strcspn(s, ",");
650  if (*t)
651  *t++ = 0;
652 
653  if (ircd->ts6 && UseTS6)
654  {
655  uid = find_nickuid(s);
656  if (uid)
657  s = uid->nick;
658  }
659 
660  /* If it is the bot that is being kicked, we make it rejoin the
661  * channel and stop immediately.
662  * --lara
663  */
664  if (s_BotServ && (bi = findbot(s)) && (ci = cs_findchan(av[0]))) {
665  bot_join(ci);
666  continue;
667  }
668 
669  if (UseTS6 && ircd->ts6) {
670  user = find_byuid(s);
671  if (!user) {
672  user = finduser(s);
673  }
674  } else {
675  user = finduser(s);
676  }
677  if (!user) {
678  if (debug) {
679  alog("debug: KICK for nonexistent user %s on %s: %s", s,
680  av[0], merge_args(ac - 2, av + 2));
681  }
682  continue;
683  }
684  if (debug) {
685  alog("debug: kicking %s from %s", user->nick, av[0]);
686  }
687  for (c = user->chans; c && stricmp(av[0], c->chan->name) != 0;
688  c = c->next);
689  if (c) {
690  send_event(EVENT_CHAN_KICK, 2, user->nick, av[0]);
691  chan_deluser(user, c->chan);
692  if (c->next)
693  c->next->prev = c->prev;
694  if (c->prev)
695  c->prev->next = c->next;
696  else
697  user->chans = c->next;
698  free(c);
699  }
700  }
701 }
702 
703 /*************************************************************************/
704 
705 /* Handle a PART command.
706  * av[0] = channels to leave
707  * av[1] = reason (optional)
708  */
709 
710 void do_part(const char *source, int ac, char **av)
711 {
712  User *user;
713  char *s, *t;
714  struct u_chanlist *c;
715  char *channame;
716 
717  if (UseTS6 && ircd->ts6) {
718  user = find_byuid(source);
719  if (!user)
720  user = finduser(source);
721  } else {
722  user = finduser(source);
723  }
724  if (!user) {
725  if (debug) {
726  alog("debug: PART from nonexistent user %s: %s", source,
727  merge_args(ac, av));
728  }
729  return;
730  }
731  t = av[0];
732  while (*(s = t)) {
733  t = s + strcspn(s, ",");
734  if (*t)
735  *t++ = 0;
736  if (debug)
737  alog("debug: %s leaves %s", source, s);
738  for (c = user->chans; c && stricmp(s, c->chan->name) != 0;
739  c = c->next);
740  if (c) {
741  if (!c->chan) {
742  alog("user: BUG parting %s: channel entry found but c->chan NULL", s);
743  return;
744  }
745  channame = sstrdup(c->chan->name);
746  send_event(EVENT_PART_CHANNEL, (ac >= 2 ? 4 : 3), EVENT_START,
747  user->nick, channame, (ac >= 2 ? av[1] : ""));
748 
749  chan_deluser(user, c->chan);
750  if (c->next)
751  c->next->prev = c->prev;
752  if (c->prev)
753  c->prev->next = c->next;
754  else
755  user->chans = c->next;
756  free(c);
757 
758  send_event(EVENT_PART_CHANNEL, (ac >= 2 ? 4 : 3), EVENT_STOP,
759  user->nick, channame, (ac >= 2 ? av[1] : ""));
760  free(channame);
761  }
762  }
763 }
764 
765 /*************************************************************************/
766 
767 /* Handle a SJOIN command.
768 
769  On channel creation, syntax is:
770 
771  av[0] = timestamp
772  av[1] = channel name
773  av[2|3|4] = modes \ depends of whether the modes k and l
774  av[3|4|5] = users / are set or not.
775 
776  When a single user joins an (existing) channel, it is:
777 
778  av[0] = timestamp
779  av[1] = user
780 
781  ============================================================
782 
783  Unreal SJOIN
784 
785  On Services connect there is
786  SJOIN !11LkOb #ircops +nt :@Trystan &*!*@*.aol.com "*@*.home.com
787 
788  av[0] = time stamp (base64)
789  av[1] = channel
790  av[2] = modes
791  av[3] = users + bans + exceptions
792 
793  On Channel Creation or a User joins an existing
794  Luna.NomadIrc.Net SJOIN !11LkW9 #akill :@Trystan
795  Luna.NomadIrc.Net SJOIN !11LkW9 #akill :Trystan`
796 
797  av[0] = time stamp (base64)
798  av[1] = channel
799  av[2] = users
800 
801 */
802 
803 void do_sjoin(const char *source, int ac, char **av)
804 {
805  Channel *c;
806  User *user;
807  Server *serv = NULL;
808  struct c_userlist *cu;
809  char *s = NULL;
810  char *end, cubuf[7], *end2, *cumodes[6], *buf;
811  int is_sqlined = 0;
812  int ts = 0;
813  int is_created = 0;
814  int keep_their_modes = 1;
815 
816  if (UseTS6 && ircd->ts6)
817  serv = findserver_uid(servlist, source);
818  if (!serv)
819  serv = findserver(servlist, source);
820 
821  if (ircd->sjb64) {
822  ts = base64dects(av[0]);
823  } else {
824  ts = strtoul(av[0], NULL, 10);
825  }
826  c = findchan(av[1]);
827  if (c != NULL) {
828  if (c->creation_time == 0 || ts == 0)
829  c->creation_time = 0;
830  else if (c->creation_time > ts) {
831  c->creation_time = ts;
832  for (cu = c->users; cu; cu = cu->next) {
833  /* XXX */
834  cumodes[0] = "-ov";
835  cumodes[1] = cu->user->nick;
836  cumodes[2] = cu->user->nick;
837  chan_set_modes(source, c, 3, cumodes, 2);
838  }
839  if (c->ci)
840  {
841  if (c->ci->bi)
842  {
843  /* This is ugly, but it always works */
844  anope_cmd_part(c->ci->bi->nick, c->name, "TS reop");
845  bot_join(c->ci);
846  }
847  /* Make sure +r is set */
848  if (ircd->chanreg && ircd->regmode)
849  {
850  c->mode |= ircd->regmode;
851  anope_cmd_mode(whosends(c->ci), c->name, "+r");
852  }
853  }
854  /* XXX simple modes and bans */
855  } else if (c->creation_time < ts)
856  keep_their_modes = 0;
857  } else
858  is_created = 1;
859 
860  /* Double check to avoid unknown modes that need parameters */
861  if (ac >= 4) {
862  if (ircd->chansqline) {
863  if (!c)
864  is_sqlined = check_chan_sqline(av[1]);
865  }
866 
867  cubuf[0] = '+';
868  cumodes[0] = cubuf;
869 
870  /* We make all the users join */
871  s = av[ac - 1]; /* Users are always the last element */
872 
873  while (*s) {
874  end = strchr(s, ' ');
875  if (end)
876  *end = 0;
877 
878  end2 = cubuf + 1;
879 
880 
881  if (ircd->sjoinbanchar) {
882  if (*s == ircd->sjoinbanchar && keep_their_modes) {
883  buf = myStrGetToken(s, ircd->sjoinbanchar, 1);
884  add_ban(c, buf);
885  if (buf)
886  free(buf);
887  if (!end)
888  break;
889  s = end + 1;
890  continue;
891  }
892  }
893  if (ircd->sjoinexchar) {
894  if (*s == ircd->sjoinexchar && keep_their_modes) {
895  buf = myStrGetToken(s, ircd->sjoinexchar, 1);
896  add_exception(c, buf);
897  if (buf)
898  free(buf);
899  if (!end)
900  break;
901  s = end + 1;
902  continue;
903  }
904  }
905 
906  if (ircd->sjoininvchar) {
907  if (*s == ircd->sjoininvchar && keep_their_modes) {
908  buf = myStrGetToken(s, ircd->sjoininvchar, 1);
909  add_invite(c, buf);
910  if (buf)
911  free(buf);
912  if (!end)
913  break;
914  s = end + 1;
915  continue;
916  }
917  }
918 
919  while (csmodes[(int) *s] != 0)
920  *end2++ = csmodes[(int) *s++];
921  *end2 = 0;
922 
923 
924  if (UseTS6 && ircd->ts6) {
925  user = find_byuid(s);
926  if (!user)
927  user = finduser(s);
928  } else {
929  user = finduser(s);
930  }
931 
932  if (!user) {
933  if (debug) {
934  alog("debug: SJOIN for nonexistent user %s on %s", s,
935  av[1]);
936  }
937  return;
938  }
939 
940  if (is_sqlined && !is_oper(user)) {
941  anope_cmd_kick(s_OperServ, av[1], s, "Q-Lined");
942  } else {
943  if (!check_kick(user, av[1], ts)) {
945  user->nick, av[1]);
946 
947  /* Make the user join; if the channel does not exist it
948  * will be created there. This ensures that the channel
949  * is not created to be immediately destroyed, and
950  * that the locked key or topic is not shown to anyone
951  * who joins the channel when empty.
952  */
953  c = join_user_update(user, c, av[1], ts);
954 
955  /* We update user mode on the channel */
956  if (end2 - cubuf > 1 && keep_their_modes) {
957  int i;
958 
959  for (i = 1; i < end2 - cubuf; i++)
960  cumodes[i] = user->nick;
961  chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
962  cumodes, 2);
963  }
964 
965  if (c->ci && (!serv || is_sync(serv))
966  && !c->topic_sync)
967  restore_topic(c->name);
968  chan_set_correct_modes(user, c, 1);
969 
971  user->nick, av[1]);
972  }
973  }
974 
975  if (!end)
976  break;
977  s = end + 1;
978  }
979 
980  if (c && keep_their_modes) {
981  /* We now update the channel mode. */
982  chan_set_modes(source, c, ac - 3, &av[2], 2);
983  }
984 
985  /* Unreal just had to be different */
986  } else if (ac == 3 && !ircd->ts6) {
987  if (ircd->chansqline) {
988  if (!c)
989  is_sqlined = check_chan_sqline(av[1]);
990  }
991 
992  cubuf[0] = '+';
993  cumodes[0] = cubuf;
994 
995  /* We make all the users join */
996  s = av[2]; /* Users are always the last element */
997 
998  while (*s) {
999  end = strchr(s, ' ');
1000  if (end)
1001  *end = 0;
1002 
1003  end2 = cubuf + 1;
1004 
1005  while (csmodes[(int) *s] != 0)
1006  *end2++ = csmodes[(int) *s++];
1007  *end2 = 0;
1008 
1009  if (UseTS6 && ircd->ts6) {
1010  user = find_byuid(s);
1011  if (!user)
1012  user = finduser(s);
1013  } else {
1014  user = finduser(s);
1015  }
1016 
1017  if (!user) {
1018  if (debug) {
1019  alog("debug: SJOIN for nonexistent user %s on %s", s,
1020  av[1]);
1021  }
1022  return;
1023  }
1024 
1025  if (is_sqlined && !is_oper(user)) {
1026  anope_cmd_kick(s_OperServ, av[1], s, "Q-Lined");
1027  } else {
1028  if (!check_kick(user, av[1], ts)) {
1030  user->nick, av[1]);
1031 
1032  /* Make the user join; if the channel does not exist it
1033  * will be created there. This ensures that the channel
1034  * is not created to be immediately destroyed, and
1035  * that the locked key or topic is not shown to anyone
1036  * who joins the channel when empty.
1037  */
1038  c = join_user_update(user, c, av[1], ts);
1039 
1040  /* We update user mode on the channel */
1041  if (end2 - cubuf > 1 && keep_their_modes) {
1042  int i;
1043 
1044  for (i = 1; i < end2 - cubuf; i++)
1045  cumodes[i] = user->nick;
1046  chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
1047  cumodes, 2);
1048  }
1049 
1050  chan_set_correct_modes(user, c, 1);
1051 
1053  user->nick, av[1]);
1054  }
1055  }
1056 
1057  if (!end)
1058  break;
1059  s = end + 1;
1060  }
1061  } else if (ac == 3 && ircd->ts6) {
1062  if (ircd->chansqline) {
1063  if (!c)
1064  is_sqlined = check_chan_sqline(av[1]);
1065  }
1066 
1067  cubuf[0] = '+';
1068  cumodes[0] = cubuf;
1069 
1070  /* We make all the users join */
1071  s = sstrdup(source); /* Users are always the last element */
1072 
1073  while (*s) {
1074  end = strchr(s, ' ');
1075  if (end)
1076  *end = 0;
1077 
1078  end2 = cubuf + 1;
1079 
1080  while (csmodes[(int) *s] != 0)
1081  *end2++ = csmodes[(int) *s++];
1082  *end2 = 0;
1083 
1084  if (UseTS6 && ircd->ts6) {
1085  user = find_byuid(s);
1086  if (!user)
1087  user = finduser(s);
1088  } else {
1089  user = finduser(s);
1090  }
1091  if (!user) {
1092  if (debug) {
1093  alog("debug: SJOIN for nonexistent user %s on %s", s,
1094  av[1]);
1095  }
1096  free(s);
1097  return;
1098  }
1099 
1100  if (is_sqlined && !is_oper(user)) {
1101  anope_cmd_kick(s_OperServ, av[1], s, "Q-Lined");
1102  } else {
1103  if (!check_kick(user, av[1], ts)) {
1105  user->nick, av[1]);
1106 
1107  /* Make the user join; if the channel does not exist it
1108  * will be created there. This ensures that the channel
1109  * is not created to be immediately destroyed, and
1110  * that the locked key or topic is not shown to anyone
1111  * who joins the channel when empty.
1112  */
1113  c = join_user_update(user, c, av[1], ts);
1114 
1115  /* We update user mode on the channel */
1116  if (end2 - cubuf > 1 && keep_their_modes) {
1117  int i;
1118 
1119  for (i = 1; i < end2 - cubuf; i++)
1120  cumodes[i] = user->nick;
1121  chan_set_modes(source, c, 1 + (end2 - cubuf - 1),
1122  cumodes, 2);
1123  }
1124 
1125  chan_set_correct_modes(user, c, 1);
1126 
1128  user->nick, av[1]);
1129  }
1130  }
1131 
1132  if (!end)
1133  break;
1134  s = end + 1;
1135  }
1136  free(s);
1137  } else if (ac == 2) {
1138  if (UseTS6 && ircd->ts6) {
1139  user = find_byuid(source);
1140  if (!user)
1141  user = finduser(source);
1142  } else {
1143  user = finduser(source);
1144  }
1145  if (!user) {
1146  if (debug) {
1147  alog("debug: SJOIN for nonexistent user %s on %s", source,
1148  av[1]);
1149  }
1150  return;
1151  }
1152 
1153  if (check_kick(user, av[1], ts))
1154  return;
1155 
1156  if (ircd->chansqline) {
1157  if (!c)
1158  is_sqlined = check_chan_sqline(av[1]);
1159  }
1160 
1161  if (is_sqlined && !is_oper(user)) {
1162  anope_cmd_kick(s_OperServ, av[1], user->nick, "Q-Lined");
1163  } else {
1165  av[1]);
1166 
1167  c = join_user_update(user, c, av[1], ts);
1168  if (is_created && c->ci)
1169  restore_topic(c->name);
1170  chan_set_correct_modes(user, c, 1);
1171 
1173  av[1]);
1174  }
1175  }
1176 }
1177 
1178 
1179 /*************************************************************************/
1180 
1181 /* Handle a channel MODE command. */
1182 
1183 void do_cmode(const char *source, int ac, char **av)
1184 {
1185  Channel *chan;
1186  ChannelInfo *ci = NULL;
1187  int i;
1188  char *t;
1189 
1190  if (ircdcap->tsmode) {
1191  /* TSMODE for bahamut - leave this code out to break MODEs. -GD */
1192  /* if they don't send it in CAPAB check if we just want to enable it */
1193  if (uplink_capab & ircdcap->tsmode || UseTSMODE) {
1194  for (i = 0; i < strlen(av[1]); i++) {
1195  if (!isdigit(av[1][i]))
1196  break;
1197  }
1198  if (av[1][i] == '\0') {
1199  /* We have a valid TS field in av[1] now, so we can strip it off */
1200  /* After we swap av[0] and av[1] ofcourse to not break stuff! :) */
1201  t = av[0];
1202  av[0] = av[1];
1203  av[1] = t;
1204  ac--;
1205  av++;
1206  } else {
1207  alog("TSMODE enabled but MODE has no valid TS");
1208  }
1209  }
1210  }
1211 
1212  /* :42XAAAAAO TMODE 1106409026 #ircops +b *!*@*.aol.com */
1213  if (UseTS6 && ircd->ts6) {
1214  if (isdigit(av[0][0])) {
1215  ac--;
1216  av++;
1217  }
1218  }
1219 
1220  chan = findchan(av[0]);
1221  if (!chan) {
1222  if (debug) {
1223  ci = cs_findchan(av[0]);
1224  if (!(ci && (ci->flags & CI_VERBOTEN)))
1225  alog("debug: MODE %s for nonexistent channel %s",
1226  merge_args(ac - 1, av + 1), av[0]);
1227  }
1228  return;
1229  }
1230 
1231  /* This shouldn't trigger on +o, etc. */
1232  if (strchr(source, '.') && !av[1][strcspn(av[1], "bovahq")]) {
1233  if (time(NULL) != chan->server_modetime) {
1234  chan->server_modecount = 0;
1235  chan->server_modetime = time(NULL);
1236  }
1237  chan->server_modecount++;
1238  }
1239 
1240  ac--;
1241  av++;
1242  chan_set_modes(source, chan, ac, av, 1);
1243 }
1244 
1245 /*************************************************************************/
1246 
1247 /* Handle a TOPIC command. */
1248 
1249 void do_topic(const char *source, int ac, char **av)
1250 {
1251  Channel *c = findchan(av[0]);
1252  ChannelInfo *ci;
1253  int ts;
1254  time_t topic_time;
1255  char *topicsetter;
1256 
1257  if (ircd->sjb64) {
1258  ts = base64dects(av[2]);
1259  if (debug) {
1260  alog("debug: encoded TOPIC TS %s converted to %d", av[2], ts);
1261  }
1262  } else {
1263  ts = strtoul(av[2], NULL, 10);
1264  }
1265 
1266  topic_time = ts;
1267 
1268  if (!c) {
1269  if (debug) {
1270  alog("debug: TOPIC %s for nonexistent channel %s",
1271  merge_args(ac - 1, av + 1), av[0]);
1272  }
1273  return;
1274  }
1275 
1276  /* We can be sure that the topic will be in sync here -GD */
1277  c->topic_sync = 1;
1278 
1279  ci = c->ci;
1280 
1281  /* For Unreal, cut off the ! and any futher part of the topic setter.
1282  * This way, nick!ident@host setters will only show the nick. -GD
1283  */
1284  topicsetter = myStrGetToken(av[1], '!', 0);
1285 
1286  /* If the current topic we have matches the last known topic for this
1287  * channel exactly, there's no need to update anything and we can as
1288  * well just return silently without updating anything. -GD
1289  * But we still need to update the topic internally for the channel - Adam
1290  */
1291  if ((ac > 3) && *av[3] && ci && ci->last_topic
1292  && (strcmp(av[3], ci->last_topic) == 0)
1293  && (strcmp(topicsetter, ci->last_topic_setter) == 0)) {
1294 
1295  if (c->topic)
1296  free(c->topic);
1297  c->topic = sstrdup(av[3]);
1298  strscpy(c->topic_setter, topicsetter, sizeof(c->topic_setter));
1299  c->topic_time = topic_time;
1300 
1301  free(topicsetter);
1302  return;
1303  }
1304 
1305  if (check_topiclock(c, topic_time)) {
1306  free(topicsetter);
1307  return;
1308  }
1309 
1310  if (c->topic) {
1311  free(c->topic);
1312  c->topic = NULL;
1313  }
1314  if (ac > 3 && *av[3]) {
1315  c->topic = sstrdup(av[3]);
1316  }
1317 
1318  strscpy(c->topic_setter, topicsetter, sizeof(c->topic_setter));
1319  c->topic_time = topic_time;
1320  free(topicsetter);
1321 
1322  record_topic(av[0]);
1323 
1324  /* Only call events if we are synced with the uplink */
1325  if (serv_uplink && is_sync(serv_uplink)) {
1326  if (ci && ci->last_topic) {
1327  send_event(EVENT_TOPIC_UPDATED, 2, av[0], ci->last_topic);
1328  } else {
1329  send_event(EVENT_TOPIC_UPDATED, 2, av[0], "");
1330  }
1331  }
1332 }
1333 
1334 /*************************************************************************/
1335 /**************************** Internal Calls *****************************/
1336 /*************************************************************************/
1337 
1338 void add_ban(Channel * chan, char *mask)
1339 {
1340  Entry *ban;
1341  /* check for NULL values otherwise we will segfault */
1342  if (!chan || !mask) {
1343  if (debug) {
1344  alog("debug: add_ban called with NULL values");
1345  }
1346  return;
1347  }
1348 
1349  /* Check if the list already exists, if not create it.
1350  * Create a new ban and add it to the list.. ~ Viper */
1351  if (!chan->bans)
1352  chan->bans = list_create();
1353  ban = entry_add(chan->bans, mask);
1354 
1355  if (!ban)
1356  fatal("Creating new ban entry failed");
1357 
1358  /* Check whether it matches a botserv bot after adding internally
1359  * and parsing it through cidr support. ~ Viper */
1360  if (s_BotServ && BSSmartJoin && chan->ci && chan->ci->bi
1361  && chan->usercount >= BSMinUsers) {
1362  BotInfo *bi = chan->ci->bi;
1363 
1364  if (entry_match(ban, bi->nick, bi->user, bi->host, 0)) {
1365  anope_cmd_mode(bi->nick, chan->name, "-b %s", mask);
1366  entry_delete(chan->bans, ban);
1367  return;
1368  }
1369  }
1370 
1371  if (debug)
1372  alog("debug: Added ban %s to channel %s", mask, chan->name);
1373 }
1374 
1375 /*************************************************************************/
1376 
1377 void add_exception(Channel * chan, char *mask)
1378 {
1379  Entry *exception;
1380 
1381  if (!chan || !mask) {
1382  if (debug)
1383  alog("debug: add_exception called with NULL values");
1384  return;
1385  }
1386 
1387  /* Check if the list already exists, if not create it.
1388  * Create a new exception and add it to the list.. ~ Viper */
1389  if (!chan->excepts)
1390  chan->excepts = list_create();
1391  exception = entry_add(chan->excepts, mask);
1392 
1393  if (!exception)
1394  fatal("Creating new exception entry failed");
1395 
1396  if (debug)
1397  alog("debug: Added except %s to channel %s", mask, chan->name);
1398 }
1399 
1400 /*************************************************************************/
1401 
1402 void add_invite(Channel * chan, char *mask)
1403 {
1404  Entry *invite;
1405 
1406  if (!chan || !mask) {
1407  if (debug)
1408  alog("debug: add_invite called with NULL values");
1409  return;
1410  }
1411 
1412  /* Check if the list already exists, if not create it.
1413  * Create a new invite and add it to the list.. ~ Viper */
1414  if (!chan->invites)
1415  chan->invites = list_create();
1416  invite = entry_add(chan->invites, mask);
1417 
1418  if (!invite)
1419  fatal("Creating new exception entry failed");
1420 
1421  if (debug)
1422  alog("debug: Added invite %s to channel %s", mask, chan->name);
1423 }
1424 
1425 /*************************************************************************/
1426 
1436 void chan_set_correct_modes(User * user, Channel * c, int give_modes)
1437 {
1438  char *tmp;
1439  char modebuf[BUFSIZE];
1440  char userbuf[BUFSIZE];
1441  int status;
1442  int add_modes = 0;
1443  int rem_modes = 0;
1444  ChannelInfo *ci;
1445 
1446  if (!c || !(ci = c->ci))
1447  return;
1448 
1449  if ((ci->flags & CI_VERBOTEN) || (*(c->name) == '+'))
1450  return;
1451 
1452  status = chan_get_user_status(c, user);
1453 
1454  if (debug)
1455  alog("debug: Setting correct user modes for %s on %s (current status: %d, %sgiving modes)", user->nick, c->name, status, (give_modes ? "" : "not "));
1456 
1457  /* Changed the second line of this if a bit, to make sure unregistered
1458  * users can always get modes (IE: they always have autoop enabled). Before
1459  * this change, you were required to have a registered nick to be able
1460  * to receive modes. I wonder who added that... *looks at Rob* ;) -GD
1461  */
1462  if (give_modes && (get_ignore(user->nick) == NULL)
1463  && (!user->na || !(user->na->nc->flags & NI_AUTOOP))) {
1464  if (ircd->owner && is_founder(user, ci))
1465  add_modes |= CUS_OWNER;
1466  else if ((ircd->protect || ircd->admin)
1467  && check_access(user, ci, CA_AUTOPROTECT))
1468  add_modes |= CUS_PROTECT;
1469  if (check_access(user, ci, CA_AUTOOP))
1470  add_modes |= CUS_OP;
1471  else if (ircd->halfop && check_access(user, ci, CA_AUTOHALFOP))
1472  add_modes |= CUS_HALFOP;
1473  else if (check_access(user, ci, CA_AUTOVOICE))
1474  add_modes |= CUS_VOICE;
1475  }
1476 
1477  /* We check if every mode they have is legally acquired here, and remove
1478  * the modes that they're not allowed to have. But only if SECUREOPS is
1479  * on, because else every mode is legal. -GD
1480  * Unless the channel has just been created. -heinz
1481  * Or the user matches CA_AUTODEOP... -GD
1482  */
1483  if (((ci->flags & CI_SECUREOPS) || (c->usercount == 1 && is_sync(user->server))
1484  || check_access(user, ci, CA_AUTODEOP))
1485  && !is_ulined(user->server->name)) {
1486  if (ircd->owner && (status & CUS_OWNER) && !is_founder(user, ci))
1487  rem_modes |= CUS_OWNER;
1488  if ((ircd->protect || ircd->admin) && (status & CUS_PROTECT)
1489  && !check_access(user, ci, CA_AUTOPROTECT)
1490  && !check_access(user, ci, CA_PROTECTME))
1491  rem_modes |= CUS_PROTECT;
1492  if ((status & CUS_OP) && !check_access(user, ci, CA_AUTOOP)
1493  && !check_access(user, ci, CA_OPDEOPME))
1494  rem_modes |= CUS_OP;
1495  if (ircd->halfop && (status & CUS_HALFOP)
1496  && !check_access(user, ci, CA_AUTOHALFOP)
1497  && !check_access(user, ci, CA_HALFOPME))
1498  rem_modes |= CUS_HALFOP;
1499  }
1500 
1501  /* No modes to add or remove, exit function -GD */
1502  if (!add_modes && !rem_modes)
1503  return;
1504 
1505  /* No need for strn* functions for modebuf, as every possible string
1506  * will always fit in. -GD
1507  */
1508  strcpy(modebuf, "");
1509  strcpy(userbuf, "");
1510  if (add_modes > 0) {
1511  strcat(modebuf, "+");
1512  if ((add_modes & CUS_OWNER) && !(status & CUS_OWNER)) {
1513  tmp = stripModePrefix(ircd->ownerset);
1514  strcat(modebuf, tmp);
1515  free(tmp);
1516  strcat(userbuf, " ");
1517  strcat(userbuf, GET_USER(user));
1518  } else {
1519  add_modes &= ~CUS_OWNER;
1520  }
1521  if ((add_modes & CUS_PROTECT) && !(status & CUS_PROTECT)) {
1522  tmp = stripModePrefix(ircd->adminset);
1523  strcat(modebuf, tmp);
1524  free(tmp);
1525  strcat(userbuf, " ");
1526  strcat(userbuf, GET_USER(user));
1527  } else {
1528  add_modes &= ~CUS_PROTECT;
1529  }
1530  if ((add_modes & CUS_OP) && !(status & CUS_OP)) {
1531  strcat(modebuf, "o");
1532  strcat(userbuf, " ");
1533  strcat(userbuf, GET_USER(user));
1534  rem_modes |= CUS_DEOPPED;
1535  } else {
1536  add_modes &= ~CUS_OP;
1537  }
1538  if ((add_modes & CUS_HALFOP) && !(status & CUS_HALFOP)) {
1539  strcat(modebuf, "h");
1540  strcat(userbuf, " ");
1541  strcat(userbuf, GET_USER(user));
1542  /* Halfops are ops too, having a halfop with CUS_DEOPPED is not good - Adam */
1543  rem_modes |= CUS_DEOPPED;
1544  } else {
1545  add_modes &= ~CUS_HALFOP;
1546  }
1547  if ((add_modes & CUS_VOICE) && !(status & CUS_VOICE)) {
1548  strcat(modebuf, "v");
1549  strcat(userbuf, " ");
1550  strcat(userbuf, GET_USER(user));
1551  } else {
1552  add_modes &= ~CUS_VOICE;
1553  }
1554  }
1555  if (rem_modes > 0) {
1556  strcat(modebuf, "-");
1557  if (rem_modes & CUS_OWNER) {
1558  tmp = stripModePrefix(ircd->ownerset);
1559  strcat(modebuf, tmp);
1560  free(tmp);
1561  strcat(userbuf, " ");
1562  strcat(userbuf, GET_USER(user));
1563  }
1564  if (rem_modes & CUS_PROTECT) {
1565  tmp = stripModePrefix(ircd->adminset);
1566  strcat(modebuf, tmp);
1567  free(tmp);
1568  strcat(userbuf, " ");
1569  strcat(userbuf, GET_USER(user));
1570  }
1571  if (rem_modes & CUS_OP) {
1572  strcat(modebuf, "o");
1573  strcat(userbuf, " ");
1574  strcat(userbuf, GET_USER(user));
1575  /* Do not mark a user as deopped if they are halfopd - Adam */
1576  if (!(add_modes & CUS_HALFOP) && !(status & CUS_HALFOP))
1577  add_modes |= CUS_DEOPPED;
1578  }
1579  if (rem_modes & CUS_HALFOP) {
1580  strcat(modebuf, "h");
1581  strcat(userbuf, " ");
1582  strcat(userbuf, GET_USER(user));
1583  /* Do not mark a user as deopped if they are opped - Adam */
1584  if (!(add_modes & CUS_OP) && !(status & CUS_OP))
1585  add_modes |= CUS_DEOPPED;
1586  }
1587  }
1588 
1589  /* Here, both can be empty again due to the "isn't it set already?"
1590  * checks above. -GD
1591  */
1592  if (!add_modes && !rem_modes)
1593  return;
1594 
1595  anope_cmd_mode(whosends(ci), c->name, "%s%s", modebuf, userbuf);
1596  if (add_modes > 0)
1597  chan_set_user_status(c, user, add_modes);
1598  if (rem_modes > 0)
1599  chan_remove_user_status(c, user, rem_modes);
1600 }
1601 
1602 /*************************************************************************/
1603 
1604 /* Add/remove a user to/from a channel, creating or deleting the channel as
1605  * necessary. If creating the channel, restore mode lock and topic as
1606  * necessary. Also check for auto-opping and auto-voicing.
1607  */
1608 
1609 void chan_adduser2(User * user, Channel * c)
1610 {
1611  struct c_userlist *u;
1612 
1613  u = scalloc(sizeof(struct c_userlist), 1);
1614  u->next = c->users;
1615  if (c->users)
1616  c->users->prev = u;
1617  c->users = u;
1618  u->user = user;
1619  c->usercount++;
1620 
1621  if (get_ignore(user->nick) == NULL) {
1622  if (c->ci && (check_access(user, c->ci, CA_MEMO))
1623  && (c->ci->memos.memocount > 0)) {
1624  if (c->ci->memos.memocount == 1) {
1625  notice_lang(s_MemoServ, user, MEMO_X_ONE_NOTICE,
1626  c->ci->memos.memocount, c->ci->name);
1627  } else {
1628  notice_lang(s_MemoServ, user, MEMO_X_MANY_NOTICE,
1629  c->ci->memos.memocount, c->ci->name);
1630  }
1631  }
1632  /* Added channelname to entrymsg - 30.03.2004, Certus */
1633  /* Also, don't send the entrymsg when bursting -GD */
1634  if (c->ci && c->ci->entry_message && is_sync(user->server))
1635  notice_user(whosends(c->ci), user, "[%s] %s", c->name,
1636  c->ci->entry_message);
1637  }
1638 
1645  if (s_BotServ && c->ci && c->ci->bi) {
1646  if (c->usercount == BSMinUsers)
1647  bot_join(c->ci);
1648  if (c->usercount >= BSMinUsers && (c->ci->botflags & BS_GREET)
1649  && user->na && user->na->nc->greet
1650  && check_access(user, c->ci, CA_GREET)) {
1651  /* Only display the greet if the main uplink we're connected
1652  * to has synced, or we'll get greet-floods when the net
1653  * recovers from a netsplit. -GD
1654  */
1655  if (is_sync(user->server)) {
1656  anope_cmd_privmsg(c->ci->bi->nick, c->name, "[%s] %s",
1657  user->na->nick, user->na->nc->greet);
1658  c->ci->bi->lastmsg = time(NULL);
1659  }
1660  }
1661  }
1662 }
1663 
1664 /*************************************************************************/
1665 
1666 /* This creates the channel structure (was originally in
1667  chan_adduser, but splitted to make it more efficient to use for
1668  SJOINs). */
1669 
1670 Channel *chan_create(char *chan, time_t ts)
1671 {
1672  Channel *c;
1673  Channel **list;
1674 
1675  if (debug)
1676  alog("debug: Creating channel %s", chan);
1677  /* Allocate pre-cleared memory */
1678  c = scalloc(sizeof(Channel), 1);
1679  strscpy(c->name, chan, sizeof(c->name));
1680  list = &chanlist[HASH(c->name)];
1681  c->next = *list;
1682  if (*list)
1683  (*list)->prev = c;
1684  *list = c;
1685  c->creation_time = ts;
1686  /* Store ChannelInfo pointer in channel record */
1687  c->ci = cs_findchan(chan);
1688  if (c->ci)
1689  c->ci->c = c;
1690  /* Restore locked modes and saved topic */
1691  if (c->ci) {
1692  check_modes(c);
1693  stick_all(c->ci);
1694  }
1695 
1696  if (serv_uplink && is_sync(serv_uplink) && (!(c->topic_sync))) {
1697  restore_topic(chan);
1698  }
1699 
1700  return c;
1701 }
1702 
1703 /*************************************************************************/
1704 
1705 /* This destroys the channel structure, freeing everything in it. */
1706 
1708 {
1709  BanData *bd, *next;
1710 
1711  if (debug)
1712  alog("debug: Deleting channel %s", c->name);
1713 
1714  for (bd = c->bd; bd; bd = next) {
1715  if (bd->mask)
1716  free(bd->mask);
1717  next = bd->next;
1718  free(bd);
1719  }
1720 
1721  if (c->ci)
1722  c->ci->c = NULL;
1723 
1724  if (c->topic)
1725  free(c->topic);
1726 
1727  if (c->key)
1728  free(c->key);
1729  if (ircd->fmode) {
1730  if (c->flood)
1731  free(c->flood);
1732  }
1733  if (ircd->Lmode) {
1734  if (c->redirect)
1735  free(c->redirect);
1736  }
1737  if (ircd->jmode) {
1738  if (c->throttle)
1739  free (c->throttle);
1740  }
1741 
1742  if (c->bans && c->bans->count) {
1743  while (c->bans->entries) {
1744  entry_delete(c->bans, c->bans->entries);
1745  }
1746  free(c->bans);
1747  }
1748 
1749  if (ircd->except) {
1750  if (c->excepts && c->excepts->count) {
1751  while (c->excepts->entries) {
1753  }
1754  free(c->excepts);
1755  }
1756  }
1757 
1758  if (ircd->invitemode) {
1759  if (c->invites && c->invites->count) {
1760  while (c->invites->entries) {
1762  }
1763  free(c->invites);
1764  }
1765  }
1766 
1767  if (c->next)
1768  c->next->prev = c->prev;
1769  if (c->prev)
1770  c->prev->next = c->next;
1771  else
1772  chanlist[HASH(c->name)] = c->next;
1773 
1774  free(c);
1775 }
1776 
1777 /*************************************************************************/
1778 
1779 void del_ban(Channel * chan, char *mask)
1780 {
1781  AutoKick *akick;
1782  Entry *ban;
1783 
1784  /* Sanity check as it seems some IRCD will just send -b without a mask */
1785  if (!mask || !chan->bans || (chan->bans->count == 0))
1786  return;
1787 
1788  ban = elist_find_mask(chan->bans, mask);
1789 
1790  if (ban) {
1791  entry_delete(chan->bans, ban);
1792  if (chan->bans->count == 0) {
1793  free(chan->bans);
1794  chan->bans = NULL;
1795  }
1796 
1797  if (debug)
1798  alog("debug: Deleted ban %s from channel %s", mask,
1799  chan->name);
1800  }
1801 
1802  if (chan->ci && (akick = is_stuck(chan->ci, mask)))
1803  stick_mask(chan->ci, akick);
1804 }
1805 
1806 /*************************************************************************/
1807 
1808 void del_exception(Channel * chan, char *mask)
1809 {
1810  Entry *exception;
1811 
1812  /* Sanity check as it seems some IRCD will just send -e without a mask */
1813  if (!mask || !chan->excepts || (chan->excepts->count == 0))
1814  return;
1815 
1816  exception = elist_find_mask(chan->excepts, mask);
1817 
1818  if (exception) {
1819  entry_delete(chan->excepts, exception);
1820  if (chan->excepts->count == 0) {
1821  free(chan->excepts);
1822  chan->excepts = NULL;
1823  }
1824 
1825  if (debug)
1826  alog("debug: Deleted except %s to channel %s", mask,
1827  chan->name);
1828  }
1829 }
1830 
1831 /*************************************************************************/
1832 
1833 void del_invite(Channel * chan, char *mask)
1834 {
1835  Entry *invite;
1836 
1837  /* Sanity check as it seems some IRCD will just send -I without a mask */
1838  if (!mask || !chan->invites || (chan->invites->count == 0)) {
1839  return;
1840  }
1841 
1842  invite = elist_find_mask(chan->invites, mask);
1843 
1844  if (invite) {
1845  entry_delete(chan->invites, invite);
1846  if(chan->invites->count == 0) {
1847  free(chan->invites);
1848  chan->invites = NULL;
1849  }
1850 
1851  if (debug)
1852  alog("debug: Deleted invite %s to channel %s", mask,
1853  chan->name);
1854  }
1855 }
1856 
1857 
1858 /*************************************************************************/
1859 
1860 char *get_flood(Channel * chan)
1861 {
1862  return chan->flood;
1863 }
1864 
1865 /*************************************************************************/
1866 
1867 char *get_throttle(Channel * chan)
1868 {
1869  return chan->throttle;
1870 }
1871 
1872 /*************************************************************************/
1873 
1874 char *get_key(Channel * chan)
1875 {
1876  return chan->key;
1877 }
1878 
1879 /*************************************************************************/
1880 
1881 char *get_limit(Channel * chan)
1882 {
1883  static char limit[16];
1884 
1885  if (chan->limit == 0)
1886  return NULL;
1887 
1888  snprintf(limit, sizeof(limit), "%lu", (unsigned long int) chan->limit);
1889  return limit;
1890 }
1891 
1892 /*************************************************************************/
1893 
1894 char *get_redirect(Channel * chan)
1895 {
1896  return chan->redirect;
1897 }
1898 
1899 /*************************************************************************/
1900 
1901 /* This is a dummy function part of making anope accept modes
1902  * it does actively parse.. ~ Viper */
1903 char *get_unkwn(Channel * chan)
1904 {
1905  return NULL;
1906 }
1907 
1908 /*************************************************************************/
1909 
1910 Channel *join_user_update(User * user, Channel * chan, char *name,
1911  time_t chants)
1912 {
1913  struct u_chanlist *c;
1914 
1915  /* If it's a new channel, so we need to create it first. */
1916  if (!chan)
1917  chan = chan_create(name, chants);
1918  else
1919  {
1920  /* Check chants against 0, as not every ircd sends JOIN with a TS. */
1921  if (chan->creation_time > chants && chants != 0)
1922  {
1923  struct c_userlist *cu;
1924  char *modes[6];
1925 
1926  chan->creation_time = chants;
1927  for (cu = chan->users; cu; cu = cu->next)
1928  {
1929  /* XXX */
1930  modes[0] = "-ov";
1931  modes[1] = cu->user->nick;
1932  modes[2] = cu->user->nick;
1933  chan_set_modes(s_OperServ, chan, 3, modes, 2);
1934  }
1935  if (chan->ci)
1936  {
1937  if (chan->ci->bi)
1938  {
1939  /* This is ugly, but it always works */
1940  anope_cmd_part(chan->ci->bi->nick, chan->name, "TS reop");
1941  bot_join(chan->ci);
1942  }
1943  /* Make sure +r is set */
1944  if (ircd->chanreg && ircd->regmode)
1945  {
1946  chan->mode |= ircd->regmode;
1947  anope_cmd_mode(whosends(chan->ci), chan->name, "+r");
1948  }
1949  }
1950  /* XXX simple modes and bans */
1951  }
1952 
1953  }
1954 
1955  if (debug)
1956  alog("debug: %s joins %s", user->nick, chan->name);
1957 
1958  c = scalloc(sizeof(*c), 1);
1959  c->next = user->chans;
1960  if (user->chans)
1961  user->chans->prev = c;
1962  user->chans = c;
1963  c->chan = chan;
1964 
1965  chan_adduser2(user, chan);
1966 
1967  return chan;
1968 }
1969 
1970 /*************************************************************************/
1971 
1972 void set_flood(Channel * chan, char *value)
1973 {
1974  if (chan->flood)
1975  free(chan->flood);
1976  chan->flood = value ? sstrdup(value) : NULL;
1977 
1978  if (debug)
1979  alog("debug: Flood mode for channel %s set to %s", chan->name,
1980  chan->flood ? chan->flood : "no flood settings");
1981 }
1982 
1983 /*************************************************************************/
1984 
1985 void chan_set_throttle(Channel * chan, char *value)
1986 {
1987  if (chan->throttle)
1988  free(chan->throttle);
1989  chan->throttle = value ? sstrdup(value) : NULL;
1990 
1991  if (debug)
1992  alog("debug: Throttle mode for channel %s set to %s", chan->name,
1993  chan->throttle ? chan->throttle : "none");
1994 }
1995 
1996 /*************************************************************************/
1997 
1998 void chan_set_key(Channel * chan, char *value)
1999 {
2000  if (chan->key)
2001  free(chan->key);
2002  chan->key = value ? sstrdup(value) : NULL;
2003 
2004  if (debug)
2005  alog("debug: Key of channel %s set to %s", chan->name,
2006  chan->key ? chan->key : "no key");
2007 }
2008 
2009 /*************************************************************************/
2010 
2011 void set_limit(Channel * chan, char *value)
2012 {
2013  chan->limit = value ? strtoul(value, NULL, 10) : 0;
2014 
2015  if (debug)
2016  alog("debug: Limit of channel %s set to %u", chan->name,
2017  chan->limit);
2018 }
2019 
2020 /*************************************************************************/
2021 
2022 void set_redirect(Channel * chan, char *value)
2023 {
2024  if (chan->redirect)
2025  free(chan->redirect);
2026  chan->redirect = value ? sstrdup(value) : NULL;
2027 
2028  if (debug)
2029  alog("debug: Redirect of channel %s set to %s", chan->name,
2030  chan->redirect ? chan->redirect : "no redirect");
2031 }
2032 
2033 /*************************************************************************/
2034 
2035 /* This is a dummy function to make anope parse a param for a mode,
2036  * yet we don't use that param internally.. ~ Viper */
2037 void set_unkwn(Channel *chan, char *value)
2038 {
2039  /* Do nothing.. */
2040 }
2041 
2042 /*************************************************************************/
2043 
2044 void do_mass_mode(char *modes)
2045 {
2046  int ac;
2047  char **av;
2048  Channel *c;
2049  char *myModes;
2050 
2051  if (!modes) {
2052  return;
2053  }
2054 
2055  /* Prevent modes being altered by split_buf */
2056  myModes = sstrdup(modes);
2057  ac = split_buf(myModes, &av, 1);
2058 
2059  for (c = firstchan(); c; c = nextchan()) {
2060  if (c->bouncy_modes) {
2061  free(av);
2062  free(myModes);
2063  return;
2064  } else {
2065  anope_cmd_mode(s_OperServ, c->name, "%s", modes);
2066  chan_set_modes(s_OperServ, c, ac, av, 1);
2067  }
2068  }
2069  free(av);
2070  free(myModes);
2071 }
2072 
2073 /*************************************************************************/
2074 
2076 {
2077  Channel *c;
2078 
2079  for (c = firstchan(); c; c = nextchan()) {
2080  if (!(c->topic_sync))
2081  restore_topic(c->name);
2082  }
2083 }
2084 
2085 /*************************************************************************/
2086 
2093 Entry *entry_create(char *mask)
2094 {
2095  Entry *entry;
2096  char *nick = NULL, *user, *host, *cidrhost;
2097  uint32 ip, cidr;
2098 
2099  entry = scalloc(1, sizeof(Entry));
2100  entry->type = ENTRYTYPE_NONE;
2101  entry->prev = NULL;
2102  entry->next = NULL;
2103  entry->nick = NULL;
2104  entry->user = NULL;
2105  entry->host = NULL;
2106  entry->mask = sstrdup(mask);
2107 
2108  host = strchr(mask, '@');
2109  if (host) {
2110  *host++ = '\0';
2111  /* If the user is purely a wildcard, ignore it */
2112  if (str_is_pure_wildcard(mask))
2113  user = NULL;
2114  else {
2115 
2116  /* There might be a nick too */
2117  user = strchr(mask, '!');
2118  if (user) {
2119  *user++ = '\0';
2120  /* If the nick is purely a wildcard, ignore it */
2121  if (str_is_pure_wildcard(mask))
2122  nick = NULL;
2123  else
2124  nick = mask;
2125  } else {
2126  nick = NULL;
2127  user = mask;
2128  }
2129  }
2130  } else {
2131  /* It is possibly an extended ban/invite mask, but we do
2132  * not support these at this point.. ~ Viper */
2133  /* If there's no user in the mask, assume a pure wildcard */
2134  user = NULL;
2135  host = mask;
2136  }
2137 
2138  if (nick) {
2139  entry->nick = sstrdup(nick);
2140  /* Check if we have a wildcard user */
2141  if (str_is_wildcard(nick))
2142  entry->type |= ENTRYTYPE_NICK_WILD;
2143  else
2144  entry->type |= ENTRYTYPE_NICK;
2145  }
2146 
2147  if (user) {
2148  entry->user = sstrdup(user);
2149  /* Check if we have a wildcard user */
2150  if (str_is_wildcard(user))
2151  entry->type |= ENTRYTYPE_USER_WILD;
2152  else
2153  entry->type |= ENTRYTYPE_USER;
2154  }
2155 
2156  /* Only check the host if it's not a pure wildcard */
2157  if (*host && !str_is_pure_wildcard(host)) {
2158  if (ircd->cidrchanbei && str_is_cidr(host, &ip, &cidr, &cidrhost)) {
2159  entry->cidr_ip = ip;
2160  entry->cidr_mask = cidr;
2161  entry->type |= ENTRYTYPE_CIDR4;
2162  host = cidrhost;
2163  } else if (ircd->cidrchanbei && strchr(host, '/')) {
2164  /* Most IRCd's don't enforce sane bans therefore it is not
2165  * so unlikely we will encounter this.
2166  * Currently we only support strict CIDR without taking into
2167  * account quirks of every single ircd (nef) that ignore everything
2168  * after the first /cidr. To add this, sanitaze before sending to
2169  * str_is_cidr() as this expects a standard cidr.
2170  * Add it to the internal list (so it is included in for example clear)
2171  * but do not use if during matching.. ~ Viper */
2172  entry->type = ENTRYTYPE_NONE;
2173  } else {
2174  entry->host = sstrdup(host);
2175  if (str_is_wildcard(host))
2176  entry->type |= ENTRYTYPE_HOST_WILD;
2177  else
2178  entry->type |= ENTRYTYPE_HOST;
2179  }
2180  }
2181  free(mask);
2182 
2183  return entry;
2184 }
2185 
2186 
2193 Entry *entry_add(EList * list, char *mask)
2194 {
2195  Entry *e;
2196  char *hostmask;
2197 
2198  hostmask = sstrdup(mask);
2199  e = entry_create(hostmask);
2200 
2201  if (!e)
2202  return NULL;
2203 
2204  e->next = list->entries;
2205  e->prev = NULL;
2206 
2207  if (list->entries)
2208  list->entries->prev = e;
2209  list->entries = e;
2210  list->count++;
2211 
2212  return e;
2213 }
2214 
2215 
2221 void entry_delete(EList * list, Entry * e)
2222 {
2223  if (!list || !e)
2224  return;
2225 
2226  if (e->next)
2227  e->next->prev = e->prev;
2228  if (e->prev)
2229  e->prev->next = e->next;
2230 
2231  if (list->entries == e)
2232  list->entries = e->next;
2233 
2234  if (e->nick)
2235  free(e->nick);
2236  if (e->user)
2237  free(e->user);
2238  if (e->host)
2239  free(e->host);
2240  free(e->mask);
2241  free(e);
2242 
2243  list->count--;
2244 }
2245 
2246 
2252 {
2253  EList *list;
2254 
2255  list = scalloc(1, sizeof(EList));
2256  list->entries = NULL;
2257  list->count = 0;
2258 
2259  return list;
2260 }
2261 
2262 
2272 int entry_match(Entry * e, char *nick, char *user, char *host, uint32 ip)
2273 {
2274  /* If we don't get an entry, or it s an invalid one, no match ~ Viper */
2275  if (!e || e->type == ENTRYTYPE_NONE)
2276  return 0;
2277 
2278  if (ircd->cidrchanbei && (e->type & ENTRYTYPE_CIDR4) &&
2279  (!ip || (ip && ((ip & e->cidr_mask) != e->cidr_ip))))
2280  return 0;
2281  if ((e->type & ENTRYTYPE_NICK)
2282  && (!nick || stricmp(e->nick, nick) != 0))
2283  return 0;
2284  if ((e->type & ENTRYTYPE_USER)
2285  && (!user || stricmp(e->user, user) != 0))
2286  return 0;
2287  if ((e->type & ENTRYTYPE_HOST)
2288  && (!host || stricmp(e->host, host) != 0))
2289  return 0;
2290  if ((e->type & ENTRYTYPE_NICK_WILD)
2291  && !match_wild_nocase(e->nick, nick))
2292  return 0;
2293  if ((e->type & ENTRYTYPE_USER_WILD)
2294  && !match_wild_nocase(e->user, user))
2295  return 0;
2296  if ((e->type & ENTRYTYPE_HOST_WILD)
2297  && !match_wild_nocase(e->host, host))
2298  return 0;
2299 
2300  return 1;
2301 }
2302 
2310 int entry_match_mask(Entry * e, char *mask, uint32 ip)
2311 {
2312  char *hostmask, *nick, *user, *host;
2313  int res;
2314 
2315  hostmask = sstrdup(mask);
2316 
2317  host = strchr(hostmask, '@');
2318  if (host) {
2319  *host++ = '\0';
2320  user = strchr(hostmask, '!');
2321  if (user) {
2322  *user++ = '\0';
2323  nick = hostmask;
2324  } else {
2325  nick = NULL;
2326  user = hostmask;
2327  }
2328  } else {
2329  nick = NULL;
2330  user = NULL;
2331  host = hostmask;
2332  }
2333 
2334  res = entry_match(e, nick, user, host, ip);
2335 
2336  /* Free the destroyed mask. */
2337  free(hostmask);
2338 
2339  return res;
2340 }
2341 
2351 Entry *elist_match(EList * list, char *nick, char *user, char *host,
2352  uint32 ip)
2353 {
2354  Entry *e;
2355 
2356  if (!list || !list->entries)
2357  return NULL;
2358 
2359  for (e = list->entries; e; e = e->next) {
2360  if (entry_match(e, nick, user, host, ip))
2361  return e;
2362  }
2363 
2364  /* We matched none */
2365  return NULL;
2366 }
2367 
2375 Entry *elist_match_mask(EList * list, char *mask, uint32 ip)
2376 {
2377  char *hostmask, *nick, *user, *host;
2378  Entry *res;
2379 
2380  if (!list || !list->entries || !mask)
2381  return NULL;
2382 
2383  hostmask = sstrdup(mask);
2384 
2385  host = strchr(hostmask, '@');
2386  if (host) {
2387  *host++ = '\0';
2388  user = strchr(hostmask, '!');
2389  if (user) {
2390  *user++ = '\0';
2391  nick = hostmask;
2392  } else {
2393  nick = NULL;
2394  user = hostmask;
2395  }
2396  } else {
2397  nick = NULL;
2398  user = NULL;
2399  host = hostmask;
2400  }
2401 
2402  res = elist_match(list, nick, user, host, ip);
2403 
2404  /* Free the destroyed mask. */
2405  free(hostmask);
2406 
2407  return res;
2408 }
2409 
2417 static Entry *_elist_match_user(EList * list, User * u, boolean full)
2418 {
2419  Entry *res = NULL;
2420  char *host;
2421  uint32 ip = 0;
2422 
2423  if (!list || !list->entries || !u)
2424  return NULL;
2425 
2426  if (u->hostip == NULL) {
2427  host = host_resolve(u->host);
2428  /* we store the just resolved hostname so we don't
2429  * need to do this again */
2430  if (host) {
2431  u->hostip = sstrdup(host);
2432  }
2433  } else {
2434  host = sstrdup(u->hostip);
2435  }
2436 
2437  /* Convert the host to an IP.. */
2438  if (host)
2439  ip = str_is_ip(host);
2440 
2441  /* Match what we ve got against the lists.. */
2442  if (full)
2443  res = elist_match(list, u->nick, u->username, u->host, ip);
2444  if (!res)
2445  res = elist_match(list, u->nick, u->vident, u->vhost, 0);
2446  if (!res)
2447  res = elist_match(list, u->nick, u->username, u->chost, 0);
2448 
2449  if (host)
2450  free(host);
2451 
2452  return res;
2453 }
2454 
2456 {
2457  return _elist_match_user(list, u, false);
2458 }
2459 
2460 Entry *elist_match_user_full(EList *list, User *u, boolean full)
2461 {
2462  return _elist_match_user(list, u, full);
2463 }
2464 
2471 Entry *elist_find_mask(EList * list, char *mask)
2472 {
2473  Entry *e;
2474 
2475  if (!list || !list->entries || !mask)
2476  return NULL;
2477 
2478  for (e = list->entries; e; e = e->next) {
2479  if (!stricmp(e->mask, mask))
2480  return e;
2481  }
2482 
2483  return NULL;
2484 }
2485 
2491 long get_memuse(EList * list)
2492 {
2493  Entry *e;
2494  long mem = 0;
2495 
2496  if (!list)
2497  return 0;
2498 
2499  mem += sizeof(EList *);
2500  mem += sizeof(Entry *) * list->count;
2501  if (list->entries) {
2502  for (e = list->entries; e; e = e->next) {
2503  if (e->nick)
2504  mem += strlen(e->nick) + 1;
2505  if (e->user)
2506  mem += strlen(e->user) + 1;
2507  if (e->host)
2508  mem += strlen(e->host) + 1;
2509  if (e->mask)
2510  mem += strlen(e->mask) + 1;
2511  }
2512  }
2513 
2514  return mem;
2515 }
2516 
2517 /*************************************************************************/
int sjoininvchar
Definition: services.h:362
E int is_oper(User *user)
Definition: users.c:937
Entry * elist_find_mask(EList *list, char *mask)
Definition: channels.c:2471
#define ENTRYTYPE_CIDR4
Definition: services.h:990
EList * invites
Definition: services.h:1014
#define CA_AUTOVOICE
Definition: services.h:755
E CBMode cbmodes[128]
Definition: extern.h:47
static Entry * _elist_match_user(EList *list, User *u, boolean full)
Definition: channels.c:2417
#define HASH(chan)
Definition: channels.c:19
char * throttle
Definition: services.h:1011
E CBModeInfo * cbmodeinfos
Definition: extern.h:48
int16 usercount
Definition: services.h:1020
void set_flood(Channel *chan, char *value)
Definition: channels.c:1972
struct c_userlist * prev
Definition: services.h:1016
#define CA_AUTOOP
Definition: services.h:753
E IRCDCAPAB * ircdcap
Definition: extern.h:40
E int match_wild_nocase(const char *pattern, const char *str)
Definition: misc.c:268
#define ENTRYTYPE_NONE
Definition: services.h:989
void chan_deluser(User *user, Channel *c)
Definition: channels.c:24
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
static Channel * current
Definition: channels.c:427
void chan_remove_user_status(Channel *chan, User *user, int16 status)
Definition: channels.c:143
uint32 flag
Definition: services.h:920
uint32 botflags
Definition: services.h:700
char * ownerset
Definition: services.h:303
#define EVENT_STOP
Definition: events.h:15
int Lmode
Definition: services.h:350
void do_part(const char *source, int ac, char **av)
Definition: channels.c:710
#define CUS_DEOPPED
Definition: services.h:1346
struct u_chanlist * next
Definition: services.h:899
int16 flags
Definition: services.h:949
#define CBM_MINUS_NO_ARG
Definition: services.h:928
E char * s_BotServ
Definition: extern.h:287
E IRCDVar * ircd
Definition: extern.h:39
Entry * elist_match_user_full(EList *list, User *u, boolean full)
Definition: channels.c:2460
Entry * entry_create(char *mask)
Definition: channels.c:2093
char * get_key(Channel *chan)
Definition: channels.c:1874
int supporthelper
Definition: services.h:367
uint32 flag
Definition: services.h:934
E int check_access(User *user, ChannelInfo *ci, int what)
Definition: chanserv.c:1974
Entry * next
Definition: services.h:1038
E char * stripModePrefix(const char *str)
Definition: misc.c:1188
E void send_event(const char *name, int argc,...)
Definition: events.c:37
char * vhost
Definition: services.h:880
void set_unkwn(Channel *chan, char *value)
Definition: channels.c:2037
uint32 regmode
Definition: services.h:336
E char csmodes[128]
Definition: extern.h:45
void add_ban(Channel *chan, char *mask)
Definition: channels.c:1338
E int is_ulined(char *server)
Definition: servers.c:495
E int stricmp(const char *s1, const char *s2)
Definition: compat.c:58
char * chost
Definition: services.h:881
E void E void E void E void notice_user(char *source, User *u, const char *fmt,...) FORMAT(printf
char * redirect
Definition: services.h:1009
void del_invite(Channel *chan, char *mask)
Definition: channels.c:1833
int32 count
Definition: services.h:1034
char * user
Definition: services.h:1042
E AutoKick * is_stuck(ChannelInfo *ci, char *mask)
Definition: chanserv.c:2666
void chan_set_correct_modes(User *user, Channel *c, int give_modes)
Definition: channels.c:1436
#define CI_VERBOTEN
Definition: services.h:725
uint16 flags
Definition: services.h:921
Channel * next
Definition: services.h:999
long get_memuse(EList *list)
Definition: channels.c:2491
E User * find_byuid(const char *uid)
Definition: users.c:378
char topic_setter[NICKMAX]
Definition: services.h:1004
int sjb64
Definition: services.h:358
#define CI_SECUREOPS
Definition: services.h:713
E int BSMinUsers
Definition: extern.h:422
Entry * elist_match_mask(EList *list, char *mask, uint32 ip)
Definition: channels.c:2375
int sjoinexchar
Definition: services.h:361
char * host
Definition: services.h:878
E Uid * find_nickuid(const char *uid)
Definition: users.c:468
#define CUS_VOICE
Definition: services.h:1342
E void stick_mask(ChannelInfo *ci, AutoKick *akick)
Definition: chanserv.c:2694
#define CA_GREET
Definition: services.h:767
int chan_has_user_status(Channel *chan, User *user, int16 status)
Definition: channels.c:124
struct user_::u_chanlist * chans
char mode
Definition: services.h:933
E char * strscpy(char *d, const char *s, size_t len)
Definition: db-merger.c:1886
int16 memocount
Definition: services.h:505
#define CA_PROTECTME
Definition: services.h:776
void add_invite(Channel *chan, char *mask)
Definition: channels.c:1402
E CUMode cumodes[128]
Definition: extern.h:49
ChannelInfo * ci
Definition: services.h:1001
E int BSSmartJoin
Definition: extern.h:424
char name[CHANMAX]
Definition: services.h:654
#define CA_AUTODEOP
Definition: services.h:754
int except
Definition: services.h:320
#define ENTRYTYPE_HOST_WILD
Definition: services.h:995
E void notice_lang(char *source, User *dest, int message,...)
Definition: send.c:169
void chan_set_modes(const char *source, Channel *chan, int ac, char **av, int check)
Definition: channels.c:161
E int nick_recognized(User *u)
Definition: nickserv.c:1131
char last_topic_setter[NICKMAX]
Definition: services.h:666
void do_cmode(const char *source, int ac, char **av)
Definition: channels.c:1183
E int is_sync(Server *server)
Definition: servers.c:516
char * last_topic
Definition: services.h:665
void do_kick(const char *source, int ac, char **av)
Definition: channels.c:638
#define CA_AUTOHALFOP
Definition: services.h:771
int16 bouncy_modes
Definition: services.h:1028
E char * sstrdup(const char *s)
Definition: memory.c:105
NickCore * nc
Definition: services.h:533
E void * scalloc(long elsize, long els)
Definition: memory.c:55
int16 topic_sync
Definition: services.h:1029
int cidrchanbei
Definition: services.h:371
E void anope_cmd_kick(char *source, char *chan, char *user, const char *fmt,...)
Definition: ircd.c:230
E void E void E void fatal(const char *fmt,...) FORMAT(printf
char * hostip
Definition: services.h:879
User * nc_on_chan(Channel *c, NickCore *nc)
Definition: channels.c:533
time_t server_modetime
Definition: services.h:1024
void do_join(const char *source, int ac, char **av)
Definition: channels.c:556
E char * s_OperServ
Definition: extern.h:289
E char * s_MemoServ
Definition: extern.h:286
uint32 flags
Definition: services.h:669
void(* addmask)(Channel *chan, char *mask)
Definition: services.h:943
E int check_chan_sqline(const char *chan)
Definition: operserv.c:1296
char * entry_message
Definition: services.h:688
int invitemode
Definition: services.h:359
E void record_topic(const char *chan)
Definition: chanserv.c:1645
char * host
Definition: services.h:1042
EList * excepts
Definition: services.h:1013
Definition: services.h:1037
char * key
Definition: services.h:1008
uint32 mode
Definition: services.h:1006
E User * finduser(const char *nick)
Definition: users.c:323
void do_topic(const char *source, int ac, char **av)
Definition: channels.c:1249
Entry * elist_match(EList *list, char *nick, char *user, char *host, uint32 ip)
Definition: channels.c:2351
E BotInfo * findbot(char *nick)
Definition: db-merger.c:1989
time_t creation_time
Definition: services.h:1002
uint16 flags
Definition: services.h:935
void set_limit(Channel *chan, char *value)
Definition: channels.c:2011
void(* setvalue)(Channel *chan, char *value)
Definition: services.h:924
Channel * nextchan(void)
Definition: channels.c:441
int entry_match(Entry *e, char *nick, char *user, char *host, uint32 ip)
Definition: channels.c:2272
uint32 type
Definition: services.h:1039
E char * HelpChannel
Definition: extern.h:279
char *(* getvalue)(Channel *chan)
Definition: services.h:938
Entry * elist_match_user(EList *list, User *u)
Definition: channels.c:2455
#define CUS_HALFOP
Definition: services.h:1343
struct channel_ * c
Definition: services.h:692
char * nick
Definition: services.h:1042
int sjoinbanchar
Definition: services.h:360
Channel * firstchan(void)
Definition: channels.c:430
E void restore_topic(char *chan)
Definition: chanserv.c:1673
char * name
Definition: services.h:854
E char * merge_args(int argc, char **argv)
Definition: misc.c:180
char * get_flood(Channel *chan)
Definition: channels.c:1860
int chansqline
Definition: services.h:325
#define CUS_PROTECT
Definition: services.h:1345
Command * c
Definition: ns_recover.c:17
int protect
Definition: services.h:333
void chan_set_key(Channel *chan, char *value)
Definition: channels.c:1998
User * next
Definition: services.h:873
Server * server
Definition: services.h:884
u_int32_t uint32
Definition: db-merger.c:123
E uint32 uplink_capab
Definition: extern.h:1054
E void alog(const char *fmt,...) FORMAT(printf
#define EVENT_PART_CHANNEL
Definition: events.h:62
E int check_kick(User *user, char *chan, time_t chants)
Definition: chanserv.c:1500
time_t lastmsg
Definition: services.h:581
void del_exception(Channel *chan, char *mask)
Definition: channels.c:1808
Channel * findchan(const char *chan)
Definition: channels.c:394
E int UseTS6
Definition: extern.h:364
char * get_redirect(Channel *chan)
Definition: channels.c:1894
void(* delmask)(Channel *chan, char *mask)
Definition: services.h:944
int16_t int16
Definition: db-merger.c:120
#define ENTRYTYPE_HOST
Definition: services.h:996
uint32 cidr_ip
Definition: services.h:1040
#define EVENT_START
Definition: events.h:14
#define ENTRYTYPE_NICK
Definition: services.h:992
void set_redirect(Channel *chan, char *value)
Definition: channels.c:2022
E Server * findserver(Server *s, const char *name)
Definition: servers.c:261
char * adminset
Definition: services.h:305
E int is_founder(User *user, ChannelInfo *ci)
Definition: chanserv.c:2255
#define CA_AUTOPROTECT
Definition: services.h:772
E void check_modes(Channel *c)
Definition: chanserv.c:1081
char * chan_get_modes(Channel *chan, int complete, int plus)
Definition: channels.c:68
void chan_set_throttle(Channel *chan, char *value)
Definition: channels.c:1985
char nick[NICKMAX]
Definition: services.h:418
E int debug
Definition: extern.h:775
E int split_buf(char *buf, char ***argv, int colon_special)
Definition: process.c:270
#define EVENT_TOPIC_UPDATED
Definition: events.h:30
E char * host_resolve(char *host)
Definition: misc.c:1134
#define CUS_OWNER
Definition: services.h:1344
struct c_userlist * next
Definition: services.h:1016
E long base64dects(char *ts)
Definition: base64.c:394
#define NI_AUTOOP
Definition: services.h:1309
#define whosends(ci)
Definition: extern.h:163
char * mask
Definition: services.h:965
char * nick
Definition: services.h:526
char * username
Definition: services.h:877
struct u_chanlist * prev
Definition: services.h:899
char * topic
Definition: services.h:1003
void do_mass_mode(char *modes)
Definition: channels.c:2044
BanData * bd
Definition: services.h:1022
E void bot_join(ChannelInfo *ci)
Definition: botserv.c:745
int entry_match_mask(Entry *e, char *mask, uint32 ip)
Definition: channels.c:2310
char * vident
Definition: services.h:882
void del_ban(Channel *chan, char *mask)
Definition: channels.c:1779
EList * bans
Definition: services.h:1012
E int check_topiclock(Channel *c, time_t topic_time)
Definition: chanserv.c:1721
E void anope_cmd_mode(char *source, char *dest, const char *fmt,...)
Definition: ircd.c:211
E int str_is_cidr(char *str, uint32 *ip, uint32 *mask, char **host)
Definition: misc.c:1602
BanData * next
Definition: services.h:963
E int str_is_wildcard(const char *str)
Definition: misc.c:1531
E Server * serv_uplink
Definition: extern.h:1053
Entry * entry_add(EList *list, char *mask)
Definition: channels.c:2193
#define ENTRYTYPE_USER_WILD
Definition: services.h:993
char * host
Definition: services.h:575
Channel * chanlist[1024]
Definition: channels.c:17
#define CA_MEMO
Definition: services.h:761
E CMMode cmmodes[128]
Definition: extern.h:46
char * flood
Definition: services.h:1010
void do_sjoin(const char *source, int ac, char **av)
Definition: channels.c:803
time_t topic_time
Definition: services.h:1005
void chan_delete(Channel *c)
Definition: channels.c:1707
E char * myStrGetToken(const char *str, const char dilim, int token_number)
Definition: misc.c:654
#define CA_OPDEOPME
Definition: services.h:773
MemoInfo memos
Definition: services.h:690
E IgnoreData * get_ignore(const char *nick)
Definition: process.c:106
uint32 tsmode
Definition: services.h:381
int jmode
Definition: services.h:374
E void anope_cmd_privmsg(char *source, char *dest, const char *fmt,...)
Definition: ircd.c:296
Entry * entries
Definition: services.h:1033
char * nick
Definition: services.h:573
int admin
Definition: services.h:324
char name[CHANMAX]
Definition: services.h:1000
#define GET_USER(u)
Definition: services.h:270
E ChannelInfo * cs_findchan(const char *chan)
Definition: db-merger.c:2000
E Server * findserver_uid(Server *s, const char *name)
Definition: servers.c:298
#define CA_HALFOPME
Definition: services.h:774
E Server * servlist
Definition: extern.h:1051
Definition: services.h:416
int owner
Definition: services.h:302
uint32 flags
Definition: services.h:548
E void common_svsmode(User *u, char *modes, char *arg)
Definition: actions.c:228
void entry_delete(EList *list, Entry *e)
Definition: channels.c:2221
int ts6
Definition: services.h:366
#define ENTRYTYPE_NICK_WILD
Definition: services.h:991
Channel * prev
Definition: services.h:999
char * greet
Definition: services.h:545
E void update_cs_lastseen(User *user, ChannelInfo *ci)
Definition: chanserv.c:2362
int16 status
Definition: services.h:948
static int next_index
Definition: channels.c:428
char * get_throttle(Channel *chan)
Definition: channels.c:1867
char * mask
Definition: services.h:1042
E int anope_get_permchan_mode()
Definition: ircd.c:1246
E int str_is_pure_wildcard(const char *str)
Definition: misc.c:1547
#define EVENT_JOIN_CHANNEL
Definition: events.h:61
uint32 limit
Definition: services.h:1007
char * get_limit(Channel *chan)
Definition: channels.c:1881
BotInfo * bi
Definition: services.h:699
Channel * join_user_update(User *user, Channel *chan, char *name, time_t chants)
Definition: channels.c:1910
int halfop
Definition: services.h:316
uint32 cidr_mask
Definition: services.h:1041
int chanreg
Definition: services.h:335
void restore_unsynced_topics(void)
Definition: channels.c:2075
#define EVENT_CHAN_KICK
Definition: events.h:68
Entry * prev
Definition: services.h:1038
char * user
Definition: services.h:574
EList * list_create()
Definition: channels.c:2251
#define ENTRYTYPE_USER
Definition: services.h:994
void get_channel_stats(long *nrec, long *memuse)
Definition: channels.c:459
E uint32 str_is_ip(char *str)
Definition: misc.c:1565
int is_on_chan(Channel *c, User *u)
Definition: channels.c:517
char * get_unkwn(Channel *chan)
Definition: channels.c:1903
int16 server_modecount
Definition: services.h:1026
E int UseTSMODE
Definition: extern.h:43
#define BS_GREET
Definition: services.h:797
#define BUFSIZE
Definition: config.h:47
Channel * chan_create(char *chan, time_t ts)
Definition: channels.c:1670
void chan_set_user_status(Channel *chan, User *user, int16 status)
Definition: channels.c:362
#define CUS_OP
Definition: services.h:1341
int fmode
Definition: services.h:349
int chan_get_user_status(Channel *chan, User *user)
Definition: channels.c:109
NickAlias * na
Definition: services.h:892
void add_exception(Channel *chan, char *mask)
Definition: channels.c:1377
#define CUF_PROTECT_BOTSERV
Definition: services.h:956
struct channel_::c_userlist * users
void chan_adduser2(User *user, Channel *c)
Definition: channels.c:1609
E void stick_all(ChannelInfo *ci)
Definition: chanserv.c:2729