Channel::Channel(const std::string &cname, time_t ts)
{
- chan_hash::iterator findchan = ServerInstance->chanlist->find(cname);
- if (findchan != ServerInstance->chanlist->end())
+ if (!ServerInstance->chanlist->insert(std::make_pair(cname, this)).second)
throw CoreException("Cannot create duplicate channel " + cname);
- (*(ServerInstance->chanlist))[cname.c_str()] = this;
- this->name.assign(cname, 0, ServerInstance->Config->Limits.ChanMax);
+ this->name = cname;
this->age = ts ? ts : ServerInstance->Time();
maxbans = topicset = 0;
}
this->topic.assign(ntopic, 0, ServerInstance->Config->Limits.MaxTopic);
- if (u)
- {
- this->setby.assign(ServerInstance->Config->FullHostInTopic ? u->GetFullHost() : u->nick, 0, 128);
- this->WriteChannel(u, "TOPIC %s :%s", this->name.c_str(), this->topic.c_str());
- }
- else
- {
- this->setby.assign(ServerInstance->Config->ServerName);
- this->WriteChannelWithServ(ServerInstance->Config->ServerName, "TOPIC %s :%s", this->name.c_str(), this->topic.c_str());
- }
+ this->setby.assign(ServerInstance->Config->FullHostInTopic ? u->GetFullHost() : u->nick, 0, 128);
+ this->WriteChannel(u, "TOPIC %s :%s", this->name.c_str(), this->topic.c_str());
this->topicset = ServerInstance->Time();
FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this));
ServerInstance->chanlist->erase(iter);
}
+
+ ClearInvites();
ServerInstance->GlobalCulls.AddItem(this);
}
}
if (mode)
{
if (mode->GetNumParams(true))
+ {
list.GetToken(parameter);
+ // If the parameter begins with a ':' then it's invalid
+ if (parameter.c_str()[0] == ':')
+ continue;
+ }
else
parameter.clear();
+ if ((mode->GetNumParams(true)) && (parameter.empty()))
+ continue;
+
mode->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, this, parameter, true);
}
}
if (!user || !cn || user->registered != REG_ALL)
return NULL;
- char cname[MAXBUF];
std::string privs;
Channel *Ptr;
}
}
- strlcpy(cname, cn, ServerInstance->Config->Limits.ChanMax);
+ std::string cname;
+ cname.assign(std::string(cn), 0, ServerInstance->Config->Limits.ChanMax);
Ptr = ServerInstance->FindChan(cname);
bool created_by_local = false;
if (IS_LOCAL(user) && override == false)
{
ModResult MOD_RESULT;
- FIRST_MOD_RESULT(OnUserPreJoin, MOD_RESULT, (user, NULL, cname, privs, key ? key : ""));
+ FIRST_MOD_RESULT(OnUserPreJoin, MOD_RESULT, (user, NULL, cname.c_str(), privs, key ? key : ""));
if (MOD_RESULT == MOD_RES_DENY)
return NULL;
}
if (IS_LOCAL(user) && override == false)
{
ModResult MOD_RESULT;
- FIRST_MOD_RESULT(OnUserPreJoin, MOD_RESULT, (user, Ptr, cname, privs, key ? key : ""));
+ FIRST_MOD_RESULT(OnUserPreJoin, MOD_RESULT, (user, Ptr, cname.c_str(), privs, key ? key : ""));
if (MOD_RESULT == MOD_RES_DENY)
{
return NULL;
return (result == MOD_RES_DENY);
// extbans were handled above, if this is one it obviously didn't match
- if (mask[1] == ':')
+ if ((mask.length() <= 2) || (mask[1] == ':'))
return false;
std::string::size_type at = mask.find('@');
char tb[MAXBUF];
snprintf(tb,MAXBUF,":%s %s", serversource ? ServerInstance->Config->ServerName.c_str() : user->GetFullHost().c_str(), text.c_str());
- std::string out = tb;
this->RawWriteAllExcept(user, serversource, status, except_list, std::string(tb));
}
int count = 0;
for (UserMembIter i = userlist.begin(); i != userlist.end(); i++)
{
- if (!(i->first->IsModeSet('i')))
+ if (!i->first->quitting && !i->first->IsModeSet('i'))
count++;
}
*/
void Channel::UserList(User *user)
{
- char list[MAXBUF];
- size_t dlen, curlen;
-
if (!IS_LOCAL(user))
return;
- if (this->IsModeSet('s') && !this->HasUser(user) && !user->HasPrivPermission("channels/auspex"))
+ bool has_privs = user->HasPrivPermission("channels/auspex");
+
+ if (this->IsModeSet('s') && !this->HasUser(user) && !has_privs)
{
user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), this->name.c_str());
return;
}
- dlen = curlen = snprintf(list,MAXBUF,"%s %c %s :", user->nick.c_str(), this->IsModeSet('s') ? '@' : this->IsModeSet('p') ? '*' : '=', this->name.c_str());
+ std::string list = user->nick;
+ list.push_back(' ');
+ list.push_back(this->IsModeSet('s') ? '@' : this->IsModeSet('p') ? '*' : '=');
+ list.push_back(' ');
+ list.append(this->name).append(" :");
+ std::string::size_type pos = list.size();
- int numusers = 0;
- char* ptr = list + dlen;
+ bool has_one = false;
/* Improvement by Brain - this doesnt change in value, so why was it inside
* the loop?
*/
bool has_user = this->HasUser(user);
- for (UserMembIter i = userlist.begin(); i != userlist.end(); i++)
+ const size_t maxlen = MAXBUF - 10 - ServerInstance->Config->ServerName.size();
+ std::string prefixlist;
+ std::string nick;
+ for (UserMembIter i = userlist.begin(); i != userlist.end(); ++i)
{
- if ((!has_user) && (i->first->IsModeSet('i')))
+ if (i->first->quitting)
+ continue;
+ if ((!has_user) && (i->first->IsModeSet('i')) && (!has_privs))
{
/*
* user is +i, and source not on the channel, does not show
continue;
}
- std::string prefixlist = this->GetPrefixChar(i->first);
- std::string nick = i->first->nick;
+ prefixlist = this->GetPrefixChar(i->first);
+ nick = i->first->nick;
FOREACH_MOD(I_OnNamesListItem, OnNamesListItem(user, i->second, prefixlist, nick));
if (nick.empty())
continue;
- size_t ptrlen = 0;
-
- if (curlen + prefixlist.length() + nick.length() + 1 > 480)
+ if (list.size() + prefixlist.length() + nick.length() + 1 > maxlen)
{
/* list overflowed into multiple numerics */
- user->WriteNumeric(RPL_NAMREPLY, std::string(list));
+ user->WriteNumeric(RPL_NAMREPLY, list);
- /* reset our lengths */
- dlen = curlen = snprintf(list,MAXBUF,"%s %c %s :", user->nick.c_str(), this->IsModeSet('s') ? '@' : this->IsModeSet('p') ? '*' : '=', this->name.c_str());
- ptr = list + dlen;
-
- numusers = 0;
+ // Erase all nicks, keep the constant part
+ list.erase(pos);
+ has_one = false;
}
- ptrlen = snprintf(ptr, MAXBUF, "%s%s ", prefixlist.c_str(), nick.c_str());
-
- curlen += ptrlen;
- ptr += ptrlen;
+ list.append(prefixlist).append(nick).push_back(' ');
- numusers++;
+ has_one = true;
}
/* if whats left in the list isnt empty, send it */
- if (numusers)
+ if (has_one)
{
- user->WriteNumeric(RPL_NAMREPLY, std::string(list));
+ user->WriteNumeric(RPL_NAMREPLY, list);
}
user->WriteNumeric(RPL_ENDOFNAMES, "%s %s :End of /NAMES list.", user->nick.c_str(), this->name.c_str());
m->second->modes.clear();
}
}
+
+void Invitation::Create(Channel* c, LocalUser* u, time_t timeout)
+{
+ if ((timeout != 0) && (ServerInstance->Time() >= timeout))
+ // Expired, don't bother
+ return;
+
+ ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Create chan=%s user=%s", c->name.c_str(), u->uuid.c_str());
+
+ Invitation* inv = Invitation::Find(c, u, false);
+ if (inv)
+ {
+ if ((inv->expiry == 0) || (inv->expiry > timeout))
+ return;
+ inv->expiry = timeout;
+ ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Create changed expiry in existing invitation %p", (void*) inv);
+ }
+ else
+ {
+ inv = new Invitation(c, u, timeout);
+ c->invites.push_back(inv);
+ u->invites.push_back(inv);
+ ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Create created new invitation %p", (void*) inv);
+ }
+}
+
+Invitation* Invitation::Find(Channel* c, LocalUser* u, bool check_expired)
+{
+ ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Find chan=%s user=%s check_expired=%d", c ? c->name.c_str() : "NULL", u ? u->uuid.c_str() : "NULL", check_expired);
+ if (!u || u->invites.empty())
+ return NULL;
+
+ InviteList locallist;
+ locallist.swap(u->invites);
+
+ Invitation* result = NULL;
+ for (InviteList::iterator i = locallist.begin(); i != locallist.end(); )
+ {
+ Invitation* inv = *i;
+ if ((check_expired) && (inv->expiry != 0) && (inv->expiry <= ServerInstance->Time()))
+ {
+ /* Expired invite, remove it. */
+ std::string expiration = ServerInstance->TimeString(inv->expiry);
+ ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Find ecountered expired entry: %p expired %s", (void*) inv, expiration.c_str());
+ i = locallist.erase(i);
+ inv->cull();
+ delete inv;
+ }
+ else
+ {
+ /* Is it what we're searching for? */
+ if (inv->chan == c)
+ {
+ result = inv;
+ break;
+ }
+ ++i;
+ }
+ }
+
+ locallist.swap(u->invites);
+ ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Find result=%p", (void*) result);
+ return result;
+}
+
+Invitation::~Invitation()
+{
+ // Remove this entry from both lists
+ InviteList::iterator it = std::find(chan->invites.begin(), chan->invites.end(), this);
+ if (it != chan->invites.end())
+ chan->invites.erase(it);
+ it = std::find(user->invites.begin(), user->invites.end(), this);
+ if (it != user->invites.end())
+ user->invites.erase(it);
+}
+
+void InviteBase::ClearInvites()
+{
+ ServerInstance->Logs->Log("INVITEBASE", DEBUG, "InviteBase::ClearInvites %p", (void*) this);
+ InviteList locallist;
+ locallist.swap(invites);
+ for (InviteList::const_iterator i = locallist.begin(); i != locallist.end(); ++i)
+ {
+ (*i)->cull();
+ delete *i;
+ }
+}