diff options
author | Adam <Adam@anope.org> | 2016-10-17 18:33:55 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2016-10-17 18:33:55 -0400 |
commit | 22d166fd4e98b67cac7103b48801fb95a0179f01 (patch) | |
tree | 300b00bd52c5d3a26978bfe23bbdc2adc9c0fa26 /src | |
parent | 1ba242179fee46583098f48421af39ce9a8985a1 (diff) |
Address casemapping issues in sqlite/mysql
Diffstat (limited to 'src')
-rw-r--r-- | src/hashcomp.cpp | 18 | ||||
-rw-r--r-- | src/tools/CMakeLists.txt | 33 | ||||
-rw-r--r-- | src/tools/anope_sqlite.cpp | 132 |
3 files changed, 161 insertions, 22 deletions
diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp index 265cb362b..72e729eba 100644 --- a/src/hashcomp.cpp +++ b/src/hashcomp.cpp @@ -212,6 +212,18 @@ bool Anope::compare_locale::operator()(const Anope::string &s1, const Anope::str return Anope::compare_ci()(s1, s2); } +Anope::string Anope::transform(const Anope::string &s) +{ +#ifdef Boost_FOUND + if (Config != nullptr && Config->locale != nullptr) + { + return Anope::locale::transform(s.str()); + } +#endif + + return s.lower(); +} + #ifdef Boost_FOUND std::locale Anope::locale::generate(const std::string &name) @@ -240,5 +252,11 @@ long Anope::locale::hash(const std::string &s) return ct.hash(boost::locale::collator_base::secondary, s.data(), s.data() + s.length()); } +std::string Anope::locale::transform(const std::string &s) +{ + const boost::locale::collator<char> &ct = std::use_facet<boost::locale::collator<char>>(*Config->locale); + return ct.transform(boost::locale::collator_base::secondary, s); +} + #endif diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index f302c3ef7..ee445a00e 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -1,27 +1,16 @@ -# Find all the *.cpp files within the current source directory, and sort the list -file(GLOB TOOLS_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp") -list(SORT TOOLS_SRCS) -# Set all the files to use C++ as well as set their compile flags -set_source_files_properties(${TOOLS_SRCS} PROPERTIES LANGUAGE CXX COMPILE_FLAGS "${CXXFLAGS}") - -# Iterate through all the source files -foreach(SRC ${TOOLS_SRCS}) - # Convert the source file extension to have no extension - string(REGEX REPLACE "\\.cpp$" "" EXE ${SRC}) - # Generate the executable and set its linker flags, also set it to depend on the main Anope executable to be built beforehand - add_executable(${EXE} ${SRC}) - set_target_properties(${EXE} PROPERTIES LINKER_LANGUAGE CXX LINK_FLAGS "${LDFLAGS}") - add_dependencies(${EXE} ${PROGRAM_NAME}) - # Set the executable to be installed to the bin directory under the main directory - install(TARGETS ${EXE} - DESTINATION ${BIN_DIR} +function(build_sqlite LIBNAME) + add_library(tools_anope_sqlite_${LIBNAME} SHARED anope_sqlite.cpp) + set_source_files_properties(anope_sqlite.cpp PROPERTIES LANGUAGE CXX COMPILE_FLAGS "${CXXFLAGS}") + set_target_properties(tools_anope_sqlite_${LIBNAME} PROPERTIES LINKER_LANGUAGE CXX LINK_FLAGS "${LDFLAGS}" OUTPUT_NAME "anope_sqlite_${LIBNAME}") + install(TARGETS tools_anope_sqlite_${LIBNAME} + DESTINATION ${LIB_DIR} ) - # Add the executable to the list of files for CPack to ignore - get_target_property(EXE_BINARY ${EXE} LOCATION) - get_filename_component(EXE_BINARY ${EXE_BINARY} NAME) - add_to_cpack_ignored_files("${EXE_BINARY}$" TRUE) -endforeach() +endfunction() + +build_sqlite(ascii) +build_sqlite(rfc1459) +build_sqlite(rfc1459_inspircd) # If not on Windows, generate anoperc and install it along with mydbgen if(NOT WIN32) diff --git a/src/tools/anope_sqlite.cpp b/src/tools/anope_sqlite.cpp new file mode 100644 index 000000000..e03f99bd2 --- /dev/null +++ b/src/tools/anope_sqlite.cpp @@ -0,0 +1,132 @@ +/* + * Anope IRC Services + * + * Copyright (C) 2016 Anope Team <team@anope.org> + * + * This file is part of Anope. Anope 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 see <http://www.gnu.org/licenses/>. + */ + +#include <sqlite3ext.h> + +#include <algorithm> +#include <string> + +#ifdef _WIN32 +# define DllExport __declspec(dllexport) +#else +# define DllExport +#endif + +SQLITE_EXTENSION_INIT1 + +namespace +{ + +enum collation +{ + ANOPE_ASCII, + ANOPE_RFC1459, + ANOPE_RFC1459_INSPIRCD +}; + +char (*anope_tolower)(char) = nullptr; + +char tolower_ascii(char c) +{ + if (c >= 'A' && c <= 'Z') + return c + 0x20; + else + return c; +} + +char tolower_rfc1459_inspircd(char c) +{ + if (c == '[' || c == ']' || c == '\\') + return c + 0x20; + else + return tolower_ascii(c); +} + +char tolower_rfc1459(char c) +{ + if (c == '[' || c == ']' || c == '\\' || c == '^') + return c + 0x20; + else + return tolower_ascii(c); +} + +void anope_canonicalize(sqlite3_context *context, int argc, sqlite3_value **argv) +{ + sqlite3_value *arg = argv[0]; + const unsigned char *text = sqlite3_value_text(arg); + + if (text == nullptr || anope_tolower == nullptr) + return; + + std::string result(reinterpret_cast<const char *>(text)); + std::transform(result.begin(), result.end(), result.begin(), anope_tolower); + + sqlite3_result_text(context, result.c_str(), -1, SQLITE_TRANSIENT); +} + +int sqlite_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi, collation col) +{ + SQLITE_EXTENSION_INIT2(pApi); + + switch (col) + { + case ANOPE_ASCII: + anope_tolower = tolower_ascii; + break; + case ANOPE_RFC1459: + anope_tolower = tolower_rfc1459; + break; + case ANOPE_RFC1459_INSPIRCD: + anope_tolower = tolower_rfc1459_inspircd; + break; + default: + return SQLITE_INTERNAL; + } + + int rc = sqlite3_create_function_v2(db, "anope_canonicalize", 1, SQLITE_DETERMINISTIC, NULL, anope_canonicalize, NULL, NULL, NULL); + + return rc; +} + +} // namespace + +extern "C" DllExport +int sqlite3_anopesqliteascii_init(sqlite3 *, char **, const sqlite3_api_routines *); + +extern "C" DllExport +int sqlite3_anopesqliterfc1459_init(sqlite3 *, char **, const sqlite3_api_routines *); + +extern "C" DllExport +int sqlite3_anopesqliterfc1459inspircd_init(sqlite3 *, char **, const sqlite3_api_routines *); + +int sqlite3_anopesqliteascii_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi) +{ + return sqlite_init(db, pzErrMsg, pApi, ANOPE_ASCII); +} + +int sqlite3_anopesqliterfc1459_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi) +{ + return sqlite_init(db, pzErrMsg, pApi, ANOPE_RFC1459); +} + +int sqlite3_anopesqliterfc1459inspircd_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi) +{ + return sqlite_init(db, pzErrMsg, pApi, ANOPE_RFC1459_INSPIRCD); +} + |