log(DEBUG,"Commencing reverse lookup");
try
{
- res_reverse = new UserResolver(ServerInstance, this, this->GetIPString(), false);
+ log(DEBUG,"Passing instance: %08x",this->ServerInstance);
+ res_reverse = new UserResolver(this->ServerInstance, this, this->GetIPString(), false);
MyServer->AddResolver(res_reverse);
}
catch (ModuleException& e)
}
UserResolver::UserResolver(InspIRCd* Instance, userrec* user, std::string to_resolve, bool forward) :
- Resolver(to_resolve, forward ? DNS_QUERY_FORWARD : DNS_QUERY_REVERSE), bound_user(user), ServerInstance(Instance)
+ Resolver(Instance, to_resolve, forward ? DNS_QUERY_FORWARD : DNS_QUERY_REVERSE), bound_user(user)
{
this->fwd = forward;
this->bound_fd = user->fd;
userrec::userrec(InspIRCd* Instance) : ServerInstance(Instance)
{
+ log(DEBUG,"userrec::userrec(): Instance: %08x",ServerInstance);
// the PROPER way to do it, AVOID bzero at *ALL* costs
*password = *nick = *ident = *host = *dhost = *fullname = *awaymsg = *oper = 0;
server = (char*)Instance->FindServerNamePtr(Instance->Config->ServerName);
if (recvq.length() > (unsigned)this->recvqmax)
{
this->SetWriteError("RecvQ exceeded");
- WriteOpers("*** User %s RecvQ of %d exceeds connect class maximum of %d",this->nick,recvq.length(),this->recvqmax);
+ ServerInstance->WriteOpers("*** User %s RecvQ of %d exceeds connect class maximum of %d",this->nick,recvq.length(),this->recvqmax);
return false;
}
* to repeatedly add the text to the sendq!
*/
this->SetWriteError("SendQ exceeded");
- WriteOpers("*** User %s SendQ of %d exceeds connect class maximum of %d",this->nick,sendq.length() + data.length(),this->sendqmax);
+ ServerInstance->WriteOpers("*** User %s SendQ of %d exceeds connect class maximum of %d",this->nick,sendq.length() + data.length(),this->sendqmax);
return;
}
if (user->registered == REG_ALL)
{
- purge_empty_chans(user);
+ user->PurgeEmptyChannels();
FOREACH_MOD_I(Instance,I_OnUserQuit,OnUserQuit(user,reason));
user->WriteCommonExcept("QUIT :%s",reason.c_str());
}
}
/*
- * this must come before the WriteOpers so that it doesnt try to fill their buffer with anything
+ * this must come before the ServerInstance->WriteOpers so that it doesnt try to fill their buffer with anything
* if they were an oper with +s.
*
* XXX -
if (user->registered == REG_ALL)
{
if (IS_LOCAL(user))
- WriteOpers("*** Client exiting: %s!%s@%s [%s]",user->nick,user->ident,user->host,reason.c_str());
+ Instance->WriteOpers("*** Client exiting: %s!%s@%s [%s]",user->nick,user->ident,user->host,reason.c_str());
user->AddToWhoWas();
}
ServerInstance->stats->statsConnects++;
this->idle_lastmsg = TIME;
- ConnectClass a = GetClass(this);
+ ConnectClass a = this->GetClass();
if (a.type == CC_DENY)
{
if (this->LocalCloneCount() > a.maxlocal)
{
Goners->AddItem(this, "No more connections allowed from your host via this connect class (local)");
- WriteOpers("*** WARNING: maximum LOCAL connections (%ld) exceeded for IP %s", a.maxlocal, this->GetIPString());
+ ServerInstance->WriteOpers("*** WARNING: maximum LOCAL connections (%ld) exceeded for IP %s", a.maxlocal, this->GetIPString());
return;
}
else if (this->GlobalCloneCount() > a.maxglobal)
{
Goners->AddItem(this, "No more connections allowed from your host via this connect class (global)");
- WriteOpers("*** WARNING: maximum GLOBAL connections (%ld) exceeded for IP %s",a.maxglobal, this->GetIPString());
+ ServerInstance->WriteOpers("*** WARNING: maximum GLOBAL connections (%ld) exceeded for IP %s",a.maxglobal, this->GetIPString());
return;
}
FOREACH_MOD(I_OnUserConnect,OnUserConnect(this));
FOREACH_MOD(I_OnGlobalConnect,OnGlobalConnect(this));
this->registered = REG_ALL;
- WriteOpers("*** Client connecting on port %d: %s!%s@%s [%s]", this->GetPort(), this->nick, this->ident, this->host, this->GetIPString());
+ ServerInstance->WriteOpers("*** Client connecting on port %d: %s!%s@%s [%s]", this->GetPort(), this->nick, this->ident, this->host, this->GetIPString());
}
/** userrec::UpdateNick()
}
}
+
+std::string userrec::ChannelList(userrec* source)
+{
+ std::string list;
+ for (std::vector<ucrec*>::const_iterator i = this->chans.begin(); i != this->chans.end(); i++)
+ {
+ ucrec* rec = *i;
+
+ if(rec->channel && rec->channel->name)
+ {
+ /* If the target is the same as the sender, let them see all their channels.
+ * If the channel is NOT private/secret OR the user shares a common channel
+ * If the user is an oper, and the <options:operspywhois> option is set.
+ */
+ if ((source == this) || (*source->oper && ServerInstance->Config->OperSpyWhois) || (((!rec->channel->modes[CM_PRIVATE]) && (!rec->channel->modes[CM_SECRET])) || (rec->channel->HasUser(source))))
+ {
+ list.append(rec->channel->GetStatusChar(this)).append(rec->channel->name).append(" ");
+ }
+ }
+ }
+ return list;
+}
+
+void userrec::SplitChanList(userrec* dest, const std::string &cl)
+{
+ std::string line;
+ std::ostringstream prefix;
+ std::string::size_type start, pos, length;
+
+ prefix << ":" << ServerInstance->Config->ServerName << " 319 " << this->nick << " " << dest->nick << " :";
+ line = prefix.str();
+
+ for (start = 0; (pos = cl.find(' ', start)) != std::string::npos; start = pos+1)
+ {
+ length = (pos == std::string::npos) ? cl.length() : pos;
+
+ if (line.length() + length - start > 510)
+ {
+ this->Write(line);
+ line = prefix.str();
+ }
+
+ if(pos == std::string::npos)
+ {
+ line += cl.substr(start, length - start);
+ break;
+ }
+ else
+ {
+ line += cl.substr(start, length - start + 1);
+ }
+ }
+
+ if (line.length())
+ {
+ this->Write(line);
+ }
+}
+
+
+/* looks up a users password for their connection class (<ALLOW>/<DENY> tags)
+ * NOTE: If the <ALLOW> or <DENY> tag specifies an ip, and this user resolves,
+ * then their ip will be taken as 'priority' anyway, so for example,
+ * <connect allow="127.0.0.1"> will match joe!bloggs@localhost
+ */
+ConnectClass& userrec::GetClass()
+{
+ for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++)
+ {
+ if ((match(this->GetIPString(),i->host.c_str(),true)) || (match(this->host,i->host.c_str())))
+ return *i;
+ }
+
+ return *(ServerInstance->Config->Classes.begin());
+}
+
+void userrec::PurgeEmptyChannels()
+{
+ std::vector<chanrec*> to_delete;
+
+ // firstly decrement the count on each channel
+ for (std::vector<ucrec*>::iterator f = this->chans.begin(); f != this->chans.end(); f++)
+ {
+ ucrec* uc = *f;
+ if (uc->channel)
+ {
+ if (uc->channel->DelUser(this) == 0)
+ {
+ /* No users left in here, mark it for deletion */
+ to_delete.push_back(uc->channel);
+ uc->channel = NULL;
+ }
+ }
+ }
+
+ for (std::vector<chanrec*>::iterator n = to_delete.begin(); n != to_delete.end(); n++)
+ {
+ chanrec* thischan = *n;
+ chan_hash::iterator i2 = ServerInstance->chanlist.find(thischan->name);
+ if (i2 != ServerInstance->chanlist.end())
+ {
+ FOREACH_MOD(I_OnChannelDelete,OnChannelDelete(i2->second));
+ DELETE(i2->second);
+ ServerInstance->chanlist.erase(i2);
+ }
+ }
+
+ this->UnOper();
+}
+