summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2014-12-29 17:26:20 -0500
committerAdam <Adam@anope.org>2014-12-29 17:26:20 -0500
commit8ab1c71d7dc7a0d47e5711dc72e3fc9c3ee850bb (patch)
treed65f46a60e49d51ee1f0192de22c35e3cdd322c9
parented920366d69801bab7fc276fa24296b7f1264ff2 (diff)
Allow configuring casemaps
-rw-r--r--data/CMakeLists.txt6
-rw-r--r--data/ascii.conf157
-rw-r--r--data/example.conf34
-rw-r--r--data/rfc1459.conf24
-rw-r--r--include/config.h4
-rw-r--r--include/hashcomp.h48
-rw-r--r--modules/database/db_flatfile.cpp1
-rw-r--r--src/config.cpp70
-rw-r--r--src/hashcomp.cpp38
-rw-r--r--src/init.cpp2
-rw-r--r--src/main.cpp3
11 files changed, 272 insertions, 115 deletions
diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt
index 8bb635dcf..2515bc082 100644
--- a/data/CMakeLists.txt
+++ b/data/CMakeLists.txt
@@ -1,6 +1,4 @@
-# Only install example.chk and example.conf from this directory
-# NOTE: I would've had this just find all files in the directory, but that would include files not needed (like this file)
-set(DATA example.chk botserv.example.conf example.conf hostserv.example.conf modules.example.conf operserv.example.conf chanserv.example.conf global.example.conf memoserv.example.conf nickserv.example.conf chanstats.example.conf irc2sql.example.conf stats.standalone.example.conf)
-install(FILES ${DATA}
+file(GLOB DATA_EXAMPLECONFS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.conf")
+install(FILES example.chk ${DATA_EXAMPLECONFS}
DESTINATION ${CONF_DIR}
)
diff --git a/data/ascii.conf b/data/ascii.conf
new file mode 100644
index 000000000..1bfcb33f0
--- /dev/null
+++ b/data/ascii.conf
@@ -0,0 +1,157 @@
+
+casemap
+{
+ lower = "a"
+ upper = "A"
+}
+
+casemap
+{
+ lower = "b"
+ upper = "B"
+}
+
+casemap
+{
+ lower = "c"
+ upper = "C"
+}
+
+casemap
+{
+ lower = "d"
+ upper = "D"
+}
+
+casemap
+{
+ lower = "e"
+ upper = "E"
+}
+
+casemap
+{
+ lower = "f"
+ upper = "F"
+}
+
+casemap
+{
+ lower = "g"
+ upper = "G"
+}
+
+casemap
+{
+ lower = "h"
+ upper = "H"
+}
+
+casemap
+{
+ lower = "i"
+ upper = "I"
+}
+
+casemap
+{
+ lower = "j"
+ upper = "J"
+}
+
+casemap
+{
+ lower = "k"
+ upper = "K"
+}
+
+casemap
+{
+ lower = "l"
+ upper = "L"
+}
+
+casemap
+{
+ lower = "m"
+ upper = "M"
+}
+
+casemap
+{
+ lower = "n"
+ upper = "N"
+}
+
+casemap
+{
+ lower = "o"
+ upper = "O"
+}
+
+casemap
+{
+ lower = "p"
+ upper = "P"
+}
+
+casemap
+{
+ lower = "q"
+ upper = "Q"
+}
+
+casemap
+{
+ lower = "r"
+ upper = "R"
+}
+
+casemap
+{
+ lower = "s"
+ upper = "S"
+}
+
+casemap
+{
+ lower = "t"
+ upper = "T"
+}
+
+casemap
+{
+ lower = "u"
+ upper = "U"
+}
+
+casemap
+{
+ lower = "v"
+ upper = "V"
+}
+
+casemap
+{
+ lower = "w"
+ upper = "W"
+}
+
+casemap
+{
+ lower = "x"
+ upper = "X"
+}
+
+casemap
+{
+ lower = "y"
+ upper = "Y"
+}
+
+casemap
+{
+ lower = "z"
+ upper = "Z"
+}
+
diff --git a/data/example.conf b/data/example.conf
index f10c62fb2..f746a2595 100644
--- a/data/example.conf
+++ b/data/example.conf
@@ -362,20 +362,6 @@ options
#group = "anope"
/*
- * The case mapping used by services. This must be set to a valid locale name
- * installed on your machine. Services use this case map to compare, with
- * case insensitivity, things such as nick names, channel names, etc.
- *
- * We provide two special casemaps shipped with Anope, ascii and rfc1459.
- *
- * This value should be set to what your IRCd uses, which is probably rfc1459,
- * however Anope has always used ascii for comparison, so the default is ascii.
- *
- * Changing this value once set is not recommended.
- */
- casemap = "ascii"
-
- /*
* This key is used to initiate the random number generator. This number
* MUST be random as you want your passcodes to be random. Don't give this
* key to anyone! Keep it private!
@@ -539,6 +525,26 @@ options
}
/*
+ * [REQUIRED] Casemapping configuration
+ *
+ * Includes the configuration for the casemap services should use.
+ * Services use this case map to compare, with case insensitivity,
+ * things such as nick names, channel names, etc.
+ *
+ * Two casemaps shipped with Anope are ascii and rfc1459.
+ *
+ * This value should be set to what your IRCd uses, which is probably rfc1459,
+ * however Anope has always used ascii for comparison, so the default is ascii.
+ *
+ * Changing this value once set is not recommended.
+ */
+include
+{
+ name = "ascii.conf"
+ #name = "rfc1459.conf"
+}
+
+/*
* [OPTIONAL] BotServ
*
* Includes botserv.example.conf, which is necessary for BotServ functionality.
diff --git a/data/rfc1459.conf b/data/rfc1459.conf
new file mode 100644
index 000000000..81ced1ac0
--- /dev/null
+++ b/data/rfc1459.conf
@@ -0,0 +1,24 @@
+
+include
+{
+ name = "ascii.conf"
+}
+
+casemap
+{
+ lower = "{"
+ upper = "["
+}
+
+casemap
+{
+ lower = "}"
+ upper = "]"
+}
+
+casemap
+{
+ lower = "|"
+ upper = "\""
+}
+
diff --git a/include/config.h b/include/config.h
index fe4a6fded..fdeddf6dc 100644
--- a/include/config.h
+++ b/include/config.h
@@ -60,9 +60,10 @@ namespace Configuration
const item_map* GetItems() const;
};
- template<> CoreExport const Anope::string Block::Get(const Anope::string &tag, const Anope::string& def) const;
+ template<> CoreExport Anope::string Block::Get(const Anope::string &tag, const Anope::string& def) const;
template<> CoreExport time_t Block::Get(const Anope::string &tag, const Anope::string &def) const;
template<> CoreExport bool Block::Get(const Anope::string &tag, const Anope::string &def) const;
+ template<> CoreExport unsigned int Block::Get(const Anope::string &tag, const Anope::string &def) const;
/** Represents a configuration file
*/
@@ -122,6 +123,7 @@ namespace Configuration
std::vector<Anope::string> ModulesAutoLoad;
/* After how many characters do we wrap lines? */
unsigned int LineWrap;
+ unsigned char CaseMapUpper[256], CaseMapLower[256];
/* module configuration blocks */
std::map<Anope::string, Block *> modules;
diff --git a/include/hashcomp.h b/include/hashcomp.h
index 2364975b9..a9a1105ee 100644
--- a/include/hashcomp.h
+++ b/include/hashcomp.h
@@ -19,56 +19,8 @@ namespace Anope
{
class string;
- /* Casemap in use by Anope. ci::string's comparation functions use this (and thus Anope::string) */
- extern std::locale casemap;
-
- extern void CaseMapRebuild();
extern unsigned char tolower(unsigned char);
extern unsigned char toupper(unsigned char);
-
- /* ASCII case insensitive ctype. */
- template<typename char_type>
- class ascii_ctype : public std::ctype<char_type>
- {
- public:
- char_type do_toupper(char_type c) const override
- {
- if (c >= 'a' && c <= 'z')
- return c - 32;
- else
- return c;
- }
-
- char_type do_tolower(char_type c) const override
- {
- if (c >= 'A' && c <= 'Z')
- return c + 32;
- else
- return c;
- }
- };
-
- /* rfc1459 case insensitive ctype, { = [, } = ], and | = \ */
- template<typename char_type>
- class rfc1459_ctype : public ascii_ctype<char_type>
- {
- public:
- char_type do_toupper(char_type c) const override
- {
- if (c == '{' || c == '}' || c == '|')
- return c - 32;
- else
- return ascii_ctype<char_type>::do_toupper(c);
- }
-
- char_type do_tolower(char_type c) const override
- {
- if (c == '[' || c == ']' || c == '\\')
- return c + 32;
- else
- return ascii_ctype<char_type>::do_tolower(c);
- }
- };
}
/** The ci namespace contains a number of helper classes relevant to case insensitive strings.
diff --git a/modules/database/db_flatfile.cpp b/modules/database/db_flatfile.cpp
index 0793269ea..2486a2307 100644
--- a/modules/database/db_flatfile.cpp
+++ b/modules/database/db_flatfile.cpp
@@ -101,7 +101,6 @@ class DBFlatFile : public Module
Serialize::Object *obj = nullptr;
for (Anope::string buf; std::getline(fd, buf.str());)
{
- Log() << buf;
if (buf.find("OBJECT ") == 0)
{
Anope::string t = buf.substr(7);
diff --git a/src/config.cpp b/src/config.cpp
index 6ac777a98..323a48519 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -72,7 +72,7 @@ const Block::item_map* Block::GetItems() const
return NULL;
}
-template<> const Anope::string Block::Get(const Anope::string &tag, const Anope::string& def) const
+template<> Anope::string Block::Get(const Anope::string &tag, const Anope::string& def) const
{
if (!this)
return def;
@@ -95,6 +95,27 @@ template<> bool Block::Get(const Anope::string &tag, const Anope::string &def) c
return !str.empty() && !str.equals_ci("no") && !str.equals_ci("off") && !str.equals_ci("false") && !str.equals_ci("0");
}
+template<> unsigned int Block::Get(const Anope::string &tag, const Anope::string &def) const
+{
+ const Anope::string &str = Get<Anope::string>(tag, def);
+ std::size_t pos = str.length();
+ unsigned long l;
+
+ try
+ {
+ l = std::stoul(str.str(), &pos, 0);
+ }
+ catch (...)
+ {
+ return 0;
+ }
+
+ if (pos != str.length())
+ return 0;
+
+ return l;
+}
+
static void ValidateNotEmpty(const Anope::string &block, const Anope::string &name, const Anope::string &value)
{
if (value.empty())
@@ -127,6 +148,8 @@ Conf::Conf() : Block("")
const Anope::string &type = include->Get<Anope::string>("type"),
&file = include->Get<Anope::string>("name");
+ ValidateNotEmpty("include", "name", file);
+
File f(file, type == "executable");
this->LoadConf(f);
}
@@ -489,6 +512,34 @@ Conf::Conf() : Block("")
this->CommandGroups.push_back(gr);
}
+ for (int i = 0; i < this->CountBlock("casemap"); ++i)
+ {
+ Block *casemap = this->GetBlock("casemap", i);
+
+ unsigned char upper = casemap->Get<unsigned int>("upper"),
+ lower = casemap->Get<unsigned int>("lower");
+
+ if (!upper)
+ {
+ Anope::string s = casemap->Get<Anope::string>("upper");
+ if (s.length() == 1)
+ upper = s[0];
+ }
+
+ if (!lower)
+ {
+ Anope::string s = casemap->Get<Anope::string>("lower");
+ if (s.length() == 1)
+ lower = s[0];
+ }
+
+ if (upper && lower)
+ {
+ CaseMapUpper[lower] = CaseMapUpper[upper] = upper;
+ CaseMapLower[lower] = CaseMapLower[upper] = lower;
+ }
+ }
+
/* Below here can't throw */
/* Clear existing conf opers */
@@ -508,23 +559,6 @@ Conf::Conf() : Block("")
Log() << "Tied oper " << na->GetAccount()->GetDisplay() << " to type " << o->GetType()->GetName();
}
- if (options->Get<Anope::string>("casemap", "ascii") == "ascii")
- Anope::casemap = std::locale(std::locale(), new Anope::ascii_ctype<char>());
- else if (options->Get<Anope::string>("casemap") == "rfc1459")
- Anope::casemap = std::locale(std::locale(), new Anope::rfc1459_ctype<char>());
- else
- {
- try
- {
- Anope::casemap = std::locale(options->Get<Anope::string>("casemap").c_str());
- }
- catch (const std::runtime_error &)
- {
- Log() << "Unknown casemap " << options->Get<Anope::string>("casemap") << " - casemap not changed";
- }
- }
- Anope::CaseMapRebuild();
-
/* Check the user keys */
if (!options->Get<unsigned>("seed"))
Log() << "Configuration option options:seed should be set. It's for YOUR safety! Remember that!";
diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp
index 62bcc404f..e17ae6176 100644
--- a/src/hashcomp.cpp
+++ b/src/hashcomp.cpp
@@ -10,32 +10,22 @@
#include "services.h"
#include "hashcomp.h"
#include "anope.h"
-
-/* Case map in use by Anope */
-std::locale Anope::casemap = std::locale(std::locale(), new Anope::ascii_ctype<char>());
-/* Cache of the above case map, forced upper */
-static unsigned char case_map_upper[256], case_map_lower[256];
-
-/* called whenever Anope::casemap is modified to rebuild the casemap cache */
-void Anope::CaseMapRebuild()
-{
- const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap);
-
- for (unsigned i = 0; i < sizeof(case_map_upper); ++i)
- {
- case_map_upper[i] = ct.toupper(i);
- case_map_lower[i] = ct.tolower(i);
- }
-}
+#include "config.h"
unsigned char Anope::tolower(unsigned char c)
{
- return case_map_lower[c];
+ if (!Config || !Config->CaseMapLower[c])
+ return std::tolower(c);
+
+ return Config->CaseMapLower[c];
}
unsigned char Anope::toupper(unsigned char c)
{
- return case_map_upper[c];
+ if (!Config || !Config->CaseMapUpper[c])
+ return std::toupper(c);
+
+ return Config->CaseMapUpper[c];
}
/*
@@ -47,7 +37,7 @@ unsigned char Anope::toupper(unsigned char c)
bool ci::ci_char_traits::eq(char c1st, char c2nd)
{
- return case_map_upper[static_cast<unsigned char>(c1st)] == case_map_upper[static_cast<unsigned char>(c2nd)];
+ return Anope::toupper(c1st) == Anope::toupper(c2nd);
}
bool ci::ci_char_traits::ne(char c1st, char c2nd)
@@ -57,15 +47,15 @@ bool ci::ci_char_traits::ne(char c1st, char c2nd)
bool ci::ci_char_traits::lt(char c1st, char c2nd)
{
- return case_map_upper[static_cast<unsigned char>(c1st)] < case_map_upper[static_cast<unsigned char>(c2nd)];
+ return Anope::toupper(c1st) < Anope::toupper(c2nd);
}
int ci::ci_char_traits::compare(const char *str1, const char *str2, size_t n)
{
for (unsigned i = 0; i < n; ++i)
{
- unsigned char c1 = case_map_upper[static_cast<unsigned char>(*str1)],
- c2 = case_map_upper[static_cast<unsigned char>(*str2)];
+ unsigned char c1 = Anope::toupper(*str1),
+ c2 = Anope::toupper(*str2);
if (c1 > c2)
return 1;
@@ -82,7 +72,7 @@ int ci::ci_char_traits::compare(const char *str1, const char *str2, size_t n)
const char *ci::ci_char_traits::find(const char *s1, int n, char c)
{
- while (n-- > 0 && case_map_upper[static_cast<unsigned char>(*s1)] != case_map_upper[static_cast<unsigned char>(c)])
+ while (n-- > 0 && Anope::toupper(*s1) != Anope::toupper(c))
++s1;
return n >= 0 ? s1 : NULL;
}
diff --git a/src/init.cpp b/src/init.cpp
index 853cf7209..0b381cbf6 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -290,8 +290,6 @@ void Anope::Init(int ac, char **av)
umask(DEFUMASK);
#endif
- //Serialize::RegisterTypes();
-
/* Parse command line arguments */
ParseCommandLineArguments(ac, av);
diff --git a/src/main.cpp b/src/main.cpp
index 1f4434f18..65fb8d3f6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -116,9 +116,6 @@ static Anope::string GetFullProgDir(const Anope::string &argv0)
int main(int ac, char **av, char **envp)
{
- /* String comparisons won't work until we build the case map cache, so do it first */
- Anope::CaseMapRebuild();
-
BinaryDir = GetFullProgDir(av[0]);
if (BinaryDir[BinaryDir.length() - 1] == '.')
BinaryDir = BinaryDir.substr(0, BinaryDir.length() - 2);