From 0ec82c104ded01a44ed36d20e25220fa41887fd0 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 27 Feb 2015 12:18:34 +0100 Subject: Add louloulibs as a submodule --- louloulibs | 1 + 1 file changed, 1 insertion(+) create mode 160000 louloulibs (limited to 'louloulibs/utils') diff --git a/louloulibs b/louloulibs new file mode 160000 index 0000000..b6af145 --- /dev/null +++ b/louloulibs @@ -0,0 +1 @@ +Subproject commit b6af145bfb9561a1bb1ecb940f50163c5ce4dbbb -- cgit v1.2.3 From e6569a1090be063f34624474f0d4578f37a169ae Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 27 Feb 2015 12:40:50 +0100 Subject: Only use include_directory() if the directory path is defined --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/utils') diff --git a/louloulibs b/louloulibs index b6af145..d6a3724 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit b6af145bfb9561a1bb1ecb940f50163c5ce4dbbb +Subproject commit d6a3724c6a0127a49a9e7adb1090bb7438c8d0f2 -- cgit v1.2.3 From e4c696861d86b62305ca0ec8136e79f147837b94 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 2 Mar 2015 11:06:40 +0100 Subject: Update louloulibs to last revision --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/utils') diff --git a/louloulibs b/louloulibs index d6a3724..5f3a1bb 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit d6a3724c6a0127a49a9e7adb1090bb7438c8d0f2 +Subproject commit 5f3a1bb54df4de5f332282bbdf791bdce07c71c4 -- cgit v1.2.3 From d88ec5fdf10ecb168355bc38dc81d83ff59a0234 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 2 Mar 2015 11:32:18 +0100 Subject: Update to latest louloulibs revision --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/utils') diff --git a/louloulibs b/louloulibs index 5f3a1bb..d0b8695 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit 5f3a1bb54df4de5f332282bbdf791bdce07c71c4 +Subproject commit d0b8695ceb13e0c6d72821fe605de36e494afcdf -- cgit v1.2.3 From c243fea660723eba00b65e639b76d0783cb59064 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 4 Mar 2015 05:56:44 +0100 Subject: Update to latest louloulibs revision --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/utils') diff --git a/louloulibs b/louloulibs index d0b8695..99757a4 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit d0b8695ceb13e0c6d72821fe605de36e494afcdf +Subproject commit 99757a44b49619ff59cae9e6d983a3b7c20c56bf -- cgit v1.2.3 From ad0465b32051e224f6a234f3ed36494905e59cbf Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 20 Apr 2015 20:33:02 +0200 Subject: Decode incoming JIDs local part according to xep 0106 This let users send message to nicks such as Q@CServe.quakenet.org fix #3047 --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/utils') diff --git a/louloulibs b/louloulibs index 99757a4..88d2b13 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit 99757a44b49619ff59cae9e6d983a3b7c20c56bf +Subproject commit 88d2b136e5f133f0d0dc01f59449284f663d53ea -- cgit v1.2.3 From 0d706741c6b3a8bdf6b4f8ca0b1ac00cb27bd8b8 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Mon, 20 Apr 2015 20:35:32 +0200 Subject: Update louloulibs submodule to the correct revision --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/utils') diff --git a/louloulibs b/louloulibs index 88d2b13..b53ae92 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit 88d2b136e5f133f0d0dc01f59449284f663d53ea +Subproject commit b53ae922f48f1465a7fa61136f65ec39e38a452e -- cgit v1.2.3 From a8225dc54c019788722bda3bda8d55151c1ccdef Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 21 Apr 2015 15:35:10 +0200 Subject: Properly check for connecting or connected status before reconnecting Note, in our context, is_connecting() includes the resolving part as well as the actual connection (if we are using c-ares) fix #3048 --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/utils') diff --git a/louloulibs b/louloulibs index b53ae92..6c812cd 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit b53ae922f48f1465a7fa61136f65ec39e38a452e +Subproject commit 6c812cd86e31569db61cac4e30f77e296d207191 -- cgit v1.2.3 From 71fec776c4d7b99b76a44deae6f333d9cffa1496 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 7 May 2015 17:42:37 +0200 Subject: Update to latest louloulibs fix #3042 --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/utils') diff --git a/louloulibs b/louloulibs index 6c812cd..eaa4fbb 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit 6c812cd86e31569db61cac4e30f77e296d207191 +Subproject commit eaa4fbba814b56b4fe7ffb62984fddfbb9280291 -- cgit v1.2.3 From fbeb5af364db54c8a82f5ea30b83df441988ea4b Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 13 May 2015 20:17:43 +0200 Subject: Update to latest louloulibs revision, and add test for hostname validity fix #2694 --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/utils') diff --git a/louloulibs b/louloulibs index eaa4fbb..89398b5 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit eaa4fbba814b56b4fe7ffb62984fddfbb9280291 +Subproject commit 89398b5d886744c3812b65195308cae57eca2b53 -- cgit v1.2.3 From 897b281e67dc82700db9fd9c2dedc5e01e5871ee Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 27 May 2015 23:44:23 +0200 Subject: Avoid some potential race conditions by blocking the signals we manage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They are atomically unblocked in the ppoll/epoll_pwait calls, avoiding any race condition on the check of the “stop” or “reload” booleans. --- louloulibs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/utils') diff --git a/louloulibs b/louloulibs index 89398b5..0f3c118 160000 --- a/louloulibs +++ b/louloulibs @@ -1 +1 @@ -Subproject commit 89398b5d886744c3812b65195308cae57eca2b53 +Subproject commit 0f3c1183e2bf0941ae2bffd3f31577bce4f3001c -- cgit v1.2.3 From e1a7114c8daa10589c830ce972cf461c3540111b Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 28 May 2015 23:42:52 +0200 Subject: louloulibs is directly included, instead of being a submodule Because this is a nightmare to manage --- louloulibs | 1 - louloulibs/utils/encoding.cpp | 254 ++++++++++++++++++++++++++++++ louloulibs/utils/encoding.hpp | 38 +++++ louloulibs/utils/reload.cpp | 13 ++ louloulibs/utils/reload.hpp | 10 ++ louloulibs/utils/revstr.cpp | 9 ++ louloulibs/utils/revstr.hpp | 11 ++ louloulibs/utils/scopeguard.hpp | 89 +++++++++++ louloulibs/utils/sha1.cpp | 154 ++++++++++++++++++ louloulibs/utils/sha1.hpp | 35 ++++ louloulibs/utils/split.cpp | 19 +++ louloulibs/utils/split.hpp | 12 ++ louloulibs/utils/timed_events.cpp | 62 ++++++++ louloulibs/utils/timed_events.hpp | 132 ++++++++++++++++ louloulibs/utils/timed_events_manager.cpp | 81 ++++++++++ louloulibs/utils/tolower.cpp | 13 ++ louloulibs/utils/tolower.hpp | 11 ++ 17 files changed, 943 insertions(+), 1 deletion(-) delete mode 160000 louloulibs create mode 100644 louloulibs/utils/encoding.cpp create mode 100644 louloulibs/utils/encoding.hpp create mode 100644 louloulibs/utils/reload.cpp create mode 100644 louloulibs/utils/reload.hpp create mode 100644 louloulibs/utils/revstr.cpp create mode 100644 louloulibs/utils/revstr.hpp create mode 100644 louloulibs/utils/scopeguard.hpp create mode 100644 louloulibs/utils/sha1.cpp create mode 100644 louloulibs/utils/sha1.hpp create mode 100644 louloulibs/utils/split.cpp create mode 100644 louloulibs/utils/split.hpp create mode 100644 louloulibs/utils/timed_events.cpp create mode 100644 louloulibs/utils/timed_events.hpp create mode 100644 louloulibs/utils/timed_events_manager.cpp create mode 100644 louloulibs/utils/tolower.cpp create mode 100644 louloulibs/utils/tolower.hpp (limited to 'louloulibs/utils') diff --git a/louloulibs b/louloulibs deleted file mode 160000 index 0f3c118..0000000 --- a/louloulibs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0f3c1183e2bf0941ae2bffd3f31577bce4f3001c diff --git a/louloulibs/utils/encoding.cpp b/louloulibs/utils/encoding.cpp new file mode 100644 index 0000000..f738ce2 --- /dev/null +++ b/louloulibs/utils/encoding.cpp @@ -0,0 +1,254 @@ +#include + +#include + +#include + +#include +#include +#include + +#include +#include + +/** + * The UTF-8-encoded character used as a place holder when a character conversion fails. + * This is U+FFFD � "replacement character" + */ +static const char* invalid_char = "\xef\xbf\xbd"; +static const size_t invalid_char_len = 3; + +namespace utils +{ + /** + * Based on http://en.wikipedia.org/wiki/UTF-8#Description + */ + bool is_valid_utf8(const char* s) + { + if (!s) + return false; + + const unsigned char* str = reinterpret_cast(s); + + while (*str) + { + // 4 bytes: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + if ((str[0] & 0b11111000) == 0b11110000) + { + if (!str[1] || !str[2] || !str[3] + || ((str[1] & 0b11000000) != 0b10000000) + || ((str[2] & 0b11000000) != 0b10000000) + || ((str[3] & 0b11000000) != 0b10000000)) + return false; + str += 4; + } + // 3 bytes: 1110xxx 10xxxxxx 10xxxxxx + else if ((str[0] & 0b11110000) == 0b11100000) + { + if (!str[1] || !str[2] + || ((str[1] & 0b11000000) != 0b10000000) + || ((str[2] & 0b11000000) != 0b10000000)) + return false; + str += 3; + } + // 2 bytes: 110xxxxx 10xxxxxx + else if (((str[0]) & 0b11100000) == 0b11000000) + { + if (!str[1] || + ((str[1] & 0b11000000) != 0b10000000)) + return false; + str += 2; + } + // 1 byte: 0xxxxxxx + else if ((str[0] & 0b10000000) != 0) + return false; + else + str++; + } + return true; + } + + std::string remove_invalid_xml_chars(const std::string& original) + { + // The given string MUST be a valid utf-8 string + unsigned char* res = new unsigned char[original.size()]; + ScopeGuard sg([&res]() { delete[] res;}); + + // pointer where we write valid chars + unsigned char* r = res; + + const unsigned char* str = reinterpret_cast(original.c_str()); + std::bitset<20> codepoint; + + while (*str) + { + // 4 bytes: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + if ((str[0] & 0b11111000) == 0b11110000) + { + codepoint = ((str[0] & 0b00000111) << 18); + codepoint |= ((str[1] & 0b00111111) << 12); + codepoint |= ((str[2] & 0b00111111) << 6 ); + codepoint |= ((str[3] & 0b00111111) << 0 ); + if (codepoint.to_ulong() <= 0x10FFFF) + { + ::memcpy(r, str, 4); + r += 4; + } + str += 4; + } + // 3 bytes: 1110xxx 10xxxxxx 10xxxxxx + else if ((str[0] & 0b11110000) == 0b11100000) + { + codepoint = ((str[0] & 0b00001111) << 12); + codepoint |= ((str[1] & 0b00111111) << 6); + codepoint |= ((str[2] & 0b00111111) << 0 ); + if (codepoint.to_ulong() <= 0xD7FF || + (codepoint.to_ulong() >= 0xE000 && codepoint.to_ulong() <= 0xFFFD)) + { + ::memcpy(r, str, 3); + r += 3; + } + str += 3; + } + // 2 bytes: 110xxxxx 10xxxxxx + else if (((str[0]) & 0b11100000) == 0b11000000) + { + // All 2 bytes char are valid, don't even bother calculating + // the codepoint + ::memcpy(r, str, 2); + r += 2; + str += 2; + } + // 1 byte: 0xxxxxxx + else if ((str[0] & 0b10000000) == 0) + { + codepoint = ((str[0] & 0b01111111)); + if (codepoint.to_ulong() == 0x09 || + codepoint.to_ulong() == 0x0A || + codepoint.to_ulong() == 0x0D || + codepoint.to_ulong() >= 0x20) + { + ::memcpy(r, str, 1); + r += 1; + } + str += 1; + } + else + throw std::runtime_error("Invalid UTF-8 passed to remove_invalid_xml_chars"); + } + return std::string(reinterpret_cast(res), r-res); + } + + std::string convert_to_utf8(const std::string& str, const char* charset) + { + std::string res; + + const iconv_t cd = iconv_open("UTF-8", charset); + if (cd == (iconv_t)-1) + throw std::runtime_error("Cannot convert into UTF-8"); + + // Make sure cd is always closed when we leave this function + ScopeGuard sg([&]{ iconv_close(cd); }); + + size_t inbytesleft = str.size(); + + // iconv will not attempt to modify this buffer, but some plateform + // require a char** anyway +#ifdef ICONV_SECOND_ARGUMENT_IS_CONST + const char* inbuf_ptr = str.c_str(); +#else + char* inbuf_ptr = const_cast(str.c_str()); +#endif + + size_t outbytesleft = str.size() * 4; + char* outbuf = new char[outbytesleft]; + char* outbuf_ptr = outbuf; + + // Make sure outbuf is always deleted when we leave this function + sg.add_callback([&]{ delete[] outbuf; }); + + bool done = false; + while (done == false) + { + size_t error = iconv(cd, &inbuf_ptr, &inbytesleft, &outbuf_ptr, &outbytesleft); + if ((size_t)-1 == error) + { + switch (errno) + { + case EILSEQ: + // Invalid byte found. Insert a placeholder instead of the + // converted character, jump one byte and continue + memcpy(outbuf_ptr, invalid_char, invalid_char_len); + outbuf_ptr += invalid_char_len; + inbytesleft--; + inbuf_ptr++; + break; + case EINVAL: + // A multibyte sequence is not terminated, but we can't + // provide any more data, so we just add a placeholder to + // indicate that the character is not properly converted, + // and we stop the conversion + memcpy(outbuf_ptr, invalid_char, invalid_char_len); + outbuf_ptr += invalid_char_len; + outbuf_ptr++; + done = true; + break; + case E2BIG: + // This should never happen + done = true; + break; + default: + // This should happen even neverer + done = true; + break; + } + } + else + { + // The conversion finished without any error, stop converting + done = true; + } + } + // Terminate the converted buffer, and copy that buffer it into the + // string we return + *outbuf_ptr = '\0'; + res = outbuf; + return res; + } + +} + +namespace xep0106 +{ + static const std::map encode_map = { + {' ', "\\20"}, + {'"', "\\22"}, + {'&', "\\26"}, + {'\'',"\\27"}, + {'/', "\\2f"}, + {':', "\\3a"}, + {'<', "\\3c"}, + {'>', "\\3e"}, + {'@', "\\40"}, + }; + + void decode(std::string& s) + { + std::string::size_type pos; + for (const auto& pair: encode_map) + while ((pos = s.find(pair.second)) != std::string::npos) + s.replace(pos, pair.second.size(), + 1, pair.first); + } + + void encode(std::string& s) + { + std::string::size_type pos; + while ((pos = s.find_first_of(" \"&'/:<>@")) != std::string::npos) + { + auto it = encode_map.find(s[pos]); + assert(it != encode_map.end()); + s.replace(pos, 1, it->second); + } + } +} diff --git a/louloulibs/utils/encoding.hpp b/louloulibs/utils/encoding.hpp new file mode 100644 index 0000000..6b7ccd2 --- /dev/null +++ b/louloulibs/utils/encoding.hpp @@ -0,0 +1,38 @@ +#ifndef ENCODING_INCLUDED +# define ENCODING_INCLUDED + +#include + +namespace utils +{ + /** + * Returns true if the given null-terminated string is valid utf-8. + * + * Based on http://en.wikipedia.org/wiki/UTF-8#Description + */ + bool is_valid_utf8(const char* s); + /** + * Remove all invalid codepoints from the given utf-8-encoded string. + * The value returned is a copy of the string, without the removed chars. + * + * See http://www.w3.org/TR/xml/#charsets for the list of valid characters + * in XML. + */ + std::string remove_invalid_xml_chars(const std::string& original); + /** + * Convert the given string (encoded is "encoding") into valid utf-8. + * If some decoding fails, insert an utf-8 placeholder character instead. + */ + std::string convert_to_utf8(const std::string& str, const char* encoding); +} + +namespace xep0106 +{ + /** + * Decode and encode inplace. + */ + void decode(std::string&); + void encode(std::string&); +} + +#endif // ENCODING_INCLUDED diff --git a/louloulibs/utils/reload.cpp b/louloulibs/utils/reload.cpp new file mode 100644 index 0000000..6600c75 --- /dev/null +++ b/louloulibs/utils/reload.cpp @@ -0,0 +1,13 @@ +#include +#include + +void reload_process() +{ + // Closing the config will just force it to be reopened the next time + // a configuration option is needed + Config::close(); + // Destroy the logger instance, to be recreated the next time a log + // line needs to be written + Logger::instance().reset(); + log_debug("Configuration and logger reloaded."); +} diff --git a/louloulibs/utils/reload.hpp b/louloulibs/utils/reload.hpp new file mode 100644 index 0000000..16d64f7 --- /dev/null +++ b/louloulibs/utils/reload.hpp @@ -0,0 +1,10 @@ +#ifndef RELOAD_HPP_INCLUDED +#define RELOAD_HPP_INCLUDED + +/** + * Reload the server's configuration, and close the logger (so that it + * closes its files etc, to take into account the new configuration) + */ +void reload_process(); + +#endif /* RELOAD_HPP_INCLUDED */ diff --git a/louloulibs/utils/revstr.cpp b/louloulibs/utils/revstr.cpp new file mode 100644 index 0000000..87fd801 --- /dev/null +++ b/louloulibs/utils/revstr.cpp @@ -0,0 +1,9 @@ +#include + +namespace utils +{ + std::string revstr(const std::string& original) + { + return {original.rbegin(), original.rend()}; + } +} diff --git a/louloulibs/utils/revstr.hpp b/louloulibs/utils/revstr.hpp new file mode 100644 index 0000000..27c9e3e --- /dev/null +++ b/louloulibs/utils/revstr.hpp @@ -0,0 +1,11 @@ +#ifndef REVSTR_HPP_INCLUDED +# define REVSTR_HPP_INCLUDED + +#include + +namespace utils +{ + std::string revstr(const std::string& original); +} + +#endif // REVSTR_HPP_INCLUDED diff --git a/louloulibs/utils/scopeguard.hpp b/louloulibs/utils/scopeguard.hpp new file mode 100644 index 0000000..df78831 --- /dev/null +++ b/louloulibs/utils/scopeguard.hpp @@ -0,0 +1,89 @@ +#ifndef SCOPEGUARD_HPP +#define SCOPEGUARD_HPP + +#include +#include + +/** + * A class to be used to make sure some functions are called when the scope + * is left, because they will be called in the ScopeGuard's destructor. It + * can for example be used to delete some pointer whenever any exception is + * called. Example: + + * { + * ScopeGuard scope; + * int* number = new int(2); + * scope.add_callback([number]() { delete number; }); + * // Do some other stuff with the number. But these stuff might throw an exception: + * throw std::runtime_error("Some error not caught here, but in our caller"); + * return true; + * } + + * In this example, our pointer will always be deleted, even when the + * exception is thrown. If we want the functions to be called only when the + * scope is left because of an unexpected exception, we can use + * ScopeGuard::disable(); + */ + +namespace utils +{ + +class ScopeGuard +{ +public: + /** + * The constructor can take a callback. But additional callbacks can be + * added later with add_callback() + */ + explicit ScopeGuard(std::function&& func): + enabled(true) + { + this->add_callback(std::move(func)); + } + /** + * default constructor, the scope guard is enabled but empty, use + * add_callback() + */ + explicit ScopeGuard(): + enabled(true) + { + } + /** + * Call all callbacks in the desctructor, unless it has been disabled. + */ + ~ScopeGuard() + { + if (this->enabled) + for (auto& func: this->callbacks) + func(); + } + /** + * Add a callback to be called in our destructor, one scope guard can be + * used for more than one task, if needed. + */ + void add_callback(std::function&& func) + { + this->callbacks.emplace_back(std::move(func)); + } + /** + * Disable that scope guard, nothing will be done when the scope is + * exited. + */ + void disable() + { + this->enabled = false; + } + +private: + bool enabled; + std::vector> callbacks; + + ScopeGuard(const ScopeGuard&) = delete; + ScopeGuard& operator=(ScopeGuard&&) = delete; + ScopeGuard(ScopeGuard&&) = delete; + ScopeGuard& operator=(const ScopeGuard&) = delete; +}; + +} + +#endif diff --git a/louloulibs/utils/sha1.cpp b/louloulibs/utils/sha1.cpp new file mode 100644 index 0000000..76476df --- /dev/null +++ b/louloulibs/utils/sha1.cpp @@ -0,0 +1,154 @@ +/* This code is public-domain - it is based on libcrypt + * placed in the public domain by Wei Dai and other contributors. + */ + +#include "sha1.hpp" + +#define SHA1_K0 0x5a827999 +#define SHA1_K20 0x6ed9eba1 +#define SHA1_K40 0x8f1bbcdc +#define SHA1_K60 0xca62c1d6 + +const uint8_t sha1InitState[] = { + 0x01,0x23,0x45,0x67, // H0 + 0x89,0xab,0xcd,0xef, // H1 + 0xfe,0xdc,0xba,0x98, // H2 + 0x76,0x54,0x32,0x10, // H3 + 0xf0,0xe1,0xd2,0xc3 // H4 +}; + +void sha1_init(sha1nfo *s) { + memcpy(s->state.b,sha1InitState,HASH_LENGTH); + s->byteCount = 0; + s->bufferOffset = 0; +} + +uint32_t sha1_rol32(uint32_t number, uint8_t bits) { + return ((number << bits) | (number >> (32-bits))); +} + +void sha1_hashBlock(sha1nfo *s) { + uint8_t i; + uint32_t a,b,c,d,e,t; + + a=s->state.w[0]; + b=s->state.w[1]; + c=s->state.w[2]; + d=s->state.w[3]; + e=s->state.w[4]; + for (i=0; i<80; i++) { + if (i>=16) { + t = s->buffer.w[(i+13)&15] ^ s->buffer.w[(i+8)&15] ^ s->buffer.w[(i+2)&15] ^ s->buffer.w[i&15]; + s->buffer.w[i&15] = sha1_rol32(t,1); + } + if (i<20) { + t = (d ^ (b & (c ^ d))) + SHA1_K0; + } else if (i<40) { + t = (b ^ c ^ d) + SHA1_K20; + } else if (i<60) { + t = ((b & c) | (d & (b | c))) + SHA1_K40; + } else { + t = (b ^ c ^ d) + SHA1_K60; + } + t+=sha1_rol32(a,5) + e + s->buffer.w[i&15]; + e=d; + d=c; + c=sha1_rol32(b,30); + b=a; + a=t; + } + s->state.w[0] += a; + s->state.w[1] += b; + s->state.w[2] += c; + s->state.w[3] += d; + s->state.w[4] += e; +} + +void sha1_addUncounted(sha1nfo *s, uint8_t data) { + s->buffer.b[s->bufferOffset ^ 3] = data; + s->bufferOffset++; + if (s->bufferOffset == BLOCK_LENGTH) { + sha1_hashBlock(s); + s->bufferOffset = 0; + } +} + +void sha1_writebyte(sha1nfo *s, uint8_t data) { + ++s->byteCount; + sha1_addUncounted(s, data); +} + +void sha1_write(sha1nfo *s, const char *data, size_t len) { + for (;len--;) sha1_writebyte(s, (uint8_t) *data++); +} + +void sha1_pad(sha1nfo *s) { + // Implement SHA-1 padding (fips180-2 §5.1.1) + + // Pad with 0x80 followed by 0x00 until the end of the block + sha1_addUncounted(s, 0x80); + while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); + + // Append length in the last 8 bytes + sha1_addUncounted(s, 0); // We're only using 32 bit lengths + sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths + sha1_addUncounted(s, 0); // So zero pad the top bits + sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 + sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as + sha1_addUncounted(s, s->byteCount >> 13); // byte. + sha1_addUncounted(s, s->byteCount >> 5); + sha1_addUncounted(s, s->byteCount << 3); +} + +uint8_t* sha1_result(sha1nfo *s) { + int i; + // Pad to complete the last block + sha1_pad(s); + + // Swap byte order back + for (i=0; i<5; i++) { + uint32_t a,b; + a=s->state.w[i]; + b=a<<24; + b|=(a<<8) & 0x00ff0000; + b|=(a>>8) & 0x0000ff00; + b|=a>>24; + s->state.w[i]=b; + } + + // Return pointer to hash (20 characters) + return s->state.b; +} + +#define HMAC_IPAD 0x36 +#define HMAC_OPAD 0x5c + +void sha1_initHmac(sha1nfo *s, const uint8_t* key, int keyLength) { + uint8_t i; + memset(s->keyBuffer, 0, BLOCK_LENGTH); + if (keyLength > BLOCK_LENGTH) { + // Hash long keys + sha1_init(s); + for (;keyLength--;) sha1_writebyte(s, *key++); + memcpy(s->keyBuffer, sha1_result(s), HASH_LENGTH); + } else { + // Block length keys are used as is + memcpy(s->keyBuffer, key, keyLength); + } + // Start inner hash + sha1_init(s); + for (i=0; ikeyBuffer[i] ^ HMAC_IPAD); + } +} + +uint8_t* sha1_resultHmac(sha1nfo *s) { + uint8_t i; + // Complete inner hash + memcpy(s->innerHash,sha1_result(s),HASH_LENGTH); + // Calculate outer hash + sha1_init(s); + for (i=0; ikeyBuffer[i] ^ HMAC_OPAD); + for (i=0; iinnerHash[i]); + return sha1_result(s); +} diff --git a/louloulibs/utils/sha1.hpp b/louloulibs/utils/sha1.hpp new file mode 100644 index 0000000..d02de75 --- /dev/null +++ b/louloulibs/utils/sha1.hpp @@ -0,0 +1,35 @@ +/* This code is public-domain - it is based on libcrypt + * placed in the public domain by Wei Dai and other contributors. + */ + +#include +#include + +#define HASH_LENGTH 20 +#define BLOCK_LENGTH 64 + +union _buffer { + uint8_t b[BLOCK_LENGTH]; + uint32_t w[BLOCK_LENGTH/4]; +}; + +union _state { + uint8_t b[HASH_LENGTH]; + uint32_t w[HASH_LENGTH/4]; +}; + +typedef struct sha1nfo { + union _buffer buffer; + uint8_t bufferOffset; + union _state state; + uint32_t byteCount; + uint8_t keyBuffer[BLOCK_LENGTH]; + uint8_t innerHash[HASH_LENGTH]; +} sha1nfo; + +void sha1_init(sha1nfo *s); +void sha1_writebyte(sha1nfo *s, uint8_t data); +void sha1_write(sha1nfo *s, const char *data, size_t len); +uint8_t* sha1_result(sha1nfo *s); +void sha1_initHmac(sha1nfo *s, const uint8_t* key, int keyLength); +uint8_t* sha1_resultHmac(sha1nfo *s); diff --git a/louloulibs/utils/split.cpp b/louloulibs/utils/split.cpp new file mode 100644 index 0000000..80f8dae --- /dev/null +++ b/louloulibs/utils/split.cpp @@ -0,0 +1,19 @@ +#include +#include + +namespace utils +{ + std::vector split(const std::string& s, const char delim, const bool allow_empty) + { + std::vector ret; + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) + { + if (item.empty() && !allow_empty) + continue ; + ret.emplace_back(std::move(item)); + } + return ret; + } +} diff --git a/louloulibs/utils/split.hpp b/louloulibs/utils/split.hpp new file mode 100644 index 0000000..6b487a9 --- /dev/null +++ b/louloulibs/utils/split.hpp @@ -0,0 +1,12 @@ +#ifndef SPLIT_INCLUDED +# define SPLIT_INCLUDED + +#include +#include + +namespace utils +{ + std::vector split(const std::string &s, const char delim, const bool allow_empty=true); +} + +#endif // SPLIT_INCLUDED diff --git a/louloulibs/utils/timed_events.cpp b/louloulibs/utils/timed_events.cpp new file mode 100644 index 0000000..5010a3f --- /dev/null +++ b/louloulibs/utils/timed_events.cpp @@ -0,0 +1,62 @@ +#include + +TimedEvent::TimedEvent(std::chrono::steady_clock::time_point&& time_point, + std::function callback, const std::string& name): + time_point(std::move(time_point)), + callback(callback), + repeat(false), + repeat_delay(0), + name(name) +{ +} + +TimedEvent::TimedEvent(std::chrono::milliseconds&& duration, + std::function callback, const std::string& name): + time_point(std::chrono::steady_clock::now() + duration), + callback(callback), + repeat(true), + repeat_delay(std::move(duration)), + name(name) +{ +} + +TimedEvent::TimedEvent(TimedEvent&& other): + time_point(std::move(other.time_point)), + callback(std::move(other.callback)), + repeat(other.repeat), + repeat_delay(std::move(other.repeat_delay)), + name(std::move(other.name)) +{ +} + +TimedEvent::~TimedEvent() +{ +} + +bool TimedEvent::is_after(const TimedEvent& other) const +{ + return this->is_after(other.time_point); +} + +bool TimedEvent::is_after(const std::chrono::steady_clock::time_point& time_point) const +{ + return this->time_point >= time_point; +} + +std::chrono::milliseconds TimedEvent::get_timeout() const +{ + auto now = std::chrono::steady_clock::now(); + if (now > this->time_point) + return std::chrono::milliseconds(0); + return std::chrono::duration_cast(this->time_point - now); +} + +void TimedEvent::execute() +{ + this->callback(); +} + +const std::string& TimedEvent::get_name() const +{ + return this->name; +} diff --git a/louloulibs/utils/timed_events.hpp b/louloulibs/utils/timed_events.hpp new file mode 100644 index 0000000..4e2800c --- /dev/null +++ b/louloulibs/utils/timed_events.hpp @@ -0,0 +1,132 @@ +#ifndef TIMED_EVENTS_HPP +# define TIMED_EVENTS_HPP + +#include +#include +#include +#include + +using namespace std::literals::chrono_literals; + +namespace utils { +static constexpr std::chrono::milliseconds no_timeout = std::chrono::milliseconds(-1); +} + +class TimedEventsManager; + +/** + * A callback with an associated date. + */ + +class TimedEvent +{ + friend class TimedEventsManager; +public: + /** + * An event the occurs only once, at the given time_point + */ + explicit TimedEvent(std::chrono::steady_clock::time_point&& time_point, + std::function callback, const std::string& name=""); + explicit TimedEvent(std::chrono::milliseconds&& duration, + std::function callback, const std::string& name=""); + + explicit TimedEvent(TimedEvent&&); + ~TimedEvent(); + /** + * Whether or not this event happens after the other one. + */ + bool is_after(const TimedEvent& other) const; + bool is_after(const std::chrono::steady_clock::time_point& time_point) const; + /** + * Return the duration difference between now and the event time point. + * If the difference would be negative (i.e. the event is expired), the + * returned value is 0 instead. The value cannot then be negative. + */ + std::chrono::milliseconds get_timeout() const; + void execute(); + const std::string& get_name() const; + +private: + /** + * The next time point at which the event is executed. + */ + std::chrono::steady_clock::time_point time_point; + /** + * The function to execute. + */ + const std::function callback; + /** + * Whether or not this events repeats itself until it is destroyed. + */ + const bool repeat; + /** + * This value is added to the time_point each time the event is executed, + * if repeat is true. Otherwise it is ignored. + */ + const std::chrono::milliseconds repeat_delay; + /** + * A name that is used to identify that event. If you want to find your + * event (for example if you want to cancel it), the name should be + * unique. + */ + const std::string name; + + TimedEvent(const TimedEvent&) = delete; + TimedEvent& operator=(const TimedEvent&) = delete; + TimedEvent& operator=(TimedEvent&&) = delete; +}; + +/** + * A class managing a list of TimedEvents. + * They are sorted, new events can be added, removed, fetch, etc. + */ + +class TimedEventsManager +{ +public: + ~TimedEventsManager(); + /** + * Return the unique instance of this class + */ + static TimedEventsManager& instance(); + /** + * Add an event to the list of managed events. The list is sorted after + * this call. + */ + void add_event(TimedEvent&& event); + /** + * Returns the duration, in milliseconds, between now and the next + * available event. If the event is already expired (the duration is + * negative), 0 is returned instead (as in “it's not too late, execute it + * now”) + * Returns a negative value if no event is available. + */ + std::chrono::milliseconds get_timeout() const; + /** + * Execute all the expired events (if their expiration time is exactly + * now, or before now). The event is then removed from the list. If the + * event does repeat, its expiration time is updated and it is reinserted + * in the list at the correct position. + * Returns the number of executed events. + */ + std::size_t execute_expired_events(); + /** + * Remove (and thus cancel) all the timed events with the given name. + * Returns the number of canceled events. + */ + std::size_t cancel(const std::string& name); + /** + * Return the number of managed events. + */ + std::size_t size() const; + +private: + explicit TimedEventsManager(); + std::list events; + TimedEventsManager(const TimedEventsManager&) = delete; + TimedEventsManager(TimedEventsManager&&) = delete; + TimedEventsManager& operator=(const TimedEventsManager&) = delete; + TimedEventsManager& operator=(TimedEventsManager&&) = delete; +}; + +#endif // TIMED_EVENTS_HPP diff --git a/louloulibs/utils/timed_events_manager.cpp b/louloulibs/utils/timed_events_manager.cpp new file mode 100644 index 0000000..2c75e48 --- /dev/null +++ b/louloulibs/utils/timed_events_manager.cpp @@ -0,0 +1,81 @@ +#include + +TimedEventsManager& TimedEventsManager::instance() +{ + static TimedEventsManager inst; + return inst; +} + +TimedEventsManager::TimedEventsManager() +{ +} + +TimedEventsManager::~TimedEventsManager() +{ +} + +void TimedEventsManager::add_event(TimedEvent&& event) +{ + for (auto it = this->events.begin(); it != this->events.end(); ++it) + { + if (it->is_after(event)) + { + this->events.emplace(it, std::move(event)); + return; + } + } + this->events.emplace_back(std::move(event)); +} + +std::chrono::milliseconds TimedEventsManager::get_timeout() const +{ + if (this->events.empty()) + return utils::no_timeout; + return this->events.front().get_timeout() + std::chrono::milliseconds(1); +} + +std::size_t TimedEventsManager::execute_expired_events() +{ + std::size_t count = 0; + const auto now = std::chrono::steady_clock::now(); + for (auto it = this->events.begin(); it != this->events.end();) + { + if (!it->is_after(now)) + { + TimedEvent copy(std::move(*it)); + it = this->events.erase(it); + ++count; + copy.execute(); + if (copy.repeat) + { + copy.time_point += copy.repeat_delay; + this->add_event(std::move(copy)); + } + continue; + } + else + break; + } + return count; +} + +std::size_t TimedEventsManager::cancel(const std::string& name) +{ + std::size_t res = 0; + for (auto it = this->events.begin(); it != this->events.end();) + { + if (it->get_name() == name) + { + it = this->events.erase(it); + res++; + } + else + ++it; + } + return res; +} + +std::size_t TimedEventsManager::size() const +{ + return this->events.size(); +} diff --git a/louloulibs/utils/tolower.cpp b/louloulibs/utils/tolower.cpp new file mode 100644 index 0000000..3e518bd --- /dev/null +++ b/louloulibs/utils/tolower.cpp @@ -0,0 +1,13 @@ +#include + +namespace utils +{ + std::string tolower(const std::string& original) + { + std::string res; + res.reserve(original.size()); + for (const char c: original) + res += static_cast(std::tolower(c)); + return res; + } +} diff --git a/louloulibs/utils/tolower.hpp b/louloulibs/utils/tolower.hpp new file mode 100644 index 0000000..0019182 --- /dev/null +++ b/louloulibs/utils/tolower.hpp @@ -0,0 +1,11 @@ +#ifndef TOLOWER_INCLUDED +# define TOLOWER_INCLUDED + +#include + +namespace utils +{ + std::string tolower(const std::string& original); +} + +#endif // SPLIT_INCLUDED -- cgit v1.2.3 From ea0b2f2bb871e7760d1936bb9b193655682df413 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 18 Sep 2015 09:18:33 +0200 Subject: Create a xdg_path function --- louloulibs/utils/xdg.cpp | 20 ++++++++++++++++++++ louloulibs/utils/xdg.hpp | 13 +++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 louloulibs/utils/xdg.cpp create mode 100644 louloulibs/utils/xdg.hpp (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/xdg.cpp b/louloulibs/utils/xdg.cpp new file mode 100644 index 0000000..7a60dd8 --- /dev/null +++ b/louloulibs/utils/xdg.cpp @@ -0,0 +1,20 @@ +#include +#include + +#include "louloulibs.h" + +std::string xdg_config_path(const std::string& filename) +{ + const char* xdg_config_home = ::getenv("XDG_CONFIG_HOME"); + if (xdg_config_home && xdg_config_home[0] == '/') + return std::string{xdg_config_home} + "/" PROJECT_NAME "/" + filename; + else + { + const char* home = ::getenv("HOME"); + if (home) + return std::string{home} + "/" ".config" "/" PROJECT_NAME "/" + filename; + else + return filename; + } +} + diff --git a/louloulibs/utils/xdg.hpp b/louloulibs/utils/xdg.hpp new file mode 100644 index 0000000..20f5bb7 --- /dev/null +++ b/louloulibs/utils/xdg.hpp @@ -0,0 +1,13 @@ +#ifndef XDG_HPP_INCLUDED +#define XDG_HPP_INCLUDED + +#include + +/** + * Returns a path for the given filename, according to the XDG base + * directory specification, see + * http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html + */ +std::string xdg_config_path(const std::string& filename); + +#endif /* XDG_HPP_INCLUDED */ -- cgit v1.2.3 From 33fa1dcd5a87035de1d9b8df65e5c7551b4bbd1b Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 18 Sep 2015 09:39:49 +0200 Subject: Also a xdg_data_path --- louloulibs/utils/xdg.cpp | 17 +++++++++++++---- louloulibs/utils/xdg.hpp | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/xdg.cpp b/louloulibs/utils/xdg.cpp index 7a60dd8..48212a1 100644 --- a/louloulibs/utils/xdg.cpp +++ b/louloulibs/utils/xdg.cpp @@ -3,11 +3,11 @@ #include "louloulibs.h" -std::string xdg_config_path(const std::string& filename) +std::string xdg_path(const std::string& filename, const char* env_var) { - const char* xdg_config_home = ::getenv("XDG_CONFIG_HOME"); - if (xdg_config_home && xdg_config_home[0] == '/') - return std::string{xdg_config_home} + "/" PROJECT_NAME "/" + filename; + const char* xdg_home = ::getenv(env_var); + if (xdg_home && xdg_home[0] == '/') + return std::string{xdg_home} + "/" PROJECT_NAME "/" + filename; else { const char* home = ::getenv("HOME"); @@ -18,3 +18,12 @@ std::string xdg_config_path(const std::string& filename) } } +std::string xdg_config_path(const std::string& filename) +{ + return xdg_path(filename, "XDG_CONFIG_HOME"); +} + +std::string xdg_data_path(const std::string& filename) +{ + return xdg_path(filename, "XDG_DATA_HOME"); +} diff --git a/louloulibs/utils/xdg.hpp b/louloulibs/utils/xdg.hpp index 20f5bb7..15f3d0b 100644 --- a/louloulibs/utils/xdg.hpp +++ b/louloulibs/utils/xdg.hpp @@ -9,5 +9,6 @@ * http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html */ std::string xdg_config_path(const std::string& filename); +std::string xdg_data_path(const std::string& filename); #endif /* XDG_HPP_INCLUDED */ -- cgit v1.2.3 From 1691cf8f64d6175c61ddf9a4f4a95b44c32d698e Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Fri, 18 Sep 2015 22:01:02 +0200 Subject: Introduce the configure ad-hoc command on irc servers Provides two options for now, and they have no effect yet --- louloulibs/utils/string.cpp | 6 ++++++ louloulibs/utils/string.hpp | 8 ++++++++ 2 files changed, 14 insertions(+) create mode 100644 louloulibs/utils/string.cpp create mode 100644 louloulibs/utils/string.hpp (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/string.cpp b/louloulibs/utils/string.cpp new file mode 100644 index 0000000..3977feb --- /dev/null +++ b/louloulibs/utils/string.cpp @@ -0,0 +1,6 @@ +#include + +bool to_bool(const std::string& val) +{ + return (val == "1" || val == "true"); +} diff --git a/louloulibs/utils/string.hpp b/louloulibs/utils/string.hpp new file mode 100644 index 0000000..3775c36 --- /dev/null +++ b/louloulibs/utils/string.hpp @@ -0,0 +1,8 @@ +#ifndef STRING_UTILS_HPP_INCLUDED +#define STRING_UTILS_HPP_INCLUDED + +#include + +bool to_bool(const std::string& val); + +#endif /* STRING_UTILS_HPP_INCLUDED */ -- cgit v1.2.3 From af42073830087d97385e507f27f601e8769541b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 4 May 2016 14:16:40 +0200 Subject: Style fix Move all constructors at the top of classes --- louloulibs/utils/scopeguard.hpp | 10 ++++++---- louloulibs/utils/timed_events.cpp | 4 ---- louloulibs/utils/timed_events.hpp | 25 ++++++++++++++----------- louloulibs/utils/timed_events_manager.cpp | 8 -------- 4 files changed, 20 insertions(+), 27 deletions(-) (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/scopeguard.hpp b/louloulibs/utils/scopeguard.hpp index df78831..fed40ff 100644 --- a/louloulibs/utils/scopeguard.hpp +++ b/louloulibs/utils/scopeguard.hpp @@ -40,6 +40,12 @@ public: { this->add_callback(std::move(func)); } + + ScopeGuard(const ScopeGuard&) = delete; + ScopeGuard& operator=(ScopeGuard&&) = delete; + ScopeGuard(ScopeGuard&&) = delete; + ScopeGuard& operator=(const ScopeGuard&) = delete; + /** * default constructor, the scope guard is enabled but empty, use * add_callback() @@ -78,10 +84,6 @@ private: bool enabled; std::vector> callbacks; - ScopeGuard(const ScopeGuard&) = delete; - ScopeGuard& operator=(ScopeGuard&&) = delete; - ScopeGuard(ScopeGuard&&) = delete; - ScopeGuard& operator=(const ScopeGuard&) = delete; }; } diff --git a/louloulibs/utils/timed_events.cpp b/louloulibs/utils/timed_events.cpp index 5010a3f..930380b 100644 --- a/louloulibs/utils/timed_events.cpp +++ b/louloulibs/utils/timed_events.cpp @@ -29,10 +29,6 @@ TimedEvent::TimedEvent(TimedEvent&& other): { } -TimedEvent::~TimedEvent() -{ -} - bool TimedEvent::is_after(const TimedEvent& other) const { return this->is_after(other.time_point); diff --git a/louloulibs/utils/timed_events.hpp b/louloulibs/utils/timed_events.hpp index 4e2800c..c3dfc40 100644 --- a/louloulibs/utils/timed_events.hpp +++ b/louloulibs/utils/timed_events.hpp @@ -31,7 +31,12 @@ public: std::function callback, const std::string& name=""); explicit TimedEvent(TimedEvent&&); - ~TimedEvent(); + ~TimedEvent() = default; + + TimedEvent(const TimedEvent&) = delete; + TimedEvent& operator=(const TimedEvent&) = delete; + TimedEvent& operator=(TimedEvent&&) = delete; + /** * Whether or not this event happens after the other one. */ @@ -70,10 +75,6 @@ private: * unique. */ const std::string name; - - TimedEvent(const TimedEvent&) = delete; - TimedEvent& operator=(const TimedEvent&) = delete; - TimedEvent& operator=(TimedEvent&&) = delete; }; /** @@ -84,7 +85,13 @@ private: class TimedEventsManager { public: - ~TimedEventsManager(); + ~TimedEventsManager() = default; + + TimedEventsManager(const TimedEventsManager&) = delete; + TimedEventsManager(TimedEventsManager&&) = delete; + TimedEventsManager& operator=(const TimedEventsManager&) = delete; + TimedEventsManager& operator=(TimedEventsManager&&) = delete; + /** * Return the unique instance of this class */ @@ -121,12 +128,8 @@ public: std::size_t size() const; private: - explicit TimedEventsManager(); std::list events; - TimedEventsManager(const TimedEventsManager&) = delete; - TimedEventsManager(TimedEventsManager&&) = delete; - TimedEventsManager& operator=(const TimedEventsManager&) = delete; - TimedEventsManager& operator=(TimedEventsManager&&) = delete; + explicit TimedEventsManager() = default; }; #endif // TIMED_EVENTS_HPP diff --git a/louloulibs/utils/timed_events_manager.cpp b/louloulibs/utils/timed_events_manager.cpp index 2c75e48..b90a237 100644 --- a/louloulibs/utils/timed_events_manager.cpp +++ b/louloulibs/utils/timed_events_manager.cpp @@ -6,14 +6,6 @@ TimedEventsManager& TimedEventsManager::instance() return inst; } -TimedEventsManager::TimedEventsManager() -{ -} - -TimedEventsManager::~TimedEventsManager() -{ -} - void TimedEventsManager::add_event(TimedEvent&& event) { for (auto it = this->events.begin(); it != this->events.end(); ++it) -- cgit v1.2.3 From 66609cfba2b581be52de6096193751d1bb4ec3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sun, 22 May 2016 12:52:05 +0200 Subject: Remove all usage of std::list --- louloulibs/utils/timed_events.cpp | 11 +---------- louloulibs/utils/timed_events.hpp | 18 +++++++++--------- 2 files changed, 10 insertions(+), 19 deletions(-) (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/timed_events.cpp b/louloulibs/utils/timed_events.cpp index 930380b..6b936c4 100644 --- a/louloulibs/utils/timed_events.cpp +++ b/louloulibs/utils/timed_events.cpp @@ -20,15 +20,6 @@ TimedEvent::TimedEvent(std::chrono::milliseconds&& duration, { } -TimedEvent::TimedEvent(TimedEvent&& other): - time_point(std::move(other.time_point)), - callback(std::move(other.callback)), - repeat(other.repeat), - repeat_delay(std::move(other.repeat_delay)), - name(std::move(other.name)) -{ -} - bool TimedEvent::is_after(const TimedEvent& other) const { return this->is_after(other.time_point); @@ -47,7 +38,7 @@ std::chrono::milliseconds TimedEvent::get_timeout() const return std::chrono::duration_cast(this->time_point - now); } -void TimedEvent::execute() +void TimedEvent::execute() const { this->callback(); } diff --git a/louloulibs/utils/timed_events.hpp b/louloulibs/utils/timed_events.hpp index c3dfc40..70e2eff 100644 --- a/louloulibs/utils/timed_events.hpp +++ b/louloulibs/utils/timed_events.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include using namespace std::literals::chrono_literals; @@ -30,12 +30,12 @@ public: explicit TimedEvent(std::chrono::milliseconds&& duration, std::function callback, const std::string& name=""); - explicit TimedEvent(TimedEvent&&); + explicit TimedEvent(TimedEvent&&) = default; + TimedEvent& operator=(TimedEvent&&) = default; ~TimedEvent() = default; TimedEvent(const TimedEvent&) = delete; TimedEvent& operator=(const TimedEvent&) = delete; - TimedEvent& operator=(TimedEvent&&) = delete; /** * Whether or not this event happens after the other one. @@ -48,7 +48,7 @@ public: * returned value is 0 instead. The value cannot then be negative. */ std::chrono::milliseconds get_timeout() const; - void execute(); + void execute() const; const std::string& get_name() const; private: @@ -59,22 +59,22 @@ private: /** * The function to execute. */ - const std::function callback; + std::function callback; /** * Whether or not this events repeats itself until it is destroyed. */ - const bool repeat; + bool repeat; /** * This value is added to the time_point each time the event is executed, * if repeat is true. Otherwise it is ignored. */ - const std::chrono::milliseconds repeat_delay; + std::chrono::milliseconds repeat_delay; /** * A name that is used to identify that event. If you want to find your * event (for example if you want to cancel it), the name should be * unique. */ - const std::string name; + std::string name; }; /** @@ -128,7 +128,7 @@ public: std::size_t size() const; private: - std::list events; + std::vector events; explicit TimedEventsManager() = default; }; -- cgit v1.2.3 From 46ff73662cc94220c5ee962b591c8ee327de6f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 14 Jun 2016 03:02:36 +0200 Subject: Clean the Config module, use static things instead of a stupid singleton --- louloulibs/utils/reload.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/reload.cpp b/louloulibs/utils/reload.cpp index 6600c75..bddfd86 100644 --- a/louloulibs/utils/reload.cpp +++ b/louloulibs/utils/reload.cpp @@ -3,9 +3,7 @@ void reload_process() { - // Closing the config will just force it to be reopened the next time - // a configuration option is needed - Config::close(); + Config::read_conf(); // Destroy the logger instance, to be recreated the next time a log // line needs to be written Logger::instance().reset(); -- cgit v1.2.3 From 80d0c19c5a8d548a8c6019033bf574ff2be4c0ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 14 Jun 2016 20:14:36 +0200 Subject: Refactor, test and improve the way we cut too-long messages for IRC --- louloulibs/utils/string.cpp | 12 ++++++++++++ louloulibs/utils/string.hpp | 2 ++ 2 files changed, 14 insertions(+) (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/string.cpp b/louloulibs/utils/string.cpp index 3977feb..7ed1aa3 100644 --- a/louloulibs/utils/string.cpp +++ b/louloulibs/utils/string.cpp @@ -4,3 +4,15 @@ bool to_bool(const std::string& val) { return (val == "1" || val == "true"); } + +std::vector cut(const std::string& val, const std::size_t size) +{ + std::vector res; + std::string::size_type pos = 0; + while (pos < val.size()) + { + res.emplace_back(val.substr(pos, size)); + pos += size; + } + return res; +} diff --git a/louloulibs/utils/string.hpp b/louloulibs/utils/string.hpp index 3775c36..1c8f001 100644 --- a/louloulibs/utils/string.hpp +++ b/louloulibs/utils/string.hpp @@ -1,8 +1,10 @@ #ifndef STRING_UTILS_HPP_INCLUDED #define STRING_UTILS_HPP_INCLUDED +#include #include bool to_bool(const std::string& val); +std::vector cut(const std::string& val, const std::size_t size); #endif /* STRING_UTILS_HPP_INCLUDED */ -- cgit v1.2.3 From 6235fb2d0326b18a9e013ae13dfb1fd0577ffd9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 15 Jun 2016 00:38:43 +0200 Subject: Add get_next_codepoint_size --- louloulibs/utils/encoding.cpp | 28 ++++++++++++++++------------ louloulibs/utils/encoding.hpp | 5 +++++ 2 files changed, 21 insertions(+), 12 deletions(-) (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/encoding.cpp b/louloulibs/utils/encoding.cpp index f738ce2..507f38a 100644 --- a/louloulibs/utils/encoding.cpp +++ b/louloulibs/utils/encoding.cpp @@ -23,6 +23,17 @@ namespace utils /** * Based on http://en.wikipedia.org/wiki/UTF-8#Description */ + std::size_t get_next_codepoint_size(const unsigned char c) + { + if ((c & 0b11111000) == 0b11110000) // 4 bytes: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + return 4; + else if ((c & 0b11110000) == 0b11100000) // 3 bytes: 1110xxx 10xxxxxx 10xxxxxx + return 3; + else if ((c & 0b11100000) == 0b11000000) // 2 bytes: 110xxxxx 10xxxxxx + return 2; + return 1; // 1 byte: 0xxxxxxx + } + bool is_valid_utf8(const char* s) { if (!s) @@ -32,38 +43,31 @@ namespace utils while (*str) { - // 4 bytes: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - if ((str[0] & 0b11111000) == 0b11110000) + const auto codepoint_size = get_next_codepoint_size(str[0]); + if (codepoint_size == 4) { if (!str[1] || !str[2] || !str[3] || ((str[1] & 0b11000000) != 0b10000000) || ((str[2] & 0b11000000) != 0b10000000) || ((str[3] & 0b11000000) != 0b10000000)) return false; - str += 4; } - // 3 bytes: 1110xxx 10xxxxxx 10xxxxxx - else if ((str[0] & 0b11110000) == 0b11100000) + else if (codepoint_size == 3) { if (!str[1] || !str[2] || ((str[1] & 0b11000000) != 0b10000000) || ((str[2] & 0b11000000) != 0b10000000)) return false; - str += 3; } - // 2 bytes: 110xxxxx 10xxxxxx - else if (((str[0]) & 0b11100000) == 0b11000000) + else if (codepoint_size == 2) { if (!str[1] || ((str[1] & 0b11000000) != 0b10000000)) return false; - str += 2; } - // 1 byte: 0xxxxxxx else if ((str[0] & 0b10000000) != 0) return false; - else - str++; + str += codepoint_size; } return true; } diff --git a/louloulibs/utils/encoding.hpp b/louloulibs/utils/encoding.hpp index 6b7ccd2..3f55055 100644 --- a/louloulibs/utils/encoding.hpp +++ b/louloulibs/utils/encoding.hpp @@ -5,6 +5,11 @@ namespace utils { + /** + * Return the size, in bytes, of the next UTF-8 codepoint, based on + * the given char. + */ + std::size_t get_next_codepoint_size(const unsigned char c); /** * Returns true if the given null-terminated string is valid utf-8. * -- cgit v1.2.3 From 4b1c580bb9bc03d656e59d702c72c3e793a1bbe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 15 Jun 2016 12:19:19 +0200 Subject: cut messages at 512 bytes, taking into account the UTF-8 codepoints ref #3067 --- louloulibs/utils/string.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/string.cpp b/louloulibs/utils/string.cpp index 7ed1aa3..2447f84 100644 --- a/louloulibs/utils/string.cpp +++ b/louloulibs/utils/string.cpp @@ -1,4 +1,5 @@ #include +#include bool to_bool(const std::string& val) { @@ -11,8 +12,17 @@ std::vector cut(const std::string& val, const std::size_t size) std::string::size_type pos = 0; while (pos < val.size()) { - res.emplace_back(val.substr(pos, size)); - pos += size; + // Get the number of chars, <= size, that contain only whole + // UTF-8 codepoints. + std::size_t s = 0; + auto codepoint_size = utils::get_next_codepoint_size(val[pos + s]); + while (s + codepoint_size <= size) + { + s += codepoint_size; + codepoint_size = utils::get_next_codepoint_size(val[pos + s]); + } + res.emplace_back(val.substr(pos, s)); + pos += s; } return res; } -- cgit v1.2.3 From 9206f4723b8c5feb8a96daa9c283d30cf73290e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Thu, 23 Jun 2016 22:40:53 +0200 Subject: Fix a bug in cut() --- louloulibs/utils/string.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/string.cpp b/louloulibs/utils/string.cpp index 2447f84..635e71a 100644 --- a/louloulibs/utils/string.cpp +++ b/louloulibs/utils/string.cpp @@ -16,7 +16,7 @@ std::vector cut(const std::string& val, const std::size_t size) // UTF-8 codepoints. std::size_t s = 0; auto codepoint_size = utils::get_next_codepoint_size(val[pos + s]); - while (s + codepoint_size <= size) + while (s + codepoint_size <= size && pos + s < val.size()) { s += codepoint_size; codepoint_size = utils::get_next_codepoint_size(val[pos + s]); -- cgit v1.2.3 From 81f8f45b371d1a0ef72c2768fbd1f9188fe83616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 4 Jul 2016 17:53:53 +0200 Subject: Replace all include guards by #pragma once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s $CURRENT_YEAR --- louloulibs/utils/encoding.hpp | 6 +++--- louloulibs/utils/reload.hpp | 6 +++--- louloulibs/utils/revstr.hpp | 6 +++--- louloulibs/utils/scopeguard.hpp | 4 +--- louloulibs/utils/split.hpp | 6 +++--- louloulibs/utils/string.hpp | 6 +++--- louloulibs/utils/timed_events.hpp | 5 +---- louloulibs/utils/tolower.hpp | 6 +++--- louloulibs/utils/xdg.hpp | 6 +++--- 9 files changed, 23 insertions(+), 28 deletions(-) (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/encoding.hpp b/louloulibs/utils/encoding.hpp index 3f55055..586edd8 100644 --- a/louloulibs/utils/encoding.hpp +++ b/louloulibs/utils/encoding.hpp @@ -1,5 +1,5 @@ -#ifndef ENCODING_INCLUDED -# define ENCODING_INCLUDED +#pragma once + #include @@ -40,4 +40,4 @@ namespace xep0106 void encode(std::string&); } -#endif // ENCODING_INCLUDED + diff --git a/louloulibs/utils/reload.hpp b/louloulibs/utils/reload.hpp index 16d64f7..6a56acd 100644 --- a/louloulibs/utils/reload.hpp +++ b/louloulibs/utils/reload.hpp @@ -1,5 +1,5 @@ -#ifndef RELOAD_HPP_INCLUDED -#define RELOAD_HPP_INCLUDED +#pragma once + /** * Reload the server's configuration, and close the logger (so that it @@ -7,4 +7,4 @@ */ void reload_process(); -#endif /* RELOAD_HPP_INCLUDED */ + diff --git a/louloulibs/utils/revstr.hpp b/louloulibs/utils/revstr.hpp index 27c9e3e..8e521ea 100644 --- a/louloulibs/utils/revstr.hpp +++ b/louloulibs/utils/revstr.hpp @@ -1,5 +1,5 @@ -#ifndef REVSTR_HPP_INCLUDED -# define REVSTR_HPP_INCLUDED +#pragma once + #include @@ -8,4 +8,4 @@ namespace utils std::string revstr(const std::string& original); } -#endif // REVSTR_HPP_INCLUDED + diff --git a/louloulibs/utils/scopeguard.hpp b/louloulibs/utils/scopeguard.hpp index fed40ff..ee1e2ef 100644 --- a/louloulibs/utils/scopeguard.hpp +++ b/louloulibs/utils/scopeguard.hpp @@ -1,5 +1,4 @@ -#ifndef SCOPEGUARD_HPP -#define SCOPEGUARD_HPP +#pragma once #include #include @@ -88,4 +87,3 @@ private: } -#endif diff --git a/louloulibs/utils/split.hpp b/louloulibs/utils/split.hpp index 6b487a9..3755ef8 100644 --- a/louloulibs/utils/split.hpp +++ b/louloulibs/utils/split.hpp @@ -1,5 +1,5 @@ -#ifndef SPLIT_INCLUDED -# define SPLIT_INCLUDED +#pragma once + #include #include @@ -9,4 +9,4 @@ namespace utils std::vector split(const std::string &s, const char delim, const bool allow_empty=true); } -#endif // SPLIT_INCLUDED + diff --git a/louloulibs/utils/string.hpp b/louloulibs/utils/string.hpp index 1c8f001..84ba101 100644 --- a/louloulibs/utils/string.hpp +++ b/louloulibs/utils/string.hpp @@ -1,5 +1,5 @@ -#ifndef STRING_UTILS_HPP_INCLUDED -#define STRING_UTILS_HPP_INCLUDED +#pragma once + #include #include @@ -7,4 +7,4 @@ bool to_bool(const std::string& val); std::vector cut(const std::string& val, const std::size_t size); -#endif /* STRING_UTILS_HPP_INCLUDED */ + diff --git a/louloulibs/utils/timed_events.hpp b/louloulibs/utils/timed_events.hpp index 70e2eff..6e28206 100644 --- a/louloulibs/utils/timed_events.hpp +++ b/louloulibs/utils/timed_events.hpp @@ -1,5 +1,4 @@ -#ifndef TIMED_EVENTS_HPP -# define TIMED_EVENTS_HPP +#pragma once #include #include @@ -131,5 +130,3 @@ private: std::vector events; explicit TimedEventsManager() = default; }; - -#endif // TIMED_EVENTS_HPP diff --git a/louloulibs/utils/tolower.hpp b/louloulibs/utils/tolower.hpp index 0019182..650e05d 100644 --- a/louloulibs/utils/tolower.hpp +++ b/louloulibs/utils/tolower.hpp @@ -1,5 +1,5 @@ -#ifndef TOLOWER_INCLUDED -# define TOLOWER_INCLUDED +#pragma once + #include @@ -8,4 +8,4 @@ namespace utils std::string tolower(const std::string& original); } -#endif // SPLIT_INCLUDED + diff --git a/louloulibs/utils/xdg.hpp b/louloulibs/utils/xdg.hpp index 15f3d0b..56e11da 100644 --- a/louloulibs/utils/xdg.hpp +++ b/louloulibs/utils/xdg.hpp @@ -1,5 +1,5 @@ -#ifndef XDG_HPP_INCLUDED -#define XDG_HPP_INCLUDED +#pragma once + #include @@ -11,4 +11,4 @@ std::string xdg_config_path(const std::string& filename); std::string xdg_data_path(const std::string& filename); -#endif /* XDG_HPP_INCLUDED */ + -- cgit v1.2.3 From 4c1b9abe7e230a39b119bdc45ebcd5e677fad488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 12 Jul 2016 00:31:57 +0200 Subject: Properly catch and handle database errors Do not use a singleton for the database. fix #3203 --- louloulibs/utils/reload.cpp | 19 ++++++++++++++++++- louloulibs/utils/reload.hpp | 8 +------- 2 files changed, 19 insertions(+), 8 deletions(-) (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/reload.cpp b/louloulibs/utils/reload.cpp index bddfd86..7125a75 100644 --- a/louloulibs/utils/reload.cpp +++ b/louloulibs/utils/reload.cpp @@ -1,11 +1,28 @@ +#include +#include #include +#include #include +void open_database() +{ + const auto db_filename = Config::get("db_name", xdg_data_path("biboumi.sqlite")); + log_info("Opening database: ", db_filename); + Database::open(db_filename); + log_info("database successfully opened."); +} + void reload_process() { Config::read_conf(); // Destroy the logger instance, to be recreated the next time a log // line needs to be written Logger::instance().reset(); - log_debug("Configuration and logger reloaded."); + log_info("Configuration and logger reloaded."); + try { + open_database(); + } catch (const litesql::DatabaseError&) { + log_warning("Re-using the previous database."); + } } + diff --git a/louloulibs/utils/reload.hpp b/louloulibs/utils/reload.hpp index 6a56acd..408426a 100644 --- a/louloulibs/utils/reload.hpp +++ b/louloulibs/utils/reload.hpp @@ -1,10 +1,4 @@ #pragma once - -/** - * Reload the server's configuration, and close the logger (so that it - * closes its files etc, to take into account the new configuration) - */ +void open_database(); void reload_process(); - - -- cgit v1.2.3 From 9fb2e116c47a9d4e2866d34450d12dcb90d4a26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 12 Jul 2016 01:15:34 +0200 Subject: Move reload.*pp from louloulibs to src --- louloulibs/utils/reload.cpp | 28 ---------------------------- louloulibs/utils/reload.hpp | 4 ---- 2 files changed, 32 deletions(-) delete mode 100644 louloulibs/utils/reload.cpp delete mode 100644 louloulibs/utils/reload.hpp (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/reload.cpp b/louloulibs/utils/reload.cpp deleted file mode 100644 index 7125a75..0000000 --- a/louloulibs/utils/reload.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include -#include -#include - -void open_database() -{ - const auto db_filename = Config::get("db_name", xdg_data_path("biboumi.sqlite")); - log_info("Opening database: ", db_filename); - Database::open(db_filename); - log_info("database successfully opened."); -} - -void reload_process() -{ - Config::read_conf(); - // Destroy the logger instance, to be recreated the next time a log - // line needs to be written - Logger::instance().reset(); - log_info("Configuration and logger reloaded."); - try { - open_database(); - } catch (const litesql::DatabaseError&) { - log_warning("Re-using the previous database."); - } -} - diff --git a/louloulibs/utils/reload.hpp b/louloulibs/utils/reload.hpp deleted file mode 100644 index 408426a..0000000 --- a/louloulibs/utils/reload.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -void open_database(); -void reload_process(); -- cgit v1.2.3 From 5c78692fcd447d94be1eb43338f79790f53051f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Thu, 28 Jul 2016 10:14:04 +0200 Subject: Do not add 1ms to the timeout of our poller MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Can’t remember why I did this, but that must be a stupid reason. Everything must work even with a timeout of 0. --- louloulibs/utils/timed_events_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/timed_events_manager.cpp b/louloulibs/utils/timed_events_manager.cpp index b90a237..67d61fe 100644 --- a/louloulibs/utils/timed_events_manager.cpp +++ b/louloulibs/utils/timed_events_manager.cpp @@ -23,7 +23,7 @@ std::chrono::milliseconds TimedEventsManager::get_timeout() const { if (this->events.empty()) return utils::no_timeout; - return this->events.front().get_timeout() + std::chrono::milliseconds(1); + return this->events.front().get_timeout(); } std::size_t TimedEventsManager::execute_expired_events() -- cgit v1.2.3 From 0d1e0629e7efe07bacce6a22e45ddfd7652eb505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Thu, 28 Jul 2016 10:47:44 +0200 Subject: Fix the timeout test, now that we don't wait 1ms too much everytime --- louloulibs/utils/timed_events.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'louloulibs/utils') diff --git a/louloulibs/utils/timed_events.cpp b/louloulibs/utils/timed_events.cpp index 6b936c4..68d009c 100644 --- a/louloulibs/utils/timed_events.cpp +++ b/louloulibs/utils/timed_events.cpp @@ -27,7 +27,7 @@ bool TimedEvent::is_after(const TimedEvent& other) const bool TimedEvent::is_after(const std::chrono::steady_clock::time_point& time_point) const { - return this->time_point >= time_point; + return this->time_point > time_point; } std::chrono::milliseconds TimedEvent::get_timeout() const -- cgit v1.2.3