Anope IRC Services  Version 2.0
channels.cpp
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 #include "services.h"
14 #include "channels.h"
15 #include "regchannel.h"
16 #include "logger.h"
17 #include "modules.h"
18 #include "users.h"
19 #include "bots.h"
20 #include "servers.h"
21 #include "protocol.h"
22 #include "users.h"
23 #include "config.h"
24 #include "access.h"
25 #include "sockets.h"
26 #include "language.h"
27 #include "uplink.h"
28 
30 
31 Channel::Channel(const Anope::string &nname, time_t ts)
32 {
33  if (nname.empty())
34  throw CoreException("A channel without a name ?");
35 
36  this->name = nname;
37 
38  this->creation_time = ts;
39  this->syncing = this->botchannel = false;
40  this->server_modetime = this->chanserv_modetime = 0;
41  this->server_modecount = this->chanserv_modecount = this->bouncy_modes = this->topic_ts = this->topic_time = 0;
42 
43  this->ci = ChannelInfo::Find(this->name);
44  if (this->ci)
45  this->ci->c = this;
46 
47  if (Me && Me->IsSynced())
48  Log(NULL, this, "create");
49 
50  FOREACH_MOD(OnChannelCreate, (this));
51 }
52 
54 {
55  FOREACH_MOD(OnChannelDelete, (this));
56 
58 
59  if (Me && Me->IsSynced())
60  Log(NULL, this, "destroy");
61 
62  if (this->ci)
63  this->ci->c = NULL;
64 
65  ChannelList.erase(this->name);
66 }
67 
69 {
70  this->modes.clear();
71 
72  for (ChanUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it)
73  {
74  ChanUserContainer *uc = it->second;
75 
76  ChannelStatus f = uc->status;
77  uc->status.Clear();
78 
79  /* reset modes for my clients */
80  if (uc->user->server == Me)
81  {
82  for (size_t i = 0; i < f.Modes().length(); ++i)
83  this->SetMode(NULL, ModeManager::FindChannelModeByChar(f.Modes()[i]), uc->user->GetUID(), false);
84  /* Modes might not exist yet, so be sure the status is really reset */
85  uc->status = f;
86  }
87  }
88 
89  for (ChanUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it)
90  this->SetCorrectModes(it->second->user, true);
91 
92  // If the channel is syncing now, do not force a sync due to Reset(), as we are probably iterating over users in Message::SJoin
93  // A sync will come soon
94  if (!syncing)
95  this->Sync();
96 }
97 
99 {
100  syncing = false;
101  FOREACH_MOD(OnChannelSync, (this));
102  CheckModes();
103 }
104 
106 {
107  if (this->bouncy_modes || this->syncing)
108  return;
109 
110  /* Check for mode bouncing */
111  if (this->server_modecount >= 3 && this->chanserv_modecount >= 3)
112  {
113  Log() << "Warning: unable to set modes on channel " << this->name << ". Are your servers' U:lines configured correctly?";
114  this->bouncy_modes = 1;
115  return;
116  }
117 
118  Reference<Channel> ref = this;
119  FOREACH_MOD(OnCheckModes, (ref));
120 }
121 
123 {
124  /* Channel is syncing from a netburst, don't destroy it as more users are probably wanting to join immediatly
125  * We also don't part the bot here either, if necessary we will part it after the sync
126  */
127  if (this->syncing)
128  return false;
129 
130  /* Permanent channels never get deleted */
131  if (this->HasMode("PERM"))
132  return false;
133 
134  EventReturn MOD_RESULT;
135  FOREACH_RESULT(OnCheckDelete, MOD_RESULT, (this));
136 
137  return MOD_RESULT != EVENT_STOP && this->users.empty();
138 }
139 
141 {
142  if (user->server && user->server->IsSynced())
143  Log(user, this, "join");
144 
145  ChanUserContainer *cuc = new ChanUserContainer(user, this);
146  user->chans[this] = cuc;
147  this->users[user] = cuc;
148  if (status)
149  cuc->status = *status;
150 
151  return cuc;
152 }
153 
155 {
156  if (user->server && user->server->IsSynced() && !user->Quitting())
157  Log(user, this, "leave");
158 
159  FOREACH_MOD(OnLeaveChannel, (user, this));
160 
161  ChanUserContainer *cu = user->FindChannel(this);
162  if (!this->users.erase(user))
163  Log(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistant user " << user->nick << " from channel " << this->name;
164 
165  if (!user->chans.erase(this))
166  Log(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistant channel " << this->name << " from " << user->nick << "'s channel list";
167  delete cu;
168 
169  if (this->CheckDelete())
170  delete this;
171 }
172 
174 {
175  ChanUserList::const_iterator it = this->users.find(u);
176  if (it != this->users.end())
177  return it->second;
178  return NULL;
179 }
180 
182 {
183  /* Usually its more efficient to search the users channels than the channels users */
184  ChanUserContainer *cc = u->FindChannel(this);
185  if (cc)
186  {
187  if (cms)
188  return cc->status.HasMode(cms->mchar);
189  else
190  return cc->status.Empty();
191  }
192 
193  return false;
194 }
195 
197 {
198  return HasUserStatus(u, anope_dynamic_static_cast<ChannelModeStatus *>(ModeManager::FindChannelModeByName(mname)));
199 }
200 
201 size_t Channel::HasMode(const Anope::string &mname, const Anope::string &param)
202 {
203  if (param.empty())
204  return modes.count(mname);
205  std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> its = this->GetModeList(mname);
206  for (; its.first != its.second; ++its.first)
207  if (its.first->second.equals_ci(param))
208  return 1;
209  return 0;
210 }
211 
212 Anope::string Channel::GetModes(bool complete, bool plus)
213 {
214  Anope::string res, params;
215 
216  for (std::multimap<Anope::string, Anope::string>::const_iterator it = this->modes.begin(), it_end = this->modes.end(); it != it_end; ++it)
217  {
219  if (!cm || cm->type == MODE_LIST)
220  continue;
221 
222  res += cm->mchar;
223 
224  if (complete && !it->second.empty())
225  {
226  ChannelModeParam *cmp = NULL;
227  if (cm->type == MODE_PARAM)
229 
230  if (plus || !cmp || !cmp->minus_no_arg)
231  params += " " + it->second;
232  }
233  }
234 
235  return res + params;
236 }
237 
239 {
240  return this->modes;
241 }
242 
243 std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> Channel::GetModeList(const Anope::string &mname)
244 {
245  Channel::ModeList::iterator it = this->modes.find(mname), it_end = it;
246  if (it != this->modes.end())
247  it_end = this->modes.upper_bound(mname);
248  return std::make_pair(it, it_end);
249 }
250 
251 void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock)
252 {
253  if (!ocm)
254  return;
255 
256  Anope::string param = oparam;
257  ChannelMode *cm = ocm->Unwrap(param);
258 
259  EventReturn MOD_RESULT;
260 
261  /* Setting v/h/o/a/q etc */
262  if (cm->type == MODE_STATUS)
263  {
264  if (param.empty())
265  {
266  Log() << "Channel::SetModeInternal() mode " << cm->mchar << " with no parameter for channel " << this->name;
267  return;
268  }
269 
270  User *u = User::Find(param);
271 
272  if (!u)
273  {
274  Log() << "MODE " << this->name << " +" << cm->mchar << " for nonexistant user " << param;
275  return;
276  }
277 
278  Log(LOG_DEBUG) << "Setting +" << cm->mchar << " on " << this->name << " for " << u->nick;
279 
280  /* Set the status on the user */
281  ChanUserContainer *cc = u->FindChannel(this);
282  if (cc)
283  cc->status.AddMode(cm->mchar);
284 
285  FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm, param));
286 
287  /* Enforce secureops, etc */
288  if (enforce_mlock && MOD_RESULT != EVENT_STOP)
289  this->SetCorrectModes(u, false);
290  return;
291  }
292 
293  if (cm->type != MODE_LIST)
294  this->modes.erase(cm->name);
295  else if (this->HasMode(cm->name, param))
296  return;
297 
298  this->modes.insert(std::make_pair(cm->name, param));
299 
300  if (param.empty() && cm->type != MODE_REGULAR)
301  {
302  Log() << "Channel::SetModeInternal() mode " << cm->mchar << " for " << this->name << " with no paramater, but is a param mode";
303  return;
304  }
305 
306  if (cm->type == MODE_LIST)
307  {
309  cml->OnAdd(this, param);
310  }
311 
312  FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm, param));
313 
314  /* Check if we should enforce mlock */
315  if (!enforce_mlock || MOD_RESULT == EVENT_STOP)
316  return;
317 
318  this->CheckModes();
319 }
320 
321 void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock)
322 {
323  if (!ocm)
324  return;
325 
326  Anope::string param = oparam;
327  ChannelMode *cm = ocm->Unwrap(param);
328 
329  EventReturn MOD_RESULT;
330 
331  /* Setting v/h/o/a/q etc */
332  if (cm->type == MODE_STATUS)
333  {
334  if (param.empty())
335  {
336  Log() << "Channel::RemoveModeInternal() mode " << cm->mchar << " with no parameter for channel " << this->name;
337  return;
338  }
339 
340  BotInfo *bi = BotInfo::Find(param);
341  User *u = bi ? bi : User::Find(param);
342 
343  if (!u)
344  {
345  Log() << "Channel::RemoveModeInternal() MODE " << this->name << "-" << cm->mchar << " for nonexistant user " << param;
346  return;
347  }
348 
349  Log(LOG_DEBUG) << "Setting -" << cm->mchar << " on " << this->name << " for " << u->nick;
350 
351  /* Remove the status on the user */
352  ChanUserContainer *cc = u->FindChannel(this);
353  if (cc)
354  cc->status.DelMode(cm->mchar);
355 
356  FOREACH_RESULT(OnChannelModeUnset, MOD_RESULT, (this, setter, cm, param));
357 
358  if (enforce_mlock && MOD_RESULT != EVENT_STOP)
359  this->SetCorrectModes(u, false);
360 
361  return;
362  }
363 
364  if (cm->type == MODE_LIST)
365  {
366  std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> its = this->GetModeList(cm->name);
367  for (; its.first != its.second; ++its.first)
368  if (param.equals_ci(its.first->second))
369  {
370  this->modes.erase(its.first);
371  break;
372  }
373  }
374  else
375  this->modes.erase(cm->name);
376 
377  if (cm->type == MODE_LIST)
378  {
380  cml->OnDel(this, param);
381  }
382 
383  FOREACH_RESULT(OnChannelModeUnset, MOD_RESULT, (this, setter, cm, param));
384 
385  if (cm->name == "PERM")
386  {
387  if (this->CheckDelete())
388  {
389  delete this;
390  return;
391  }
392  }
393 
394  /* Check for mlock */
395  if (!enforce_mlock || MOD_RESULT == EVENT_STOP)
396  return;
397 
398  this->CheckModes();
399 }
400 
401 void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param, bool enforce_mlock)
402 {
403  Anope::string wparam = param;
404  if (!cm)
405  return;
406  /* Don't set modes already set */
407  if (cm->type == MODE_REGULAR && HasMode(cm->name))
408  return;
409  else if (cm->type == MODE_PARAM)
410  {
412  if (!cmp->IsValid(wparam))
413  return;
414 
415  Anope::string cparam;
416  if (GetParam(cm->name, cparam) && cparam.equals_cs(wparam))
417  return;
418  }
419  else if (cm->type == MODE_STATUS)
420  {
421  User *u = User::Find(param);
422  if (!u || HasUserStatus(u, anope_dynamic_static_cast<ChannelModeStatus *>(cm)))
423  return;
424  }
425  else if (cm->type == MODE_LIST)
426  {
428 
429  if (!cml->IsValid(wparam))
430  return;
431 
432  if (this->HasMode(cm->name, wparam))
433  return;
434  }
435 
436  if (Me->IsSynced())
437  {
438  if (this->chanserv_modetime != Anope::CurTime)
439  {
440  this->chanserv_modecount = 0;
442  }
443 
444  this->chanserv_modecount++;
445  }
446 
447  ChannelMode *wcm = cm->Wrap(wparam);
448 
449  ModeManager::StackerAdd(bi, this, wcm, true, wparam);
450  MessageSource ms(bi);
451  SetModeInternal(ms, wcm, wparam, enforce_mlock);
452 }
453 
454 void Channel::SetMode(BotInfo *bi, const Anope::string &mname, const Anope::string &param, bool enforce_mlock)
455 {
456  SetMode(bi, ModeManager::FindChannelModeByName(mname), param, enforce_mlock);
457 }
458 
459 void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param, bool enforce_mlock)
460 {
461  if (!cm)
462  return;
463  /* Don't unset modes that arent set */
464  if ((cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && !HasMode(cm->name))
465  return;
466  /* Don't unset status that aren't set */
467  else if (cm->type == MODE_STATUS)
468  {
469  User *u = User::Find(param);
470  if (!u || !HasUserStatus(u, anope_dynamic_static_cast<ChannelModeStatus *>(cm)))
471  return;
472  }
473  else if (cm->type == MODE_LIST)
474  {
475  if (!this->HasMode(cm->name, param))
476  return;
477  }
478 
479  /* Get the param to send, if we need it */
480  Anope::string realparam = param;
481  if (cm->type == MODE_PARAM)
482  {
483  realparam.clear();
485  if (!cmp->minus_no_arg)
486  this->GetParam(cmp->name, realparam);
487  }
488 
489  if (Me->IsSynced())
490  {
491  if (this->chanserv_modetime != Anope::CurTime)
492  {
493  this->chanserv_modecount = 0;
495  }
496 
497  this->chanserv_modecount++;
498  }
499 
500  Anope::string wparam = realparam;
501  ChannelMode *wcm = cm->Wrap(wparam);
502 
503  ModeManager::StackerAdd(bi, this, wcm, false, wparam);
504  MessageSource ms(bi);
505  RemoveModeInternal(ms, wcm, wparam, enforce_mlock);
506 }
507 
508 void Channel::RemoveMode(BotInfo *bi, const Anope::string &mname, const Anope::string &param, bool enforce_mlock)
509 {
510  RemoveMode(bi, ModeManager::FindChannelModeByName(mname), param, enforce_mlock);
511 }
512 
513 bool Channel::GetParam(const Anope::string &mname, Anope::string &target) const
514 {
515  std::multimap<Anope::string, Anope::string>::const_iterator it = this->modes.find(mname);
516 
517  target.clear();
518 
519  if (it != this->modes.end())
520  {
521  target = it->second;
522  return true;
523  }
524 
525  return false;
526 }
527 
528 void Channel::SetModes(BotInfo *bi, bool enforce_mlock, const char *cmodes, ...)
529 {
530  char buf[BUFSIZE] = "";
531  va_list args;
532  Anope::string modebuf, sbuf;
533  int add = -1;
534  va_start(args, cmodes);
535  vsnprintf(buf, BUFSIZE - 1, cmodes, args);
536  va_end(args);
537 
538  Reference<Channel> this_reference(this);
539 
540  spacesepstream sep(buf);
541  sep.GetToken(modebuf);
542  for (unsigned i = 0, end = modebuf.length(); this_reference && i < end; ++i)
543  {
544  ChannelMode *cm;
545 
546  switch (modebuf[i])
547  {
548  case '+':
549  add = 1;
550  continue;
551  case '-':
552  add = 0;
553  continue;
554  default:
555  if (add == -1)
556  continue;
557  cm = ModeManager::FindChannelModeByChar(modebuf[i]);
558  if (!cm)
559  continue;
560  }
561 
562  if (add)
563  {
564  if (cm->type != MODE_REGULAR && sep.GetToken(sbuf))
565  {
566  if (cm->type == MODE_STATUS)
567  {
568  User *targ = User::Find(sbuf);
569  if (targ != NULL)
570  sbuf = targ->GetUID();
571  }
572  this->SetMode(bi, cm, sbuf, enforce_mlock);
573  }
574  else
575  this->SetMode(bi, cm, "", enforce_mlock);
576  }
577  else if (!add)
578  {
579  if (cm->type != MODE_REGULAR && sep.GetToken(sbuf))
580  {
581  if (cm->type == MODE_STATUS)
582  {
583  User *targ = User::Find(sbuf);
584  if (targ != NULL)
585  sbuf = targ->GetUID();
586  }
587  this->RemoveMode(bi, cm, sbuf, enforce_mlock);
588  }
589  else
590  this->RemoveMode(bi, cm, "", enforce_mlock);
591  }
592  }
593 }
594 
595 void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode, time_t ts, bool enforce_mlock)
596 {
597  if (!ts)
598  ;
599  else if (ts > this->creation_time)
600  {
601  Log(LOG_DEBUG) << "Dropping mode " << mode << " on " << this->name << ", " << ts << " > " << this->creation_time;
602  return;
603  }
604  else if (ts < this->creation_time)
605  {
606  Log(LOG_DEBUG) << "Changing TS of " << this->name << " from " << this->creation_time << " to " << ts;
607  this->creation_time = ts;
608  this->Reset();
609  }
610 
611  User *setter = source.GetUser();
612  /* Removing channel modes *may* delete this channel */
613  Reference<Channel> this_reference(this);
614 
615  spacesepstream sep_modes(mode);
616  Anope::string m;
617 
618  sep_modes.GetToken(m);
619 
620  Anope::string modestring;
621  Anope::string paramstring;
622  int add = -1;
623  bool changed = false;
624  for (unsigned int i = 0, end = m.length(); i < end && this_reference; ++i)
625  {
626  ChannelMode *cm;
627 
628  switch (m[i])
629  {
630  case '+':
631  modestring += '+';
632  add = 1;
633  continue;
634  case '-':
635  modestring += '-';
636  add = 0;
637  continue;
638  default:
639  if (add == -1)
640  continue;
642  if (!cm)
643  {
644  Log(LOG_DEBUG) << "Channel::SetModeInternal: Unknown mode char " << m[i];
645  continue;
646  }
647  modestring += cm->mchar;
648  }
649 
650  if (cm->type == MODE_REGULAR)
651  {
652  /* something changed if we are adding a mode we dont have, or removing one we have */
653  changed |= !!add != this->HasMode(cm->name);
654  if (add)
655  this->SetModeInternal(source, cm, "", false);
656  else
657  this->RemoveModeInternal(source, cm, "", false);
658  continue;
659  }
660  else if (cm->type == MODE_PARAM)
661  {
663 
664  if (!add && cmp->minus_no_arg)
665  {
666  this->RemoveModeInternal(source, cm, "", false);
667  continue;
668  }
669  }
670  Anope::string token;
671  if (sep_modes.GetToken(token))
672  {
673  User *u = NULL;
674  if (cm->type == MODE_STATUS && (u = User::Find(token)))
675  paramstring += " " + u->nick;
676  else
677  paramstring += " " + token;
678 
679  changed |= !!add != this->HasMode(cm->name, token);
680  /* CheckModes below doesn't check secureops (+ the module event) */
681  if (add)
682  this->SetModeInternal(source, cm, token, enforce_mlock);
683  else
684  this->RemoveModeInternal(source, cm, token, enforce_mlock);
685  }
686  else
687  Log() << "warning: Channel::SetModesInternal() recieved more modes requiring params than params, modes: " << mode;
688  }
689 
690  if (!this_reference)
691  return;
692 
693  if (changed && source.GetServer() && source.GetServer()->IsSynced())
694  {
695  if (Anope::CurTime != this->server_modetime)
696  {
697  this->server_modecount = 0;
699  }
700 
701  ++this->server_modecount;
702  }
703 
704  if (setter)
705  Log(setter, this, "mode") << modestring << paramstring;
706  else
707  Log(LOG_DEBUG) << source.GetName() << " is setting " << this->name << " to " << modestring << paramstring;
708 
709  if (enforce_mlock)
710  this->CheckModes();
711 }
712 
714 {
715  if (!this->HasMode(mode))
716  return false;
717 
718 
719  std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> m = this->GetModeList(mode);
720  for (; m.first != m.second; ++m.first)
721  {
722  Entry e(mode, m.first->second);
723  if (e.Matches(u))
724  return true;
725  }
726 
727  return false;
728 }
729 
730 void Channel::KickInternal(const MessageSource &source, const Anope::string &nick, const Anope::string &reason)
731 {
732  User *sender = source.GetUser();
733  User *target = User::Find(nick);
734  if (!target)
735  {
736  Log(LOG_DEBUG) << "Channel::KickInternal got a nonexistent user " << nick << " on " << this->name << ": " << reason;
737  return;
738  }
739 
740  if (sender)
741  Log(sender, this, "kick") << "kicked " << target->nick << " (" << reason << ")";
742  else
743  Log(target, this, "kick") << "was kicked by " << source.GetSource() << " (" << reason << ")";
744 
745  Anope::string chname = this->name;
746 
747  ChanUserContainer *cu = target->FindChannel(this);
748  if (cu == NULL)
749  {
750  Log(LOG_DEBUG) << "Channel::KickInternal got kick for user " << target->nick << " from " << source.GetSource() << " who isn't on channel " << this->name;
751  return;
752  }
753 
754  Anope::string this_name = this->name;
755  ChannelStatus status = cu->status;
756 
757  FOREACH_MOD(OnPreUserKicked, (source, cu, reason));
758  this->DeleteUser(target); /* This can delete this; */
759  FOREACH_MOD(OnUserKicked, (source, target, this_name, status, reason));
760 }
761 
762 bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...)
763 {
764  va_list args;
765  char buf[BUFSIZE] = "";
766  va_start(args, reason);
767  vsnprintf(buf, BUFSIZE - 1, reason, args);
768  va_end(args);
769 
770  /* Do not kick protected clients or Ulines */
771  if (u->IsProtected())
772  return false;
773 
774  if (bi == NULL)
775  bi = this->ci->WhoSends();
776 
777  EventReturn MOD_RESULT;
778  FOREACH_RESULT(OnBotKick, MOD_RESULT, (bi, this, u, buf));
779  if (MOD_RESULT == EVENT_STOP)
780  return false;
781  IRCD->SendKick(bi, this, u, "%s", buf);
782  this->KickInternal(bi, u->nick, buf);
783  return true;
784 }
785 
786 void Channel::ChangeTopicInternal(const Anope::string &user, const Anope::string &newtopic, time_t ts)
787 {
788  User *u = User::Find(user);
789 
790  this->topic = newtopic;
791  this->topic_setter = u ? u->nick : user;
792  this->topic_ts = ts;
793  this->topic_time = Anope::CurTime;
794 
795  Log(LOG_DEBUG) << "Topic of " << this->name << " changed by " << (u ? u->nick : user) << " to " << newtopic;
796 
797  FOREACH_MOD(OnTopicUpdated, (this, user, this->topic));
798 }
799 
800 void Channel::ChangeTopic(const Anope::string &user, const Anope::string &newtopic, time_t ts)
801 {
802  User *u = User::Find(user);
803 
804  this->topic = newtopic;
805  this->topic_setter = u ? u->nick : user;
806  this->topic_ts = ts;
807 
808  IRCD->SendTopic(this->ci->WhoSends(), this);
809 
810  /* Now that the topic is set update the time set. This is *after* we set it so the protocol modules are able to tell the old last set time */
811  this->topic_time = Anope::CurTime;
812 
813  FOREACH_MOD(OnTopicUpdated, (this, user, this->topic));
814 }
815 
816 void Channel::SetCorrectModes(User *user, bool give_modes)
817 {
818  if (user == NULL)
819  return;
820 
821  if (!this->ci)
822  return;
823 
824  Log(LOG_DEBUG) << "Setting correct user modes for " << user->nick << " on " << this->name << " (" << (give_modes ? "" : "not ") << "giving modes)";
825 
826  AccessGroup u_access = ci->AccessFor(user);
827 
828  /* Initially only take modes if the channel is being created by a non netmerge */
829  bool take_modes = this->syncing && user->server->IsSynced();
830 
831  FOREACH_MOD(OnSetCorrectModes, (user, this, u_access, give_modes, take_modes));
832 
833  /* Never take modes from ulines */
834  if (user->server->IsULined())
835  take_modes = false;
836 
837  /* whether or not we are giving modes */
838  bool giving = give_modes;
839  /* whether or not we have given a mode */
840  bool given = false;
841  for (unsigned i = 0; i < ModeManager::GetStatusChannelModesByRank().size(); ++i)
842  {
844  bool has_priv = u_access.HasPriv("AUTO" + cm->name);
845 
846  if (give_modes && has_priv)
847  {
848  /* Always give op. If we have already given one mode, don't give more until it has a symbol */
849  if (cm->name == "OP" || !given || (giving && cm->symbol))
850  {
851  this->SetMode(NULL, cm, user->GetUID(), false);
852  /* Now if this contains a symbol don't give any more modes, to prevent setting +qaohv etc on users */
853  giving = !cm->symbol;
854  given = true;
855  }
856  }
857  else if (take_modes && !has_priv && !u_access.HasPriv(cm->name + "ME"))
858  {
859  /* Only remove modes if they are > voice */
860  if (cm->name == "VOICE")
861  take_modes = false;
862  else
863  this->RemoveMode(NULL, cm, user->GetUID(), false);
864  }
865  }
866 }
867 
868 bool Channel::Unban(User *u, const Anope::string &mode, bool full)
869 {
870  if (!this->HasMode(mode))
871  return false;
872 
873  bool ret = false;
874 
875  std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = this->GetModeList(mode);
876  for (; bans.first != bans.second;)
877  {
878  Entry ban(mode, bans.first->second);
879  ++bans.first;
880  if (ban.Matches(u, full))
881  {
882  this->RemoveMode(NULL, mode, ban.GetMask());
883  ret = true;
884  }
885  }
886 
887  return ret;
888 }
889 
891 {
892  if (user->super_admin)
893  return false;
894 
895  /* We don't enforce services restrictions on clients on ulined services
896  * as this will likely lead to kick/rejoin floods. ~ Viper */
897  if (user->IsProtected())
898  return false;
899 
900  Anope::string mask, reason;
901 
902  EventReturn MOD_RESULT;
903  FOREACH_RESULT(OnCheckKick, MOD_RESULT, (user, this, mask, reason));
904  if (MOD_RESULT != EVENT_STOP)
905  return false;
906 
907  if (mask.empty())
908  mask = this->ci->GetIdealBan(user);
909  if (reason.empty())
911 
912  Log(LOG_DEBUG) << "Autokicking " << user->nick << " (" << mask << ") from " << this->name;
913 
914  this->SetMode(NULL, "BAN", mask);
915  this->Kick(NULL, user, "%s", reason.c_str());
916 
917  return true;
918 }
919 
921 {
922  channel_map::const_iterator it = ChannelList.find(name);
923 
924  if (it != ChannelList.end())
925  return it->second;
926  return NULL;
927 }
928 
929 Channel *Channel::FindOrCreate(const Anope::string &name, bool &created, time_t ts)
930 {
931  Channel* &chan = ChannelList[name];
932  created = chan == NULL;
933  if (!chan)
934  chan = new Channel(name, ts);
935  return chan;
936 }
937 
~Channel()
Definition: channels.cpp:53
Definition: bots.h:24
ChanUserContainer * JoinUser(User *u, const ChannelStatus *status)
Definition: channels.cpp:140
bool equals_cs(const char *_str) const
Definition: anope.h:74
const Anope::string GetMask() const
Definition: modes.cpp:817
const ModeList & GetModes() const
Definition: channels.cpp:238
int16_t server_modecount
Definition: channels.h:72
static ChannelMode * FindChannelModeByName(const Anope::string &name)
Definition: modes.cpp:542
bool Matches(User *u, bool full=false) const
Definition: modes.cpp:830
bool IsSynced() const
Definition: servers.cpp:298
Definition: hashcomp.h:84
void clear()
Definition: anope.h:187
void DeleteUser(User *u)
Definition: channels.cpp:154
void Reset()
Definition: channels.cpp:68
bool minus_no_arg
Definition: modes.h:174
virtual void SendTopic(const MessageSource &, Channel *)
Definition: protocol.cpp:170
ChanUserList chans
Definition: users.h:87
#define BUFSIZE
Definition: services.h:18
time_t creation_time
Definition: channels.h:48
virtual bool IsValid(Anope::string &mask) const
Definition: modes.cpp:178
Definition: users.h:34
Anope::string topic_setter
Definition: channels.h:61
virtual void SendKick(const MessageSource &source, const Channel *chan, User *user, const char *fmt,...)
Definition: protocol.cpp:208
ChanUserContainer * FindChannel(Channel *c) const
Definition: users.cpp:716
void DelMode(char c)
Definition: modes.cpp:76
time_t server_modetime
Definition: channels.h:70
void RemoveModeInternal(MessageSource &source, ChannelMode *cm, const Anope::string &param="", bool enforce_mlock=true)
Definition: channels.cpp:321
time_t chanserv_modetime
Definition: channels.h:71
#define FOREACH_RESULT(ename, ret, args)
Definition: modules.h:95
time_t topic_ts
Definition: channels.h:66
bool equals_ci(const char *_str) const
Definition: anope.h:78
static Channel * FindOrCreate(const Anope::string &name, bool &created, time_t ts=Anope::CurTime)
Definition: channels.cpp:929
const Anope::string & GetSource() const
Definition: protocol.cpp:473
bool HasMode(char c) const
Definition: modes.cpp:81
Anope::string name
Definition: channels.h:44
CoreExport time_t CurTime
Definition: main.cpp:41
Anope::string topic
Definition: channels.h:59
bool HasUserStatus(User *u, ChannelModeStatus *cms)
Definition: channels.cpp:181
#define FOREACH_MOD(ename, args)
Definition: modules.h:62
ModeList modes
Definition: channels.h:40
std::pair< ModeList::iterator, ModeList::iterator > GetModeList(const Anope::string &name)
Definition: channels.cpp:243
bool CheckKick(User *user)
Definition: channels.cpp:890
bool GetParam(const Anope::string &name, Anope::string &target) const
Definition: channels.cpp:513
static ChannelInfo * Find(const Anope::string &name)
Definition: regchannel.cpp:630
bool botchannel
Definition: channels.h:52
ChannelMode * Unwrap(Anope::string &param)
Definition: modes.cpp:156
static void StackerDel(User *u)
Definition: modes.cpp:682
bool Unban(User *u, const Anope::string &mode, bool full=false)
Definition: channels.cpp:868
bool IsProtected()
Definition: users.cpp:724
std::multimap< Anope::string, Anope::string > ModeList
Definition: channels.h:36
size_type length() const
Definition: anope.h:131
void CheckModes()
Definition: channels.cpp:105
bool Quitting() const
Definition: users.cpp:763
channel_map ChannelList
Definition: channels.cpp:29
ModeType type
Definition: modes.h:49
#define CHAN_NOT_ALLOWED_TO_JOIN
Definition: language.h:101
Server * GetServer() const
Definition: protocol.cpp:488
virtual ChannelMode * Wrap(Anope::string &param)
Definition: modes.cpp:151
const Anope::string & GetUID() const
Definition: users.cpp:230
void AddMode(char c)
Definition: modes.cpp:70
int16_t bouncy_modes
Definition: channels.h:74
void ChangeTopicInternal(const Anope::string &user, const Anope::string &newtopic, time_t ts=Anope::CurTime)
Definition: channels.cpp:786
char mchar
Definition: modes.h:47
virtual bool IsValid(Anope::string &value) const
Definition: modes.h:180
static ChannelMode * FindChannelModeByChar(char mode)
Definition: modes.cpp:524
void KickInternal(const MessageSource &source, const Anope::string &nick, const Anope::string &reason)
Definition: channels.cpp:730
User * GetUser() const
Definition: protocol.cpp:478
bool empty() const
Definition: anope.h:126
void SetModeInternal(MessageSource &source, ChannelMode *cm, const Anope::string &param="", bool enforce_mlock=true)
Definition: channels.cpp:251
void SetCorrectModes(User *u, bool give_modes)
Definition: channels.cpp:816
void SetModesInternal(MessageSource &source, const Anope::string &mode, time_t ts=0, bool enforce_mlock=true)
Definition: channels.cpp:595
virtual void OnDel(Channel *chan, const Anope::string &mask)
Definition: modes.h:158
time_t topic_time
Definition: channels.h:68
CoreExport IRCDProto * IRCD
Definition: protocol.cpp:23
EventReturn
Definition: modules.h:129
bool CheckDelete()
Definition: channels.cpp:122
Server * server
Definition: users.h:77
CoreExport const char * Translate(const char *string)
Definition: language.cpp:59
ChanUserList users
Definition: channels.h:56
ChanUserContainer * FindUser(User *u) const
Definition: channels.cpp:173
size_t HasMode(const Anope::string &name, const Anope::string &param="")
Definition: channels.cpp:201
ChannelStatus status
Definition: channels.h:28
static void StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool set, const Anope::string &param="")
Definition: modes.cpp:607
void SetModes(BotInfo *bi, bool enforce_mlock, const char *cmodes,...)
Definition: channels.cpp:528
bool MatchesList(User *u, const Anope::string &list)
Definition: channels.cpp:713
Anope::string nick
Definition: users.h:62
bool Kick(BotInfo *bi, User *u, const char *reason=NULL,...)
Definition: channels.cpp:762
static User * Find(const Anope::string &name, bool nick_only=false)
Definition: users.cpp:815
void Clear()
Definition: modes.cpp:91
bool syncing
Definition: channels.h:50
NickCore * Account() const
Definition: users.cpp:422
static Channel * Find(const Anope::string &name)
Definition: channels.cpp:920
bool GetToken(Anope::string &token)
Definition: hashcomp.cpp:99
T anope_dynamic_static_cast(O ptr)
Definition: anope.h:774
Anope::string name
Definition: access.cpp:22
void SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param="", bool enforce_mlock=true)
Definition: channels.cpp:401
bool Empty() const
Definition: modes.cpp:86
CoreExport Server * Me
Definition: servers.cpp:24
const Anope::string & Modes() const
Definition: modes.cpp:96
int16_t chanserv_modecount
Definition: channels.h:73
const char * c_str() const
Definition: anope.h:117
Definition: logger.h:53
bool IsULined() const
Definition: servers.cpp:308
void ChangeTopic(const Anope::string &user, const Anope::string &newtopic, time_t ts=Anope::CurTime)
Definition: channels.cpp:800
Definition: modes.h:388
static const std::vector< ChannelModeStatus * > & GetStatusChannelModesByRank()
Definition: modes.cpp:581
bool super_admin
Definition: users.h:83
Anope::string name
Definition: modes.h:43
virtual void OnAdd(Channel *chan, const Anope::string &mask)
Definition: modes.h:152
void Sync()
Definition: channels.cpp:98
static BotInfo * Find(const Anope::string &nick, bool nick_only=false)
Definition: bots.cpp:249
Channel(const Anope::string &nname, time_t ts=Anope::CurTime)
Definition: channels.cpp:31
const Anope::string & GetName() const
Definition: protocol.cpp:463
void RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param="", bool enforce_mlock=true)
Definition: channels.cpp:459