+ 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();
+}
+
+void Channel::WriteChannel(User* user, const char* text, ...)
+{
+ char textbuffer[MAXBUF];
+ va_list argsPtr;
+
+ if (!user || !text)
+ return;
+
+ va_start(argsPtr, text);
+ vsnprintf(textbuffer, MAXBUF, text, argsPtr);
+ va_end(argsPtr);
+
+ this->WriteChannel(user, std::string(textbuffer));
+}
+
+void Channel::WriteChannel(User* user, const std::string &text)
+{
+ CUList *ulist = this->GetUsers();
+ char tb[MAXBUF];
+
+ if (!user)
+ return;
+
+ snprintf(tb,MAXBUF,":%s %s",user->GetFullHost(),text.c_str());
+ std::string out = tb;
+
+ for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
+ {
+ if (IS_LOCAL(i->first))
+ i->first->Write(out);
+ }
+}
+
+void Channel::WriteChannelWithServ(const char* ServName, const char* text, ...)
+{
+ char textbuffer[MAXBUF];
+ va_list argsPtr;
+
+ if (!text)
+ return;
+
+ va_start(argsPtr, text);
+ vsnprintf(textbuffer, MAXBUF, text, argsPtr);
+ va_end(argsPtr);
+
+ this->WriteChannelWithServ(ServName, std::string(textbuffer));
+}
+
+void Channel::WriteChannelWithServ(const char* ServName, const std::string &text)
+{
+ CUList *ulist = this->GetUsers();
+ char tb[MAXBUF];
+
+ snprintf(tb,MAXBUF,":%s %s",ServName ? ServName : ServerInstance->Config->ServerName, text.c_str());
+ std::string out = tb;
+
+ for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
+ {
+ if (IS_LOCAL(i->first))
+ i->first->Write(out);
+ }
+}
+
+/* write formatted text from a source user to all users on a channel except
+ * for the sender (for privmsg etc) */
+void Channel::WriteAllExceptSender(User* user, bool serversource, char status, const char* text, ...)
+{
+ char textbuffer[MAXBUF];
+ va_list argsPtr;
+
+ if (!text)
+ return;
+
+ va_start(argsPtr, text);
+ vsnprintf(textbuffer, MAXBUF, text, argsPtr);
+ va_end(argsPtr);
+
+ this->WriteAllExceptSender(user, serversource, status, std::string(textbuffer));
+}
+
+void Channel::WriteAllExcept(User* user, bool serversource, char status, CUList &except_list, const char* text, ...)
+{
+ char textbuffer[MAXBUF];
+ va_list argsPtr;
+
+ if (!text)
+ return;
+
+ va_start(argsPtr, text);
+ vsnprintf(textbuffer, MAXBUF, text, argsPtr);
+ va_end(argsPtr);
+
+ this->WriteAllExcept(user, serversource, status, except_list, std::string(textbuffer));
+}
+
+void Channel::WriteAllExcept(User* user, bool serversource, char status, CUList &except_list, const std::string &text)
+{
+ CUList *ulist = this->GetUsers();
+ char tb[MAXBUF];
+
+ snprintf(tb,MAXBUF,":%s %s",user->GetFullHost(),text.c_str());
+ std::string out = tb;
+
+ for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
+ {
+ if ((IS_LOCAL(i->first)) && (except_list.find(i->first) == except_list.end()))
+ {
+ /* User doesnt have the status we're after */
+ if (status && !strchr(this->GetAllPrefixChars(i->first), status))
+ continue;
+
+ if (serversource)
+ i->first->WriteServ(text);
+ else
+ i->first->Write(out);
+ }
+ }
+}
+
+void Channel::WriteAllExceptSender(User* user, bool serversource, char status, const std::string& text)
+{
+ CUList except_list;
+ except_list[user] = user->nick;
+ this->WriteAllExcept(user, serversource, status, except_list, std::string(text));
+}
+
+/*
+ * return a count of the users on a specific channel accounting for
+ * invisible users who won't increase the count. e.g. for /LIST
+ */
+int Channel::CountInvisible()
+{
+ int count = 0;
+ CUList *ulist= this->GetUsers();
+ for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
+ {
+ if (!(i->first->IsModeSet('i')))
+ count++;
+ }
+
+ return count;
+}
+
+char* Channel::ChanModes(bool showkey)
+{
+ static char scratch[MAXBUF];
+ static char sparam[MAXBUF];
+ char* offset = scratch;
+ std::string extparam;
+
+ *scratch = '\0';
+ *sparam = '\0';
+
+ /* This was still iterating up to 190, Channel::modes is only 64 elements -- Om */
+ for(int n = 0; n < 64; n++)
+ {
+ if(this->modes[n])
+ {
+ *offset++ = n + 65;
+ extparam.clear();
+ switch (n)
+ {
+ case CM_KEY:
+ extparam = (showkey ? this->key : "<key>");
+ break;
+ case CM_LIMIT:
+ extparam = ConvToStr(this->limit);
+ break;
+ case CM_NOEXTERNAL:
+ case CM_TOPICLOCK:
+ case CM_INVITEONLY:
+ case CM_MODERATED:
+ case CM_SECRET:
+ case CM_PRIVATE:
+ /* We know these have no parameters */
+ break;
+ default:
+ extparam = this->GetModeParameter(n + 65);
+ break;
+ }
+ if (!extparam.empty())
+ {
+ charlcat(sparam,' ',MAXBUF);
+ strlcat(sparam,extparam.c_str(),MAXBUF);
+ }
+ }
+ }
+
+ /* Null terminate scratch */
+ *offset = '\0';
+ strlcat(scratch,sparam,MAXBUF);
+ return scratch;
+}
+
+/* compile a userlist of a channel into a string, each nick seperated by
+ * spaces and op, voice etc status shown as @ and +, and send it to 'user'
+ */
+void Channel::UserList(User *user, CUList *ulist)
+{
+ char list[MAXBUF];
+ size_t dlen, curlen;
+ int MOD_RESULT = 0;
+ bool call_modules = true;
+
+ if (!IS_LOCAL(user))
+ return;
+
+ FOREACH_RESULT(I_OnUserList,OnUserList(user, this, ulist));
+ if (MOD_RESULT == 1)
+ call_modules = false;
+
+ if (MOD_RESULT != -1)
+ {
+ if ((this->IsModeSet('s')) && (!this->HasUser(user)))
+ {
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick, this->name);