+ // XXX. do we need events?
+ char mask[MAXBUF];
+ char *maskptr;
+
+ snprintf(mask, MAXBUF, "%s!%s@%s", user->nick, user->ident, user->GetIPString());
+
+ for (BanList::iterator i = this->bans.begin(); i != this->bans.end(); i++)
+ {
+ if (i->data[0] != type || i->data[1] != ':')
+ continue;
+
+ // Iterate past char and : to get to the mask without doing a data copy(!)
+ maskptr = i->data;
+ maskptr++; // past the char
+ maskptr++; // past the :
+
+ /* This allows CIDR ban matching
+ *
+ * Full masked host Full unmasked host IP with/without CIDR
+ */
+ if ((match(user->GetFullHost(), maskptr)) || (match(user->GetFullRealHost(), maskptr)) || (match(mask, maskptr, true)))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Channel::PartUser
+ * remove a channel from a users record, and return the number of users left.
+ * Therefore, if this function returns 0 the caller should delete the Channel.
+ */
+long Channel::PartUser(User *user, const char* reason)
+{
+ bool silent = false;
+
+ if (!user)
+ return this->GetUserCounter();
+
+ UCListIter i = user->chans.find(this);
+ if (i != user->chans.end())
+ {
+ FOREACH_MOD(I_OnUserPart,OnUserPart(user, this, reason ? reason : "", silent));
+
+ if (!silent)
+ this->WriteChannel(user, "PART %s%s%s", this->name, reason ? " :" : "", reason ? reason : "");
+
+ user->chans.erase(i);
+ this->RemoveAllPrefixes(user);
+ }
+
+ if (!this->DelUser(user)) /* if there are no users left on the channel... */
+ {
+ chan_hash::iterator iter = ServerInstance->chanlist->find(this->name);
+ /* kill the record */
+ if (iter != ServerInstance->chanlist->end())
+ {
+ int MOD_RESULT = 0;
+ FOREACH_RESULT_I(ServerInstance,I_OnChannelPreDelete, OnChannelPreDelete(this));
+ if (MOD_RESULT == 1)
+ return 1; // delete halted by module
+ FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this));
+ ServerInstance->chanlist->erase(iter);
+ }
+ return 0;
+ }
+
+ return this->GetUserCounter();
+}
+
+long Channel::ServerKickUser(User* user, const char* reason, bool triggerevents, const char* servername)
+{
+ bool silent = false;
+
+ if (!user || !reason)
+ return this->GetUserCounter();
+
+ if (IS_LOCAL(user))
+ {
+ if (!this->HasUser(user))
+ {
+ /* Not on channel */
+ return this->GetUserCounter();
+ }
+ }
+
+ if (servername == NULL || *ServerInstance->Config->HideWhoisServer)
+ servername = ServerInstance->Config->ServerName;
+
+ if (triggerevents)
+ {
+ FOREACH_MOD(I_OnUserKick,OnUserKick(NULL, user, this, reason, silent));
+ }
+
+ UCListIter i = user->chans.find(this);
+ if (i != user->chans.end())
+ {
+ if (!silent)
+ this->WriteChannelWithServ(servername, "KICK %s %s :%s", this->name, user->nick, reason);
+
+ user->chans.erase(i);
+ this->RemoveAllPrefixes(user);
+ }
+
+ if (!this->DelUser(user))
+ {
+ chan_hash::iterator iter = ServerInstance->chanlist->find(this->name);
+ /* kill the record */
+ if (iter != ServerInstance->chanlist->end())
+ {
+ int MOD_RESULT = 0;
+ FOREACH_RESULT_I(ServerInstance,I_OnChannelPreDelete, OnChannelPreDelete(this));
+ if (MOD_RESULT == 1)
+ return 1; // delete halted by module
+ FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this));
+ ServerInstance->chanlist->erase(iter);
+ }
+ return 0;
+ }
+
+ return this->GetUserCounter();
+}
+
+long Channel::KickUser(User *src, User *user, const char* reason)
+{
+ bool silent = false;
+
+ if (!src || !user || !reason)
+ return this->GetUserCounter();
+
+ if (IS_LOCAL(src))
+ {
+ if (!this->HasUser(user))
+ {
+ src->WriteNumeric(441, "%s %s %s :They are not on that channel",src->nick, user->nick, this->name);
+ return this->GetUserCounter();
+ }
+ if ((ServerInstance->ULine(user->server)) && (!ServerInstance->ULine(src->server)))
+ {
+ src->WriteNumeric(482, "%s %s :Only a u-line may kick a u-line from a channel.",src->nick, this->name);
+ return this->GetUserCounter();
+ }
+ int MOD_RESULT = 0;
+
+ if (!ServerInstance->ULine(src->server))
+ {
+ MOD_RESULT = 0;
+ FOREACH_RESULT(I_OnUserPreKick,OnUserPreKick(src,user,this,reason));
+ if (MOD_RESULT == 1)
+ return this->GetUserCounter();
+ }
+ /* Set to -1 by OnUserPreKick if explicit allow was set */
+ if (MOD_RESULT != -1)
+ {
+ FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(src,user,this,AC_KICK));
+ if ((MOD_RESULT == ACR_DENY) && (!ServerInstance->ULine(src->server)))
+ return this->GetUserCounter();
+
+ if ((MOD_RESULT == ACR_DEFAULT) || (!ServerInstance->ULine(src->server)))
+ {
+ int them = this->GetStatus(src);
+ int us = this->GetStatus(user);
+ if ((them < STATUS_HOP) || (them < us))
+ {
+ src->WriteNumeric(482, "%s %s :You must be a channel %soperator",src->nick, this->name, them == STATUS_HOP ? "" : "half-");
+ return this->GetUserCounter();
+ }
+ }
+ }
+ }
+
+ FOREACH_MOD(I_OnUserKick,OnUserKick(src, user, this, reason, silent));
+
+ UCListIter i = user->chans.find(this);
+ if (i != user->chans.end())
+ {
+ /* zap it from the channel list of the user */
+ if (!silent)
+ this->WriteChannel(src, "KICK %s %s :%s", this->name, user->nick, reason);
+
+ user->chans.erase(i);
+ this->RemoveAllPrefixes(user);
+ }
+
+ if (!this->DelUser(user))
+ /* if there are no users left on the channel */
+ {
+ chan_hash::iterator iter = ServerInstance->chanlist->find(this->name);
+
+ /* kill the record */
+ if (iter != ServerInstance->chanlist->end())
+ {
+ int MOD_RESULT = 0;
+ FOREACH_RESULT_I(ServerInstance,I_OnChannelPreDelete, OnChannelPreDelete(this));
+ if (MOD_RESULT == 1)
+ return 1; // delete halted by module
+ FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this));
+ ServerInstance->chanlist->erase(iter);
+ }
+ return 0;
+ }
+
+ return this->GetUserCounter();