diff options
Diffstat (limited to 'src')
34 files changed, 488 insertions, 663 deletions
diff --git a/src/channels.cpp b/src/channels.cpp index f1dba5315..c265171b5 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -1013,7 +1013,7 @@ Invitation* Invitation::Find(Channel* c, LocalUser* u, bool check_expired) if ((check_expired) && (inv->expiry != 0) && (inv->expiry <= ServerInstance->Time())) { /* Expired invite, remove it. */ - ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Find ecountered expired entry: %p timed out at %lu", (void*) inv, inv->expiry); + ServerInstance->Logs->Log("INVITATION", DEBUG, "Invitation::Find ecountered expired entry: %p expired %s", (void*) inv, ServerInstance->TimeString(inv->expiry).c_str()); i = locallist.erase(i); inv->cull(); delete inv; diff --git a/src/commands/cmd_commands.cpp b/src/commands/cmd_commands.cpp index 13bd3fab8..36408b363 100644 --- a/src/commands/cmd_commands.cpp +++ b/src/commands/cmd_commands.cpp @@ -48,6 +48,10 @@ CmdResult CommandCommands::Handle (const std::vector<std::string>&, User *user) list.reserve(ServerInstance->Parser->cmdlist.size()); for (Commandtable::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++) { + // Don't show S2S commands to users + if (i->second->flags_needed == FLAG_SERVERONLY) + continue; + Module* src = i->second->creator; char buffer[MAXBUF]; snprintf(buffer, MAXBUF, ":%s %03d %s :%s %s %d %d", diff --git a/src/commands/cmd_stats.cpp b/src/commands/cmd_stats.cpp index 6944a4c44..6b21d0db6 100644 --- a/src/commands/cmd_stats.cpp +++ b/src/commands/cmd_stats.cpp @@ -20,17 +20,8 @@ #include "inspircd.h" -#ifndef WIN32 - #include <sys/resource.h> - /* This is just to be completely certain that the change which fixed getrusage on RH7 doesn't break anything else -- Om */ - #ifndef RUSAGE_SELF - #define RUSAGE_SELF 0 - #endif -#else - #include <psapi.h> - #include "inspircd_win32wrapper.h" - #pragma comment(lib, "psapi.lib") -#endif +#include "xline.h" +#include "commands/cmd_whowas.h" /** Handle /STATS. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work @@ -39,6 +30,7 @@ */ class CommandStats : public Command { + void DoStats(char statschar, User* user, string_list &results); public: /** Constructor for stats. */ @@ -58,13 +50,349 @@ class CommandStats : public Command } }; +void CommandStats::DoStats(char statschar, User* user, string_list &results) +{ + std::string sn(ServerInstance->Config->ServerName); + + bool isPublic = ServerInstance->Config->UserStats.find(statschar) != std::string::npos; + bool isRemoteOper = IS_REMOTE(user) && IS_OPER(user); + bool isLocalOperWithPrivs = IS_LOCAL(user) && user->HasPrivPermission("servers/auspex"); + + if (!isPublic && !isRemoteOper && !isLocalOperWithPrivs) + { + ServerInstance->SNO->WriteToSnoMask('t', + "%s '%c' denied for %s (%s@%s)", + (IS_LOCAL(user) ? "Stats" : "Remote stats"), + statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str()); + results.push_back(sn + " 481 " + user->nick + " :Permission denied - STATS " + statschar + " requires the servers/auspex priv."); + return; + } + + ModResult MOD_RESULT; + FIRST_MOD_RESULT(OnStats, MOD_RESULT, (statschar, user, results)); + if (MOD_RESULT == MOD_RES_DENY) + { + results.push_back(sn+" 219 "+user->nick+" "+statschar+" :End of /STATS report"); + ServerInstance->SNO->WriteToSnoMask('t',"%s '%c' requested by %s (%s@%s)", + (IS_LOCAL(user) ? "Stats" : "Remote stats"), statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str()); + return; + } + + switch (statschar) + { + /* stats p (show listening ports) */ + case 'p': + { + for (std::vector<ListenSocket*>::const_iterator i = ServerInstance->ports.begin(); i != ServerInstance->ports.end(); ++i) + { + ListenSocket* ls = *i; + std::string ip = ls->bind_addr; + if (ip.empty()) + ip.assign("*"); + std::string type = ls->bind_tag->getString("type", "clients"); + std::string hook = ls->bind_tag->getString("ssl", "plaintext"); + + results.push_back(sn+" 249 "+user->nick+" :"+ ip + ":"+ConvToStr(ls->bind_port)+ + " (" + type + ", " + hook + ")"); + } + } + break; + + /* These stats symbols must be handled by a linking module */ + case 'n': + case 'c': + break; + + case 'i': + { + for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++) + { + ConnectClass* c = *i; + std::stringstream res; + res << sn << " 215 " << user->nick << " I " << c->name << ' '; + if (c->type == CC_ALLOW) + res << '+'; + if (c->type == CC_DENY) + res << '-'; + + if (c->type == CC_NAMED) + res << '*'; + else + res << c->host; + + res << ' ' << c->config->getString("port", "*") << ' '; + + res << c->GetRecvqMax() << ' ' << c->GetSendqSoftMax() << ' ' << c->GetSendqHardMax() + << ' ' << c->GetCommandRate() << ' ' << c->GetPenaltyThreshold(); + if (c->fakelag) + res << '*'; + results.push_back(res.str()); + } + } + break; + + case 'Y': + { + int idx = 0; + for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++) + { + ConnectClass* c = *i; + results.push_back(sn+" 215 "+user->nick+" i NOMATCH * "+c->GetHost()+" "+ConvToStr(c->limit ? c->limit : ServerInstance->SE->GetMaxFds())+" "+ConvToStr(idx)+" "+ServerInstance->Config->ServerName+" *"); + results.push_back(sn+" 218 "+user->nick+" Y "+ConvToStr(idx)+" "+ConvToStr(c->GetPingTime())+" 0 "+ConvToStr(c->GetSendqHardMax())+" :"+ + ConvToStr(c->GetRecvqMax())+" "+ConvToStr(c->GetRegTimeout())); + idx++; + } + } + break; + + case 'U': + { + for(std::map<irc::string, bool>::iterator i = ServerInstance->Config->ulines.begin(); i != ServerInstance->Config->ulines.end(); ++i) + { + results.push_back(sn+" 248 "+user->nick+" U "+std::string(i->first.c_str())); + } + } + break; + + case 'P': + { + int idx = 0; + for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); i++) + { + if (IS_OPER(i->second) && !ServerInstance->ULine(i->second->server)) + { + results.push_back(sn+" 249 "+user->nick+" :"+i->second->nick+" ("+i->second->ident+"@"+i->second->dhost+") Idle: "+ + (IS_LOCAL(i->second) ? ConvToStr(ServerInstance->Time() - i->second->idle_lastmsg) + " secs" : "unavailable")); + idx++; + } + } + results.push_back(sn+" 249 "+user->nick+" :"+ConvToStr(idx)+" OPER(s)"); + } + break; + + case 'k': + ServerInstance->XLines->InvokeStats("K",216,user,results); + break; + case 'g': + ServerInstance->XLines->InvokeStats("G",223,user,results); + break; + case 'q': + ServerInstance->XLines->InvokeStats("Q",217,user,results); + break; + case 'Z': + ServerInstance->XLines->InvokeStats("Z",223,user,results); + break; + case 'e': + ServerInstance->XLines->InvokeStats("E",223,user,results); + break; + case 'E': + results.push_back(sn+" 249 "+user->nick+" :Total events: "+ConvToStr(ServerInstance->SE->TotalEvents)); + results.push_back(sn+" 249 "+user->nick+" :Read events: "+ConvToStr(ServerInstance->SE->ReadEvents)); + results.push_back(sn+" 249 "+user->nick+" :Write events: "+ConvToStr(ServerInstance->SE->WriteEvents)); + results.push_back(sn+" 249 "+user->nick+" :Error events: "+ConvToStr(ServerInstance->SE->ErrorEvents)); + break; + + /* stats m (list number of times each command has been used, plus bytecount) */ + case 'm': + for (Commandtable::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++) + { + if (i->second->use_count) + { + /* RPL_STATSCOMMANDS */ + results.push_back(sn+" 212 "+user->nick+" "+i->second->name+" "+ConvToStr(i->second->use_count)+" "+ConvToStr(i->second->total_bytes)); + } + } + break; + + /* stats z (debug and memory info) */ + case 'z': + { + results.push_back(sn+" 249 "+user->nick+" :Users: "+ConvToStr(ServerInstance->Users->clientlist->size())); + results.push_back(sn+" 249 "+user->nick+" :Channels: "+ConvToStr(ServerInstance->chanlist->size())); + results.push_back(sn+" 249 "+user->nick+" :Commands: "+ConvToStr(ServerInstance->Parser->cmdlist.size())); + + if (!ServerInstance->Config->WhoWasGroupSize == 0 && !ServerInstance->Config->WhoWasMaxGroups == 0) + { + Module* whowas = ServerInstance->Modules->Find("cmd_whowas.so"); + if (whowas) + { + WhowasRequest req(NULL, whowas, WhowasRequest::WHOWAS_STATS); + req.user = user; + req.Send(); + results.push_back(sn+" 249 "+user->nick+" :"+req.value); + } + } + + float kbitpersec_in, kbitpersec_out, kbitpersec_total; + char kbitpersec_in_s[30], kbitpersec_out_s[30], kbitpersec_total_s[30]; + + ServerInstance->SE->GetStats(kbitpersec_in, kbitpersec_out, kbitpersec_total); + + snprintf(kbitpersec_total_s, 30, "%03.5f", kbitpersec_total); + snprintf(kbitpersec_out_s, 30, "%03.5f", kbitpersec_out); + snprintf(kbitpersec_in_s, 30, "%03.5f", kbitpersec_in); + + results.push_back(sn+" 249 "+user->nick+" :Bandwidth total: "+ConvToStr(kbitpersec_total_s)+" kilobits/sec"); + results.push_back(sn+" 249 "+user->nick+" :Bandwidth out: "+ConvToStr(kbitpersec_out_s)+" kilobits/sec"); + results.push_back(sn+" 249 "+user->nick+" :Bandwidth in: "+ConvToStr(kbitpersec_in_s)+" kilobits/sec"); + +#ifndef WIN32 + /* Moved this down here so all the not-windows stuff (look w00tie, I didn't say win32!) is in one ifndef. + * Also cuts out some identical code in both branches of the ifndef. -- Om + */ + rusage R; + + /* Not sure why we were doing '0' with a RUSAGE_SELF comment rather than just using RUSAGE_SELF -- Om */ + if (!getrusage(RUSAGE_SELF,&R)) /* RUSAGE_SELF */ + { + results.push_back(sn+" 249 "+user->nick+" :Total allocation: "+ConvToStr(R.ru_maxrss)+"K"); + results.push_back(sn+" 249 "+user->nick+" :Signals: "+ConvToStr(R.ru_nsignals)); + results.push_back(sn+" 249 "+user->nick+" :Page faults: "+ConvToStr(R.ru_majflt)); + results.push_back(sn+" 249 "+user->nick+" :Swaps: "+ConvToStr(R.ru_nswap)); + results.push_back(sn+" 249 "+user->nick+" :Context Switches: Voluntary; "+ConvToStr(R.ru_nvcsw)+" Involuntary; "+ConvToStr(R.ru_nivcsw)); + + char percent[30]; + + float n_elapsed = (ServerInstance->Time() - ServerInstance->stats->LastSampled.tv_sec) * 1000000 + + (ServerInstance->Time_ns() - ServerInstance->stats->LastSampled.tv_nsec) / 1000; + float n_eaten = ((R.ru_utime.tv_sec - ServerInstance->stats->LastCPU.tv_sec) * 1000000 + R.ru_utime.tv_usec - ServerInstance->stats->LastCPU.tv_usec); + float per = (n_eaten / n_elapsed) * 100; + + snprintf(percent, 30, "%03.5f%%", per); + results.push_back(sn+" 249 "+user->nick+" :CPU Use (now): "+percent); + + n_elapsed = ServerInstance->Time() - ServerInstance->startup_time; + n_eaten = (float)R.ru_utime.tv_sec + R.ru_utime.tv_usec / 100000.0; + per = (n_eaten / n_elapsed) * 100; + snprintf(percent, 30, "%03.5f%%", per); + results.push_back(sn+" 249 "+user->nick+" :CPU Use (total): "+percent); + } +#else + PROCESS_MEMORY_COUNTERS MemCounters; + if (GetProcessMemoryInfo(GetCurrentProcess(), &MemCounters, sizeof(MemCounters))) + { + results.push_back(sn+" 249 "+user->nick+" :Total allocation: "+ConvToStr((MemCounters.WorkingSetSize + MemCounters.PagefileUsage) / 1024)+"K"); + results.push_back(sn+" 249 "+user->nick+" :Pagefile usage: "+ConvToStr(MemCounters.PagefileUsage / 1024)+"K"); + results.push_back(sn+" 249 "+user->nick+" :Page faults: "+ConvToStr(MemCounters.PageFaultCount)); + results.push_back(sn+" 249 "+user->nick+" :CPU Usage: " + ConvToStr(getcpu()) + "%"); + } +#endif + } + break; + + case 'T': + { + char buffer[MAXBUF]; + results.push_back(sn+" 249 "+user->nick+" :accepts "+ConvToStr(ServerInstance->stats->statsAccept)+" refused "+ConvToStr(ServerInstance->stats->statsRefused)); + results.push_back(sn+" 249 "+user->nick+" :unknown commands "+ConvToStr(ServerInstance->stats->statsUnknown)); + results.push_back(sn+" 249 "+user->nick+" :nick collisions "+ConvToStr(ServerInstance->stats->statsCollisions)); + results.push_back(sn+" 249 "+user->nick+" :dns requests "+ConvToStr(ServerInstance->stats->statsDnsGood+ServerInstance->stats->statsDnsBad)+" succeeded "+ConvToStr(ServerInstance->stats->statsDnsGood)+" failed "+ConvToStr(ServerInstance->stats->statsDnsBad)); + results.push_back(sn+" 249 "+user->nick+" :connection count "+ConvToStr(ServerInstance->stats->statsConnects)); + snprintf(buffer,MAXBUF," 249 %s :bytes sent %5.2fK recv %5.2fK", + user->nick.c_str(),ServerInstance->stats->statsSent / 1024.0,ServerInstance->stats->statsRecv / 1024.0); + results.push_back(sn+buffer); + } + break; + + /* stats o */ + case 'o': + { + ConfigTagList tags = ServerInstance->Config->ConfTags("oper"); + for(ConfigIter i = tags.first; i != tags.second; ++i) + { + ConfigTag* tag = i->second; + results.push_back(sn+" 243 "+user->nick+" O "+tag->getString("host")+" * "+ + tag->getString("name") + " " + tag->getString("type")+" 0"); + } + } + break; + case 'O': + { + for(OperIndex::iterator i = ServerInstance->Config->oper_blocks.begin(); i != ServerInstance->Config->oper_blocks.end(); i++) + { + // just the types, not the actual oper blocks... + if (i->first[0] != ' ') + continue; + OperInfo* tag = i->second; + tag->init(); + std::string umodes; + std::string cmodes; + for(char c='A'; c < 'z'; c++) + { + ModeHandler* mh = ServerInstance->Modes->FindMode(c, MODETYPE_USER); + if (mh && mh->NeedsOper() && tag->AllowedUserModes[c - 'A']) + umodes.push_back(c); + mh = ServerInstance->Modes->FindMode(c, MODETYPE_CHANNEL); + if (mh && mh->NeedsOper() && tag->AllowedChanModes[c - 'A']) + cmodes.push_back(c); + } + results.push_back(sn+" 243 "+user->nick+" O "+tag->NameStr() + " " + umodes + " " + cmodes); + } + } + break; + + /* stats l (show user I/O stats) */ + case 'l': + results.push_back(sn+" 211 "+user->nick+" :nick[ident@host] sendq cmds_out bytes_out cmds_in bytes_in time_open"); + for (std::vector<LocalUser*>::iterator n = ServerInstance->Users->local_users.begin(); n != ServerInstance->Users->local_users.end(); n++) + { + LocalUser* i = *n; + results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->dhost+"] "+ConvToStr(i->eh.getSendQSize())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(ServerInstance->Time() - i->age)); + } + break; + + /* stats L (show user I/O stats with IP addresses) */ + case 'L': + results.push_back(sn+" 211 "+user->nick+" :nick[ident@ip] sendq cmds_out bytes_out cmds_in bytes_in time_open"); + for (std::vector<LocalUser*>::iterator n = ServerInstance->Users->local_users.begin(); n != ServerInstance->Users->local_users.end(); n++) + { + LocalUser* i = *n; + results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->GetIPString()+"] "+ConvToStr(i->eh.getSendQSize())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(ServerInstance->Time() - i->age)); + } + break; + + /* stats u (show server uptime) */ + case 'u': + { + time_t current_time = 0; + current_time = ServerInstance->Time(); + time_t server_uptime = current_time - ServerInstance->startup_time; + struct tm* stime; + stime = gmtime(&server_uptime); + /* i dont know who the hell would have an ircd running for over a year nonstop, but + * Craig suggested this, and it seemed a good idea so in it went */ + if (stime->tm_year > 70) + { + char buffer[MAXBUF]; + snprintf(buffer,MAXBUF," 242 %s :Server up %d years, %d days, %.2d:%.2d:%.2d",user->nick.c_str(),(stime->tm_year-70),stime->tm_yday,stime->tm_hour,stime->tm_min,stime->tm_sec); + results.push_back(sn+buffer); + } + else + { + char buffer[MAXBUF]; + snprintf(buffer,MAXBUF," 242 %s :Server up %d days, %.2d:%.2d:%.2d",user->nick.c_str(),stime->tm_yday,stime->tm_hour,stime->tm_min,stime->tm_sec); + results.push_back(sn+buffer); + } + } + break; + + default: + break; + } + + results.push_back(sn+" 219 "+user->nick+" "+statschar+" :End of /STATS report"); + ServerInstance->SNO->WriteToSnoMask('t',"%s '%c' requested by %s (%s@%s)", + (IS_LOCAL(user) ? "Stats" : "Remote stats"), statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str()); + return; +} + CmdResult CommandStats::Handle (const std::vector<std::string>& parameters, User *user) { if (parameters.size() > 1 && parameters[1] != ServerInstance->Config->ServerName) return CMD_SUCCESS; string_list values; char search = parameters[0][0]; - ServerInstance->DoStats(search, user, values); + DoStats(search, user, values); for (size_t i = 0; i < values.size(); i++) user->SendText(":%s", values[i].c_str()); diff --git a/src/configparser.cpp b/src/configparser.cpp index a8e36f6e0..b6e3f7187 100644 --- a/src/configparser.cpp +++ b/src/configparser.cpp @@ -307,7 +307,7 @@ void ParseStack::DoReadFile(const std::string& key, const std::string& name, int if (exec && (flags & FLAG_NO_EXEC)) throw CoreException("Invalid <execfiles> tag in file included with noexec=\"yes\""); - FileWrapper file(exec ? popen(name.c_str(), "r") : fopen(name.c_str(), "r")); + FileWrapper file(exec ? popen(name.c_str(), "r") : fopen(name.c_str(), "r"), exec); if (!file) throw CoreException("Could not read \"" + name + "\" for \"" + key + "\" file"); @@ -364,7 +364,7 @@ bool ParseStack::ParseExec(const std::string& name, int flags) /* It's not already included, add it to the list of files we've loaded */ - FileWrapper file(popen(name.c_str(), "r")); + FileWrapper file(popen(name.c_str(), "r"), true); if (!file) throw CoreException("Could not open executable \"" + name + "\" for include"); diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp index 92de37e61..2cb6fb972 100644 --- a/src/hashcomp.cpp +++ b/src/hashcomp.cpp @@ -483,29 +483,17 @@ std::string& irc::stringjoiner::GetJoined() return joined; } -irc::portparser::portparser(const std::string &source, bool allow_overlapped) : in_range(0), range_begin(0), range_end(0), overlapped(allow_overlapped) +irc::portparser::portparser(const std::string &source, bool allow_overlapped) + : sep(source), in_range(0), range_begin(0), range_end(0), overlapped(allow_overlapped) { - sep = new irc::commasepstream(source); - overlap_set.clear(); -} - -irc::portparser::~portparser() -{ - delete sep; } bool irc::portparser::Overlaps(long val) { - if (!overlapped) + if (overlapped) return false; - if (overlap_set.find(val) == overlap_set.end()) - { - overlap_set[val] = true; - return false; - } - else - return true; + return (!overlap_set.insert(val).second); } long irc::portparser::GetToken() @@ -533,14 +521,14 @@ long irc::portparser::GetToken() } std::string x; - sep->GetToken(x); + sep.GetToken(x); if (x.empty()) return 0; while (Overlaps(atoi(x.c_str()))) { - if (!sep->GetToken(x)) + if (!sep.GetToken(x)) return 0; } diff --git a/src/inspircd.cpp b/src/inspircd.cpp index cf8c22633..aa03d62de 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -195,24 +195,21 @@ void InspIRCd::ResetMaxBans() void InspIRCd::RehashUsersAndChans() { user_hash* old_users = Users->clientlist; - user_hash* old_uuid = Users->uuidlist; - chan_hash* old_chans = chanlist; - - Users->clientlist = new user_hash(); - Users->uuidlist = new user_hash(); - chanlist = new chan_hash(); - + Users->clientlist = new user_hash; for (user_hash::const_iterator n = old_users->begin(); n != old_users->end(); n++) Users->clientlist->insert(*n); + delete old_users; + user_hash* old_uuid = Users->uuidlist; + Users->uuidlist = new user_hash; for (user_hash::const_iterator n = old_uuid->begin(); n != old_uuid->end(); n++) Users->uuidlist->insert(*n); + delete old_uuid; + chan_hash* old_chans = chanlist; + chanlist = new chan_hash; for (chan_hash::const_iterator n = old_chans->begin(); n != old_chans->end(); n++) chanlist->insert(*n); - - delete old_users; - delete old_uuid; delete old_chans; // Reset the already_sent IDs so we don't wrap it around and drop a message diff --git a/src/modules/extra/m_ldapoper.cpp b/src/modules/extra/m_ldapoper.cpp index 6bd834dc8..6eade1fbd 100644 --- a/src/modules/extra/m_ldapoper.cpp +++ b/src/modules/extra/m_ldapoper.cpp @@ -32,7 +32,7 @@ # pragma comment(lib, "lber.lib") #endif -/* $ModDesc: Allow/Deny connections based upon answer from LDAP server */ +/* $ModDesc: Adds the ability to authenticate opers via LDAP */ /* $LinkerFlags: -lldap */ class ModuleLDAPAuth : public Module @@ -181,7 +181,7 @@ public: virtual Version GetVersion() { - return Version("Allow/Deny connections based upon answer from LDAP server", VF_VENDOR); + return Version("Adds the ability to authenticate opers via LDAP", VF_VENDOR); } }; diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index 6ca876d4c..c631642ce 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -28,6 +28,17 @@ #include "ssl.h" #include "m_cap.h" +#ifdef WINDOWS +# pragma comment(lib, "libgnutls.lib") +# pragma comment(lib, "libgcrypt.lib") +# pragma comment(lib, "libgpg-error.lib") +# pragma comment(lib, "user32.lib") +# pragma comment(lib, "advapi32.lib") +# pragma comment(lib, "libgcc.lib") +# pragma comment(lib, "libmingwex.lib") +# pragma comment(lib, "gdi32.lib") +#endif + /* $ModDesc: Provides SSL support for clients */ /* $CompileFlags: pkgconfincludes("gnutls","/gnutls/gnutls.h","") */ /* $LinkerFlags: rpath("pkg-config --libs gnutls") pkgconflibs("gnutls","/libgnutls.so","-lgnutls") -lgcrypt */ diff --git a/src/modules/m_blockamsg.cpp b/src/modules/m_blockamsg.cpp index 1d26b7639..8160fcf54 100644 --- a/src/modules/m_blockamsg.cpp +++ b/src/modules/m_blockamsg.cpp @@ -98,8 +98,8 @@ class ModuleBlockAmsg : public Module virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line) { - // Don't do anything with unregistered users, or remote ones. - if(!user || (user->registered != REG_ALL) || !IS_LOCAL(user)) + // Don't do anything with unregistered users + if (user->registered != REG_ALL) return MOD_RES_PASSTHRU; // We want case insensitive command comparison. diff --git a/src/modules/m_chanhistory.cpp b/src/modules/m_chanhistory.cpp index 482d526eb..16eba953f 100644 --- a/src/modules/m_chanhistory.cpp +++ b/src/modules/m_chanhistory.cpp @@ -129,12 +129,7 @@ class ModuleChanHistory : public Module { ConfigTag* tag = ServerInstance->Config->ConfValue("chanhistory"); m.maxlines = tag->getInt("maxlines", 50); - sendnotice = tag->getInt("notice", true); - } - - ~ModuleChanHistory() - { - ServerInstance->Modes->DelMode(&m); + sendnotice = tag->getBool("notice", true); } void OnUserMessage(User* user,void* dest,int target_type, const std::string &text, char status, const CUList&) diff --git a/src/modules/m_chanlog.cpp b/src/modules/m_chanlog.cpp index ed5063fad..29385b8e2 100644 --- a/src/modules/m_chanlog.cpp +++ b/src/modules/m_chanlog.cpp @@ -28,7 +28,8 @@ class ModuleChanLog : public Module /* * Multimap so people can redirect a snomask to multiple channels. */ - std::multimap<char, std::string> logstreams; + typedef std::multimap<char, std::string> ChanLogTargets; + ChanLogTargets logstreams; public: ModuleChanLog() { @@ -72,30 +73,21 @@ class ModuleChanLog : public Module virtual ModResult OnSendSnotice(char &sno, std::string &desc, const std::string &msg) { - std::multimap<char, std::string>::const_iterator it = logstreams.find(sno); - char buf[MAXBUF]; - - if (it == logstreams.end()) + std::pair<ChanLogTargets::const_iterator, ChanLogTargets::const_iterator> itpair = logstreams.equal_range(sno); + if (itpair.first == itpair.second) return MOD_RES_PASSTHRU; + char buf[MAXBUF]; snprintf(buf, MAXBUF, "\2%s\2: %s", desc.c_str(), msg.c_str()); - while (it != logstreams.end()) + for (ChanLogTargets::const_iterator it = itpair.first; it != itpair.second; ++it) { - if (it->first != sno) - { - it++; - continue; - } - Channel *c = ServerInstance->FindChan(it->second); if (c) { c->WriteChannelWithServ(ServerInstance->Config->ServerName.c_str(), "PRIVMSG %s :%s", c->name.c_str(), buf); ServerInstance->PI->SendChannelPrivmsg(c, 0, buf); } - - it++; } return MOD_RES_PASSTHRU; diff --git a/src/modules/m_chgname.cpp b/src/modules/m_chgname.cpp index 194ecf80e..2ac24c5d5 100644 --- a/src/modules/m_chgname.cpp +++ b/src/modules/m_chgname.cpp @@ -44,16 +44,22 @@ class CommandChgname : public Command return CMD_FAILURE; } + if (parameters[1].empty()) + { + user->WriteServ("NOTICE %s :*** CHGNAME: GECOS must be specified", user->nick.c_str()); + return CMD_FAILURE; + } + if (parameters[1].length() > ServerInstance->Config->Limits.MaxGecos) { - user->WriteServ("NOTICE %s :*** GECOS too long", user->nick.c_str()); + user->WriteServ("NOTICE %s :*** CHGNAME: GECOS too long", user->nick.c_str()); return CMD_FAILURE; } if (IS_LOCAL(dest)) { dest->ChangeName(parameters[1].c_str()); - ServerInstance->SNO->WriteGlobalSno('a', "%s used CHGNAME to change %s's real name to '%s'", user->nick.c_str(), dest->nick.c_str(), dest->fullname.c_str()); + ServerInstance->SNO->WriteGlobalSno('a', "%s used CHGNAME to change %s's GECOS to '%s'", user->nick.c_str(), dest->nick.c_str(), dest->fullname.c_str()); } return CMD_SUCCESS; diff --git a/src/modules/m_commonchans.cpp b/src/modules/m_commonchans.cpp index ac8a7ba29..877ba87d7 100644 --- a/src/modules/m_commonchans.cpp +++ b/src/modules/m_commonchans.cpp @@ -23,32 +23,10 @@ /** Handles user mode +c */ -class PrivacyMode : public ModeHandler +class PrivacyMode : public SimpleUserModeHandler { public: - PrivacyMode(Module* Creator) : ModeHandler(Creator, "deaf_commonchan", 'c', PARAM_NONE, MODETYPE_USER) { } - - ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) - { - if (adding) - { - if (!dest->IsModeSet('c')) - { - dest->SetMode('c',true); - return MODEACTION_ALLOW; - } - } - else - { - if (dest->IsModeSet('c')) - { - dest->SetMode('c',false); - return MODEACTION_ALLOW; - } - } - - return MODEACTION_DENY; - } + PrivacyMode(Module* Creator) : SimpleUserModeHandler(Creator, "deaf_commonchan", 'c') { } }; class ModulePrivacyMode : public Module diff --git a/src/modules/m_globops.cpp b/src/modules/m_globops.cpp index db55858d6..d9dd8f2ac 100644 --- a/src/modules/m_globops.cpp +++ b/src/modules/m_globops.cpp @@ -38,13 +38,7 @@ class CommandGlobops : public Command CmdResult Handle (const std::vector<std::string> ¶meters, User *user) { - std::string line = "From " + std::string(user->nick) + ": "; - for (int i = 0; i < (int)parameters.size(); i++) - { - line = line + parameters[i] + " "; - } - ServerInstance->SNO->WriteGlobalSno('g',line); - + ServerInstance->SNO->WriteGlobalSno('g', "From " + user->nick + ": " + parameters[0]); return CMD_SUCCESS; } }; diff --git a/src/modules/m_halfop.cpp b/src/modules/m_halfop.cpp index f0eda3e56..7a43f0241 100644 --- a/src/modules/m_halfop.cpp +++ b/src/modules/m_halfop.cpp @@ -92,11 +92,6 @@ class ModuleHalfop : public Module throw ModuleException("Could not add new modes!"); } - ~ModuleHalfop() - { - ServerInstance->Modes->DelMode(&mh); - } - Version GetVersion() { return Version("Channel half-operator mode provider", VF_VENDOR); diff --git a/src/modules/m_helpop.cpp b/src/modules/m_helpop.cpp index bbc7ae3ac..60c23f45b 100644 --- a/src/modules/m_helpop.cpp +++ b/src/modules/m_helpop.cpp @@ -29,35 +29,13 @@ static std::map<irc::string, std::string> helpop_map; /** Handles user mode +h */ -class Helpop : public ModeHandler +class Helpop : public SimpleUserModeHandler { public: - Helpop(Module* Creator) : ModeHandler(Creator, "helpop", 'h', PARAM_NONE, MODETYPE_USER) + Helpop(Module* Creator) : SimpleUserModeHandler(Creator, "helpop", 'h') { oper = true; } - - ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) - { - if (adding) - { - if (!dest->IsModeSet('h')) - { - dest->SetMode('h',true); - return MODEACTION_ALLOW; - } - } - else - { - if (dest->IsModeSet('h')) - { - dest->SetMode('h',false); - return MODEACTION_ALLOW; - } - } - - return MODEACTION_DENY; - } }; /** Handles /HELPOP diff --git a/src/modules/m_hidechans.cpp b/src/modules/m_hidechans.cpp index 17e2e8605..9c582551b 100644 --- a/src/modules/m_hidechans.cpp +++ b/src/modules/m_hidechans.cpp @@ -24,32 +24,10 @@ /** Handles user mode +I */ -class HideChans : public ModeHandler +class HideChans : public SimpleUserModeHandler { public: - HideChans(Module* Creator) : ModeHandler(Creator, "hidechans", 'I', PARAM_NONE, MODETYPE_USER) { } - - ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) - { - if (adding) - { - if (!dest->IsModeSet('I')) - { - dest->SetMode('I',true); - return MODEACTION_ALLOW; - } - } - else - { - if (dest->IsModeSet('I')) - { - dest->SetMode('I',false); - return MODEACTION_ALLOW; - } - } - - return MODEACTION_DENY; - } + HideChans(Module* Creator) : SimpleUserModeHandler(Creator, "hidechans", 'I') { } }; class ModuleHideChans : public Module diff --git a/src/modules/m_hideoper.cpp b/src/modules/m_hideoper.cpp index cde50b1a9..998a57bb3 100644 --- a/src/modules/m_hideoper.cpp +++ b/src/modules/m_hideoper.cpp @@ -25,35 +25,13 @@ /** Handles user mode +H */ -class HideOper : public ModeHandler +class HideOper : public SimpleUserModeHandler { public: - HideOper(Module* Creator) : ModeHandler(Creator, "hideoper", 'H', PARAM_NONE, MODETYPE_USER) + HideOper(Module* Creator) : SimpleUserModeHandler(Creator, "hideoper", 'H') { oper = true; } - - ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) - { - if (adding) - { - if (!dest->IsModeSet('H')) - { - dest->SetMode('H',true); - return MODEACTION_ALLOW; - } - } - else - { - if (dest->IsModeSet('H')) - { - dest->SetMode('H',false); - return MODEACTION_ALLOW; - } - } - - return MODEACTION_DENY; - } }; class ModuleHideOper : public Module diff --git a/src/modules/m_ident.cpp b/src/modules/m_ident.cpp index b7c9c1cfd..c30e4d200 100644 --- a/src/modules/m_ident.cpp +++ b/src/modules/m_ident.cpp @@ -216,15 +216,17 @@ class IdentRequestSocket : public EventHandler char ibuf[MAXBUF]; int recvresult = ServerInstance->SE->Recv(this, ibuf, MAXBUF-1, 0); + /* Close (but don't delete from memory) our socket + * and flag as done since the ident lookup has finished + */ + Close(); + done = true; + /* Cant possibly be a valid response shorter than 3 chars, * because the shortest possible response would look like: '1,1' */ if (recvresult < 3) - { - Close(); - done = true; return; - } ServerInstance->Logs->Log("m_ident",DEBUG,"ReadResponse()"); @@ -263,13 +265,6 @@ class IdentRequestSocket : public EventHandler break; } - - /* Close (but dont delete from memory) our socket - * and flag as done - */ - Close(); - done = true; - return; } }; @@ -388,7 +383,11 @@ class ModuleIdent : public Module { /* Module unloading, tidy up users */ if (target_type == TYPE_USER) - OnUserDisconnect((LocalUser*)item); + { + LocalUser* user = IS_LOCAL((User*) item); + if (user) + OnUserDisconnect(user); + } } virtual void OnUserDisconnect(LocalUser *user) diff --git a/src/modules/m_inviteexception.cpp b/src/modules/m_inviteexception.cpp index 1ecec735e..5e6628e6d 100644 --- a/src/modules/m_inviteexception.cpp +++ b/src/modules/m_inviteexception.cpp @@ -47,6 +47,7 @@ class InviteException : public ListModeBase class ModuleInviteException : public Module { + bool invite_bypass_key; InviteException ie; public: ModuleInviteException() : ie(this) @@ -54,9 +55,10 @@ public: if (!ServerInstance->Modes->AddMode(&ie)) throw ModuleException("Could not add new modes!"); + OnRehash(NULL); ie.DoImplements(this); - Implementation eventlist[] = { I_On005Numeric, I_OnCheckInvite, I_OnCheckKey }; - ServerInstance->Modules->Attach(eventlist, this, 3); + Implementation eventlist[] = { I_On005Numeric, I_OnCheckInvite, I_OnCheckKey, I_OnRehash }; + ServerInstance->Modules->Attach(eventlist, this, 4); } void On005Numeric(std::string &output) @@ -66,17 +68,14 @@ public: ModResult OnCheckInvite(User* user, Channel* chan) { - if(chan != NULL) + modelist* list = ie.extItem.get(chan); + if (list) { - modelist* list = ie.extItem.get(chan); - if (list) + for (modelist::iterator it = list->begin(); it != list->end(); it++) { - for (modelist::iterator it = list->begin(); it != list->end(); it++) + if (chan->CheckBan(user, it->mask)) { - if (chan->CheckBan(user, it->mask)) - { - return MOD_RES_ALLOW; - } + return MOD_RES_ALLOW; } } } @@ -86,7 +85,7 @@ public: ModResult OnCheckKey(User* user, Channel* chan, const std::string& key) { - if (ServerInstance->Config->ConfValue("inviteexception")->getBool("bypasskey", true)) + if (invite_bypass_key) return OnCheckInvite(user, chan); return MOD_RES_PASSTHRU; } @@ -103,6 +102,7 @@ public: void OnRehash(User* user) { + invite_bypass_key = ServerInstance->Config->ConfValue("inviteexception")->getBool("bypasskey", true); ie.DoRehash(); } diff --git a/src/modules/m_lockserv.cpp b/src/modules/m_lockserv.cpp index cc2e25308..3408e4621 100644 --- a/src/modules/m_lockserv.cpp +++ b/src/modules/m_lockserv.cpp @@ -34,15 +34,20 @@ class CommandLockserv : public Command public: CommandLockserv(Module* Creator, bool& lock) : Command(Creator, "LOCKSERV", 0), locked(lock) { - flags_needed = 'o'; syntax.clear(); + flags_needed = 'o'; } CmdResult Handle (const std::vector<std::string> ¶meters, User *user) { + if (locked) + { + user->WriteServ("NOTICE %s :The server is already locked.", user->nick.c_str()); + return CMD_FAILURE; + } + locked = true; user->WriteNumeric(988, "%s %s :Closed for new connections", user->nick.c_str(), user->server.c_str()); - ServerInstance->SNO->WriteGlobalSno('a', "Oper %s used LOCKSERV to temporarily close for new connections", user->nick.c_str()); - /* Dont send to the network */ + ServerInstance->SNO->WriteGlobalSno('a', "Oper %s used LOCKSERV to temporarily disallow new connections", user->nick.c_str()); return CMD_SUCCESS; } }; @@ -55,15 +60,20 @@ private: public: CommandUnlockserv(Module* Creator, bool &lock) : Command(Creator, "UNLOCKSERV", 0), locked(lock) { - flags_needed = 'o'; syntax.clear(); + flags_needed = 'o'; } CmdResult Handle (const std::vector<std::string> ¶meters, User *user) { + if (!locked) + { + user->WriteServ("NOTICE %s :The server isn't locked.", user->nick.c_str()); + return CMD_FAILURE; + } + locked = false; user->WriteNumeric(989, "%s %s :Open for new connections", user->nick.c_str(), user->server.c_str()); - ServerInstance->SNO->WriteGlobalSno('a', "Oper %s used UNLOCKSERV to allow for new connections", user->nick.c_str()); - /* Dont send to the network */ + ServerInstance->SNO->WriteGlobalSno('a', "Oper %s used UNLOCKSERV to allow new connections", user->nick.c_str()); return CMD_SUCCESS; } }; diff --git a/src/modules/m_mlock.cpp b/src/modules/m_mlock.cpp index e9ca3bfd0..3fb60a3d2 100644 --- a/src/modules/m_mlock.cpp +++ b/src/modules/m_mlock.cpp @@ -54,17 +54,15 @@ public: return MOD_RES_PASSTHRU; std::string *mlock_str = mlock.get(channel); - if (!mlock_str || mlock_str->empty()) + if (!mlock_str) return MOD_RES_PASSTHRU; - for (const char *modes = parameters[1].c_str(); *modes; modes++) + std::string::size_type p = parameters[1].find_first_of(*mlock_str); + if (p != std::string::npos) { - if (mlock_str->find(*modes) != std::string::npos) - { - source->WriteNumeric(742, "%s %c %s :MODE cannot be set due to channel having an active MLOCK restriction policy", - channel->name.c_str(), *modes, mlock_str->c_str()); - return MOD_RES_DENY; - } + source->WriteNumeric(742, "%s %c %s :MODE cannot be set due to channel having an active MLOCK restriction policy", + channel->name.c_str(), parameters[1][p], mlock_str->c_str()); + return MOD_RES_DENY; } return MOD_RES_PASSTHRU; diff --git a/src/modules/m_operchans.cpp b/src/modules/m_operchans.cpp index 074c644e1..2e6fad79f 100644 --- a/src/modules/m_operchans.cpp +++ b/src/modules/m_operchans.cpp @@ -24,32 +24,13 @@ /* $ModDesc: Provides support for oper-only chans via the +O channel mode */ -class OperChans : public ModeHandler +class OperChans : public SimpleChannelModeHandler { public: /* This is an oper-only mode */ - OperChans(Module* Creator) : ModeHandler(Creator, "operonly", 'O', PARAM_NONE, MODETYPE_CHANNEL) { oper = true; } - - ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) + OperChans(Module* Creator) : SimpleChannelModeHandler(Creator, "operonly", 'O') { - if (adding) - { - if (!channel->IsModeSet('O')) - { - channel->SetMode('O',true); - return MODEACTION_ALLOW; - } - } - else - { - if (channel->IsModeSet('O')) - { - channel->SetMode('O',false); - return MODEACTION_ALLOW; - } - } - - return MODEACTION_DENY; + oper = true; } }; diff --git a/src/modules/m_satopic.cpp b/src/modules/m_satopic.cpp index bf65cc5d5..a0e3319af 100644 --- a/src/modules/m_satopic.cpp +++ b/src/modules/m_satopic.cpp @@ -44,8 +44,7 @@ class CommandSATopic : public Command // 3rd parameter overrides access checks target->SetTopic(user, newTopic, true); - ServerInstance->SNO->WriteToSnoMask('a', user->nick + " used SATOPIC on " + target->name + ", new topic: " + newTopic); - ServerInstance->PI->SendSNONotice("A", user->nick + " used SATOPIC on " + target->name + ", new topic: " + newTopic); + ServerInstance->SNO->WriteGlobalSno('a', user->nick + " used SATOPIC on " + target->name + ", new topic: " + newTopic); return CMD_SUCCESS; } diff --git a/src/modules/m_services_account.cpp b/src/modules/m_services_account.cpp index cd34e955a..a28be61dc 100644 --- a/src/modules/m_services_account.cpp +++ b/src/modules/m_services_account.cpp @@ -39,19 +39,17 @@ class Channel_r : public ModeHandler if (!IS_LOCAL(source) || ServerInstance->ULine(source->nick.c_str()) || ServerInstance->ULine(source->server)) { // Only change the mode if it's not redundant - if ((adding && !channel->IsModeSet('r')) || (!adding && channel->IsModeSet('r'))) + if ((adding != channel->IsModeSet('r'))) { channel->SetMode('r',adding); return MODEACTION_ALLOW; } - - return MODEACTION_DENY; } else { source->WriteNumeric(500, "%s :Only a server may modify the +r channel mode", source->nick.c_str()); - return MODEACTION_DENY; } + return MODEACTION_DENY; } }; @@ -67,18 +65,17 @@ class User_r : public ModeHandler { if (!IS_LOCAL(source) || ServerInstance->ULine(source->nick.c_str()) || ServerInstance->ULine(source->server)) { - if ((adding && !dest->IsModeSet('r')) || (!adding && dest->IsModeSet('r'))) + if ((adding != dest->IsModeSet('r'))) { dest->SetMode('r',adding); return MODEACTION_ALLOW; } - return MODEACTION_DENY; } else { source->WriteNumeric(500, "%s :Only a server may modify the +r user mode", source->nick.c_str()); - return MODEACTION_DENY; } + return MODEACTION_DENY; } }; diff --git a/src/modules/m_setname.cpp b/src/modules/m_setname.cpp index 0d6b1d9f3..32c1d5dc3 100644 --- a/src/modules/m_setname.cpp +++ b/src/modules/m_setname.cpp @@ -36,7 +36,7 @@ class CommandSetname : public Command CmdResult Handle (const std::vector<std::string>& parameters, User *user) { - if (parameters.size() == 0) + if (parameters[0].empty()) { user->WriteServ("NOTICE %s :*** SETNAME: GECOS must be specified", user->nick.c_str()); return CMD_FAILURE; @@ -50,8 +50,7 @@ class CommandSetname : public Command if (user->ChangeName(parameters[0].c_str())) { - ServerInstance->SNO->WriteGlobalSno('a', "%s used SETNAME to change their GECOS to %s", user->nick.c_str(), parameters[0].c_str()); - return CMD_SUCCESS; + ServerInstance->SNO->WriteGlobalSno('a', "%s used SETNAME to change their GECOS to '%s'", user->nick.c_str(), parameters[0].c_str()); } return CMD_SUCCESS; diff --git a/src/modules/m_showwhois.cpp b/src/modules/m_showwhois.cpp index 6eec64bd5..d81dd553d 100644 --- a/src/modules/m_showwhois.cpp +++ b/src/modules/m_showwhois.cpp @@ -27,35 +27,13 @@ /** Handle user mode +W */ -class SeeWhois : public ModeHandler +class SeeWhois : public SimpleUserModeHandler { public: - SeeWhois(Module* Creator, bool IsOpersOnly) : ModeHandler(Creator, "showwhois", 'W', PARAM_NONE, MODETYPE_USER) + SeeWhois(Module* Creator, bool IsOpersOnly) : SimpleUserModeHandler(Creator, "showwhois", 'W') { oper = IsOpersOnly; } - - ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) - { - if (adding) - { - if (!dest->IsModeSet('W')) - { - dest->SetMode('W',true); - return MODEACTION_ALLOW; - } - } - else - { - if (dest->IsModeSet('W')) - { - dest->SetMode('W',false); - return MODEACTION_ALLOW; - } - } - - return MODEACTION_DENY; - } }; class WhoisNoticeCmd : public Command diff --git a/src/modules/m_shun.cpp b/src/modules/m_shun.cpp index fe1c41162..197bbc1bf 100644 --- a/src/modules/m_shun.cpp +++ b/src/modules/m_shun.cpp @@ -158,7 +158,7 @@ class CommandShun : public Command else { delete r; - user->WriteServ("NOTICE %s :*** Shun for %s already exists", user->nick.c_str(), expr.c_str()); + user->WriteServ("NOTICE %s :*** Shun for %s already exists", user->nick.c_str(), target.c_str()); return CMD_FAILURE; } } diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h index be5455bce..13dfad3f1 100644 --- a/src/modules/m_spanningtree/treesocket.h +++ b/src/modules/m_spanningtree/treesocket.h @@ -315,6 +315,10 @@ class TreeSocket : public BufferedSocket /** Handle server quit on close */ virtual void Close(); + + /** Returns true if this server was introduced to the rest of the network + */ + bool Introduced(); }; #endif diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index dcb35af31..7804c870d 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -183,7 +183,7 @@ void TreeSocket::Squit(TreeServer* Current, const std::string &reason) { DelServerEvent(Utils->Creator, Current->GetName()); - if (!Current->GetSocket() || Current->GetSocket()->GetLinkState() == CONNECTED) + if (!Current->GetSocket() || Current->GetSocket()->Introduced()) { parameterlist params; params.push_back(Current->GetName()); @@ -245,3 +245,8 @@ void TreeSocket::OnDataReady() SendError("RecvQ overrun (line too long)"); Utils->Creator->loopCall = false; } + +bool TreeSocket::Introduced() +{ + return (capab == NULL); +} diff --git a/src/modules/m_stripcolor.cpp b/src/modules/m_stripcolor.cpp index cd4f35c4b..86f307bae 100644 --- a/src/modules/m_stripcolor.cpp +++ b/src/modules/m_stripcolor.cpp @@ -72,8 +72,8 @@ class ModuleStripColor : public Module { /* refactor this completely due to SQUIT bug since the old code would strip last char and replace with \0 --peavey */ int seq = 0; - std::string::iterator i,safei; - for (i = sentence.begin(); i != sentence.end();) + + for (std::string::iterator i = sentence.begin(); i != sentence.end();) { if (*i == 3) seq = 1; @@ -89,20 +89,7 @@ class ModuleStripColor : public Module seq = 0; if (seq || ((*i == 2) || (*i == 15) || (*i == 22) || (*i == 21) || (*i == 31))) - { - if (i != sentence.begin()) - { - safei = i; - --i; - sentence.erase(safei); - ++i; - } - else - { - sentence.erase(i); - i = sentence.begin(); - } - } + i = sentence.erase(i); else ++i; } diff --git a/src/modules/m_swhois.cpp b/src/modules/m_swhois.cpp index dc53f2f0c..a98c06c75 100644 --- a/src/modules/m_swhois.cpp +++ b/src/modules/m_swhois.cpp @@ -90,7 +90,7 @@ class ModuleSWhois : public Module ModuleSWhois() : cmd(this) { ServerInstance->AddCommand(&cmd); - Implementation eventlist[] = { I_OnWhoisLine, I_OnPostCommand }; + Implementation eventlist[] = { I_OnWhoisLine, I_OnPostOper }; ServerInstance->Modules->Attach(eventlist, this, 2); } @@ -112,11 +112,10 @@ class ModuleSWhois : public Module return MOD_RES_PASSTHRU; } - void OnPostCommand(const std::string &command, const std::vector<std::string> ¶ms, LocalUser *user, CmdResult result, const std::string &original_line) + void OnPostOper(User* user, const std::string &opertype, const std::string &opername) { - if ((command != "OPER") || (result != CMD_SUCCESS)) + if (!IS_LOCAL(user)) return; - ConfigReader Conf; std::string swhois = user->oper->getConfig("swhois"); diff --git a/src/modules/m_xline_db.cpp b/src/modules/m_xline_db.cpp index 1918f3fc5..683c14afa 100644 --- a/src/modules/m_xline_db.cpp +++ b/src/modules/m_xline_db.cpp @@ -25,6 +25,7 @@ class ModuleXLineDB : public Module { + std::vector<XLine *> xlines; bool reading_db; // If this is true, addlines are as a result of db reading, so don't bother flushing the db to disk. // DO REMEMBER TO SET IT, otherwise it's annoying :P public: @@ -49,6 +50,7 @@ class ModuleXLineDB : public Module void OnAddLine(User* source, XLine* line) { ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Adding a line"); + xlines.push_back(line); if (!reading_db) { @@ -74,6 +76,15 @@ class ModuleXLineDB : public Module void RemoveLine(XLine *line) { ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Removing a line"); + for (std::vector<XLine *>::iterator i = xlines.begin(); i != xlines.end(); i++) + { + if ((*i) == line) + { + xlines.erase(i); + break; + } + } + WriteDatabase(); } @@ -108,19 +119,12 @@ class ModuleXLineDB : public Module fprintf(f, "VERSION 1\n"); // Now, let's write. - std::vector<std::string> types = ServerInstance->XLines->GetAllTypes(); - for (std::vector<std::string>::const_iterator it = types.begin(); it != types.end(); ++it) + XLine *line; + for (std::vector<XLine *>::iterator i = xlines.begin(); i != xlines.end(); i++) { - XLineLookup* lookup = ServerInstance->XLines->GetAll(*it); - if (!lookup) - continue; - - for (LookupIter i = lookup->begin(); i != lookup->end(); ++i) - { - XLine *line = i->second; - fprintf(f, "LINE %s %s %s %lu %lu :%s\n", line->type.c_str(), line->Displayable(), - ServerInstance->Config->ServerName.c_str(), (unsigned long)line->set_time, (unsigned long)line->duration, line->reason.c_str()); - } + line = (*i); + fprintf(f, "LINE %s %s %s %lu %lu :%s\n", line->type.c_str(), line->Displayable(), + ServerInstance->Config->ServerName.c_str(), (unsigned long)line->set_time, (unsigned long)line->duration, line->reason.c_str()); } ServerInstance->Logs->Log("m_xline_db",DEBUG, "xlinedb: Finished writing XLines. Checking for error.."); diff --git a/src/stats.cpp b/src/stats.cpp deleted file mode 100644 index e5ea94b9c..000000000 --- a/src/stats.cpp +++ /dev/null @@ -1,357 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org> - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "inspircd.h" -#include "xline.h" -#include "commands/cmd_whowas.h" - -void InspIRCd::DoStats(char statschar, User* user, string_list &results) -{ - std::string sn(this->Config->ServerName); - - bool isPublic = Config->UserStats.find(statschar) != std::string::npos; - bool isRemoteOper = IS_REMOTE(user) && IS_OPER(user); - bool isLocalOperWithPrivs = IS_LOCAL(user) && user->HasPrivPermission("servers/auspex"); - - if (!isPublic && !isRemoteOper && !isLocalOperWithPrivs) - { - this->SNO->WriteToSnoMask('t', - "%s '%c' denied for %s (%s@%s)", - (IS_LOCAL(user) ? "Stats" : "Remote stats"), - statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str()); - results.push_back(sn + " 481 " + user->nick + " :Permission denied - STATS " + statschar + " requires the servers/auspex priv."); - return; - } - - ModResult MOD_RESULT; - FIRST_MOD_RESULT(OnStats, MOD_RESULT, (statschar, user, results)); - if (MOD_RESULT == MOD_RES_DENY) - { - results.push_back(sn+" 219 "+user->nick+" "+statschar+" :End of /STATS report"); - this->SNO->WriteToSnoMask('t',"%s '%c' requested by %s (%s@%s)", - (IS_LOCAL(user) ? "Stats" : "Remote stats"), statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str()); - return; - } - - switch (statschar) - { - /* stats p (show listening ports) */ - case 'p': - { - for (size_t i = 0; i < this->ports.size(); i++) - { - std::string ip = this->ports[i]->bind_addr; - if (ip.empty()) - ip.assign("*"); - std::string type = ports[i]->bind_tag->getString("type", "clients"); - std::string hook = ports[i]->bind_tag->getString("ssl", "plaintext"); - - results.push_back(sn+" 249 "+user->nick+" :"+ ip + ":"+ConvToStr(ports[i]->bind_port)+ - " (" + type + ", " + hook + ")"); - } - } - break; - - /* These stats symbols must be handled by a linking module */ - case 'n': - case 'c': - break; - - case 'i': - { - for (ClassVector::iterator i = this->Config->Classes.begin(); i != this->Config->Classes.end(); i++) - { - ConnectClass* c = *i; - std::stringstream res; - res << sn << " 215 " << user->nick << " I " << c->name << ' '; - if (c->type == CC_ALLOW) - res << '+'; - if (c->type == CC_DENY) - res << '-'; - - if (c->type == CC_NAMED) - res << '*'; - else - res << c->host; - - res << ' ' << c->config->getString("port", "*") << ' '; - - res << c->GetRecvqMax() << ' ' << c->GetSendqSoftMax() << ' ' << c->GetSendqHardMax() - << ' ' << c->GetCommandRate() << ' ' << c->GetPenaltyThreshold(); - if (c->fakelag) - res << '*'; - results.push_back(res.str()); - } - } - break; - - case 'Y': - { - int idx = 0; - for (ClassVector::iterator i = this->Config->Classes.begin(); i != this->Config->Classes.end(); i++) - { - ConnectClass* c = *i; - results.push_back(sn+" 215 "+user->nick+" i NOMATCH * "+c->GetHost()+" "+ConvToStr(c->limit ? c->limit : this->SE->GetMaxFds())+" "+ConvToStr(idx)+" "+this->Config->ServerName+" *"); - results.push_back(sn+" 218 "+user->nick+" Y "+ConvToStr(idx)+" "+ConvToStr(c->GetPingTime())+" 0 "+ConvToStr(c->GetSendqHardMax())+" :"+ - ConvToStr(c->GetRecvqMax())+" "+ConvToStr(c->GetRegTimeout())); - idx++; - } - } - break; - - case 'U': - { - for(std::map<irc::string, bool>::iterator i = Config->ulines.begin(); i != Config->ulines.end(); ++i) - { - results.push_back(sn+" 248 "+user->nick+" U "+std::string(i->first.c_str())); - } - } - break; - - case 'P': - { - int idx = 0; - for (user_hash::iterator i = this->Users->clientlist->begin(); i != this->Users->clientlist->end(); i++) - { - if (IS_OPER(i->second) && !this->ULine(i->second->server)) - { - results.push_back(sn+" 249 "+user->nick+" :"+i->second->nick+" ("+i->second->ident+"@"+i->second->dhost+") Idle: "+ - (IS_LOCAL(i->second) ? ConvToStr(this->Time() - i->second->idle_lastmsg) + " secs" : "unavailable")); - idx++; - } - } - results.push_back(sn+" 249 "+user->nick+" :"+ConvToStr(idx)+" OPER(s)"); - } - break; - - case 'k': - this->XLines->InvokeStats("K",216,user,results); - break; - case 'g': - this->XLines->InvokeStats("G",223,user,results); - break; - case 'q': - this->XLines->InvokeStats("Q",217,user,results); - break; - case 'Z': - this->XLines->InvokeStats("Z",223,user,results); - break; - case 'e': - this->XLines->InvokeStats("E",223,user,results); - break; - case 'E': - results.push_back(sn+" 249 "+user->nick+" :Total events: "+ConvToStr(this->SE->TotalEvents)); - results.push_back(sn+" 249 "+user->nick+" :Read events: "+ConvToStr(this->SE->ReadEvents)); - results.push_back(sn+" 249 "+user->nick+" :Write events: "+ConvToStr(this->SE->WriteEvents)); - results.push_back(sn+" 249 "+user->nick+" :Error events: "+ConvToStr(this->SE->ErrorEvents)); - break; - - /* stats m (list number of times each command has been used, plus bytecount) */ - case 'm': - for (Commandtable::iterator i = this->Parser->cmdlist.begin(); i != this->Parser->cmdlist.end(); i++) - { - if (i->second->use_count) - { - /* RPL_STATSCOMMANDS */ - results.push_back(sn+" 212 "+user->nick+" "+i->second->name+" "+ConvToStr(i->second->use_count)+" "+ConvToStr(i->second->total_bytes)); - } - } - break; - - /* stats z (debug and memory info) */ - case 'z': - { - results.push_back(sn+" 249 "+user->nick+" :Users: "+ConvToStr(this->Users->clientlist->size())); - results.push_back(sn+" 249 "+user->nick+" :Channels: "+ConvToStr(this->chanlist->size())); - results.push_back(sn+" 249 "+user->nick+" :Commands: "+ConvToStr(this->Parser->cmdlist.size())); - - if (!this->Config->WhoWasGroupSize == 0 && !this->Config->WhoWasMaxGroups == 0) - { - Module* whowas = Modules->Find("cmd_whowas.so"); - if (whowas) - { - WhowasRequest req(NULL, whowas, WhowasRequest::WHOWAS_STATS); - req.user = user; - req.Send(); - results.push_back(sn+" 249 "+user->nick+" :"+req.value); - } - } - - float kbitpersec_in, kbitpersec_out, kbitpersec_total; - char kbitpersec_in_s[30], kbitpersec_out_s[30], kbitpersec_total_s[30]; - - this->SE->GetStats(kbitpersec_in, kbitpersec_out, kbitpersec_total); - - snprintf(kbitpersec_total_s, 30, "%03.5f", kbitpersec_total); - snprintf(kbitpersec_out_s, 30, "%03.5f", kbitpersec_out); - snprintf(kbitpersec_in_s, 30, "%03.5f", kbitpersec_in); - - results.push_back(sn+" 249 "+user->nick+" :Bandwidth total: "+ConvToStr(kbitpersec_total_s)+" kilobits/sec"); - results.push_back(sn+" 249 "+user->nick+" :Bandwidth out: "+ConvToStr(kbitpersec_out_s)+" kilobits/sec"); - results.push_back(sn+" 249 "+user->nick+" :Bandwidth in: "+ConvToStr(kbitpersec_in_s)+" kilobits/sec"); - -#ifndef WIN32 - /* Moved this down here so all the not-windows stuff (look w00tie, I didn't say win32!) is in one ifndef. - * Also cuts out some identical code in both branches of the ifndef. -- Om - */ - rusage R; - - /* Not sure why we were doing '0' with a RUSAGE_SELF comment rather than just using RUSAGE_SELF -- Om */ - if (!getrusage(RUSAGE_SELF,&R)) /* RUSAGE_SELF */ - { - results.push_back(sn+" 249 "+user->nick+" :Total allocation: "+ConvToStr(R.ru_maxrss)+"K"); - results.push_back(sn+" 249 "+user->nick+" :Signals: "+ConvToStr(R.ru_nsignals)); - results.push_back(sn+" 249 "+user->nick+" :Page faults: "+ConvToStr(R.ru_majflt)); - results.push_back(sn+" 249 "+user->nick+" :Swaps: "+ConvToStr(R.ru_nswap)); - results.push_back(sn+" 249 "+user->nick+" :Context Switches: Voluntary; "+ConvToStr(R.ru_nvcsw)+" Involuntary; "+ConvToStr(R.ru_nivcsw)); - - char percent[30]; - - float n_elapsed = (ServerInstance->Time() - this->stats->LastSampled.tv_sec) * 1000000 - + (ServerInstance->Time_ns() - this->stats->LastSampled.tv_nsec) / 1000; - float n_eaten = ((R.ru_utime.tv_sec - this->stats->LastCPU.tv_sec) * 1000000 + R.ru_utime.tv_usec - this->stats->LastCPU.tv_usec); - float per = (n_eaten / n_elapsed) * 100; - - snprintf(percent, 30, "%03.5f%%", per); - results.push_back(sn+" 249 "+user->nick+" :CPU Use (now): "+percent); - - n_elapsed = ServerInstance->Time() - ServerInstance->startup_time; - n_eaten = (float)R.ru_utime.tv_sec + R.ru_utime.tv_usec / 100000.0; - per = (n_eaten / n_elapsed) * 100; - snprintf(percent, 30, "%03.5f%%", per); - results.push_back(sn+" 249 "+user->nick+" :CPU Use (total): "+percent); - } -#else - PROCESS_MEMORY_COUNTERS MemCounters; - if (GetProcessMemoryInfo(GetCurrentProcess(), &MemCounters, sizeof(MemCounters))) - { - results.push_back(sn+" 249 "+user->nick+" :Total allocation: "+ConvToStr((MemCounters.WorkingSetSize + MemCounters.PagefileUsage) / 1024)+"K"); - results.push_back(sn+" 249 "+user->nick+" :Pagefile usage: "+ConvToStr(MemCounters.PagefileUsage / 1024)+"K"); - results.push_back(sn+" 249 "+user->nick+" :Page faults: "+ConvToStr(MemCounters.PageFaultCount)); - results.push_back(sn+" 249 "+user->nick+" :CPU Usage: " + ConvToStr(getcpu()) + "%"); - } -#endif - } - break; - - case 'T': - { - char buffer[MAXBUF]; - results.push_back(sn+" 249 "+user->nick+" :accepts "+ConvToStr(this->stats->statsAccept)+" refused "+ConvToStr(this->stats->statsRefused)); - results.push_back(sn+" 249 "+user->nick+" :unknown commands "+ConvToStr(this->stats->statsUnknown)); - results.push_back(sn+" 249 "+user->nick+" :nick collisions "+ConvToStr(this->stats->statsCollisions)); - results.push_back(sn+" 249 "+user->nick+" :dns requests "+ConvToStr(this->stats->statsDnsGood+this->stats->statsDnsBad)+" succeeded "+ConvToStr(this->stats->statsDnsGood)+" failed "+ConvToStr(this->stats->statsDnsBad)); - results.push_back(sn+" 249 "+user->nick+" :connection count "+ConvToStr(this->stats->statsConnects)); - snprintf(buffer,MAXBUF," 249 %s :bytes sent %5.2fK recv %5.2fK", - user->nick.c_str(),this->stats->statsSent / 1024.0,this->stats->statsRecv / 1024.0); - results.push_back(sn+buffer); - } - break; - - /* stats o */ - case 'o': - { - ConfigTagList tags = ServerInstance->Config->ConfTags("oper"); - for(ConfigIter i = tags.first; i != tags.second; ++i) - { - ConfigTag* tag = i->second; - results.push_back(sn+" 243 "+user->nick+" O "+tag->getString("host")+" * "+ - tag->getString("name") + " " + tag->getString("type")+" 0"); - } - } - break; - case 'O': - { - for(OperIndex::iterator i = ServerInstance->Config->oper_blocks.begin(); i != ServerInstance->Config->oper_blocks.end(); i++) - { - // just the types, not the actual oper blocks... - if (i->first[0] != ' ') - continue; - OperInfo* tag = i->second; - tag->init(); - std::string umodes; - std::string cmodes; - for(char c='A'; c < 'z'; c++) - { - ModeHandler* mh = ServerInstance->Modes->FindMode(c, MODETYPE_USER); - if (mh && mh->NeedsOper() && tag->AllowedUserModes[c - 'A']) - umodes.push_back(c); - mh = ServerInstance->Modes->FindMode(c, MODETYPE_CHANNEL); - if (mh && mh->NeedsOper() && tag->AllowedChanModes[c - 'A']) - cmodes.push_back(c); - } - results.push_back(sn+" 243 "+user->nick+" O "+tag->NameStr() + " " + umodes + " " + cmodes); - } - } - break; - - /* stats l (show user I/O stats) */ - case 'l': - results.push_back(sn+" 211 "+user->nick+" :nick[ident@host] sendq cmds_out bytes_out cmds_in bytes_in time_open"); - for (std::vector<LocalUser*>::iterator n = this->Users->local_users.begin(); n != this->Users->local_users.end(); n++) - { - LocalUser* i = *n; - results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->dhost+"] "+ConvToStr(i->eh.getSendQSize())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(this->Time() - i->age)); - } - break; - - /* stats L (show user I/O stats with IP addresses) */ - case 'L': - results.push_back(sn+" 211 "+user->nick+" :nick[ident@ip] sendq cmds_out bytes_out cmds_in bytes_in time_open"); - for (std::vector<LocalUser*>::iterator n = this->Users->local_users.begin(); n != this->Users->local_users.end(); n++) - { - LocalUser* i = *n; - results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->GetIPString()+"] "+ConvToStr(i->eh.getSendQSize())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(this->Time() - i->age)); - } - break; - - /* stats u (show server uptime) */ - case 'u': - { - time_t current_time = 0; - current_time = this->Time(); - time_t server_uptime = current_time - this->startup_time; - struct tm* stime; - stime = gmtime(&server_uptime); - /* i dont know who the hell would have an ircd running for over a year nonstop, but - * Craig suggested this, and it seemed a good idea so in it went */ - if (stime->tm_year > 70) - { - char buffer[MAXBUF]; - snprintf(buffer,MAXBUF," 242 %s :Server up %d years, %d days, %.2d:%.2d:%.2d",user->nick.c_str(),(stime->tm_year-70),stime->tm_yday,stime->tm_hour,stime->tm_min,stime->tm_sec); - results.push_back(sn+buffer); - } - else - { - char buffer[MAXBUF]; - snprintf(buffer,MAXBUF," 242 %s :Server up %d days, %.2d:%.2d:%.2d",user->nick.c_str(),stime->tm_yday,stime->tm_hour,stime->tm_min,stime->tm_sec); - results.push_back(sn+buffer); - } - } - break; - - default: - break; - } - - results.push_back(sn+" 219 "+user->nick+" "+statschar+" :End of /STATS report"); - this->SNO->WriteToSnoMask('t',"%s '%c' requested by %s (%s@%s)", - (IS_LOCAL(user) ? "Stats" : "Remote stats"), statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str()); - return; -} |