Channel::Channel(InspIRCd* Instance, const std::string &cname, time_t ts) : ServerInstance(Instance)
{
- chan_hash::iterator findchan = ServerInstance->chanlist->find(name);
+ chan_hash::iterator findchan = ServerInstance->chanlist->find(cname);
if (findchan != Instance->chanlist->end())
throw CoreException("Cannot create duplicate channel " + cname);
void Channel::SetDefaultModes()
{
+ ServerInstance->Logs->Log("CHANNELS", DEBUG, "SetDefaultModes %s", ServerInstance->Config->DefaultModes);
irc::spacesepstream list(ServerInstance->Config->DefaultModes);
std::string modeseq;
std::string parameter;
{
if (user->chans.size() >= user->GetMaxChans())
{
- user->WriteServ("405 %s %s :You are on too many channels",user->nick, cn);
+ user->WriteNumeric(405, "%s %s :You are on too many channels",user->nick, cn);
return NULL;
}
}
{
if (user->chans.size() >= Instance->Config->OperMaxChans)
{
- user->WriteServ("405 %s %s :You are on too many channels",user->nick, cn);
+ user->WriteNumeric(405, "%s %s :You are on too many channels",user->nick, cn);
return NULL;
}
}
{
if (user->chans.size() >= Instance->Config->MaxChans)
{
- user->WriteServ("405 %s %s :You are on too many channels",user->nick, cn);
+ user->WriteNumeric(405, "%s %s :You are on too many channels",user->nick, cn);
return NULL;
}
}
if (IS_LOCAL(user) && override == false)
{
MOD_RESULT = 0;
- FOREACH_RESULT_I(Instance,I_OnUserPreJoin,OnUserPreJoin(user,NULL,cname,privs));
+ FOREACH_RESULT_I(Instance,I_OnUserPreJoin, OnUserPreJoin(user, NULL, cname, privs, key ? key : ""));
if (MOD_RESULT == 1)
return NULL;
}
if (IS_LOCAL(user) && override == false)
{
MOD_RESULT = 0;
- FOREACH_RESULT_I(Instance,I_OnUserPreJoin,OnUserPreJoin(user,Ptr,cname,privs));
+ FOREACH_RESULT_I(Instance,I_OnUserPreJoin, OnUserPreJoin(user, Ptr, cname, privs, key ? key : ""));
if (MOD_RESULT == 1)
{
return NULL;
{
if ((!key) || strcmp(key,Ptr->key))
{
- user->WriteServ("475 %s %s :Cannot join channel (Incorrect channel key)",user->nick, Ptr->name);
+ user->WriteNumeric(475, "%s %s :Cannot join channel (Incorrect channel key)",user->nick, Ptr->name);
return NULL;
}
}
{
if (!user->IsInvited(Ptr->name))
{
- user->WriteServ("473 %s %s :Cannot join channel (Invite only)",user->nick, Ptr->name);
+ user->WriteNumeric(473, "%s %s :Cannot join channel (Invite only)",user->nick, Ptr->name);
return NULL;
}
}
{
if (Ptr->GetUserCounter() >= Ptr->limit)
{
- user->WriteServ("471 %s %s :Cannot join channel (Channel is full)",user->nick, Ptr->name);
+ user->WriteNumeric(471, "%s %s :Cannot join channel (Channel is full)",user->nick, Ptr->name);
return NULL;
}
}
{
if (Ptr->IsBanned(user))
{
- user->WriteServ("474 %s %s :Cannot join channel (You're banned)",user->nick, Ptr->name);
+ user->WriteNumeric(474, "%s %s :Cannot join channel (You're banned)",user->nick, Ptr->name);
return NULL;
}
}
}
/* As spotted by jilles, dont bother to set this on remote users */
- if (IS_LOCAL(user) && Ptr->GetUserCounter() == 1)
+ if (IS_LOCAL(user) && Ptr->GetUserCounter() == 0)
Ptr->SetDefaultModes();
return Channel::ForceChan(Instance, Ptr, user, privs, bursting);
{
if (Ptr->topicset)
{
- user->WriteServ("332 %s %s :%s", user->nick, Ptr->name, Ptr->topic);
- user->WriteServ("333 %s %s %s %lu", user->nick, Ptr->name, Ptr->setby, (unsigned long)Ptr->topicset);
+ user->WriteNumeric(332, "%s %s :%s", user->nick, Ptr->name, Ptr->topic);
+ user->WriteNumeric(333, "%s %s %s %lu", user->nick, Ptr->name, Ptr->setby, (unsigned long)Ptr->topicset);
}
Ptr->UserList(user);
}
char mask[MAXBUF];
int MOD_RESULT = 0;
FOREACH_RESULT(I_OnCheckBan,OnCheckBan(user, this));
- if (!MOD_RESULT)
+
+ if (MOD_RESULT == -1)
+ return true;
+ else if (MOD_RESULT == 0)
{
snprintf(mask, MAXBUF, "%s!%s@%s", user->nick, user->ident, user->GetIPString());
for (BanList::iterator i = this->bans.begin(); i != this->bans.end(); i++)
return false;
}
+bool Channel::IsExtBanned(User *user, char type)
+{
+ // 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.
return this->GetUserCounter();
}
-long Channel::ServerKickUser(User* user, const char* reason, bool triggerevents)
+long Channel::ServerKickUser(User* user, const char* reason, bool triggerevents, const char* servername)
{
bool silent = false;
}
}
+ if (servername == NULL || *ServerInstance->Config->HideWhoisServer)
+ servername = ServerInstance->Config->ServerName;
+
if (triggerevents)
{
FOREACH_MOD(I_OnUserKick,OnUserKick(NULL, user, this, reason, silent));
if (i != user->chans.end())
{
if (!silent)
- this->WriteChannelWithServ(ServerInstance->Config->ServerName, "KICK %s %s :%s", this->name, user->nick, reason);
+ this->WriteChannelWithServ(servername, "KICK %s %s :%s", this->name, user->nick, reason);
user->chans.erase(i);
this->RemoveAllPrefixes(user);
{
if (!this->HasUser(user))
{
- src->WriteServ("441 %s %s %s :They are not on that channel",src->nick, user->nick, this->name);
+ 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->WriteServ("482 %s %s :Only a u-line may kick a u-line from a channel.",src->nick, this->name);
+ 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;
int us = this->GetStatus(user);
if ((them < STATUS_HOP) || (them < us))
{
- src->WriteServ("482 %s %s :You must be a channel %soperator",src->nick, this->name, them == STATUS_HOP ? "" : "half-");
+ src->WriteNumeric(482, "%s %s :You must be a channel %soperator",src->nick, this->name, them == STATUS_HOP ? "" : "half-");
return this->GetUserCounter();
}
}
void Channel::WriteAllExcept(User* user, bool serversource, char status, CUList &except_list, const std::string &text)
{
- CUList *ulist;
+ CUList *ulist = this->GetUsers();
char tb[MAXBUF];
- switch (status)
- {
- case '@':
- ulist = this->GetOppedUsers();
- break;
- case '%':
- ulist = this->GetHalfoppedUsers();
- break;
- case '+':
- ulist = this->GetVoicedUsers();
- break;
- default:
- ulist = this->GetUsers();
- break;
- }
-
snprintf(tb,MAXBUF,":%s %s",user->GetFullHost(),text.c_str());
std::string out = tb;
{
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
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)
- return;
+ call_modules = false;
+
if (MOD_RESULT != -1)
{
if ((this->IsModeSet('s')) && (!this->HasUser(user)))
{
- user->WriteServ("401 %s %s :No such nick/channel",user->nick, this->name);
+ user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick, this->name);
return;
}
}
- dlen = curlen = snprintf(list,MAXBUF,"353 %s %c %s :", user->nick, this->IsModeSet('s') ? '@' : this->IsModeSet('p') ? '*' : '=', this->name);
+ dlen = curlen = snprintf(list,MAXBUF,"%s %c %s :", user->nick, this->IsModeSet('s') ? '@' : this->IsModeSet('p') ? '*' : '=', this->name);
int numusers = 0;
char* ptr = list + dlen;
if (i->first->Visibility && !i->first->Visibility->VisibleTo(user))
continue;
- size_t ptrlen = snprintf(ptr, MAXBUF, "%s%s ", this->GetPrefixChar(i->first), i->second.c_str());
- /* OnUserList can change this - reset it back to normal */
- i->second = i->first->nick;
+ std::string prefixlist = this->GetPrefixChar(i->first);
+ std::string nick = i->first->nick;
- curlen += ptrlen;
- ptr += ptrlen;
-
- numusers++;
+ if (call_modules)
+ {
+ FOREACH_MOD(I_OnNamesListItem, OnNamesListItem(user, i->first, this, prefixlist, nick));
+
+ /* Nick was nuked, a module wants us to skip it */
+ if (nick.empty())
+ continue;
+ }
+
+ size_t ptrlen = 0;
if (curlen > (480-NICKMAX))
{
user->WriteServ(std::string(list));
/* reset our lengths */
- dlen = curlen = snprintf(list,MAXBUF,"353 %s %c %s :", user->nick, this->IsModeSet('s') ? '@' : this->IsModeSet('p') ? '*' : '=', this->name);
+ dlen = curlen = snprintf(list,MAXBUF,"%s %c %s :", user->nick, this->IsModeSet('s') ? '@' : this->IsModeSet('p') ? '*' : '=', this->name);
ptr = list + dlen;
ptrlen = 0;
numusers = 0;
}
+
+ ptrlen = snprintf(ptr, MAXBUF, "%s%s ", prefixlist.c_str(), nick.c_str());
+
+ curlen += ptrlen;
+ ptr += ptrlen;
+
+ numusers++;
}
/* if whats left in the list isnt empty, send it */
if (numusers)
{
- user->WriteServ(std::string(list));
+ user->WriteNumeric(353,std::string(list));
}
- user->WriteServ("366 %s %s :End of /NAMES list.", user->nick, this->name);
+ user->WriteNumeric(366, "%s %s :End of /NAMES list.", user->nick, this->name);
}
long Channel::GetMaxBans()
return pf;
}
+
const char* Channel::GetAllPrefixChars(User* user)
{
static char prefix[MAXBUF];