summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure7
-rw-r--r--docs/conf/inspircd.helpop-full.example1
-rw-r--r--docs/conf/modules.conf.example9
-rw-r--r--include/configparser.h10
-rw-r--r--include/hashcomp.h8
-rw-r--r--include/inspircd.h4
-rw-r--r--make/gnutlscert.pm2
-rw-r--r--src/channels.cpp2
-rw-r--r--src/commands/cmd_commands.cpp4
-rw-r--r--src/commands/cmd_stats.cpp345
-rw-r--r--src/configparser.cpp4
-rw-r--r--src/hashcomp.cpp24
-rw-r--r--src/inspircd.cpp19
-rw-r--r--src/mode.cpp77
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp95
-rw-r--r--src/modules/extra/m_ssl_openssl.cpp40
-rw-r--r--src/modules/m_blockamsg.cpp4
-rw-r--r--src/modules/m_chanhistory.cpp7
-rw-r--r--src/modules/m_chanlog.cpp20
-rw-r--r--src/modules/m_chgname.cpp4
-rw-r--r--src/modules/m_commonchans.cpp26
-rw-r--r--src/modules/m_connflood.cpp22
-rw-r--r--src/modules/m_cycle.cpp4
-rw-r--r--src/modules/m_halfop.cpp5
-rw-r--r--src/modules/m_helpop.cpp26
-rw-r--r--src/modules/m_hidechans.cpp26
-rw-r--r--src/modules/m_hideoper.cpp26
-rw-r--r--src/modules/m_hostchange.cpp96
-rw-r--r--src/modules/m_ident.cpp23
-rw-r--r--src/modules/m_messageflood.cpp152
-rw-r--r--src/modules/m_namesx.cpp14
-rw-r--r--src/modules/m_noctcp.cpp2
-rw-r--r--src/modules/m_nokicks.cpp4
-rw-r--r--src/modules/m_operchans.cpp25
-rw-r--r--src/modules/m_opermotd.cpp71
-rw-r--r--src/modules/m_sapart.cpp4
-rw-r--r--src/modules/m_satopic.cpp3
-rw-r--r--src/modules/m_services_account.cpp11
-rw-r--r--src/modules/m_servprotect.cpp4
-rw-r--r--src/modules/m_setname.cpp2
-rw-r--r--src/modules/m_showwhois.cpp26
-rw-r--r--src/modules/m_spanningtree/encap.cpp2
-rw-r--r--src/modules/m_spanningtree/protocolinterface.cpp28
-rw-r--r--src/modules/m_spanningtree/treesocket.h5
-rw-r--r--src/modules/m_spanningtree/treesocket1.cpp11
-rw-r--r--src/modules/m_spanningtree/treesocket2.cpp4
-rw-r--r--src/modules/m_uhnames.cpp3
-rw-r--r--src/modules/m_uninvite.cpp23
-rw-r--r--src/modules/m_xline_db.cpp28
-rw-r--r--src/server.cpp2
-rw-r--r--src/stats.cpp357
-rw-r--r--src/users.cpp4
-rwxr-xr-xsrc/version.sh2
-rw-r--r--src/xline.cpp4
-rw-r--r--win/configure.cpp7
-rw-r--r--win/inspircd.nsi12
-rw-r--r--win/inspircd.vcxproj3
-rw-r--r--win/inspircd_win32wrapper.cpp7
-rw-r--r--win/inspircd_win32wrapper.h1
-rw-r--r--win/make_gnutls_cert.bat14
60 files changed, 822 insertions, 953 deletions
diff --git a/configure b/configure
index 8edcdfe08..6021a805d 100755
--- a/configure
+++ b/configure
@@ -848,6 +848,11 @@ sub writefiles {
chomp(my $incos = `uname -n -s -r`);
chomp(my $version = `sh src/version.sh`);
chomp(my $revision2 = getrevision());
+ my $branch = "InspIRCd-0.0";
+ if ($version =~ /^(InspIRCd-[0-9]+\.[0-9]+)\.[0-9]+/)
+ {
+ $branch = $1;
+ }
if ($writeheader == 1)
{
print "Writing \e[1;32minspircd_config.h\e[0m\n";
@@ -861,6 +866,7 @@ sub writefiles {
#define CoreExport /**/
#define DllExport /**/
+#define CONFIG_PATH "$config{CONFIG_DIR}"
#define MOD_PATH "$config{MODULE_DIR}"
#define SOMAXCONN_S "$config{_SOMAXCONN}"
#define ENTRYPOINT int main(int argc, char** argv)
@@ -932,6 +938,7 @@ print FILEHANDLE "#define MAXBUF " . ($config{MAXBUF}+2) . "\n";
open(FILEHANDLE, ">include/inspircd_version.h.tmp");
print FILEHANDLE <<EOF;
+#define BRANCH "$branch"
#define VERSION "$version"
#define REVISION "$revision2"
#define SYSTEM "$incos"
diff --git a/docs/conf/inspircd.helpop-full.example b/docs/conf/inspircd.helpop-full.example
index c4936eea6..27b689f51 100644
--- a/docs/conf/inspircd.helpop-full.example
+++ b/docs/conf/inspircd.helpop-full.example
@@ -954,6 +954,7 @@ Y Show connection classes
O Show opertypes and the allowed user and channel modes it can set
E Show socket engine events
S Show currently held registered nicknames
+G Show how many local users are connected from each country according to GeoIP
Note that all /STATS use is broadcast to online IRC operators.">
diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example
index 9d9b61b93..76563fbeb 100644
--- a/docs/conf/modules.conf.example
+++ b/docs/conf/modules.conf.example
@@ -305,7 +305,7 @@
#<module name="m_cban.so">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
-# Censor module: Adds the channel mode +G
+# Censor module: Adds channel and user mode +G
#<module name="m_censor.so">
#
#-#-#-#-#-#-#-#-#-#-#- CENSOR CONFIGURATION -#-#-#-#-#-#-#-#-#-#-#-#
@@ -378,8 +378,13 @@
# joining a channel with +H 'X:T' set; 'T' is the maximum time to keep
# lines in the history buffer. Designed so that the new user knows what
# the current topic of conversation is when joining the channel.
-# NOTE: Currently hard-limited to a maximum of 50 lines.
#<module name="m_chanhistory.so">
+#
+# Set the maximum number of lines allowed to be stored per channel below.
+# This is the hard limit for 'X'.
+# If notice is set to yes, joining users will get a NOTICE before playback
+# telling them about the following lines being the pre-join history.
+#<chanhistory maxlines="20" notice="yes">
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# Channel logging module: used to send snotice output to channels, to
diff --git a/include/configparser.h b/include/configparser.h
index 478899ed9..4b83d26d7 100644
--- a/include/configparser.h
+++ b/include/configparser.h
@@ -61,13 +61,19 @@ struct ParseStack
struct FileWrapper
{
FILE* const f;
- FileWrapper(FILE* file) : f(file) {}
+ bool close_with_pclose;
+ FileWrapper(FILE* file, bool use_pclose = false) : f(file), close_with_pclose(use_pclose) {}
operator bool() { return f; }
operator FILE*() { return f; }
~FileWrapper()
{
if (f)
- fclose(f);
+ {
+ if (close_with_pclose)
+ pclose(f);
+ else
+ fclose(f);
+ }
}
};
diff --git a/include/hashcomp.h b/include/hashcomp.h
index 0340cb634..59986e66f 100644
--- a/include/hashcomp.h
+++ b/include/hashcomp.h
@@ -441,7 +441,7 @@ namespace irc
/** Used to split on commas
*/
- commasepstream* sep;
+ commasepstream sep;
/** Current position in a range of ports
*/
@@ -462,7 +462,7 @@ namespace irc
/** Used to determine overlapping of ports
* without O(n) algorithm being used
*/
- std::map<long, bool> overlap_set;
+ std::set<long> overlap_set;
/** Returns true if val overlaps an existing range
*/
@@ -475,10 +475,6 @@ namespace irc
*/
portparser(const std::string &source, bool allow_overlapped = true);
- /** Frees the internal commasepstream object
- */
- ~portparser();
-
/** Fetch the next token from the stream
* @return The next port number is returned, or 0 if none remain
*/
diff --git a/include/inspircd.h b/include/inspircd.h
index 78e0c1b3e..c06a28043 100644
--- a/include/inspircd.h
+++ b/include/inspircd.h
@@ -790,10 +790,6 @@ class CoreExport InspIRCd
*/
void SendWhoisLine(User* user, User* dest, int numeric, const char* format, ...) CUSTOM_PRINTF(5, 6);
- /** Handle /STATS
- */
- void DoStats(char statschar, User* user, string_list &results);
-
/** Handle /WHOIS
*/
void DoWhois(User* user, User* dest,unsigned long signon, unsigned long idle, const char* nick);
diff --git a/make/gnutlscert.pm b/make/gnutlscert.pm
index 1621c2c27..ab8aae427 100644
--- a/make/gnutlscert.pm
+++ b/make/gnutlscert.pm
@@ -36,7 +36,7 @@ sub make_gnutls_cert()
my $timestr = time();
my $org = promptstring_s("Please enter the organization name", "My IRC Network");
my $unit = promptstring_s("Please enter the unit Name", "Server Admins");
- my $state = promptstring_s("Pleae enter your state (two letter code)", "CA");
+ my $state = promptstring_s("Please enter your state (two letter code)", "CA");
my $country = promptstring_s("Please enter your country", "Oompa Loompa Land");
my $commonname = promptstring_s("Please enter the certificate common name (hostname)", "irc.mynetwork.com");
my $email = promptstring_s("Please enter a contact email address", "oompa\@loompa.com");
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 244bb44c3..3b0507175 100644
--- a/src/commands/cmd_stats.cpp
+++ b/src/commands/cmd_stats.cpp
@@ -20,6 +20,12 @@
#include "inspircd.h"
+#include "xline.h"
+#include "commands/cmd_whowas.h"
+
+#ifdef WINDOWS
+# pragma comment(lib, "psapi.lib") // For GetProcessMemoryInfo()
+#endif
/** Handle /STATS. These command handlers can be reloaded by the core,
* and handle basic RFC1459 commands. Commands within modules work
@@ -28,6 +34,7 @@
*/
class CommandStats : public Command
{
+ void DoStats(char statschar, User* user, string_list &results);
public:
/** Constructor for stats.
*/
@@ -47,13 +54,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..4abfb496a 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
@@ -306,7 +303,7 @@ void InspIRCd::WritePID(const std::string &filename)
}
InspIRCd::InspIRCd(int argc, char** argv) :
- ConfigFileName("conf/inspircd.conf"),
+ ConfigFileName(CONFIG_PATH "/inspircd.conf"),
/* Functor pointer initialisation.
*
diff --git a/src/mode.cpp b/src/mode.cpp
index 5efc98250..845b23fb0 100644
--- a/src/mode.cpp
+++ b/src/mode.cpp
@@ -1,6 +1,7 @@
/*
* InspIRCd -- Internet Relay Chat Daemon
*
+ * Copyright (C) 2012 Shawn Smith <shawn@inspircd.org>
* Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
* Copyright (C) 2007, 2009 Dennis Friis <peavey@inspircd.org>
* Copyright (C) 2006-2008 Robin Burchell <robin+git@viroteck.net>
@@ -132,47 +133,39 @@ bool ModeHandler::ResolveModeConflict(std::string& theirs, const std::string& ou
ModeAction SimpleUserModeHandler::OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
{
- if (adding)
- {
- if (!dest->IsModeSet(this->GetModeChar()))
- {
- dest->SetMode(this->GetModeChar(),true);
- return MODEACTION_ALLOW;
- }
- }
- else
- {
- if (dest->IsModeSet(this->GetModeChar()))
- {
- dest->SetMode(this->GetModeChar(),false);
- return MODEACTION_ALLOW;
- }
- }
+ /* We're either trying to add a mode we already have or
+ remove a mode we don't have, deny. */
+ if (dest->IsModeSet(this->GetModeChar()) == adding)
+ return MODEACTION_DENY;
- return MODEACTION_DENY;
+ /* adding will be either true or false, depending on if we
+ are adding or removing the mode, since we already checked
+ to make sure we aren't adding a mode we have or that we
+ aren't removing a mode we don't have, we don't have to do any
+ other checks here to see if it's true or false, just add or
+ remove the mode */
+ dest->SetMode(this->GetModeChar(), adding);
+
+ return MODEACTION_ALLOW;
}
ModeAction SimpleChannelModeHandler::OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
{
- if (adding)
- {
- if (!channel->IsModeSet(this->GetModeChar()))
- {
- channel->SetMode(this->GetModeChar(),true);
- return MODEACTION_ALLOW;
- }
- }
- else
- {
- if (channel->IsModeSet(this->GetModeChar()))
- {
- channel->SetMode(this->GetModeChar(),false);
- return MODEACTION_ALLOW;
- }
- }
+ /* We're either trying to add a mode we already have or
+ remove a mode we don't have, deny. */
+ if (channel->IsModeSet(this->GetModeChar()) == adding)
+ return MODEACTION_DENY;
- return MODEACTION_DENY;
+ /* adding will be either true or false, depending on if we
+ are adding or removing the mode, since we already checked
+ to make sure we aren't adding a mode we have or that we
+ aren't removing a mode we don't have, we don't have to do any
+ other checks here to see if it's true or false, just add or
+ remove the mode */
+ channel->SetMode(this->GetModeChar(), adding);
+
+ return MODEACTION_ALLOW;
}
ModeAction ParamChannelModeHandler::OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
@@ -906,9 +899,6 @@ bool ModeParser::DelModeWatcher(ModeWatcher* mw)
*/
void ModeHandler::RemoveMode(User* user, irc::modestacker* stack)
{
- char moderemove[MAXBUF];
- std::vector<std::string> parameters;
-
if (user->IsModeSet(this->GetModeChar()))
{
if (stack)
@@ -917,9 +907,10 @@ void ModeHandler::RemoveMode(User* user, irc::modestacker* stack)
}
else
{
- sprintf(moderemove,"-%c",this->GetModeChar());
+ std::vector<std::string> parameters;
parameters.push_back(user->nick);
- parameters.push_back(moderemove);
+ parameters.push_back("-");
+ parameters[1].push_back(this->GetModeChar());
ServerInstance->Modes->Process(parameters, ServerInstance->FakeClient);
}
}
@@ -930,9 +921,6 @@ void ModeHandler::RemoveMode(User* user, irc::modestacker* stack)
*/
void ModeHandler::RemoveMode(Channel* channel, irc::modestacker* stack)
{
- char moderemove[MAXBUF];
- std::vector<std::string> parameters;
-
if (channel->IsModeSet(this->GetModeChar()))
{
if (stack)
@@ -941,9 +929,10 @@ void ModeHandler::RemoveMode(Channel* channel, irc::modestacker* stack)
}
else
{
- sprintf(moderemove,"-%c",this->GetModeChar());
+ std::vector<std::string> parameters;
parameters.push_back(channel->name);
- parameters.push_back(moderemove);
+ parameters.push_back("-");
+ parameters[1].push_back(this->GetModeChar());
ServerInstance->SendMode(parameters, ServerInstance->FakeClient);
}
}
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp
index 6ca876d4c..7d8e9581e 100644
--- a/src/modules/extra/m_ssl_gnutls.cpp
+++ b/src/modules/extra/m_ssl_gnutls.cpp
@@ -28,8 +28,19 @@
#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","") */
+/* $CompileFlags: pkgconfincludes("gnutls","/gnutls/gnutls.h","") -Wno-deprecated-declarations */
/* $LinkerFlags: rpath("pkg-config --libs gnutls") pkgconflibs("gnutls","/libgnutls.so","-lgnutls") -lgcrypt */
enum issl_status { ISSL_NONE, ISSL_HANDSHAKING_READ, ISSL_HANDSHAKING_WRITE, ISSL_HANDSHAKEN, ISSL_CLOSING, ISSL_CLOSED };
@@ -151,6 +162,7 @@ class ModuleSSLGnuTLS : public Module
gnutls_certificate_credentials x509_cred;
gnutls_dh_params dh_params;
gnutls_digest_algorithm_t hash;
+ gnutls_priority_t priority;
std::string sslports;
int dh_bits;
@@ -172,6 +184,8 @@ class ModuleSSLGnuTLS : public Module
gnutls_global_init(); // This must be called once in the program
gnutls_x509_privkey_init(&x509_key);
+ // Init this here so it's always initialized, avoids an extra boolean
+ gnutls_priority_init(&priority, "NORMAL", NULL);
cred_alloc = false;
dh_alloc = false;
@@ -203,6 +217,10 @@ class ModuleSSLGnuTLS : public Module
if (Conf->getBool("showports", true))
{
+ sslports = Conf->getString("advertisedports");
+ if (!sslports.empty())
+ return;
+
for (size_t i = 0; i < ServerInstance->ports.size(); i++)
{
ListenSocket* port = ServerInstance->ports[i];
@@ -213,11 +231,20 @@ class ModuleSSLGnuTLS : public Module
ServerInstance->Logs->Log("m_ssl_gnutls", DEFAULT, "m_ssl_gnutls.so: Enabling SSL for port %s", portid.c_str());
if (port->bind_tag->getString("type", "clients") == "clients" && port->bind_addr != "127.0.0.1")
- sslports.append(portid).append(";");
+ {
+ /*
+ * Found an SSL port for clients that is not bound to 127.0.0.1 and handled by us, display
+ * the IP:port in ISUPPORT.
+ *
+ * We used to advertise all ports seperated by a ';' char that matched the above criteria,
+ * but this resulted in too long ISUPPORT lines if there were lots of ports to be displayed.
+ * To solve this by default we now only display the first IP:port found and let the user
+ * configure the exact value for the 005 token, if necessary.
+ */
+ sslports = portid;
+ break;
+ }
}
-
- if (!sslports.empty())
- sslports.erase(sslports.end() - 1);
}
}
@@ -241,6 +268,13 @@ class ModuleSSLGnuTLS : public Module
dh_bits = Conf->getInt("dhbits");
std::string hashname = Conf->getString("hash", "md5");
+ // The GnuTLS manual states that the gnutls_set_default_priority()
+ // call we used previously when initializing the session is the same
+ // as setting the "NORMAL" priority string.
+ // Thus if the setting below is not in the config we will behave exactly
+ // the same as before, when the priority setting wasn't available.
+ std::string priorities = Conf->getString("priority", "NORMAL");
+
if((dh_bits != 768) && (dh_bits != 1024) && (dh_bits != 2048) && (dh_bits != 3072) && (dh_bits != 4096))
dh_bits = 1024;
@@ -305,6 +339,21 @@ class ModuleSSLGnuTLS : public Module
if((ret = gnutls_certificate_set_x509_key(x509_cred, &x509_certs[0], certcount, x509_key)) < 0)
throw ModuleException("Unable to set GnuTLS cert/key pair: " + std::string(gnutls_strerror(ret)));
+ // It's safe to call this every time as we cannot have this uninitialized, see constructor and below.
+ gnutls_priority_deinit(priority);
+
+ // Try to set the priorities for ciphers, kex methods etc. to the user supplied string
+ // If the user did not supply anything then the string is already set to "NORMAL"
+ const char* priocstr = priorities.c_str();
+ const char* prioerror;
+
+ if ((ret = gnutls_priority_init(&priority, priocstr, &prioerror)) < 0)
+ {
+ // gnutls did not understand the user supplied string, log and fall back to the default priorities
+ ServerInstance->Logs->Log("m_ssl_gnutls",DEFAULT, "m_ssl_gnutls.so: Failed to set priorities to \"%s\": %s Syntax error at position %d, falling back to default (NORMAL)", priorities.c_str(), gnutls_strerror(ret), (prioerror - priocstr));
+ gnutls_priority_init(&priority, "NORMAL", NULL);
+ }
+
gnutls_certificate_client_set_retrieve_function (x509_cred, cert_callback);
ret = gnutls_dh_params_init(&dh_params);
@@ -338,6 +387,7 @@ class ModuleSSLGnuTLS : public Module
gnutls_x509_crt_deinit(x509_certs[i]);
gnutls_x509_privkey_deinit(x509_key);
+ gnutls_priority_deinit(priority);
if (dh_alloc)
gnutls_dh_params_deinit(dh_params);
@@ -399,44 +449,39 @@ class ModuleSSLGnuTLS : public Module
}
}
- void OnStreamSocketAccept(StreamSocket* user, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
+ void InitSession(StreamSocket* user, bool me_server)
{
- int fd = user->GetFd();
- issl_session* session = &sessions[fd];
-
- /* For STARTTLS: Don't try and init a session on a socket that already has a session */
- if (session->sess)
- return;
+ issl_session* session = &sessions[user->GetFd()];
- gnutls_init(&session->sess, GNUTLS_SERVER);
+ gnutls_init(&session->sess, me_server ? GNUTLS_SERVER : GNUTLS_CLIENT);
- gnutls_set_default_priority(session->sess); // Avoid calling all the priority functions, defaults are adequate.
+ gnutls_priority_set(session->sess, priority);
gnutls_credentials_set(session->sess, GNUTLS_CRD_CERTIFICATE, x509_cred);
gnutls_dh_set_prime_bits(session->sess, dh_bits);
-
gnutls_transport_set_ptr(session->sess, reinterpret_cast<gnutls_transport_ptr_t>(user));
gnutls_transport_set_push_function(session->sess, gnutls_push_wrapper);
gnutls_transport_set_pull_function(session->sess, gnutls_pull_wrapper);
- gnutls_certificate_server_set_request(session->sess, GNUTLS_CERT_REQUEST); // Request client certificate if any.
+ if (me_server)
+ gnutls_certificate_server_set_request(session->sess, GNUTLS_CERT_REQUEST); // Request client certificate if any.
Handshake(session, user);
}
- void OnStreamSocketConnect(StreamSocket* user)
+ void OnStreamSocketAccept(StreamSocket* user, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
{
issl_session* session = &sessions[user->GetFd()];
- gnutls_init(&session->sess, GNUTLS_CLIENT);
+ /* For STARTTLS: Don't try and init a session on a socket that already has a session */
+ if (session->sess)
+ return;
- gnutls_set_default_priority(session->sess); // Avoid calling all the priority functions, defaults are adequate.
- gnutls_credentials_set(session->sess, GNUTLS_CRD_CERTIFICATE, x509_cred);
- gnutls_dh_set_prime_bits(session->sess, dh_bits);
- gnutls_transport_set_ptr(session->sess, reinterpret_cast<gnutls_transport_ptr_t>(user));
- gnutls_transport_set_push_function(session->sess, gnutls_push_wrapper);
- gnutls_transport_set_pull_function(session->sess, gnutls_pull_wrapper);
+ InitSession(user, true);
+ }
- Handshake(session, user);
+ void OnStreamSocketConnect(StreamSocket* user)
+ {
+ InitSession(user, false);
}
void OnStreamSocketClose(StreamSocket* user)
diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp
index 0a5a76792..a8020bba1 100644
--- a/src/modules/extra/m_ssl_openssl.cpp
+++ b/src/modules/extra/m_ssl_openssl.cpp
@@ -159,20 +159,34 @@ class ModuleSSLOpenSSL : public Module
if (Conf->getBool("showports", true))
{
+ sslports = Conf->getString("advertisedports");
+ if (!sslports.empty())
+ return;
+
for (size_t i = 0; i < ServerInstance->ports.size(); i++)
{
ListenSocket* port = ServerInstance->ports[i];
if (port->bind_tag->getString("ssl") != "openssl")
continue;
- std::string portid = port->bind_desc;
+ const std::string& portid = port->bind_desc;
ServerInstance->Logs->Log("m_ssl_openssl", DEFAULT, "m_ssl_openssl.so: Enabling SSL for port %s", portid.c_str());
+
if (port->bind_tag->getString("type", "clients") == "clients" && port->bind_addr != "127.0.0.1")
- sslports.append(portid).append(";");
+ {
+ /*
+ * Found an SSL port for clients that is not bound to 127.0.0.1 and handled by us, display
+ * the IP:port in ISUPPORT.
+ *
+ * We used to advertise all ports seperated by a ';' char that matched the above criteria,
+ * but this resulted in too long ISUPPORT lines if there were lots of ports to be displayed.
+ * To solve this by default we now only display the first IP:port found and let the user
+ * configure the exact value for the 005 token, if necessary.
+ */
+ sslports = portid;
+ break;
+ }
}
-
- if (!sslports.empty())
- sslports.erase(sslports.end() - 1);
}
}
@@ -198,6 +212,16 @@ class ModuleSSLOpenSSL : public Module
throw ModuleException("Unknown hash type " + hash);
use_sha = (hash == "sha1");
+ std::string ciphers = conf->getString("ciphers", "");
+
+ if (!ciphers.empty())
+ {
+ if ((!SSL_CTX_set_cipher_list(ctx, ciphers.c_str())) || (!SSL_CTX_set_cipher_list(clictx, ciphers.c_str())))
+ {
+ ServerInstance->Logs->Log("m_ssl_openssl",DEFAULT, "m_ssl_openssl.so: Can't set cipher list to %s.", ciphers.c_str());
+ ERR_print_errors_cb(error_callback, this);
+ }
+ }
/* Load our keys and certificates
* NOTE: OpenSSL's error logging API sucks, don't blame us for this clusterfuck.
@@ -262,8 +286,10 @@ class ModuleSSLOpenSSL : public Module
if (sessions[user->eh.GetFd()].sess)
{
if (!sessions[user->eh.GetFd()].cert->fingerprint.empty())
- user->WriteServ("NOTICE %s :*** You are connected using SSL fingerprint %s",
- user->nick.c_str(), sessions[user->eh.GetFd()].cert->fingerprint.c_str());
+ user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\""
+ " and your SSL fingerprint is %s", user->nick.c_str(), SSL_get_cipher(sessions[user->eh.GetFd()].sess), sessions[user->eh.GetFd()].cert->fingerprint.c_str());
+ else
+ user->WriteServ("NOTICE %s :*** You are connected using SSL cipher \"%s\"", user->nick.c_str(), SSL_get_cipher(sessions[user->eh.GetFd()].sess));
}
}
}
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> &parameters, 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 667ddd928..2ac24c5d5 100644
--- a/src/modules/m_chgname.cpp
+++ b/src/modules/m_chgname.cpp
@@ -52,14 +52,14 @@ class CommandChgname : public Command
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 &parameter, 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_connflood.cpp b/src/modules/m_connflood.cpp
index d0e925716..9d7c9cb2c 100644
--- a/src/modules/m_connflood.cpp
+++ b/src/modules/m_connflood.cpp
@@ -23,27 +23,25 @@
/* $ModDesc: Connection throttle */
-int conns = 0, throttled = 0;
-
class ModuleConnFlood : public Module
{
private:
- int seconds, maxconns, timeout, boot_wait;
+ int seconds, timeout, boot_wait;
+ unsigned int conns;
+ unsigned int maxconns;
+ bool throttled;
time_t first;
std::string quitmsg;
public:
- ModuleConnFlood() {
-
+ ModuleConnFlood()
+ : conns(0), throttled(false)
+ {
InitConf();
Implementation eventlist[] = { I_OnRehash, I_OnUserRegister };
ServerInstance->Modules->Attach(eventlist, this, 2);
}
- virtual ~ModuleConnFlood()
- {
- }
-
virtual Version GetVersion()
{
return Version("Connection throttle", VF_VENDOR);
@@ -78,12 +76,12 @@ public:
/* increase connection count */
conns++;
- if (throttled == 1)
+ if (throttled)
{
if (tdiff > seconds + timeout)
{
/* expire throttle */
- throttled = 0;
+ throttled = false;
ServerInstance->SNO->WriteGlobalSno('a', "Connection throttle deactivated");
return MOD_RES_PASSTHRU;
}
@@ -96,7 +94,7 @@ public:
{
if (conns >= maxconns)
{
- throttled = 1;
+ throttled = true;
ServerInstance->SNO->WriteGlobalSno('a', "Connection throttle activated");
ServerInstance->Users->QuitUser(user, quitmsg);
return MOD_RES_DENY;
diff --git a/src/modules/m_cycle.cpp b/src/modules/m_cycle.cpp
index b28edde83..1eb3c1899 100644
--- a/src/modules/m_cycle.cpp
+++ b/src/modules/m_cycle.cpp
@@ -20,7 +20,7 @@
#include "inspircd.h"
-/* $ModDesc: Provides support for unreal-style CYCLE command. */
+/* $ModDesc: Provides command CYCLE, acts as a server-side HOP command to part and rejoin a channel. */
/** Handle /CYCLE
*/
@@ -97,7 +97,7 @@ class ModuleCycle : public Module
virtual Version GetVersion()
{
- return Version("Provides support for unreal-style CYCLE command.", VF_VENDOR);
+ return Version("Provides command CYCLE, acts as a server-side HOP command to part and rejoin a channel.", VF_VENDOR);
}
};
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 &parameter, 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 &parameter, 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 &parameter, 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_hostchange.cpp b/src/modules/m_hostchange.cpp
index 2635015c7..e63c61631 100644
--- a/src/modules/m_hostchange.cpp
+++ b/src/modules/m_hostchange.cpp
@@ -28,12 +28,22 @@
class Host
{
public:
- std::string action;
+ enum HostChangeAction
+ {
+ HCA_SET,
+ HCA_SUFFIX,
+ HCA_ADDNICK
+ };
+
+ HostChangeAction action;
std::string newhost;
std::string ports;
+
+ Host(HostChangeAction Action, const std::string& Newhost, const std::string& Ports) :
+ action(Action), newhost(Newhost), ports(Ports) {}
};
-typedef std::map<std::string,Host*> hostchanges_t;
+typedef std::vector<std::pair<std::string, Host> > hostchanges_t;
class ModuleHostChange : public Module
{
@@ -51,44 +61,39 @@ class ModuleHostChange : public Module
ServerInstance->Modules->Attach(eventlist, this, 2);
}
- virtual ~ModuleHostChange()
- {
- for (hostchanges_t::iterator i = hostchanges.begin(); i != hostchanges.end(); i++)
- {
- delete i->second;
- }
- hostchanges.clear();
- }
-
- void Prioritize()
- {
- Module* cloak = ServerInstance->Modules->Find("m_cloaking.so");
- ServerInstance->Modules->SetPriority(this, I_OnUserConnect, PRIORITY_AFTER, &cloak);
- }
-
-
virtual void OnRehash(User* user)
{
ConfigReader Conf;
MySuffix = Conf.ReadValue("host","suffix",0);
MyPrefix = Conf.ReadValue("host","prefix","",0);
MySeparator = Conf.ReadValue("host","separator",".",0);
- for (hostchanges_t::iterator i = hostchanges.begin(); i != hostchanges.end(); i++)
- {
- delete i->second;
- }
hostchanges.clear();
- for (int index = 0; index < Conf.Enumerate("hostchange"); index++)
+
+ std::set<std::string> dupecheck;
+ ConfigTagList tags = ServerInstance->Config->ConfTags("hostchange");
+ for (ConfigIter i = tags.first; i != tags.second; ++i)
{
- std::string mask = Conf.ReadValue("hostchange", "mask", index);
- std::string ports = Conf.ReadValue("hostchange", "ports", index);
- std::string action = Conf.ReadValue("hostchange", "action", index);
- std::string newhost = Conf.ReadValue("hostchange", "value", index);
- Host* x = new Host;
- x->action = action;
- x->ports = ports;
- x->newhost = newhost;
- hostchanges[mask] = x;
+ ConfigTag* tag = i->second;
+ std::string mask = tag->getString("mask");
+ if (!dupecheck.insert(mask).second)
+ throw ModuleException("Duplicate hostchange entry: " + mask);
+
+ Host::HostChangeAction act;
+ std::string newhost;
+ std::string action = tag->getString("action");
+ if (!strcasecmp(action.c_str(), "set"))
+ {
+ act = Host::HCA_SET;
+ newhost = tag->getString("newhost");
+ }
+ else if (!strcasecmp(action.c_str(), "suffix"))
+ act = Host::HCA_SUFFIX;
+ else if (!strcasecmp(action.c_str(), "addnick"))
+ act = Host::HCA_ADDNICK;
+ else
+ throw ModuleException("Invalid hostchange action: " + action);
+
+ hostchanges.push_back(std::make_pair(mask, Host(act, tag->getString("ports"), newhost)));
}
}
@@ -105,11 +110,11 @@ class ModuleHostChange : public Module
{
if (((InspIRCd::MatchCIDR(user->MakeHost(), i->first)) || (InspIRCd::MatchCIDR(user->MakeHostIP(), i->first))))
{
- Host* h = i->second;
+ const Host& h = i->second;
- if (!h->ports.empty())
+ if (!h.ports.empty())
{
- irc::portparser portrange(h->ports, false);
+ irc::portparser portrange(h.ports, false);
long portno = -1;
bool foundany = false;
@@ -123,27 +128,26 @@ class ModuleHostChange : public Module
// host of new user matches a hostchange tag's mask
std::string newhost;
- if (h->action == "set")
+ if (h.action == Host::HCA_SET)
{
- newhost = h->newhost;
+ newhost = h.newhost;
}
- else if (h->action == "suffix")
+ else if (h.action == Host::HCA_SUFFIX)
{
newhost = MySuffix;
}
- else if (h->action == "addnick")
+ else if (h.action == Host::HCA_ADDNICK)
{
// first take their nick and strip out non-dns, leaving just [A-Z0-9\-]
std::string complete;
- std::string old = user->nick;
- for (unsigned int j = 0; j < old.length(); j++)
+ for (std::string::const_iterator j = user->nick.begin(); j != user->nick.end(); ++j)
{
- if (((old[j] >= 'A') && (old[j] <= 'Z')) ||
- ((old[j] >= 'a') && (old[j] <= 'z')) ||
- ((old[j] >= '0') && (old[j] <= '9')) ||
- (old[j] == '-'))
+ if (((*j >= 'A') && (*j <= 'Z')) ||
+ ((*j >= 'a') && (*j <= 'z')) ||
+ ((*j >= '0') && (*j <= '9')) ||
+ (*j == '-'))
{
- complete = complete + old[j];
+ complete = complete + *j;
}
}
if (complete.empty())
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_messageflood.cpp b/src/modules/m_messageflood.cpp
index f3045cf52..ff92fcaa3 100644
--- a/src/modules/m_messageflood.cpp
+++ b/src/modules/m_messageflood.cpp
@@ -33,47 +33,30 @@ class floodsettings
{
public:
bool ban;
- int secs;
- int lines;
+ unsigned int secs;
+ unsigned int lines;
time_t reset;
- std::map<User*,int> counters;
+ std::map<User*, unsigned int> counters;
floodsettings(bool a, int b, int c) : ban(a), secs(b), lines(c)
{
reset = ServerInstance->Time() + secs;
- };
+ }
- void addmessage(User* who)
+ bool addmessage(User* who)
{
- std::map<User*,int>::iterator iter = counters.find(who);
- if (iter != counters.end())
- {
- iter->second++;
- }
- else
- {
- counters[who] = 1;
- }
if (ServerInstance->Time() > reset)
{
counters.clear();
reset = ServerInstance->Time() + secs;
}
- }
- bool shouldkick(User* who)
- {
- std::map<User*,int>::iterator iter = counters.find(who);
- if (iter != counters.end())
- {
- return (iter->second >= this->lines);
- }
- else return false;
+ return (++counters[who] >= this->lines);
}
void clear(User* who)
{
- std::map<User*,int>::iterator iter = counters.find(who);
+ std::map<User*, unsigned int>::iterator iter = counters.find(who);
if (iter != counters.end())
{
counters.erase(iter);
@@ -92,101 +75,45 @@ class MsgFlood : public ModeHandler
ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
{
- floodsettings *f = ext.get(channel);
-
if (adding)
{
- char ndata[MAXBUF];
- char* data = ndata;
- strlcpy(ndata,parameter.c_str(),MAXBUF);
- char* lines = data;
- char* secs = NULL;
- bool ban = false;
- if (*data == '*')
- {
- ban = true;
- lines++;
- }
- else
+ std::string::size_type colon = parameter.find(':');
+ if ((colon == std::string::npos) || (parameter.find('-') != std::string::npos))
{
- ban = false;
- }
- while (*data)
- {
- if (*data == ':')
- {
- *data = 0;
- data++;
- secs = data;
- break;
- }
- else data++;
- }
- if (secs)
- {
- /* Set up the flood parameters for this channel */
- int nlines = atoi(lines);
- int nsecs = atoi(secs);
- if ((nlines<2) || (nsecs<1))
- {
- source->WriteNumeric(608, "%s %s :Invalid flood parameter",source->nick.c_str(),channel->name.c_str());
- parameter.clear();
- return MODEACTION_DENY;
- }
- else
- {
- if (!f)
- {
- parameter = std::string(ban ? "*" : "") + ConvToStr(nlines) + ":" +ConvToStr(nsecs);
- f = new floodsettings(ban,nsecs,nlines);
- ext.set(channel, f);
- channel->SetModeParam('f', parameter);
- return MODEACTION_ALLOW;
- }
- else
- {
- std::string cur_param = channel->GetModeParameter('f');
- parameter = std::string(ban ? "*" : "") + ConvToStr(nlines) + ":" +ConvToStr(nsecs);
- if (cur_param == parameter)
- {
- // mode params match
- return MODEACTION_DENY;
- }
- else
- {
- if ((((nlines != f->lines) || (nsecs != f->secs) || (ban != f->ban))) && (((nsecs > 0) && (nlines > 0))))
- {
- floodsettings *fs = new floodsettings(ban,nsecs,nlines);
- ext.set(channel, fs);
- channel->SetModeParam('f', parameter);
- return MODEACTION_ALLOW;
- }
- else
- {
- return MODEACTION_DENY;
- }
- }
- }
- }
+ source->WriteNumeric(608, "%s %s :Invalid flood parameter",source->nick.c_str(),channel->name.c_str());
+ return MODEACTION_DENY;
}
- else
+
+ /* Set up the flood parameters for this channel */
+ bool ban = (parameter[0] == '*');
+ unsigned int nlines = ConvToInt(parameter.substr(ban ? 1 : 0, ban ? colon-1 : colon));
+ unsigned int nsecs = ConvToInt(parameter.substr(colon+1));
+
+ if ((nlines<2) || (nsecs<1))
{
source->WriteNumeric(608, "%s %s :Invalid flood parameter",source->nick.c_str(),channel->name.c_str());
- parameter.clear();
return MODEACTION_DENY;
}
+
+ floodsettings* f = ext.get(channel);
+ if ((f) && (nlines == f->lines) && (nsecs == f->secs) && (ban == f->ban))
+ // mode params match
+ return MODEACTION_DENY;
+
+ ext.set(channel, new floodsettings(ban, nsecs, nlines));
+ parameter = std::string(ban ? "*" : "") + ConvToStr(nlines) + ":" + ConvToStr(nsecs);
+ channel->SetModeParam('f', parameter);
+ return MODEACTION_ALLOW;
}
else
{
- if (f)
- {
- ext.unset(channel);
- channel->SetModeParam('f', "");
- return MODEACTION_ALLOW;
- }
- }
+ if (!channel->IsModeSet('f'))
+ return MODEACTION_DENY;
- return MODEACTION_DENY;
+ ext.unset(channel);
+ channel->SetModeParam('f', "");
+ return MODEACTION_ALLOW;
+ }
}
};
@@ -208,15 +135,16 @@ class ModuleMsgFlood : public Module
ModResult ProcessMessages(User* user,Channel* dest, const std::string &text)
{
- ModResult res = ServerInstance->OnCheckExemption(user,dest,"flood");
- if (!IS_LOCAL(user) || res == MOD_RES_ALLOW)
+ if ((!IS_LOCAL(user)) || !dest->IsModeSet('f'))
+ return MOD_RES_PASSTHRU;
+
+ if (ServerInstance->OnCheckExemption(user,dest,"flood") == MOD_RES_ALLOW)
return MOD_RES_PASSTHRU;
floodsettings *f = mf.ext.get(dest);
if (f)
{
- f->addmessage(user);
- if (f->shouldkick(user))
+ if (f->addmessage(user))
{
/* Youre outttta here! */
f->clear(user);
@@ -230,7 +158,7 @@ class ModuleMsgFlood : public Module
}
char kickmessage[MAXBUF];
- snprintf(kickmessage, MAXBUF, "Channel flood triggered (limit is %d lines in %d secs)", f->lines, f->secs);
+ snprintf(kickmessage, MAXBUF, "Channel flood triggered (limit is %u lines in %u secs)", f->lines, f->secs);
dest->KickUser(ServerInstance->FakeClient, user, kickmessage);
diff --git a/src/modules/m_namesx.cpp b/src/modules/m_namesx.cpp
index 2603b0ce5..535f6ec10 100644
--- a/src/modules/m_namesx.cpp
+++ b/src/modules/m_namesx.cpp
@@ -52,13 +52,12 @@ class ModuleNamesX : public Module
ModResult OnPreCommand(std::string &command, std::vector<std::string> &parameters, LocalUser *user, bool validated, const std::string &original_line)
{
- irc::string c = command.c_str();
/* We don't actually create a proper command handler class for PROTOCTL,
* because other modules might want to have PROTOCTL hooks too.
* Therefore, we just hook its as an unvalidated command therefore we
* can capture it even if it doesnt exist! :-)
*/
- if (c == "PROTOCTL")
+ if (command == "PROTOCTL")
{
if ((parameters.size()) && (!strcasecmp(parameters[0].c_str(),"NAMESX")))
{
@@ -83,13 +82,16 @@ class ModuleNamesX : public Module
void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, std::string& line)
{
- if (!cap.ext.get(source) || line.empty())
+ if (!cap.ext.get(source))
return;
- std::string::size_type pos = line.find(':');
- if (pos == std::string::npos || pos < 2)
+ // Channel names can contain ":", and ":" as a 'start-of-token' delimiter is
+ // only ever valid after whitespace, so... find the actual delimiter first!
+ // Thanks to FxChiP for pointing this out.
+ std::string::size_type pos = line.find(" :");
+ if (pos == std::string::npos || pos == 0)
return;
- pos -= 2;
+ pos--;
// Don't do anything if the user has no prefixes
if ((line[pos] == 'H') || (line[pos] == 'G') || (line[pos] == '*'))
return;
diff --git a/src/modules/m_noctcp.cpp b/src/modules/m_noctcp.cpp
index 8c8e1c473..d6db7a7f7 100644
--- a/src/modules/m_noctcp.cpp
+++ b/src/modules/m_noctcp.cpp
@@ -67,7 +67,7 @@ class ModuleNoCTCP : public Module
if (!c->IsModeSet('C'))
return MOD_RES_PASSTHRU;
- if ((text.empty()) || (text[0] != '\001') || (strncmp(text.c_str(),"\1ACTION ",8)))
+ if ((text.empty()) || (text[0] != '\001') || (!strncmp(text.c_str(),"\1ACTION ",8)))
return MOD_RES_PASSTHRU;
ModResult res = ServerInstance->OnCheckExemption(user,c,"noctcp");
diff --git a/src/modules/m_nokicks.cpp b/src/modules/m_nokicks.cpp
index 2e598dafe..58e6fbea1 100644
--- a/src/modules/m_nokicks.cpp
+++ b/src/modules/m_nokicks.cpp
@@ -22,7 +22,7 @@
#include "inspircd.h"
-/* $ModDesc: Provides support for unreal-style channel mode +Q */
+/* $ModDesc: Provides channel mode +Q to prevent kicks on the channel. */
class NoKicks : public SimpleChannelModeHandler
{
@@ -74,7 +74,7 @@ class ModuleNoKicks : public Module
Version GetVersion()
{
- return Version("Provides support for unreal-style channel mode +Q", VF_VENDOR);
+ return Version("Provides channel mode +Q to prevent kicks on the channel.", VF_VENDOR);
}
};
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 &parameter, 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_opermotd.cpp b/src/modules/m_opermotd.cpp
index 3a05fbd56..5c107b6b1 100644
--- a/src/modules/m_opermotd.cpp
+++ b/src/modules/m_opermotd.cpp
@@ -24,42 +24,47 @@
/* $ModDesc: Shows a message to opers after oper-up, adds /opermotd */
-static FileReader* opermotd;
-
-CmdResult ShowOperMOTD(User* user)
-{
- if(!opermotd->FileSize())
- {
- user->WriteServ(std::string("425 ") + user->nick + std::string(" :OPERMOTD file is missing"));
- return CMD_FAILURE;
- }
-
- user->WriteServ(std::string("375 ") + user->nick + std::string(" :- IRC Operators Message of the Day"));
-
- for(int i=0; i != opermotd->FileSize(); i++)
- {
- user->WriteServ(std::string("372 ") + user->nick + std::string(" :- ") + opermotd->GetLine(i));
- }
-
- user->WriteServ(std::string("376 ") + user->nick + std::string(" :- End of OPERMOTD"));
-
- /* don't route me */
- return CMD_SUCCESS;
-}
-
/** Handle /OPERMOTD
*/
class CommandOpermotd : public Command
{
public:
- CommandOpermotd(Module* Creator) : Command(Creator,"OPERMOTD", 0)
+ FileReader opermotd;
+
+ CommandOpermotd(Module* Creator) : Command(Creator,"OPERMOTD", 0, 1)
{
flags_needed = 'o'; syntax = "[<servername>]";
}
CmdResult Handle (const std::vector<std::string>& parameters, User* user)
{
- return ShowOperMOTD(user);
+ if ((parameters.empty()) || (parameters[0] == ServerInstance->Config->ServerName))
+ ShowOperMOTD(user);
+ return CMD_SUCCESS;
+ }
+
+ RouteDescriptor GetRouting(User* user, const std::vector<std::string>& parameters)
+ {
+ if (!parameters.empty())
+ return ROUTE_OPT_UCAST(parameters[0]);
+ return ROUTE_LOCALONLY;
+ }
+
+ void ShowOperMOTD(User* user)
+ {
+ const std::string& servername = ServerInstance->Config->ServerName;
+ if (!opermotd.FileSize())
+ {
+ user->SendText(":%s 455 %s :OPERMOTD file is missing", servername.c_str(), user->nick.c_str());
+ return;
+ }
+
+ user->SendText(":%s 375 %s :- IRC Operators Message of the Day", servername.c_str(), user->nick.c_str());
+
+ for (int i=0; i != opermotd.FileSize(); i++)
+ user->SendText(":%s 372 %s :- %s", servername.c_str(), user->nick.c_str(), opermotd.GetLine(i).c_str());
+
+ user->SendText(":%s 376 %s :- End of OPERMOTD", servername.c_str(), user->nick.c_str());
}
};
@@ -73,36 +78,28 @@ class ModuleOpermotd : public Module
void LoadOperMOTD()
{
ConfigTag* conf = ServerInstance->Config->ConfValue("opermotd");
- opermotd->LoadFile(conf->getString("file","opermotd"));
+ cmd.opermotd.LoadFile(conf->getString("file","opermotd"));
onoper = conf->getBool("onoper", true);
}
ModuleOpermotd()
: cmd(this)
{
- opermotd = NULL;
ServerInstance->AddCommand(&cmd);
- opermotd = new FileReader;
LoadOperMOTD();
Implementation eventlist[] = { I_OnRehash, I_OnOper };
ServerInstance->Modules->Attach(eventlist, this, 2);
}
- virtual ~ModuleOpermotd()
- {
- delete opermotd;
- opermotd = NULL;
- }
-
virtual Version GetVersion()
{
- return Version("Shows a message to opers after oper-up, adds /opermotd", VF_VENDOR);
+ return Version("Shows a message to opers after oper-up, adds /opermotd", VF_VENDOR | VF_OPTCOMMON);
}
virtual void OnOper(User* user, const std::string &opertype)
{
- if (onoper)
- ShowOperMOTD(user);
+ if (onoper && IS_LOCAL(user))
+ cmd.ShowOperMOTD(user);
}
virtual void OnRehash(User* user)
diff --git a/src/modules/m_sapart.cpp b/src/modules/m_sapart.cpp
index 1a19c6645..c1e6f6c08 100644
--- a/src/modules/m_sapart.cpp
+++ b/src/modules/m_sapart.cpp
@@ -21,7 +21,7 @@
#include "inspircd.h"
-/* $ModDesc: Provides support for unreal-style SAPART command */
+/* $ModDesc: Provides command SAPART to force-part users from a channel. */
/** Handle /SAPART
*/
@@ -116,7 +116,7 @@ class ModuleSapart : public Module
virtual Version GetVersion()
{
- return Version("Provides support for unreal-style SAPART command", VF_OPTCOMMON | VF_VENDOR);
+ return Version("Provides command SAPART to force-part users from a channel.", VF_OPTCOMMON | VF_VENDOR);
}
};
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 57a08ada4..08986d53c 100644
--- a/src/modules/m_services_account.cpp
+++ b/src/modules/m_services_account.cpp
@@ -40,19 +40,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;
}
};
@@ -68,18 +66,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_servprotect.cpp b/src/modules/m_servprotect.cpp
index 7df9effcc..c98eebec3 100644
--- a/src/modules/m_servprotect.cpp
+++ b/src/modules/m_servprotect.cpp
@@ -21,7 +21,7 @@
#include "inspircd.h"
-/* $ModDesc: Provides support for Austhex style +k / UnrealIRCD +S services mode */
+/* $ModDesc: Provides usermode +k to protect services from kicks, kills and mode changes. */
/** Handles user mode +k
*/
@@ -64,7 +64,7 @@ class ModuleServProtectMode : public Module
Version GetVersion()
{
- return Version("Provides support for Austhex style +k / UnrealIRCD +S services mode", VF_VENDOR);
+ return Version("Provides usermode +k to protect services from kicks, kills, and mode changes.", VF_VENDOR);
}
void OnWhois(User* src, User* dst)
diff --git a/src/modules/m_setname.cpp b/src/modules/m_setname.cpp
index 3b8d4d149..32c1d5dc3 100644
--- a/src/modules/m_setname.cpp
+++ b/src/modules/m_setname.cpp
@@ -50,7 +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());
+ 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 &parameter, 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_spanningtree/encap.cpp b/src/modules/m_spanningtree/encap.cpp
index 51194e6d7..0cc293fa5 100644
--- a/src/modules/m_spanningtree/encap.cpp
+++ b/src/modules/m_spanningtree/encap.cpp
@@ -38,7 +38,7 @@ void TreeSocket::Encap(User* who, parameterlist &params)
params[params.size() - 1] = ":" + params[params.size() - 1];
- if (params[0].find('*') != std::string::npos)
+ if (params[0].find_first_of("*?") != std::string::npos)
{
Utils->DoOneToAllButSender(who->uuid, "ENCAP", params, who->server);
}
diff --git a/src/modules/m_spanningtree/protocolinterface.cpp b/src/modules/m_spanningtree/protocolinterface.cpp
index efc00334d..3ab5dae9d 100644
--- a/src/modules/m_spanningtree/protocolinterface.cpp
+++ b/src/modules/m_spanningtree/protocolinterface.cpp
@@ -48,7 +48,7 @@ void SpanningTreeProtocolInterface::GetServerList(ProtoServerList &sl)
bool SpanningTreeProtocolInterface::SendEncapsulatedData(const parameterlist &encap)
{
- if (encap[0].find('*') != std::string::npos)
+ if (encap[0].find_first_of("*?") != std::string::npos)
{
Utils->DoOneToMany(ServerInstance->Config->GetSID(), "ENCAP", encap);
return true;
@@ -164,26 +164,16 @@ void SpanningTreeProtocolInterface::SendChannelNotice(Channel* target, char stat
void SpanningTreeProtocolInterface::SendUserPrivmsg(User* target, const std::string &text)
{
- TreeServer* serv = Utils->FindServer(target->server);
- if (serv)
- {
- TreeSocket* sock = serv->GetSocket();
- if (sock)
- {
- sock->WriteLine(":" + ServerInstance->Config->GetSID() + " PRIVMSG " + target->nick + " :"+text);
- }
- }
+ parameterlist p;
+ p.push_back(target->uuid);
+ p.push_back(":" + text);
+ Utils->DoOneToOne(ServerInstance->Config->GetSID(), "PRIVMSG", p, target->server);
}
void SpanningTreeProtocolInterface::SendUserNotice(User* target, const std::string &text)
{
- TreeServer* serv = Utils->FindServer(target->server);
- if (serv)
- {
- TreeSocket* sock = serv->GetSocket();
- if (sock)
- {
- sock->WriteLine(":" + ServerInstance->Config->GetSID() + " NOTICE " + target->nick + " :"+text);
- }
- }
+ parameterlist p;
+ p.push_back(target->uuid);
+ p.push_back(":" + text);
+ Utils->DoOneToOne(ServerInstance->Config->GetSID(), "NOTICE", p, target->server);
}
diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h
index be5455bce..aebc7e03b 100644
--- a/src/modules/m_spanningtree/treesocket.h
+++ b/src/modules/m_spanningtree/treesocket.h
@@ -94,6 +94,7 @@ class TreeSocket : public BufferedSocket
time_t NextPing; /* Time when we are due to ping this server */
bool LastPingWasGood; /* Responded to last ping we sent? */
int proto_version; /* Remote protocol version */
+ bool ConnectionFailureShown; /* Set to true if a connection failure message was shown */
public:
time_t age;
@@ -315,6 +316,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..3e916544b 100644
--- a/src/modules/m_spanningtree/treesocket1.cpp
+++ b/src/modules/m_spanningtree/treesocket1.cpp
@@ -49,6 +49,7 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, Link* link, Autoconnect* mya
capab->capab_phase = 0;
MyRoot = NULL;
proto_version = 0;
+ ConnectionFailureShown = false;
LinkState = CONNECTING;
if (!link->Hook.empty())
{
@@ -78,6 +79,7 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, int newfd, ListenSocket* via
age = ServerInstance->Time();
LinkState = WAIT_AUTH_1;
proto_version = 0;
+ ConnectionFailureShown = false;
linkID = "inbound from " + client->addr();
FOREACH_MOD(I_OnHookIO, OnHookIO(this, via));
@@ -134,7 +136,7 @@ void TreeSocket::OnConnected()
void TreeSocket::OnError(BufferedSocketError e)
{
- ServerInstance->SNO->WriteGlobalSno('l', "Connection to \002%s\002 failed with error: %s",
+ ServerInstance->SNO->WriteGlobalSno('l', "Connection to '\002%s\002' failed with error: %s",
linkID.c_str(), getError().c_str());
LinkState = DYING;
}
@@ -183,7 +185,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 +247,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_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp
index e6fbad4c6..0a0c22e39 100644
--- a/src/modules/m_spanningtree/treesocket2.cpp
+++ b/src/modules/m_spanningtree/treesocket2.cpp
@@ -484,13 +484,13 @@ void TreeSocket::Close()
if (MyRoot)
Squit(MyRoot,getError());
- if (!linkID.empty())
+ if (!ConnectionFailureShown)
{
+ ConnectionFailureShown = true;
ServerInstance->SNO->WriteGlobalSno('l', "Connection to '\2%s\2' failed.",linkID.c_str());
time_t server_uptime = ServerInstance->Time() - this->age;
if (server_uptime)
ServerInstance->SNO->WriteGlobalSno('l', "Connection to '\2%s\2' was established for %s", linkID.c_str(), Utils->Creator->TimeToStr(server_uptime).c_str());
- linkID.clear();
}
}
diff --git a/src/modules/m_uhnames.cpp b/src/modules/m_uhnames.cpp
index 37bd67440..5693eb807 100644
--- a/src/modules/m_uhnames.cpp
+++ b/src/modules/m_uhnames.cpp
@@ -51,13 +51,12 @@ class ModuleUHNames : public Module
ModResult OnPreCommand(std::string &command, std::vector<std::string> &parameters, LocalUser *user, bool validated, const std::string &original_line)
{
- irc::string c = command.c_str();
/* We don't actually create a proper command handler class for PROTOCTL,
* because other modules might want to have PROTOCTL hooks too.
* Therefore, we just hook its as an unvalidated command therefore we
* can capture it even if it doesnt exist! :-)
*/
- if (c == "PROTOCTL")
+ if (command == "PROTOCTL")
{
if ((parameters.size()) && (!strcasecmp(parameters[0].c_str(),"UHNAMES")))
{
diff --git a/src/modules/m_uninvite.cpp b/src/modules/m_uninvite.cpp
index 6c392fe49..9287589bb 100644
--- a/src/modules/m_uninvite.cpp
+++ b/src/modules/m_uninvite.cpp
@@ -63,22 +63,27 @@ class CommandUninvite : public Command
}
}
- irc::string xname(c->name.c_str());
-
- if (IS_LOCAL(u))
+ /* Servers remember invites only for their local users, so act
+ * only if the target is local. Otherwise the command will be
+ * passed to the target users server.
+ */
+ LocalUser* lu = IS_LOCAL(u);
+ if (lu)
{
- // TODO send messages & such out to remote servers
- LocalUser* lu = IS_LOCAL(u);
+ irc::string xname(c->name.c_str());
if (!lu->IsInvited(xname))
{
- user->WriteNumeric(505, "%s %s %s :Is not invited to channel %s", user->nick.c_str(), u->nick.c_str(), c->name.c_str(), c->name.c_str());
+ user->SendText(":%s 505 %s %s %s :Is not invited to channel %s", user->server.c_str(), user->nick.c_str(), u->nick.c_str(), c->name.c_str(), c->name.c_str());
return CMD_FAILURE;
}
- user->WriteNumeric(494, "%s %s %s :Uninvited", user->nick.c_str(), c->name.c_str(), u->nick.c_str());
+
+ user->SendText(":%s 494 %s %s %s :Uninvited", user->server.c_str(), user->nick.c_str(), c->name.c_str(), u->nick.c_str());
lu->RemoveInvite(xname);
lu->WriteNumeric(493, "%s :You were uninvited from %s by %s", u->nick.c_str(), c->name.c_str(), user->nick.c_str());
- c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :*** %s uninvited %s.",
- c->name.c_str(), user->nick.c_str(), u->nick.c_str());
+
+ std::string msg = "*** " + user->nick + " uninvited " + u->nick + ".";
+ c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE " + c->name + " :" + msg);
+ ServerInstance->PI->SendChannelNotice(c, 0, msg);
}
return CMD_SUCCESS;
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/server.cpp b/src/server.cpp
index 4bd81a6d1..b7e58c56b 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -72,7 +72,7 @@ std::string InspIRCd::GetVersionString(bool operstring)
if (operstring)
snprintf(versiondata,MAXBUF,"%s %s :%s [%s,%s,%s]",VERSION,Config->ServerName.c_str(),SYSTEM,REVISION,SE->GetName().c_str(),Config->sid.c_str());
else
- snprintf(versiondata,MAXBUF,"InspIRCd-2.0 %s :%s",Config->ServerName.c_str(),Config->CustomVersion.c_str());
+ snprintf(versiondata,MAXBUF,"%s %s :%s",BRANCH,Config->ServerName.c_str(),Config->CustomVersion.c_str());
return versiondata;
}
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;
-}
diff --git a/src/users.cpp b/src/users.cpp
index 9c3d645f7..459b9e3ce 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -772,9 +772,9 @@ void LocalUser::FullConnect()
this->WriteServ("NOTICE Auth :Welcome to \002%s\002!",ServerInstance->Config->Network.c_str());
this->WriteNumeric(RPL_WELCOME, "%s :Welcome to the %s IRC Network %s!%s@%s",this->nick.c_str(), ServerInstance->Config->Network.c_str(), this->nick.c_str(), this->ident.c_str(), this->host.c_str());
- this->WriteNumeric(RPL_YOURHOSTIS, "%s :Your host is %s, running version InspIRCd-2.0",this->nick.c_str(),ServerInstance->Config->ServerName.c_str());
+ this->WriteNumeric(RPL_YOURHOSTIS, "%s :Your host is %s, running version %s",this->nick.c_str(),ServerInstance->Config->ServerName.c_str(),BRANCH);
this->WriteNumeric(RPL_SERVERCREATED, "%s :This server was created %s %s", this->nick.c_str(), __TIME__, __DATE__);
- this->WriteNumeric(RPL_SERVERVERSION, "%s %s InspIRCd-2.0 %s %s %s", this->nick.c_str(), ServerInstance->Config->ServerName.c_str(), ServerInstance->Modes->UserModeList().c_str(), ServerInstance->Modes->ChannelModeList().c_str(), ServerInstance->Modes->ParaModeList().c_str());
+ this->WriteNumeric(RPL_SERVERVERSION, "%s %s %s %s %s %s", this->nick.c_str(), ServerInstance->Config->ServerName.c_str(), BRANCH, ServerInstance->Modes->UserModeList().c_str(), ServerInstance->Modes->ChannelModeList().c_str(), ServerInstance->Modes->ParaModeList().c_str());
ServerInstance->Config->Send005(this);
this->WriteNumeric(RPL_YOURUUID, "%s %s :your unique ID", this->nick.c_str(), this->uuid.c_str());
diff --git a/src/version.sh b/src/version.sh
index 008c807dd..08ee17904 100755
--- a/src/version.sh
+++ b/src/version.sh
@@ -1,2 +1,2 @@
#!/bin/sh
-echo "InspIRCd-2.0.7"
+echo "InspIRCd-2.0.8"
diff --git a/src/xline.cpp b/src/xline.cpp
index ed3ed6364..397b937ec 100644
--- a/src/xline.cpp
+++ b/src/xline.cpp
@@ -252,8 +252,6 @@ IdentHostPair XLineManager::IdentSplit(const std::string &ident_and_host)
bool XLineManager::AddLine(XLine* line, User* user)
{
- ServerInstance->BanCache->RemoveEntries(line->type, false); // XXX perhaps remove ELines here?
-
if (line->duration && ServerInstance->Time() > line->expiry)
return false; // Don't apply expired XLines.
@@ -273,6 +271,8 @@ bool XLineManager::AddLine(XLine* line, User* user)
if (!xlf)
return false;
+ ServerInstance->BanCache->RemoveEntries(line->type, false); // XXX perhaps remove ELines here?
+
if (xlf->AutoApplyToUserList(line))
pending_lines.push_back(line);
diff --git a/win/configure.cpp b/win/configure.cpp
index ee03b3659..768b68cc5 100644
--- a/win/configure.cpp
+++ b/win/configure.cpp
@@ -275,7 +275,11 @@ void Run()
fclose(fI);
}
else
- strcpy(version, "InspIRCD-Unknown");
+ strcpy(version, "InspIRCd-0.0.0");
+
+ string branch(version);
+ branch.erase(branch.find_last_of('.'));
+
#ifdef WIN64
printf_c("Your operating system is: \033[1;32mwindows_x64 \033[0m\n");
#else
@@ -351,6 +355,7 @@ void Run()
sc(TGREEN); printf(" done\n"); sc(TNORMAL);
printf("Writing inspircd_version.h...");
f = fopen("inspircd_version.h", "w");
+ fprintf(f, "#define BRANCH \"%s\"\n", branch.c_str());
fprintf(f, "#define VERSION \"%s\"\n", version);
fprintf(f, "#define REVISION \"%s\"\n", revision.c_str());
fprintf(f, "#define SYSTEM \"%s\"\n", machine_text);
diff --git a/win/inspircd.nsi b/win/inspircd.nsi
index e263f4561..1fa21c6f9 100644
--- a/win/inspircd.nsi
+++ b/win/inspircd.nsi
@@ -153,6 +153,10 @@ SectionEnd
Section "Config Files" SEC02
SetOutPath "$INSTDIR\conf"
File "..\docs\conf\*.example"
+ SetOutPath "$INSTDIR\conf\aliases"
+ File "..\docs\conf\aliases\*.example"
+ SetOutPath "$INSTDIR\conf\modules"
+ File "..\docs\conf\modules\modules.*"
SectionEnd
Section "Command Handlers" SEC03
@@ -163,6 +167,10 @@ SectionEnd
Section "Modules" SEC04
SetOutPath "$INSTDIR\modules"
File "..\bin\${BUILD}\modules\m_*.so"
+ ; Copy DLLs required for modules
+ SetOutPath "$INSTDIR"
+ File /nonfatal "*.dll"
+ File "make_gnutls_cert.bat"
SectionEnd
Section -AdditionalIcons
@@ -216,9 +224,13 @@ Section Uninstall
Delete "$INSTDIR\uninst.exe"
Delete "$INSTDIR\modules\*.so"
Delete "$INSTDIR\conf\*.example"
+ Delete "$INSTDIR\conf\aliases\*.example"
+ Delete "$INSTDIR\conf\modules\*.example"
Delete "$INSTDIR\*.log"
Delete "$INSTDIR\logs\*"
Delete "$INSTDIR\data\*"
+ Delete "$INSTDIR\*.dll"
+ Delete "$INSTDIR\make_gnutls_cert.bat"
Delete "$INSTDIR\inspircd.exe"
Delete "$SMPROGRAMS\InspIRCd\Uninstall.lnk"
Delete "$SMPROGRAMS\InspIRCd\InspIRCd Website.lnk"
diff --git a/win/inspircd.vcxproj b/win/inspircd.vcxproj
index 03bacaad3..d6da89562 100644
--- a/win/inspircd.vcxproj
+++ b/win/inspircd.vcxproj
@@ -308,7 +308,6 @@ nmake -f modules.mak
<ClCompile Include="..\src\socket.cpp" />
<ClCompile Include="..\src\socketengine.cpp" />
<ClCompile Include="..\src\socketengines\socketengine_select.cpp" />
- <ClCompile Include="..\src\stats.cpp" />
<ClCompile Include="..\src\testsuite.cpp" />
<ClCompile Include="..\src\threadengine.cpp" />
<ClCompile Include="..\src\threadengines\threadengine_win32.cpp" />
@@ -390,4 +389,4 @@ nmake -f modules.mak
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/win/inspircd_win32wrapper.cpp b/win/inspircd_win32wrapper.cpp
index 43ca87240..ec4e7833b 100644
--- a/win/inspircd_win32wrapper.cpp
+++ b/win/inspircd_win32wrapper.cpp
@@ -738,6 +738,7 @@ static void unused_function()
reference<Link> unused_Link;
reference<Autoconnect> unused_Autoconnect;
reference<ssl_cert> unused_Cert;
+ reference<OperInfo> unused_OperInfo;
if (unused_Link)
unused_Link->Port = -1;
@@ -745,20 +746,26 @@ static void unused_function()
unused_Autoconnect->NextConnectTime = -1;
if (unused_Cert)
unused_Cert->dn = "";
+ if (unused_OperInfo)
+ unused_OperInfo->name = "";
Autoconnect *a = unused_Autoconnect;
Link *l = unused_Link;
ssl_cert *s = unused_Cert;
+ OperInfo *o = unused_OperInfo;
unused_Link = reference<Link>(unused_Link);
unused_Autoconnect = reference<Autoconnect>(unused_Autoconnect);
unused_Cert = reference<ssl_cert>(unused_Cert);
+ unused_OperInfo = reference<OperInfo>(unused_OperInfo);
unused_Link = reference<Link>(l);
unused_Autoconnect = reference<Autoconnect>(a);
unused_Cert = reference<ssl_cert>(s);
+ unused_OperInfo = reference<OperInfo>(o);
delete unused_Link;
delete unused_Autoconnect;
delete unused_Cert;
+ delete unused_OperInfo;
}
diff --git a/win/inspircd_win32wrapper.h b/win/inspircd_win32wrapper.h
index 85572fd64..bc7165262 100644
--- a/win/inspircd_win32wrapper.h
+++ b/win/inspircd_win32wrapper.h
@@ -231,7 +231,6 @@ CoreExport int clock_gettime(int clock, struct timespec * tv);
typedef unsigned char uint8_t;
typedef unsigned long long uint64_t;
typedef signed char int8_t;
-typedef signed long int32_t;
typedef signed long long int64_t;
typedef signed long ssize_t;
diff --git a/win/make_gnutls_cert.bat b/win/make_gnutls_cert.bat
new file mode 100644
index 000000000..97792cc29
--- /dev/null
+++ b/win/make_gnutls_cert.bat
@@ -0,0 +1,14 @@
+@echo off
+
+echo This program will generate SSL certificates for m_ssl_gnutls.so
+echo Ensure certtool.exe is in your system path. It can be downloaded
+echo at ftp://ftp.gnu.org/gnu/gnutls/w32/. If you do not know the answer
+echo to one of the questions just press enter.
+echo.
+
+pause
+
+certtool --generate-privkey --outfile conf/key.pem
+certtool --generate-self-signed --load-privkey conf/key.pem --outfile conf/cert.pem
+
+pause \ No newline at end of file