* @param user The user to delete
* @return number of users left on the channel after deletion of the user
*/
- unsigned long DelUser(User* user);
+ void DelUser(User* user);
/** Obtain the internal reference list
* The internal reference list contains a list of User*.
* @return The number of users left on the channel. If this is zero
* when the method returns, you MUST delete the Channel immediately!
*/
- long KickUser(User *src, User *user, const char* reason);
+ void KickUser(User *src, User *user, const char* reason);
/** Make the server kick user from this channel with the given reason.
* @param user The user being kicked (must be on this channel)
* @return The number of users left on the channel. If this is zero
* when the method returns, you MUST delete the Channel immediately!
*/
- long ServerKickUser(User* user, const char* reason, const std::string& servername = "");
+ void ServerKickUser(User* user, const char* reason, const std::string& servername = "");
/** Part a user from this channel with the given reason.
* If the reason field is NULL, no reason will be sent.
* @return The number of users left on the channel. If this is zero
* when the method returns, you MUST delete the Channel immediately!
*/
- long PartUser(User *user, std::string &reason);
+ void PartUser(User *user, std::string &reason);
/* Join a user to a channel. May be a channel that doesnt exist yet.
* @param user The user to join to the channel.
*/
inline const ExtensibleStore& GetExtList() const { return extensions; }
+ Extensible();
virtual CullResult cull();
virtual ~Extensible();
void doUnhookExtensions(const std::vector<ExtensionItem*>& toRemove);
}
}
+Extensible::Extensible()
+{
+ extensions[NULL] = NULL;
+}
+
CullResult Extensible::cull()
{
for(ExtensibleStore::iterator i = extensions.begin(); i != extensions.end(); ++i)
{
- i->first->free(i->second);
+ if (i->first)
+ i->first->free(i->second);
}
+ extensions.clear();
return classbase::cull();
}
Extensible::~Extensible()
{
+ if (!extensions.empty() && ServerInstance && ServerInstance->Logs)
+ ServerInstance->Logs->Log("CULLLIST", DEBUG,
+ "Extensible destructor called without cull @%p", (void*)this);
}
LocalExtItem::LocalExtItem(const std::string& Key, Module* mod) : ExtensionItem(Key, mod)
return memb;
}
-unsigned long Channel::DelUser(User* user)
+void Channel::DelUser(User* user)
{
UserMembIter a = userlist.find(user);
if (a != userlist.end())
{
+ a->second->cull();
delete a->second;
userlist.erase(a);
}
-
- return userlist.size();
}
bool Channel::HasUser(User* user)
* 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, std::string &reason)
+void Channel::PartUser(User *user, std::string &reason)
{
if (!user)
- return this->GetUserCounter();
+ return;
Membership* memb = GetUser(user);
this->RemoveAllPrefixes(user);
}
- if (!this->DelUser(user)) /* if there are no users left on the channel... */
+ this->DelUser(user);
+ if (userlist.empty())
{
+ ModResult res;
+ FIRST_MOD_RESULT(OnChannelPreDelete, res, (this));
+ if (res == MOD_RES_DENY)
+ return;
chan_hash::iterator iter = ServerInstance->chanlist->find(this->name);
/* kill the record */
if (iter != ServerInstance->chanlist->end())
{
- ModResult res;
- FIRST_MOD_RESULT(OnChannelPreDelete, res, (this));
- if (res == MOD_RES_DENY)
- return 1; // delete halted by module
FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this));
ServerInstance->chanlist->erase(iter);
}
- return 0;
+ ServerInstance->GlobalCulls.AddItem(this);
}
-
- return this->GetUserCounter();
}
-long Channel::ServerKickUser(User* user, const char* reason, const std::string& servername)
+void Channel::ServerKickUser(User* user, const char* reason, const std::string& servername)
{
if (servername.empty() || !ServerInstance->Config->HideWhoisServer.empty())
ServerInstance->FakeClient->server = ServerInstance->Config->ServerName;
else
ServerInstance->FakeClient->server = servername;
- return this->KickUser(ServerInstance->FakeClient, user, reason);
+ KickUser(ServerInstance->FakeClient, user, reason);
}
-long Channel::KickUser(User *src, User *user, const char* reason)
+void Channel::KickUser(User *src, User *user, const char* reason)
{
if (!src || !user || !reason)
- return this->GetUserCounter();
+ return;
Membership* memb = GetUser(user);
if (IS_LOCAL(src))
if (!memb)
{
src->WriteNumeric(ERR_USERNOTINCHANNEL, "%s %s %s :They are not on that channel",src->nick.c_str(), user->nick.c_str(), this->name.c_str());
- return this->GetUserCounter();
+ return;
}
if ((ServerInstance->ULine(user->server)) && (!ServerInstance->ULine(src->server)))
{
src->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :Only a u-line may kick a u-line from a channel.",src->nick.c_str(), this->name.c_str());
- return this->GetUserCounter();
+ return;
}
ModResult res;
FIRST_MOD_RESULT(OnUserPreKick, res, (src,memb,reason));
if (res == MOD_RES_DENY)
- return this->GetUserCounter();
+ return;
if (res == MOD_RES_PASSTHRU)
{
if ((them < HALFOP_VALUE) || (them < us))
{
src->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must be a channel %soperator",src->nick.c_str(), this->name.c_str(), them >= HALFOP_VALUE ? "" : "half-");
- return this->GetUserCounter();
+ return;
}
}
}
this->RemoveAllPrefixes(user);
}
- if (!this->DelUser(user))
- /* if there are no users left on the channel */
+ this->DelUser(user);
+ if (userlist.empty())
{
- chan_hash::iterator iter = ServerInstance->chanlist->find(this->name.c_str());
-
+ ModResult res;
+ FIRST_MOD_RESULT(OnChannelPreDelete, res, (this));
+ if (res == MOD_RES_DENY)
+ return;
+ chan_hash::iterator iter = ServerInstance->chanlist->find(this->name);
/* kill the record */
if (iter != ServerInstance->chanlist->end())
{
- ModResult res;
- FIRST_MOD_RESULT(OnChannelPreDelete, res, (this));
- if (res == MOD_RES_DENY)
- return 1; // delete halted by module
FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this));
ServerInstance->chanlist->erase(iter);
}
- return 0;
+ ServerInstance->GlobalCulls.AddItem(this);
}
-
- return this->GetUserCounter();
}
void Channel::WriteChannel(User* user, const char* text, ...)
reason.assign(user->nick, 0, ServerInstance->Config->Limits.MaxKick);
}
- if (!c->KickUser(user, u, reason.c_str()))
- /* Nobody left here, delete the Channel */
- delete c;
+ c->KickUser(user, u, reason.c_str());
return CMD_SUCCESS;
}
if (c)
{
- if (!c->PartUser(user, reason))
- /* Arse, who stole our channel! :/ */
- delete c;
+ c->PartUser(user, reason);
}
else
{
}
const UserMembList* users = c->GetUsers();
for(UserMembCIter j = users->begin(); j != users->end(); ++j)
- if (IS_LOCAL(j->first) && !c->ServerKickUser(j->first, "Channel name no longer valid", NULL))
- delete c;
+ if (IS_LOCAL(j->first))
+ c->ServerKickUser(j->first, "Channel name no longer valid", NULL);
}
badchan = false;
}
return CMD_FAILURE;
}
- /* XXX in the future, this may move to a static Channel method (the delete.) -- w00t */
- if (!channel->PartUser(user, reason))
- delete channel;
+ channel->PartUser(user, reason);
Channel::JoinUser(user, parameters[0].c_str(), true, "", false, ServerInstance->Time());
}
char kickmessage[MAXBUF];
snprintf(kickmessage, MAXBUF, "Channel flood triggered (limit is %d lines in %d secs)", f->lines, f->secs);
- if (!dest->ServerKickUser(user, kickmessage))
- {
- delete dest;
- }
+ dest->ServerKickUser(user, kickmessage);
return MOD_RES_DENY;
}
channel->WriteChannelWithServ(ServerInstance->Config->ServerName.c_str(), "NOTICE %s :%s removed %s from the channel", channel->name.c_str(), user->nick.c_str(), target->nick.c_str());
target->WriteServ("NOTICE %s :*** %s removed you from %s with the message: %s", target->nick.c_str(), user->nick.c_str(), channel->name.c_str(), reasonparam.c_str());
- if (!channel->PartUser(target, reason))
- delete channel;
+ channel->PartUser(target, reason);
}
else
{
*/
if (IS_LOCAL(dest))
{
- if (!channel->ServerKickUser(dest, reason, servername))
- delete channel;
+ channel->ServerKickUser(dest, reason, servername);
Channel *n = ServerInstance->FindChan(parameters[1]);
if (n && n->HasUser(dest))
*/
if (IS_LOCAL(dest))
{
- if (!channel->PartUser(dest, reason))
- delete channel;
+ channel->PartUser(dest, reason);
Channel* n = ServerInstance->FindChan(parameters[1]);
if (!n)
{
/* only part if it's local, otherwise just pass it on! */
if (IS_LOCAL(u))
- if (!c->PartUser(u, reason))
- delete c;
+ c->PartUser(u, reason);
Utils->DoOneToAllButSender(prefix,"SVSPART",params,prefix);
}
{
Channel* c = *f;
c->RemoveAllPrefixes(this);
- if (c->DelUser(this) == 0)
- {
- /* No users left in here, mark it for deletion */
- try
- {
- to_delete.push_back(c);
- }
- catch (...)
- {
- ServerInstance->Logs->Log("USERS", DEBUG,"Exception in User::PurgeEmptyChannels to_delete.push_back()");
- }
- }
- }
-
- for (std::vector<Channel*>::iterator n = to_delete.begin(); n != to_delete.end(); n++)
- {
- Channel* thischan = *n;
- chan_hash::iterator i2 = ServerInstance->chanlist->find(thischan->name);
- if (i2 != ServerInstance->chanlist->end())
- {
- ModResult MOD_RESULT;
- FIRST_MOD_RESULT(OnChannelPreDelete, MOD_RESULT, (i2->second));
- if (MOD_RESULT == MOD_RES_DENY)
- continue; // delete halted by module
- FOREACH_MOD(I_OnChannelDelete,OnChannelDelete(i2->second));
- delete i2->second;
- ServerInstance->chanlist->erase(i2);
- this->chans.erase(*n);
- }
+ c->DelUser(this);
}
this->UnOper();