diff options
Diffstat (limited to 'Swiften/Base')
66 files changed, 2661 insertions, 1560 deletions
diff --git a/Swiften/Base/API.h b/Swiften/Base/API.h index 388ad0a..06359ba 100644 --- a/Swiften/Base/API.h +++ b/Swiften/Base/API.h @@ -1,15 +1,16 @@ /* - * Copyright (c) 2012-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <Swiften/Base/Platform.h> +#include <boost/config.hpp> #ifdef SWIFTEN_STATIC -# define SWIFTEN_API +# define SWIFTEN_API #else # ifdef SWIFTEN_PLATFORM_WINDOWS # ifdef SWIFTEN_BUILDING @@ -20,6 +21,22 @@ # elif __GNUC__ >= 4 # define SWIFTEN_API __attribute__((visibility("default"))) # else -# define SWIFTEN_API +# define SWIFTEN_API # endif #endif + +#ifdef BOOST_NO_DEFAULTED_FUNCTIONS +# define SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(cls) +# define SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(cls) +#else +# define SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(cls) \ + cls(const cls&) = default; +# define SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(cls) \ + cls& operator=(const cls&) = default; +#endif + +#ifdef BOOST_NO_NOEXCEPT +#define SWIFTEN_NOEXCEPT throw() +#else +#define SWIFTEN_NOEXCEPT noexcept +#endif diff --git a/Swiften/Base/Algorithm.h b/Swiften/Base/Algorithm.h index d5edab1..ee761b7 100644 --- a/Swiften/Base/Algorithm.h +++ b/Swiften/Base/Algorithm.h @@ -1,154 +1,187 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> +#include <algorithm> #include <list> #include <map> -#include <algorithm> +#include <string> +#include <vector> namespace Swift { - /* - * Generic erase() - */ - namespace Detail { - struct VectorCategory {}; - struct ListCategory {}; - struct MapCategory {}; - - template<typename T> - struct ContainerTraits; - - template<typename A, typename B> - struct ContainerTraits< std::vector<A, B> > { - typedef VectorCategory Category; - }; - - template<> - struct ContainerTraits< std::string > { - typedef VectorCategory Category; - }; - - template<typename A, typename B> - struct ContainerTraits< std::list<A, B> > { - typedef ListCategory Category; - }; - - template<typename A, typename B, typename C, typename D> - struct ContainerTraits< std::map<A, B, C, D> > { - typedef MapCategory Category; - }; - - template<typename C, typename V> - void eraseImpl(C& c, const V& v, VectorCategory) { - c.erase(std::remove(c.begin(), c.end(), v), c.end()); - } - - template<typename C, typename V> - void eraseImpl(C& c, const V& v, ListCategory) { - c.remove(v); - } - - template<typename C, typename V> - void eraseImpl(C& c, const V& v, MapCategory) { - for (typename C::iterator it = c.begin(); it != c.end(); ) { - if (it->second == v) { - c.erase(it++); - } - else { - ++it; - } - } - } - - template<typename C, typename P> - void eraseIfImpl(C& c, const P& p, MapCategory) { - for (typename C::iterator it = c.begin(); it != c.end(); ) { - if (p(*it)) { - c.erase(it++); - } - else { - ++it; - } - } - } - - template<typename C, typename P> - void eraseIfImpl(C& c, const P& p, VectorCategory) { - c.erase(std::remove_if(c.begin(), c.end(), p), c.end()); - } - } - - template<typename C, typename V> - void erase(C& container, const V& value) { - Detail::eraseImpl(container, value, typename Detail::ContainerTraits<C>::Category()); - } - - template<typename C, typename P> - void eraseIf(C& container, const P& predicate) { - Detail::eraseIfImpl(container, predicate, typename Detail::ContainerTraits<C>::Category()); - } - - template<typename Source, typename Target> - void append(Target& target, const Source& source) { - target.insert(target.end(), source.begin(), source.end()); - } - - template<typename Source, typename Target> - void assign(Target& target, const Source& source) { - target.assign(source.begin(), source.end()); - } - - template<typename A, typename B, typename C, typename D> - B get(const std::map<A, B, C, D>& map, const A& key, const B& defaultValue) { - typename std::map<A, B, C, D>::const_iterator i = map.find(key); - if (i != map.end()) { - return i->second; - } - else { - return defaultValue; - } - } - - template<typename Container> - void safeClear(Container& c) { - std::fill(c.begin(), c.end(), 0); - c.clear(); - } - - /* - * Functors - */ - template<typename K, typename V> - class PairFirstEquals { - public: - PairFirstEquals(const K& value) : value(value) { - } - - bool operator()(const std::pair<K,V>& pair) const { - return pair.first == value; - } - - private: - K value; - }; - - template<typename K, typename V> - class PairSecondEquals { - public: - PairSecondEquals(const V& value) : value(value) { - } - - bool operator()(const std::pair<K,V>& pair) const { - return pair.second == value; - } - - private: - V value; - }; + /* + * Generic erase() + */ + namespace Detail { + struct VectorCategory {}; + struct ListCategory {}; + struct MapCategory {}; + + template<typename T> + struct ContainerTraits; + + template<typename A, typename B> + struct ContainerTraits< std::vector<A, B> > { + typedef VectorCategory Category; + }; + + template<> + struct ContainerTraits< std::string > { + typedef VectorCategory Category; + }; + + template<typename A, typename B> + struct ContainerTraits< std::list<A, B> > { + typedef ListCategory Category; + }; + + template<typename A, typename B, typename C, typename D> + struct ContainerTraits< std::map<A, B, C, D> > { + typedef MapCategory Category; + }; + + template<typename C, typename V> + void eraseImpl(C& c, const V& v, VectorCategory) { + c.erase(std::remove(c.begin(), c.end(), v), c.end()); + } + + template<typename C, typename V> + void eraseImpl(C& c, const V& v, ListCategory) { + c.remove(v); + } + + template<typename C, typename V> + void eraseImpl(C& c, const V& v, MapCategory) { + for (typename C::iterator it = c.begin(); it != c.end(); ) { + if (it->second == v) { + c.erase(it++); + } + else { + ++it; + } + } + } + + template<typename C, typename P> + void eraseIfImpl(C& c, const P& p, MapCategory) { + for (typename C::iterator it = c.begin(); it != c.end(); ) { + if (p(*it)) { + c.erase(it++); + } + else { + ++it; + } + } + } + + template<typename C, typename P> + void eraseIfImpl(C& c, const P& p, VectorCategory) { + c.erase(std::remove_if(c.begin(), c.end(), p), c.end()); + } + } + + template<typename C, typename V> + void erase(C& container, const V& value) { + Detail::eraseImpl(container, value, typename Detail::ContainerTraits<C>::Category()); + } + + template<typename C, typename P> + void eraseIf(C& container, const P& predicate) { + Detail::eraseIfImpl(container, predicate, typename Detail::ContainerTraits<C>::Category()); + } + + template<typename Source, typename Target> + void append(Target& target, const Source& source) { + target.insert(target.end(), source.begin(), source.end()); + } + + template<typename Source, typename Target> + void assign(Target& target, const Source& source) { + target.assign(source.begin(), source.end()); + } + + template<typename A, typename B, typename C, typename D> + B get(const std::map<A, B, C, D>& map, const A& key, const B& defaultValue) { + typename std::map<A, B, C, D>::const_iterator i = map.find(key); + if (i != map.end()) { + return i->second; + } + else { + return defaultValue; + } + } + + template<typename Container> + void safeClear(Container& c) { + std::fill(c.begin(), c.end(), 0); + c.clear(); + } + + /* + * Functors + */ + template<typename K, typename V> + class PairFirstEquals { + public: + PairFirstEquals(const K& value) : value(value) { + } + + bool operator()(const std::pair<K,V>& pair) const { + return pair.first == value; + } + + private: + K value; + }; + + template<typename K, typename V> + class PairSecondEquals { + public: + PairSecondEquals(const V& value) : value(value) { + } + + bool operator()(const std::pair<K,V>& pair) const { + return pair.second == value; + } + + private: + V value; + }; + + template <typename Map> + bool key_compare(Map const& lhs, Map const& rhs) { + + auto pred = [](decltype(*lhs.begin()) a, decltype(a) b) { return a.first == b.first; }; + + return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin(), pred); + } + + /** + * Ranges + */ + template <typename T> + class range_t { + public: + range_t(T b, T e) : b_(b), e_(e) {} + + T begin() { + return b_; + } + T end() { + return e_; + } + private: + T b_; + T e_; + }; + + template <typename T> + range_t<T> range(T b, T e) { + return range_t<T>(b, e); + } } diff --git a/Swiften/Base/Atomic.h b/Swiften/Base/Atomic.h new file mode 100644 index 0000000..ae065d4 --- /dev/null +++ b/Swiften/Base/Atomic.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <mutex> + +namespace Swift { + +/** + * This class template provides a read/write access synchronized wrapper for other types. + */ +template <typename ValueType> +class Atomic { + public: + Atomic(const ValueType& v) : value_(v) { + } + + /** + * Synchronized write access. + */ + Atomic<ValueType>& operator=(const ValueType& newValue) { + std::lock_guard<std::mutex> lock(valueMutex_); + value_ = newValue; + return *this; + } + + /** + * Synchronized read access. + */ + operator ValueType() { + std::lock_guard<std::mutex> lock(valueMutex_); + return value_; + } + + private: + std::mutex valueMutex_; + ValueType value_; +}; + +} diff --git a/Swiften/Base/BoostFilesystemVersion.h b/Swiften/Base/BoostFilesystemVersion.h index 1b1676c..fff6ce9 100644 --- a/Swiften/Base/BoostFilesystemVersion.h +++ b/Swiften/Base/BoostFilesystemVersion.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2012 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once diff --git a/Swiften/Base/BoostRandomGenerator.cpp b/Swiften/Base/BoostRandomGenerator.cpp deleted file mode 100644 index a661639..0000000 --- a/Swiften/Base/BoostRandomGenerator.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include <Swiften/Base/BoostRandomGenerator.h> - -#include <numeric> -#include <boost/random/uniform_int.hpp> -#include <boost/random/variate_generator.hpp> -#include <ctime> - -namespace Swift { - -BoostRandomGenerator::BoostRandomGenerator() { - // FIXME: Not a good seed - generator.seed(static_cast<unsigned int>(std::time(0))); -} - -int BoostRandomGenerator::generateRandomInteger(int maximum) { - boost::uniform_int<> distribution(0, maximum); - return distribution(generator); -} - -} diff --git a/Swiften/Base/BoostRandomGenerator.h b/Swiften/Base/BoostRandomGenerator.h deleted file mode 100644 index 6065ff3..0000000 --- a/Swiften/Base/BoostRandomGenerator.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include <Swiften/Base/RandomGenerator.h> -#include <Swiften/Base/Override.h> - -#include <boost/random/mersenne_twister.hpp> - -namespace Swift { - class BoostRandomGenerator : public RandomGenerator{ - public: - BoostRandomGenerator(); - - int generateRandomInteger(int max) SWIFTEN_OVERRIDE; - - private: - boost::mt19937 generator; - }; -} diff --git a/Swiften/Base/ByteArray.cpp b/Swiften/Base/ByteArray.cpp index 466db5f..882421d 100644 --- a/Swiften/Base/ByteArray.cpp +++ b/Swiften/Base/ByteArray.cpp @@ -1,50 +1,50 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/ByteArray.h> -#include <boost/numeric/conversion/cast.hpp> #include <boost/filesystem/fstream.hpp> +#include <boost/numeric/conversion/cast.hpp> namespace Swift { static const int BUFFER_SIZE = 4096; void readByteArrayFromFile(ByteArray& data, const boost::filesystem::path& file) { - boost::filesystem::ifstream input(file, std::ios_base::in|std::ios_base::binary); - while (input.good()) { - size_t oldSize = data.size(); - data.resize(oldSize + BUFFER_SIZE); - input.read(reinterpret_cast<char*>(&data[oldSize]), BUFFER_SIZE); - data.resize(oldSize + boost::numeric_cast<size_t>(input.gcount())); - } - input.close(); + boost::filesystem::ifstream input(file, std::ios_base::in|std::ios_base::binary); + while (input.good()) { + size_t oldSize = data.size(); + data.resize(oldSize + BUFFER_SIZE); + input.read(reinterpret_cast<char*>(&data[oldSize]), BUFFER_SIZE); + data.resize(oldSize + boost::numeric_cast<size_t>(input.gcount())); + } + input.close(); } std::vector<unsigned char> createByteArray(const std::string& s) { - return std::vector<unsigned char>(s.begin(), s.end()); + return std::vector<unsigned char>(s.begin(), s.end()); } std::vector<unsigned char> createByteArray(const char* c) { - std::vector<unsigned char> data; - while (*c) { - data.push_back(static_cast<unsigned char>(*c)); - ++c; - } - return data; + std::vector<unsigned char> data; + while (*c) { + data.push_back(static_cast<unsigned char>(*c)); + ++c; + } + return data; } std::string byteArrayToString(const ByteArray& b) { - size_t i; - for (i = b.size(); i > 0; --i) { - if (b[i - 1] != 0) { - break; - } - } - return i > 0 ? std::string(reinterpret_cast<const char*>(vecptr(b)), i) : ""; + size_t i; + for (i = b.size(); i > 0; --i) { + if (b[i - 1] != 0) { + break; + } + } + return i > 0 ? std::string(reinterpret_cast<const char*>(vecptr(b)), i) : ""; } } diff --git a/Swiften/Base/ByteArray.h b/Swiften/Base/ByteArray.h index 133b75f..b567b5a 100644 --- a/Swiften/Base/ByteArray.h +++ b/Swiften/Base/ByteArray.h @@ -1,47 +1,48 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> #include <string> +#include <vector> -#include <Swiften/Base/API.h> #include <boost/filesystem/path.hpp> +#include <Swiften/Base/API.h> + namespace Swift { - typedef std::vector<unsigned char> ByteArray; + typedef std::vector<unsigned char> ByteArray; + + SWIFTEN_API ByteArray createByteArray(const std::string& s); + SWIFTEN_API ByteArray createByteArray(const char* c); - SWIFTEN_API ByteArray createByteArray(const std::string& s); - SWIFTEN_API ByteArray createByteArray(const char* c); + inline ByteArray createByteArray(const unsigned char* c, size_t n) { + return ByteArray(c, c + n); + } - inline ByteArray createByteArray(const unsigned char* c, size_t n) { - return ByteArray(c, c + n); - } + inline ByteArray createByteArray(const char* c, size_t n) { + return ByteArray(c, c + n); + } - inline ByteArray createByteArray(const char* c, size_t n) { - return ByteArray(c, c + n); - } + inline ByteArray createByteArray(char c) { + return std::vector<unsigned char>(1, static_cast<unsigned char>(c)); + } - inline ByteArray createByteArray(char c) { - return std::vector<unsigned char>(1, static_cast<unsigned char>(c)); - } + template<typename T, typename A> + static const T* vecptr(const std::vector<T, A>& v) { + return v.empty() ? nullptr : &v[0]; + } - template<typename T, typename A> - static const T* vecptr(const std::vector<T, A>& v) { - return v.empty() ? NULL : &v[0]; - } + template<typename T, typename A> + static T* vecptr(std::vector<T, A>& v) { + return v.empty() ? nullptr : &v[0]; + } - template<typename T, typename A> - static T* vecptr(std::vector<T, A>& v) { - return v.empty() ? NULL : &v[0]; - } - - SWIFTEN_API std::string byteArrayToString(const ByteArray& b); + SWIFTEN_API std::string byteArrayToString(const ByteArray& b); - SWIFTEN_API void readByteArrayFromFile(ByteArray&, const boost::filesystem::path& file); + SWIFTEN_API void readByteArrayFromFile(ByteArray&, const boost::filesystem::path& file); } diff --git a/Swiften/Base/Concat.h b/Swiften/Base/Concat.h index 83a43b6..8923a8f 100644 --- a/Swiften/Base/Concat.h +++ b/Swiften/Base/Concat.h @@ -1,73 +1,41 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -namespace Swift { - template<typename C> - C concat(const C& c1, const C& c2) { - C result; - result.resize(c1.size() + c2.size()); - std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin())); - return result; - } - - template<typename C> - C concat(const C& c1, const C& c2, const C& c3) { - C result; - result.resize(c1.size() + c2.size() + c3.size()); - std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin()))); - return result; - } - - template<typename C> - C concat(const C& c1, const C& c2, const C& c3, const C& c4) { - C result; - result.resize(c1.size() + c2.size() + c3.size() + c4.size()); - std::copy(c4.begin(), c4.end(), std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin())))); - return result; - } - - template<typename C> - C concat(const C& c1, const C& c2, const C& c3, const C& c4, const C& c5) { - C result; - result.resize(c1.size() + c2.size() + c3.size() + c4.size() + c5.size()); - std::copy(c5.begin(), c5.end(), std::copy(c4.begin(), c4.end(), std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin()))))); - return result; - } +#include <algorithm> +#include <type_traits> - template<typename C> - C concat(const C& c1, const C& c2, const C& c3, const C& c4, const C& c5, const C& c6) { - C result; - result.resize(c1.size() + c2.size() + c3.size() + c4.size() + c5.size() + c6.size()); - std::copy(c6.begin(), c6.end(), std::copy(c5.begin(), c5.end(), std::copy(c4.begin(), c4.end(), std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin())))))); - return result; - } - - template<typename C> - C concat(const C& c1, const C& c2, const C& c3, const C& c4, const C& c5, const C& c6, const C& c7) { - C result; - result.resize(c1.size() + c2.size() + c3.size() + c4.size() + c5.size() + c6.size() + c7.size()); - std::copy(c7.begin(), c7.end(), std::copy(c6.begin(), c6.end(), std::copy(c5.begin(), c5.end(), std::copy(c4.begin(), c4.end(), std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin()))))))); - return result; - } - - template<typename C> - C concat(const C& c1, const C& c2, const C& c3, const C& c4, const C& c5, const C& c6, const C& c7, const C& c8) { - C result; - result.resize(c1.size() + c2.size() + c3.size() + c4.size() + c5.size() + c6.size() + c7.size() + c8.size()); - std::copy(c8.begin(), c8.end(), std::copy(c7.begin(), c7.end(), std::copy(c6.begin(), c6.end(), std::copy(c5.begin(), c5.end(), std::copy(c4.begin(), c4.end(), std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin())))))))); - return result; - } +namespace Swift { + template<typename V1, typename V2, typename... Rest> + std::size_t getReserveAmount(V1 const& v1, V2 const& v2, Rest const&... rest) SWIFTEN_NOEXCEPT + { + // Total size of the concatenated output is equal to sum of sizes of all the containers that were passed in. + // Two first can be accessed directly: + std::size_t sizeSum = v1.size() + v2.size(); + // While the rest needs to be calculated in parameter pack expansion: + // http://stackoverflow.com/a/25683817/61574 + // Pack expansion can occur inside a braced-init-list - dummy array is used for that (with side effect of accumulating the size) + int dummy[] = {0, ((sizeSum += rest.size()), void(), 0)...}; + + (void)dummy; // dummy is unused - suppress compiler warning + return sizeSum; +} - template<typename C> - C concat(const C& c1, const C& c2, const C& c3, const C& c4, const C& c5, const C& c6, const C& c7, const C& c8, const C& c9) { - C result; - result.resize(c1.size() + c2.size() + c3.size() + c4.size() + c5.size() + c6.size() + c7.size() + c8.size() + c9.size()); - std::copy(c9.begin(), c9.end(), std::copy(c8.begin(), c8.end(), std::copy(c7.begin(), c7.end(), std::copy(c6.begin(), c6.end(), std::copy(c5.begin(), c5.end(), std::copy(c4.begin(), c4.end(), std::copy(c3.begin(), c3.end(), std::copy(c2.begin(), c2.end(), std::copy(c1.begin(), c1.end(), result.begin()))))))))); - return result; - } + template<typename V1, typename V2, typename... Rest> + typename std::decay<V1>::type concat(V1&& v1, V2&& v2, Rest&&... rest) { + // Create the output container and reserve the required amount of space + typename std::decay<V1>::type v; + v.reserve(getReserveAmount(v1, v2, rest...)); + // Insert the elements from input containers to output. Directly for the first two: + v.insert(v.cend(), v1.cbegin(), v1.cend()); + v.insert(v.cend(), v2.cbegin(), v2.cend()); + // Use pack expansion for the others: + int dummy[] = {0, ((v.insert(v.cend(), rest.cbegin(), rest.cend())), void(), 0 )...}; + (void)dummy; + return v; + } } diff --git a/Swiften/Base/DateTime.cpp b/Swiften/Base/DateTime.cpp index 5d192c4..23b3b84 100644 --- a/Swiften/Base/DateTime.cpp +++ b/Swiften/Base/DateTime.cpp @@ -1,39 +1,48 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/DateTime.h> #include <locale> -#include <boost/date_time/time_facet.hpp> + +#include <boost/date_time/c_local_time_adjustor.hpp> #include <boost/date_time/local_time/local_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp> -#include <boost/date_time/c_local_time_adjustor.hpp> +#include <boost/date_time/time_facet.hpp> +#include <Swiften/Base/Log.h> #include <Swiften/Base/String.h> namespace Swift { boost::posix_time::ptime stringToDateTime(const std::string& string) { - static std::locale locale(std::locale::classic(), new boost::local_time::local_time_input_facet("%Y-%m-%d %H:%M:%S%F%ZP")); - std::istringstream stream(string); - stream.imbue(locale); - boost::local_time::local_date_time result(boost::date_time::not_a_date_time); - stream >> result; - return result.utc_time(); + static std::locale locale(std::locale::classic(), new boost::local_time::local_time_input_facet("%Y-%m-%d %H:%M:%S%F%ZP")); + std::istringstream stream(string); + stream.imbue(locale); + boost::local_time::local_date_time result(boost::date_time::not_a_date_time); + stream >> result; + return result.utc_time(); } std::string dateTimeToString(const boost::posix_time::ptime& time) { - std::string stampString = std::string(boost::posix_time::to_iso_extended_string(time)); - String::replaceAll(stampString, ',', "."); - stampString += "Z"; - return stampString; + std::string stampString = std::string(boost::posix_time::to_iso_extended_string(time)); + String::replaceAll(stampString, ',', "."); + stampString += "Z"; + return stampString; } std::string dateTimeToLocalString(const boost::posix_time::ptime& time) { - return boost::posix_time::to_simple_string(boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local(time)); + std::string localString; + try { + localString = boost::posix_time::to_simple_string(boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local(time)); + } + catch(std::out_of_range& exception) { + SWIFT_LOG(debug) << exception.what(); + } + return localString; } } diff --git a/Swiften/Base/DateTime.h b/Swiften/Base/DateTime.h index 891b170..36cff65 100644 --- a/Swiften/Base/DateTime.h +++ b/Swiften/Base/DateTime.h @@ -1,28 +1,29 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/API.h> #include <boost/date_time/posix_time/ptime.hpp> +#include <Swiften/Base/API.h> + namespace Swift { - /** - * Converts a date formatted according to XEP-0082 into a ptime - * object (in UTC). - */ - SWIFTEN_API boost::posix_time::ptime stringToDateTime(const std::string& string); + /** + * Converts a date formatted according to XEP-0082 into a ptime + * object (in UTC). + */ + SWIFTEN_API boost::posix_time::ptime stringToDateTime(const std::string& string); - /** - * Converts a UTC ptime object to a XEP-0082 formatted string. - */ - SWIFTEN_API std::string dateTimeToString(const boost::posix_time::ptime& time); + /** + * Converts a UTC ptime object to a XEP-0082 formatted string. + */ + SWIFTEN_API std::string dateTimeToString(const boost::posix_time::ptime& time); - /** - * Converts a UTC ptime object to a localized human readable string. - */ - SWIFTEN_API std::string dateTimeToLocalString(const boost::posix_time::ptime& time); + /** + * Converts a UTC ptime object to a localized human readable string. + */ + SWIFTEN_API std::string dateTimeToLocalString(const boost::posix_time::ptime& time); } diff --git a/Swiften/Base/Debug.cpp b/Swiften/Base/Debug.cpp new file mode 100644 index 0000000..b4245c3 --- /dev/null +++ b/Swiften/Base/Debug.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2015-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Base/Debug.h> + +#include <iostream> +#include <memory> + +#include <Swiften/Client/ClientError.h> +#include <Swiften/Client/ClientSession.h> +#include <Swiften/Serializer/PayloadSerializer.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> +#include <Swiften/Serializer/XMPPSerializer.h> + +std::ostream& operator<<(std::ostream& os, const Swift::ClientError& error) { + os << "ClientError("; + switch(error.getType()) { + case Swift::ClientError::UnknownError: + os << "UnknownError"; + break; + case Swift::ClientError::DomainNameResolveError: + os << "DomainNameResolveError"; + break; + case Swift::ClientError::ConnectionError: + os << "ConnectionError"; + break; + case Swift::ClientError::ConnectionReadError: + os << "ConnectionReadError"; + break; + case Swift::ClientError::ConnectionWriteError: + os << "ConnectionWriteError"; + break; + case Swift::ClientError::XMLError: + os << "XMLError"; + break; + case Swift::ClientError::AuthenticationFailedError: + os << "AuthenticationFailedError"; + break; + case Swift::ClientError::CompressionFailedError: + os << "CompressionFailedError"; + break; + case Swift::ClientError::ServerVerificationFailedError: + os << "ServerVerificationFailedError"; + break; + case Swift::ClientError::NoSupportedAuthMechanismsError: + os << "NoSupportedAuthMechanismsError"; + break; + case Swift::ClientError::UnexpectedElementError: + os << "UnexpectedElementError"; + break; + case Swift::ClientError::ResourceBindError: + os << "ResourceBindError"; + break; + case Swift::ClientError::SessionStartError: + os << "SessionStartError"; + break; + case Swift::ClientError::StreamError: + os << "StreamError"; + break; + case Swift::ClientError::TLSError: + os << "TLSError"; + break; + case Swift::ClientError::ClientCertificateLoadError: + os << "ClientCertificateLoadError"; + break; + case Swift::ClientError::ClientCertificateError: + os << "ClientCertificateError"; + break; + case Swift::ClientError::CertificateCardRemoved: + os << "CertificateCardRemoved"; + break; + case Swift::ClientError::UnknownCertificateError: + os << "UnknownCertificateError"; + break; + case Swift::ClientError::CertificateExpiredError: + os << "CertificateExpiredError"; + break; + case Swift::ClientError::CertificateNotYetValidError: + os << "CertificateNotYetValidError"; + break; + case Swift::ClientError::CertificateSelfSignedError: + os << "CertificateSelfSignedError"; + break; + case Swift::ClientError::CertificateRejectedError: + os << "CertificateRejectedError"; + break; + case Swift::ClientError::CertificateUntrustedError: + os << "CertificateUntrustedError"; + break; + case Swift::ClientError::InvalidCertificatePurposeError: + os << "InvalidCertificatePurposeError"; + break; + case Swift::ClientError::CertificatePathLengthExceededError: + os << "CertificatePathLengthExceededError"; + break; + case Swift::ClientError::InvalidCertificateSignatureError: + os << "InvalidCertificateSignatureError"; + break; + case Swift::ClientError::InvalidCAError: + os << "InvalidCAError"; + break; + case Swift::ClientError::InvalidServerIdentityError: + os << "InvalidServerIdentityError"; + break; + case Swift::ClientError::RevokedError: + os << "RevokedError"; + break; + case Swift::ClientError::RevocationCheckFailedError: + os << "RevocationCheckFailedError"; + break; + } + os << ")"; + return os; +} + +std::ostream& operator<<(std::ostream& os, Swift::Element* ele) { + using namespace Swift; + + std::shared_ptr<Element> element = std::shared_ptr<Element>(ele); + + std::shared_ptr<Payload> payload = std::dynamic_pointer_cast<Payload>(element); + if (payload) { + FullPayloadSerializerCollection payloadSerializerCollection; + PayloadSerializer *serializer = payloadSerializerCollection.getPayloadSerializer(payload); + os << "Payload(" << serializer->serialize(payload) << ")"; + return os; + } + std::shared_ptr<ToplevelElement> topLevelElement = std::dynamic_pointer_cast<ToplevelElement>(element); + if (topLevelElement) { + FullPayloadSerializerCollection payloadSerializerCollection; + XMPPSerializer xmppSerializer(&payloadSerializerCollection, ClientStreamType, false); + SafeByteArray serialized = xmppSerializer.serializeElement(topLevelElement); + os << "TopLevelElement(" << safeByteArrayToString(serialized) << ")"; + return os; + } + os << "Element(Unknown)"; + return os; +} + +std::ostream& operator<<(std::ostream& os, Swift::ClientSession::State state) { + using CS = Swift::ClientSession; + switch (state) { + case CS::State::Initial: + os << "ClientSession::State::Initial"; + break; + case CS::State::WaitingForStreamStart: + os << "ClientSession::State::WaitingForStreamStart"; + break; + case CS::State::Negotiating: + os << "ClientSession::State::Negotiating"; + break; + case CS::State::Compressing: + os << "ClientSession::State::Compressing"; + break; + case CS::State::WaitingForEncrypt: + os << "ClientSession::State::WaitingForEncrypt"; + break; + case CS::State::Encrypting: + os << "ClientSession::State::Encrypting"; + break; + case CS::State::WaitingForCredentials: + os << "ClientSession::State::WaitingForCredentials"; + break; + case CS::State::Authenticating: + os << "ClientSession::State::Authenticating"; + break; + case CS::State::EnablingSessionManagement: + os << "ClientSession::State::EnablingSessionManagement"; + break; + case CS::State::BindingResource: + os << "ClientSession::State::BindingResource"; + break; + case CS::State::StartingSession: + os << "ClientSession::State::StartingSession"; + break; + case CS::State::Initialized: + os << "ClientSession::State::Initialized"; + break; + case CS::State::Finishing: + os << "ClientSession::State::Finishing"; + break; + case CS::State::Finished: + os << "ClientSession::State::Finished"; + break; + } + return os; +} diff --git a/Swiften/Base/Debug.h b/Swiften/Base/Debug.h new file mode 100644 index 0000000..75575de --- /dev/null +++ b/Swiften/Base/Debug.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <iosfwd> + +#include <Swiften/Client/ClientSession.h> + +namespace Swift { + class ClientError; + class Element; +} + +SWIFTEN_API std::ostream& operator<<(std::ostream& os, const Swift::ClientError& error); + +SWIFTEN_API std::ostream& operator<<(std::ostream& os, Swift::Element* ele); + +SWIFTEN_API std::ostream& operator<<(std::ostream& os, Swift::ClientSession::State state); diff --git a/Swiften/Base/Error.cpp b/Swiften/Base/Error.cpp index 60ad7ac..4745f34 100644 --- a/Swiften/Base/Error.cpp +++ b/Swiften/Base/Error.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/Error.h> diff --git a/Swiften/Base/Error.h b/Swiften/Base/Error.h index d9f3b91..af4f27e 100644 --- a/Swiften/Base/Error.h +++ b/Swiften/Base/Error.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,8 +9,11 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API Error { - public: - virtual ~Error(); - }; + class SWIFTEN_API Error { + public: + Error() {} + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(Error) + SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(Error) + virtual ~Error(); + }; } diff --git a/Swiften/Base/FileSize.cpp b/Swiften/Base/FileSize.cpp new file mode 100644 index 0000000..a335337 --- /dev/null +++ b/Swiften/Base/FileSize.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Base/FileSize.h> + +#include <boost/format.hpp> + +namespace Swift { + +std::string formatSize(const boost::uintmax_t bytes) { + static const char *siPrefix[] = {"k", "M", "G", "T", "P", "E", "Z", "Y", nullptr}; + int power = 0; + double engBytes = bytes; + while (engBytes >= 1000) { + ++power; + engBytes = engBytes / 1000.0; + } + return str( boost::format("%.1lf %sB") % engBytes % (power > 0 ? siPrefix[power-1] : "") ); +} + +} diff --git a/Swiften/Base/FileSize.h b/Swiften/Base/FileSize.h new file mode 100644 index 0000000..af303cc --- /dev/null +++ b/Swiften/Base/FileSize.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#include <boost/cstdint.hpp> + +#include <Swiften/Base/API.h> + +namespace Swift { + +SWIFTEN_API std::string formatSize(const boost::uintmax_t bytes); + +} diff --git a/Swiften/Base/IDGenerator.cpp b/Swiften/Base/IDGenerator.cpp index 5556f7b..b59a39c 100644 --- a/Swiften/Base/IDGenerator.cpp +++ b/Swiften/Base/IDGenerator.cpp @@ -1,24 +1,27 @@ /* - * Copyright (c) 2010-2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/IDGenerator.h> +#include <boost/lexical_cast.hpp> #include <boost/uuid/uuid.hpp> -#include <boost/uuid/uuid_io.hpp> #include <boost/uuid/uuid_generators.hpp> -#include <boost/lexical_cast.hpp> +#include <boost/uuid/uuid_io.hpp> namespace Swift { IDGenerator::IDGenerator() { } +IDGenerator::~IDGenerator() { +} + std::string IDGenerator::generateID() { - static boost::uuids::random_generator generator; - return boost::lexical_cast<std::string>(generator()); + static boost::uuids::random_generator generator; + return boost::lexical_cast<std::string>(generator()); } } diff --git a/Swiften/Base/IDGenerator.h b/Swiften/Base/IDGenerator.h index 14ecfdc..6b53994 100644 --- a/Swiften/Base/IDGenerator.h +++ b/Swiften/Base/IDGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -11,10 +11,11 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API IDGenerator { - public: - IDGenerator(); + class SWIFTEN_API IDGenerator { + public: + IDGenerator(); + virtual ~IDGenerator(); - std::string generateID(); - }; + virtual std::string generateID(); + }; } diff --git a/Swiften/Base/LRUCache.h b/Swiften/Base/LRUCache.h new file mode 100644 index 0000000..1f92612 --- /dev/null +++ b/Swiften/Base/LRUCache.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <functional> +#include <utility> + +#include <boost/multi_index_container.hpp> +#include <boost/multi_index/member.hpp> +#include <boost/multi_index/hashed_index.hpp> +#include <boost/multi_index/sequenced_index.hpp> +#include <boost/optional.hpp> + +namespace Swift { + + +/** + * The \ref LRUCache template class implements a lookup cache which removes + * the least recently used cached item from the cache, if the cache size hits + * the \p MAX_SIZE limit. + * + * An example use is a cache for entity capabilities hash to DiscoInfo. + */ +template <typename KEY_TYPE, typename VALUE_TYPE, size_t MAX_SIZE> +class LRUCache { +public: + using cacheMissFunction = std::function<boost::optional<VALUE_TYPE>(const KEY_TYPE& )>; + +public: + /** + * Inserts the key/value pair in the front of the cache. If the \p key + * already exists in the cache, it is moved to the front instead. If + * afterwards, the cahe size exceeds the \p MAX_SIZE limit, the least + * recently item is removed from the cache. + */ + void insert(const KEY_TYPE& key, VALUE_TYPE value) { + auto pushResult = cache.push_front(entry_t(key, value)); + if (!pushResult.second) { + cache.relocate(cache.begin(), pushResult.first); + } + else if (cache.size() > MAX_SIZE) { + cache.pop_back(); + } + } + + /** + * Looks up a cache entry based on the provided \p key and moves it back + * to the front of the cache. If there is no cache entry for the provided + * \p key, an uninitialized \p boost::optional is returned. + * If the optional \p missFunction is provided, it is called on a cache miss. + * If the \p missFunction returns an initialized \p boost::optional, the + * value is inserted in the cache. + */ + boost::optional<VALUE_TYPE> get(const KEY_TYPE& key, cacheMissFunction missFunction = cacheMissFunction()) { + boost::optional<VALUE_TYPE> cachedValue; + auto cacheItemIterator = boost::multi_index::get<1>(cache).find(key); + if (cacheItemIterator != boost::multi_index::get<1>(cache).end()) { + cachedValue = cacheItemIterator->second; + cache.relocate(cache.begin(), cache.iterator_to(*cacheItemIterator)); + } + else if (missFunction && (cachedValue = missFunction(key))) { + insert(key, cachedValue.get()); + } + return cachedValue; + } + +private: + using entry_t = std::pair<KEY_TYPE, VALUE_TYPE>; + +private: + boost::multi_index_container< entry_t, boost::multi_index::indexed_by< boost::multi_index::sequenced<>, boost::multi_index::hashed_unique< + BOOST_MULTI_INDEX_MEMBER(entry_t, KEY_TYPE, first)> > > cache; +}; + +} diff --git a/Swiften/Base/Listenable.h b/Swiften/Base/Listenable.h index 445dfd7..ae83f4e 100644 --- a/Swiften/Base/Listenable.h +++ b/Swiften/Base/Listenable.h @@ -1,52 +1,55 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2015 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/API.h> -#include <boost/bind.hpp> #include <algorithm> +#include <vector> + +#include <boost/bind.hpp> + +#include <Swiften/Base/API.h> namespace Swift { - template<typename T> - class SWIFTEN_API Listenable { - public: - void addListener(T* listener) { - listeners.push_back(listener); - } - - void removeListener(T* listener) { - listeners.erase(std::remove(listeners.begin(), listeners.end(), listener), listeners.end()); - } - - protected: - template<typename F> - void notifyListeners(F event) { - for (typename std::vector<T*>::iterator i = listeners.begin(); i != listeners.end(); ++i) { - event(*i); - } - } - - template<typename F, typename A1> - void notifyListeners(F f, const A1& a1) { - notifyListeners(boost::bind(f, _1, a1)); - } - - template<typename F, typename A1, typename A2> - void notifyListeners(F f, const A1& a1, const A2& a2) { - notifyListeners(boost::bind(f, _1, a1, a2)); - } - - template<typename F, typename A1, typename A2, typename A3> - void notifyListeners(F f, const A1& a1, const A2& a2, const A3& a3) { - notifyListeners(boost::bind(f, _1, a1, a2, a3)); - } - - private: - std::vector<T*> listeners; - }; + template<typename T> + class SWIFTEN_API Listenable { + public: + void addListener(T* listener) { + listeners.push_back(listener); + } + + void removeListener(T* listener) { + listeners.erase(std::remove(listeners.begin(), listeners.end(), listener), listeners.end()); + } + + protected: + template<typename F> + void notifyListeners(F event) { + for (typename std::vector<T*>::iterator i = listeners.begin(); i != listeners.end(); ++i) { + event(*i); + } + } + + template<typename F, typename A1> + void notifyListeners(F f, const A1& a1) { + notifyListeners(boost::bind(f, _1, a1)); + } + + template<typename F, typename A1, typename A2> + void notifyListeners(F f, const A1& a1, const A2& a2) { + notifyListeners(boost::bind(f, _1, a1, a2)); + } + + template<typename F, typename A1, typename A2, typename A3> + void notifyListeners(F f, const A1& a1, const A2& a2, const A3& a3) { + notifyListeners(boost::bind(f, _1, a1, a2, a3)); + } + + private: + std::vector<T*> listeners; + }; } diff --git a/Swiften/Base/Log.cpp b/Swiften/Base/Log.cpp index 317798c..b6f1851 100644 --- a/Swiften/Base/Log.cpp +++ b/Swiften/Base/Log.cpp @@ -1,43 +1,83 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/Log.h> #include <cstdio> +#if defined(SWIFT_ANDROID_LOGGING) && defined(__ANDROID__) +#include <android/log.h> +#endif + namespace Swift { static Log::Severity logLevel = Log::warning; +std::unique_ptr<FILE, Log::LogFileClose> Log::logfile; +Log::Callback Log::logCallback; Log::Log() { } Log::~Log() { - // Using stdio for thread safety (POSIX file i/o calls are guaranteed to be atomic) - fprintf(stderr, "%s", stream.str().c_str()); - fflush(stderr); +#if defined(SWIFT_ANDROID_LOGGING) && defined(__ANDROID__) + __android_log_print(ANDROID_LOG_VERBOSE, "Swift", stream.str().c_str(), 1); +#else + // Using stdio for thread safety (POSIX file i/o calls are guaranteed to be atomic) + if (logCallback) { + logCallback(severity_, std::move(file_), line_, std::move(function_), stream.str()); + } + else { + stream << std::endl; + if (logfile) { + fwrite(stream.str().c_str(), sizeof(char), stream.str().size(), logfile.get()); + fflush(logfile.get()); + } + else { + fwrite(stream.str().c_str(), sizeof(char), stream.str().size(), stderr); + fflush(stderr); + } + } +#endif } std::ostringstream& Log::getStream( - Severity /*severity*/, - const std::string& severityString, - const std::string& file, - int line, - const std::string& function) { - stream << "[" << severityString << "] " << file << ":" << line << " " << function << ": "; - return stream; + Severity severity, + std::string severityString, + std::string file, + int line, + std::string function) { + if (logCallback) { + severity_ = severity; + file_ = std::move(file); + line_ = line; + function_ = std::move(function); + } + else { + stream << "[" << severityString << "] " << file << ":" << line << " " << function << ": "; + } + return stream; } Log::Severity Log::getLogLevel() { - return logLevel; + return logLevel; } void Log::setLogLevel(Severity level) { - logLevel = level; + logLevel = level; +} + +void Log::setLogFile(const std::string& fileName) { + if (!fileName.empty()) { + logfile = std::unique_ptr<FILE, Log::LogFileClose>(fopen(fileName.c_str(), "a")); + } +} + +void Log::setLogCallback(Callback callback) { + Log::logCallback = callback; } } diff --git a/Swiften/Base/Log.h b/Swiften/Base/Log.h index a46860f..255e478 100644 --- a/Swiften/Base/Log.h +++ b/Swiften/Base/Log.h @@ -1,44 +1,63 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <cstdio> +#include <functional> +#include <memory> #include <sstream> #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API Log { - public: - enum Severity { - error, warning, info, debug - }; - - Log(); - ~Log(); - - std::ostringstream& getStream( - Severity severity, - const std::string& severityString, - const std::string& file, - int line, - const std::string& function); - - static Severity getLogLevel(); - static void setLogLevel(Severity level); - - private: - std::ostringstream stream; - }; + class SWIFTEN_API Log { + public: + enum Severity { + error, warning, info, debug + }; + using Callback = std::function<void(Severity severity, std::string file, int line, std::string function, std::string message)>; + + Log(); + ~Log(); + + std::ostringstream& getStream( + Severity severity, + std::string severityString, + std::string file, + int line, + std::string function); + + static Severity getLogLevel(); + static void setLogLevel(Severity level); + static void setLogFile(const std::string& fileName); + static void setLogCallback(Callback callback); + + private: + struct LogFileClose { + void operator()(FILE* p) { + if (p) { + fclose(p); + } + } + }; + std::ostringstream stream; + static std::unique_ptr<FILE, LogFileClose> logfile; + static Callback logCallback; + Severity severity_; + std::string file_; + int line_; + std::string function_; + }; } #define SWIFT_LOG(severity) \ - if (Log::severity > Log::getLogLevel()) ; \ - else Log().getStream(Log::severity, #severity, __FILE__, __LINE__, __FUNCTION__) + if (Log::severity > Log::getLogLevel()) ; \ + else Log().getStream(Log::severity, #severity, __FILE__, __LINE__, __FUNCTION__) #define SWIFT_LOG_ASSERT(test, severity) \ - if (Log::severity > Log::getLogLevel() || (test)) ; \ - else Log().getStream(Log::severity, #severity, __FILE__, __LINE__, __FUNCTION__) << "Assertion failed: " << #test << ". " + if (Log::severity > Log::getLogLevel() || (test)) ; \ + else Log().getStream(Log::severity, #severity, __FILE__, __LINE__, __FUNCTION__) << "Assertion failed: " << #test << ". " diff --git a/Swiften/Base/LogSerializers.cpp b/Swiften/Base/LogSerializers.cpp new file mode 100644 index 0000000..3f8e9ce --- /dev/null +++ b/Swiften/Base/LogSerializers.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2016-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Base/LogSerializers.h> + +#include <Swiften/Elements/Presence.h> +#include <Swiften/Network/BOSHConnection.h> + +namespace Swift { + +std::ostream& operator<<(std::ostream& stream, const Presence& presence) { + std::string typeString; + switch (presence.getType()) { + case Presence::Available: + typeString = "Available"; + break; + case Presence::Error: + typeString = "Error"; + break; + case Presence::Probe: + typeString = "Probe"; + break; + case Presence::Subscribe: + typeString = "Subscribe"; + break; + case Presence::Subscribed: + typeString = "Subscribed"; + break; + case Presence::Unavailable: + typeString = "Unavailable"; + break; + case Presence::Unsubscribe: + typeString = "Unsubscribe"; + break; + case Presence::Unsubscribed: + typeString = "Unsubscribed"; + break; + } + + std::string showTypeString; + switch (presence.getShow()) { + case StatusShow::Online: + showTypeString = "Online"; + break; + case StatusShow::Away: + showTypeString = "Away"; + break; + case StatusShow::FFC: + showTypeString = "FFC"; + break; + case StatusShow::DND: + showTypeString = "DND"; + break; + case StatusShow::XA: + showTypeString = "XA"; + break; + case StatusShow::None: + showTypeString = "None"; + break; + } + + stream << "Presence(" << "from: " << presence.getFrom() << ", to: " << presence.getTo() << ", type: " << typeString << ", status: " << showTypeString << ", priority: " << presence.getPriority() << ", '" << presence.getStatus() << "'" << " )"; + return stream; +} + +std::ostream& operator<<(std::ostream& stream, const BOSHError& boshError) { + std::string errorString; + switch (boshError.getType()) { + case BOSHError::BadRequest: + errorString = "BadRequest"; + break; + case BOSHError::HostGone: + errorString = "HostGone"; + break; + case BOSHError::HostUnknown: + errorString = "HostUnknown"; + break; + case BOSHError::ImproperAddressing: + errorString = "ImproperAddressing"; + break; + case BOSHError::InternalServerError: + errorString = "InternalServerError"; + break; + case BOSHError::ItemNotFound: + errorString = "ItemNotFound"; + break; + case BOSHError::OtherRequest: + errorString = "OtherRequest"; + break; + case BOSHError::PolicyViolation: + errorString = "PolicyViolation"; + break; + case BOSHError::RemoteConnectionFailed: + errorString = "RemoteConnectionFailed"; + break; + case BOSHError::RemoteStreamError: + errorString = "RemoteStreamError"; + break; + case BOSHError::SeeOtherURI: + errorString = "SeeOtherURI"; + break; + case BOSHError::SystemShutdown: + errorString = "SystemShutdown"; + break; + case BOSHError::UndefinedCondition: + errorString = "UndefinedCondition"; + break; + case BOSHError::NoError: + errorString = "NoError"; + break; + } + + stream << "BOSHError( " << errorString << " )"; + return stream; +} + +}; + +::std::ostream& operator<<(::std::ostream& os, const boost::optional<std::string>& optStr) { + if (optStr.is_initialized()) { + return os << "boost::optional<std::string>(\"" << optStr.get() << "\")"; + } + else { + return os << "boost::optional<std::string>()"; + } +} + diff --git a/Swiften/Base/LogSerializers.h b/Swiften/Base/LogSerializers.h new file mode 100644 index 0000000..7f73686 --- /dev/null +++ b/Swiften/Base/LogSerializers.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <map> +#include <memory> +#include <ostream> +#include <string> +#include <utility> +#include <vector> + +#include <boost/optional.hpp> + +namespace Swift { + +class Presence; +class BOSHError; + +template <typename T> +std::ostream& operator<<(std::ostream& stream, const std::shared_ptr<T>& ptr) { + if (ptr) { + stream << *ptr; + } + else { + stream << "nullptr"; + } + return stream; +} + +template <typename T> +std::ostream& operator<<(std::ostream& stream, const std::vector<T>& vec) { + stream << "["; + if (!vec.empty()) { + auto it = std::begin(vec); + stream << *it; + + ++it; + for (auto end = std::end(vec); it != end; ++it) { + stream << ", " << *it; + } + } + stream << "]"; + return stream; +} + +template <typename KEY, typename VALUE> +std::ostream& operator<<(std::ostream& stream, const std::pair<KEY, VALUE>& pair) { + stream << pair.first << ":" << pair.second; + return stream; +} + +template <typename KEY, typename VALUE> +std::ostream& operator<<(std::ostream& stream, const std::map<KEY, VALUE>& map) { + stream << "{"; + if (!map.empty()) { + auto it = std::begin(map); + stream << *it; + + ++it; + for (auto end = std::end(map); it != end; ++it) { + stream << ", " << *it; + } + } + stream << "}"; + return stream; +} + +std::ostream& operator<<(std::ostream& stream, const Presence& presence); + +std::ostream& operator<<(std::ostream& stream, const BOSHError& boshError); + +}; + +::std::ostream& operator<<(::std::ostream& os, const boost::optional<std::string>& optStr); + diff --git a/Swiften/Base/Override.h b/Swiften/Base/Override.h deleted file mode 100644 index 6d9baaa..0000000 --- a/Swiften/Base/Override.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#if defined(__clang__) -# if __has_feature(cxx_override_control) || __has_extension(cxx_override_control) -# define SWIFTEN_OVERRIDE override -# else -# define SWIFTEN_OVERRIDE -# endif - -#elif defined(__GNUC__) -# if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))) && defined(__GXX_EXPERIMENTAL_CXX0X__) -# define SWIFTEN_OVERRIDE override -# else -# define SWIFTEN_OVERRIDE -# endif - -#elif defined(_MSC_VER) -// Actually, 1700 is the first version that supports the C++11 override, but -// older versions apparently support a similar keyword. -# if _MSC_VER >= 1400 -# define SWIFTEN_OVERRIDE override -# else -# define SWIFTEN_OVERRIDE -# endif - -#else -# define SWIFTEN_OVERRIDE -#endif diff --git a/Swiften/Base/Path.cpp b/Swiften/Base/Path.cpp index 2a49676..ffee09b 100644 --- a/Swiften/Base/Path.cpp +++ b/Swiften/Base/Path.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -13,16 +13,16 @@ using namespace Swift; boost::filesystem::path Swift::stringToPath(const std::string& path) { #ifdef SWIFTEN_PLATFORM_WINDOWS - return boost::filesystem::path(convertStringToWString(path)); + return boost::filesystem::path(convertStringToWString(path)); #else - return boost::filesystem::path(path); + return boost::filesystem::path(path); #endif } std::string Swift::pathToString(const boost::filesystem::path& path) { #ifdef SWIFTEN_PLATFORM_WINDOWS - return convertWStringToString(path.native()); + return convertWStringToString(path.native()); #else - return path.native(); + return path.native(); #endif } diff --git a/Swiften/Base/Path.h b/Swiften/Base/Path.h index ea99be9..40141b5 100644 --- a/Swiften/Base/Path.h +++ b/Swiften/Base/Path.h @@ -1,27 +1,29 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/API.h> -#include <boost/filesystem/path.hpp> #include <string> +#include <boost/filesystem/path.hpp> + +#include <Swiften/Base/API.h> + namespace Swift { - /** - * Creates a path for the given UTF-8 encoded string. - * This works independently of global locale settings. - */ - SWIFTEN_API boost::filesystem::path stringToPath(const std::string&); - - /** - * Returns the UTF-8 representation of the given path - * This works independently of global locale settings. - */ - SWIFTEN_API std::string pathToString(const boost::filesystem::path&); + /** + * Creates a path for the given UTF-8 encoded string. + * This works independently of global locale settings. + */ + SWIFTEN_API boost::filesystem::path stringToPath(const std::string&); + + /** + * Returns the UTF-8 representation of the given path + * This works independently of global locale settings. + */ + SWIFTEN_API std::string pathToString(const boost::filesystem::path&); } diff --git a/Swiften/Base/Paths.cpp b/Swiften/Base/Paths.cpp index 8ad1159..cbb16f3 100644 --- a/Swiften/Base/Paths.cpp +++ b/Swiften/Base/Paths.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/Paths.h> @@ -21,28 +21,28 @@ namespace Swift { boost::filesystem::path Paths::getExecutablePath() { #if defined(SWIFTEN_PLATFORM_MACOSX) - ByteArray path; - uint32_t size = 4096; - path.resize(size); - if (_NSGetExecutablePath(const_cast<char*>(reinterpret_cast<const char*>(vecptr(path))), &size) == 0) { - return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(path)), path.size()).c_str()).parent_path(); - } + ByteArray path; + uint32_t size = 4096; + path.resize(size); + if (_NSGetExecutablePath(const_cast<char*>(reinterpret_cast<const char*>(vecptr(path))), &size) == 0) { + return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(path)), path.size()).c_str()).parent_path(); + } #elif defined(SWIFTEN_PLATFORM_LINUX) - ByteArray path; - path.resize(4096); - size_t size = static_cast<size_t>(readlink("/proc/self/exe", reinterpret_cast<char*>(vecptr(path)), path.size())); - if (size > 0) { - path.resize(size); - return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(path)), path.size()).c_str()).parent_path(); - } + ByteArray path; + path.resize(4096); + size_t size = static_cast<size_t>(readlink("/proc/self/exe", reinterpret_cast<char*>(vecptr(path)), path.size())); + if (size > 0) { + path.resize(size); + return boost::filesystem::path(std::string(reinterpret_cast<const char*>(vecptr(path)), path.size()).c_str()).parent_path(); + } #elif defined(SWIFTEN_PLATFORM_WINDOWS) - std::vector<wchar_t> data; - data.resize(2048); - GetModuleFileNameW(NULL, vecptr(data), data.size()); - return boost::filesystem::path( - std::wstring(vecptr(data), data.size())).parent_path(); + std::vector<wchar_t> data; + data.resize(2048); + GetModuleFileNameW(NULL, vecptr(data), data.size()); + return boost::filesystem::path( + std::wstring(vecptr(data), data.size())).parent_path(); #endif - return boost::filesystem::path(); + return boost::filesystem::path(); } } diff --git a/Swiften/Base/Paths.h b/Swiften/Base/Paths.h index 94e62d1..71b55fb 100644 --- a/Swiften/Base/Paths.h +++ b/Swiften/Base/Paths.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -11,8 +11,8 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API Paths { - public: - static boost::filesystem::path getExecutablePath(); - }; + class SWIFTEN_API Paths { + public: + static boost::filesystem::path getExecutablePath(); + }; } diff --git a/Swiften/Base/Platform.h b/Swiften/Base/Platform.h index a22f556..22dff30 100644 --- a/Swiften/Base/Platform.h +++ b/Swiften/Base/Platform.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -43,9 +43,9 @@ #endif // Endianness -#include <boost/detail/endian.hpp> -#if defined(BOOST_LITTLE_ENDIAN) +#include <boost/predef/other/endian.h> +#if defined(BOOST_ENDIAN_LITTLE_BYTE) #define SWIFTEN_LITTLE_ENDIAN -#elif defined(BOOST_BIG_ENDIAN) +#elif defined(BOOST_ENDIAN_BIG_BYTE) #define SWIFTEN_BIG_ENDIAN #endif diff --git a/Swiften/Base/RandomGenerator.cpp b/Swiften/Base/RandomGenerator.cpp index f2dcca3..e43c01a 100644 --- a/Swiften/Base/RandomGenerator.cpp +++ b/Swiften/Base/RandomGenerator.cpp @@ -1,15 +1,13 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/RandomGenerator.h> namespace Swift { -RandomGenerator::~RandomGenerator() { - -} +RandomGenerator::~RandomGenerator() = default; } diff --git a/Swiften/Base/RandomGenerator.h b/Swiften/Base/RandomGenerator.h index eb5b84d..06677ec 100644 --- a/Swiften/Base/RandomGenerator.h +++ b/Swiften/Base/RandomGenerator.h @@ -1,23 +1,24 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/API.h> #include <vector> +#include <Swiften/Base/API.h> + namespace Swift { - class SWIFTEN_API RandomGenerator { - public: - virtual ~RandomGenerator(); + class SWIFTEN_API RandomGenerator { + public: + virtual ~RandomGenerator(); - /** - * Generates a random integer between 0 and 'max', - * 'max' inclusive. - */ - virtual int generateRandomInteger(int max) = 0; - }; + /** + * Generates a random integer between 0 and 'max', + * 'max' inclusive. + */ + virtual int generateRandomInteger(int max) = 0; + }; } diff --git a/Swiften/Base/Regex.cpp b/Swiften/Base/Regex.cpp index 5e3d89a..7843833 100644 --- a/Swiften/Base/Regex.cpp +++ b/Swiften/Base/Regex.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2013 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ /* @@ -18,20 +18,20 @@ namespace Swift { - namespace Regex { - std::string escape(const std::string& source) { - // escape regex special characters: ^.$| etc - // these need to be escaped: [\^\$\|.........] - // and then C++ requires '\' to be escaped, too.... - static const boost::regex esc("([\\^\\.\\$\\|\\(\\)\\[\\]\\*\\+\\?\\/\\{\\}\\\\])"); - // matched character should be prepended with '\' - // replace matched special character with \\\1 - // and escape once more for C++ rules... - static const std::string rep("\\\\\\1"); - return boost::regex_replace(source, esc, rep); - } - - } + namespace Regex { + std::string escape(const std::string& source) { + // escape regex special characters: ^.$| etc + // these need to be escaped: [\^\$\|.........] + // and then C++ requires '\' to be escaped, too.... + static const boost::regex esc("([\\^\\.\\$\\|\\(\\)\\[\\]\\*\\+\\?\\/\\{\\}\\\\])"); + // matched character should be prepended with '\' + // replace matched special character with \\\1 + // and escape once more for C++ rules... + static const std::string rep("\\\\\\1"); + return boost::regex_replace(source, esc, rep); + } + + } } - + diff --git a/Swiften/Base/Regex.h b/Swiften/Base/Regex.h index 6d12a60..7d352c0 100644 --- a/Swiften/Base/Regex.h +++ b/Swiften/Base/Regex.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2013 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -12,8 +12,8 @@ namespace Swift { - namespace Regex { - SWIFTEN_API std::string escape(const std::string& source); - } + namespace Regex { + SWIFTEN_API std::string escape(const std::string& source); + } } diff --git a/Swiften/Base/SConscript b/Swiften/Base/SConscript index 094059a..1f48f19 100644 --- a/Swiften/Base/SConscript +++ b/Swiften/Base/SConscript @@ -1,21 +1,23 @@ Import("swiften_env") objects = swiften_env.SwiftenObject([ - "ByteArray.cpp", - "DateTime.cpp", - "SafeByteArray.cpp", - "SafeAllocator.cpp", - "Error.cpp", - "Log.cpp", - "Path.cpp", - "Paths.cpp", - "String.cpp", - "IDGenerator.cpp", - "SimpleIDGenerator.cpp", - "RandomGenerator.cpp", - "BoostRandomGenerator.cpp", - "sleep.cpp", - "URL.cpp", - "Regex.cpp" - ]) + "ByteArray.cpp", + "DateTime.cpp", + "Error.cpp", + "FileSize.cpp", + "IDGenerator.cpp", + "Log.cpp", + "LogSerializers.cpp", + "Path.cpp", + "Paths.cpp", + "RandomGenerator.cpp", + "Regex.cpp", + "SafeAllocator.cpp", + "SafeByteArray.cpp", + "SimpleIDGenerator.cpp", + "StdRandomGenerator.cpp", + "String.cpp", + "URL.cpp", + "sleep.cpp", + ]) swiften_env.Append(SWIFTEN_OBJECTS = [objects]) diff --git a/Swiften/Base/SafeAllocator.cpp b/Swiften/Base/SafeAllocator.cpp index d61d8b9..df51e20 100644 --- a/Swiften/Base/SafeAllocator.cpp +++ b/Swiften/Base/SafeAllocator.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/SafeByteArray.h> @@ -13,14 +13,14 @@ namespace Swift { -void secureZeroMemory(char* memory, size_t numberOfBytes) { +SWIFTEN_API void secureZeroMemory(char* memory, size_t numberOfBytes) { #ifdef SWIFTEN_PLATFORM_WINDOWS - SecureZeroMemory(memory, numberOfBytes); + SecureZeroMemory(memory, numberOfBytes); #else - volatile char* p = memory; - for (size_t i = 0; i < numberOfBytes; ++i) { - *(p++) = 0; - } + volatile char* p = memory; + for (size_t i = 0; i < numberOfBytes; ++i) { + *(p++) = 0; + } #endif } diff --git a/Swiften/Base/SafeAllocator.h b/Swiften/Base/SafeAllocator.h index b01d77d..d47bb02 100644 --- a/Swiften/Base/SafeAllocator.h +++ b/Swiften/Base/SafeAllocator.h @@ -1,34 +1,36 @@ /* - * Copyright (c) 2011-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <vector> #include <algorithm> +#include <vector> + +#include <Swiften/Base/API.h> namespace Swift { - void secureZeroMemory(char* memory, size_t numberOfBytes); - - template<typename T> - class SafeAllocator : public std::allocator<T> { - public: - template <class U> struct rebind { - typedef SafeAllocator<U> other; - }; - - SafeAllocator() throw() {} - SafeAllocator(const SafeAllocator&) throw() : std::allocator<T>() {} - template <class U> SafeAllocator(const SafeAllocator<U>&) throw() {} - ~SafeAllocator() throw() {} - - void deallocate (T* p, size_t num) { - secureZeroMemory(reinterpret_cast<char*>(p), num); - std::allocator<T>::deallocate(p, num); - } - - private: - }; + SWIFTEN_API void secureZeroMemory(char* memory, size_t numberOfBytes); + + template<typename T> + class SWIFTEN_API SafeAllocator : public std::allocator<T> { + public: + template <class U> struct rebind { + typedef SafeAllocator<U> other; + }; + + SafeAllocator() SWIFTEN_NOEXCEPT {} + SafeAllocator(const SafeAllocator&) SWIFTEN_NOEXCEPT : std::allocator<T>() {} + template <class U> SafeAllocator(const SafeAllocator<U>&) SWIFTEN_NOEXCEPT {} + ~SafeAllocator() SWIFTEN_NOEXCEPT {} + + void deallocate (T* p, size_t num) { + secureZeroMemory(reinterpret_cast<char*>(p), num); + std::allocator<T>::deallocate(p, num); + } + + SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(SafeAllocator) + }; } diff --git a/Swiften/Base/SafeByteArray.cpp b/Swiften/Base/SafeByteArray.cpp index 848b6d8..dd3736e 100644 --- a/Swiften/Base/SafeByteArray.cpp +++ b/Swiften/Base/SafeByteArray.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/SafeByteArray.h> @@ -11,12 +11,12 @@ using namespace Swift; namespace Swift { SafeByteArray createSafeByteArray(const char* c) { - SafeByteArray data; - while (*c) { - data.push_back(static_cast<unsigned char>(*c)); - ++c; - } - return data; + SafeByteArray data; + while (*c) { + data.push_back(static_cast<unsigned char>(*c)); + ++c; + } + return data; } } diff --git a/Swiften/Base/SafeByteArray.h b/Swiften/Base/SafeByteArray.h index b85373c..342c185 100644 --- a/Swiften/Base/SafeByteArray.h +++ b/Swiften/Base/SafeByteArray.h @@ -1,59 +1,59 @@ /* - * Copyright (c) 2011-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <memory> #include <vector> #include <Swiften/Base/API.h> -#include <Swiften/Base/SafeAllocator.h> #include <Swiften/Base/ByteArray.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Base/SafeAllocator.h> namespace Swift { - typedef std::vector<unsigned char, SafeAllocator<unsigned char> > SafeByteArray; + typedef std::vector<unsigned char, SafeAllocator<unsigned char> > SafeByteArray; - inline SafeByteArray createSafeByteArray(const ByteArray& a) { - return SafeByteArray(a.begin(), a.end()); - } + inline SafeByteArray createSafeByteArray(const ByteArray& a) { + return SafeByteArray(a.begin(), a.end()); + } - SWIFTEN_API SafeByteArray createSafeByteArray(const char* c); + SWIFTEN_API SafeByteArray createSafeByteArray(const char* c); - inline SafeByteArray createSafeByteArray(const std::string& s) { - return SafeByteArray(s.begin(), s.end()); - } + inline SafeByteArray createSafeByteArray(const std::string& s) { + return SafeByteArray(s.begin(), s.end()); + } - inline boost::shared_ptr<SafeByteArray> createSafeByteArrayRef(const std::string& s) { - return boost::make_shared<SafeByteArray>(s.begin(), s.end()); - } + inline std::shared_ptr<SafeByteArray> createSafeByteArrayRef(const std::string& s) { + return std::make_shared<SafeByteArray>(s.begin(), s.end()); + } - inline SafeByteArray createSafeByteArray(char c) { - return SafeByteArray(1, static_cast<unsigned char>(c)); - } + inline SafeByteArray createSafeByteArray(char c) { + return SafeByteArray(1, static_cast<unsigned char>(c)); + } - inline SafeByteArray createSafeByteArray(const char* c, size_t n) { - return SafeByteArray(c, c + n); - } + inline SafeByteArray createSafeByteArray(const char* c, size_t n) { + return SafeByteArray(c, c + n); + } - inline boost::shared_ptr<SafeByteArray> createSafeByteArrayRef(const char* c, size_t n) { - return boost::make_shared<SafeByteArray>(c, c + n); - } + inline std::shared_ptr<SafeByteArray> createSafeByteArrayRef(const char* c, size_t n) { + return std::make_shared<SafeByteArray>(c, c + n); + } - inline SafeByteArray createSafeByteArray(const unsigned char* c, size_t n) { - return SafeByteArray(c, c + n); - } + inline SafeByteArray createSafeByteArray(const unsigned char* c, size_t n) { + return SafeByteArray(c, c + n); + } - inline boost::shared_ptr<SafeByteArray> createSafeByteArrayRef(const unsigned char* c, size_t n) { - return boost::make_shared<SafeByteArray>(c, c + n); - } + inline std::shared_ptr<SafeByteArray> createSafeByteArrayRef(const unsigned char* c, size_t n) { + return std::make_shared<SafeByteArray>(c, c + n); + } - /* WARNING! This breaks the safety of the data in the safe byte array. - * Do not use in modes that require data safety. */ - inline std::string safeByteArrayToString(const SafeByteArray& b) { - return byteArrayToString(ByteArray(b.begin(), b.end())); - } + /* WARNING! This breaks the safety of the data in the safe byte array. + * Do not use in modes that require data safety. */ + inline std::string safeByteArrayToString(const SafeByteArray& b) { + return byteArrayToString(ByteArray(b.begin(), b.end())); + } } diff --git a/Swiften/Base/SafeString.h b/Swiften/Base/SafeString.h index ef9c7cc..5e54537 100644 --- a/Swiften/Base/SafeString.h +++ b/Swiften/Base/SafeString.h @@ -1,32 +1,33 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <Swiften/Base/API.h> #include <Swiften/Base/SafeByteArray.h> namespace Swift { - class SafeString { - public: - SafeString(const SafeByteArray& data) : data(data) { - } + class SWIFTEN_API SafeString { + public: + SafeString(const SafeByteArray& data) : data(data) { + } - SafeString(const std::string& s) { - data = createSafeByteArray(s); - } + SafeString(const std::string& s) { + data = createSafeByteArray(s); + } - SafeString(const char* s) { - data = createSafeByteArray(s); - } + SafeString(const char* s) { + data = createSafeByteArray(s); + } - operator SafeByteArray () const { - return data; - } + operator SafeByteArray () const { + return data; + } - private: - SafeByteArray data; - }; + private: + SafeByteArray data; + }; } diff --git a/Swiften/Base/SimpleIDGenerator.cpp b/Swiften/Base/SimpleIDGenerator.cpp index 06cccea..e6d72b3 100644 --- a/Swiften/Base/SimpleIDGenerator.cpp +++ b/Swiften/Base/SimpleIDGenerator.cpp @@ -1,34 +1,37 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include "Swiften/Base/SimpleIDGenerator.h" +#include <Swiften/Base/SimpleIDGenerator.h> namespace Swift { SimpleIDGenerator::SimpleIDGenerator() { } +SimpleIDGenerator::~SimpleIDGenerator() { +} + std::string SimpleIDGenerator::generateID() { - bool carry = true; - size_t i = 0; - while (carry && i < currentID.size()) { - char c = currentID[i]; - if (c >= 'z') { - currentID[i] = 'a'; - } - else { - currentID[i] = c+1; - carry = false; - } - ++i; - } - if (carry) { - currentID += 'a'; - } - return currentID; + bool carry = true; + size_t i = 0; + while (carry && i < currentID.size()) { + char c = currentID[i]; + if (c >= 'z') { + currentID[i] = 'a'; + } + else { + currentID[i] = c+1; + carry = false; + } + ++i; + } + if (carry) { + currentID += 'a'; + } + return currentID; } } diff --git a/Swiften/Base/SimpleIDGenerator.h b/Swiften/Base/SimpleIDGenerator.h index fee857d..09e01de 100644 --- a/Swiften/Base/SimpleIDGenerator.h +++ b/Swiften/Base/SimpleIDGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,15 +9,23 @@ #include <string> #include <Swiften/Base/API.h> +#include <Swiften/Base/IDGenerator.h> namespace Swift { - class SWIFTEN_API SimpleIDGenerator { - public: - SimpleIDGenerator(); - std::string generateID(); + /** + * @brief The SimpleIDGenerator class implements a IDGenerator generating consecutive ID strings from + * the lower case latin alphabet. + */ - private: - std::string currentID; - }; + class SWIFTEN_API SimpleIDGenerator : public IDGenerator { + public: + SimpleIDGenerator(); + ~SimpleIDGenerator() override; + + std::string generateID() override; + + private: + std::string currentID; + }; } diff --git a/Swiften/Base/StartStopper.h b/Swiften/Base/StartStopper.h index 7ea6049..af1a72d 100644 --- a/Swiften/Base/StartStopper.h +++ b/Swiften/Base/StartStopper.h @@ -1,23 +1,23 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once namespace Swift { - template<typename T> class StartStopper { - public: - StartStopper(T* target) : target(target) { - target->start(); - } + template<typename T> class StartStopper { + public: + StartStopper(T* target) : target(target) { + target->start(); + } - ~StartStopper() { - target->stop(); - } - - private: - T* target; - }; + ~StartStopper() { + target->stop(); + } + + private: + T* target; + }; } diff --git a/Swiften/Base/StdRandomGenerator.cpp b/Swiften/Base/StdRandomGenerator.cpp new file mode 100644 index 0000000..8b1dee0 --- /dev/null +++ b/Swiften/Base/StdRandomGenerator.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2012-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/Base/StdRandomGenerator.h> + +#include <algorithm> +#include <functional> + +namespace { + template<class T = std::mt19937, std::size_t N = T::state_size> + typename std::enable_if<!!N, T>::type createSeededRandomEngine() { + typename T::result_type random_data[N]; + std::random_device source; + std::generate(std::begin(random_data), std::end(random_data), std::ref(source)); + std::seed_seq seeds(std::begin(random_data), std::end(random_data)); + return T(seeds); + } +} + +namespace Swift { + +StdRandomGenerator::StdRandomGenerator() : generator(createSeededRandomEngine()) { +} + +int StdRandomGenerator::generateRandomInteger(int maximum) { + std::uniform_int_distribution<> distribution(0, maximum); + return distribution(generator); +} + +} diff --git a/Swiften/Base/StdRandomGenerator.h b/Swiften/Base/StdRandomGenerator.h new file mode 100644 index 0000000..159d361 --- /dev/null +++ b/Swiften/Base/StdRandomGenerator.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2012-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <random> + +#include <Swiften/Base/API.h> +#include <Swiften/Base/RandomGenerator.h> + +namespace Swift { + class SWIFTEN_API StdRandomGenerator : public RandomGenerator { + public: + StdRandomGenerator(); + + int generateRandomInteger(int max) override; + + private: + std::mt19937 generator; + }; +} diff --git a/Swiften/Base/String.cpp b/Swiften/Base/String.cpp index 40ea2e1..bbc3003 100644 --- a/Swiften/Base/String.cpp +++ b/Swiften/Base/String.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/Platform.h> @@ -17,136 +17,232 @@ #include <Swiften/Base/String.h> #include <Swiften/Base/ByteArray.h> +namespace { +const static std::uint32_t UTF8_ACCEPT = 0; + +const static std::uint8_t UTF8D[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df + 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef + 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff + 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0 + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2 + 1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4 + 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6 + 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8 +}; + +//http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ +std::uint32_t decode(std::uint32_t & state, std::uint32_t & codepoint, std::uint8_t byte) { + const auto type = UTF8D[byte]; + codepoint = (state != UTF8_ACCEPT) ? (byte & 0x3fu) | (codepoint << 6) : (0xff >> type) & (byte); + state = UTF8D[256 + state * 16 + type]; + return state; +} + +std::uint32_t getNextCodepoint(const char * begin, const char * end, std::size_t & consumed, bool & ok) { + consumed = 0; + ok = true; + + std::uint32_t state = 0; + std::uint32_t codepoint = 0; + + for (auto it = begin; it != end; ++it) { + ++consumed; + if (!decode(state, codepoint, static_cast<std::uint8_t>(*it))) + return codepoint; + } + if (state != UTF8_ACCEPT) { + ok = false; + } + return codepoint; +} + +} + namespace Swift { static inline size_t sequenceLength(char firstByte) { - if ((firstByte & 0x80) == 0) { - return 1; - } - if ((firstByte & 0xE0) == 0xC0) { - return 2; - } - if ((firstByte & 0xF0) == 0xE0) { - return 3; - } - if ((firstByte & 0xF8) == 0xF0) { - return 4; - } - if ((firstByte & 0xFC) == 0xF8) { - return 5; - } - if ((firstByte & 0xFE) == 0xFC) { - return 6; - } - assert(false); - return 1; + if ((firstByte & 0x80) == 0) { + return 1; + } + if ((firstByte & 0xE0) == 0xC0) { + return 2; + } + if ((firstByte & 0xF0) == 0xE0) { + return 3; + } + if ((firstByte & 0xF8) == 0xF0) { + return 4; + } + if ((firstByte & 0xFC) == 0xF8) { + return 5; + } + if ((firstByte & 0xFE) == 0xFC) { + return 6; + } + assert(false); + return 1; } std::vector<unsigned int> String::getUnicodeCodePoints(const std::string& s) { - std::vector<unsigned int> result; - for (size_t i = 0; i < s.size();) { - unsigned int codePoint = 0; - char firstChar = s[i]; - size_t length = sequenceLength(firstChar); - - // First character is special - size_t firstCharBitSize = 7 - length; - if (length == 1) { - firstCharBitSize = 7; - } - codePoint = firstChar & ((1<<(firstCharBitSize+1)) - 1); - - for (size_t j = 1; j < length; ++j) { - codePoint = (codePoint<<6) | (s[i+j] & 0x3F); - } - result.push_back(codePoint); - i += length; - } - return result; + std::vector<unsigned int> result; + for (size_t i = 0; i < s.size();) { + unsigned int codePoint = 0; + char firstChar = s[i]; + size_t length = sequenceLength(firstChar); + + // First character is special + size_t firstCharBitSize = 7 - length; + if (length == 1) { + firstCharBitSize = 7; + } + codePoint = firstChar & ((1<<(firstCharBitSize+1)) - 1); + + for (size_t j = 1; j < length; ++j) { + codePoint = (codePoint<<6) | (s[i+j] & 0x3F); + } + result.push_back(codePoint); + i += length; + } + return result; } std::pair<std::string,std::string> String::getSplittedAtFirst(const std::string& s, char c) { - assert((c & 0x80) == 0); - size_t firstMatch = s.find(c); - if (firstMatch != s.npos) { - return std::make_pair(s.substr(0,firstMatch),s.substr(firstMatch+1,s.npos)); - } - else { - return std::make_pair(s, ""); - } + assert((c & 0x80) == 0); + size_t firstMatch = s.find(c); + if (firstMatch != s.npos) { + return std::make_pair(s.substr(0,firstMatch),s.substr(firstMatch+1,s.npos)); + } + else { + return std::make_pair(s, ""); + } } void String::replaceAll(std::string& src, char c, const std::string& s) { - size_t lastPos = 0; - size_t matchingIndex = 0; - while ((matchingIndex = src.find(c, lastPos)) != src.npos) { - src.replace(matchingIndex, 1, s); - lastPos = matchingIndex + s.size(); - } + size_t lastPos = 0; + size_t matchingIndex = 0; + while ((matchingIndex = src.find(c, lastPos)) != src.npos) { + src.replace(matchingIndex, 1, s); + lastPos = matchingIndex + s.size(); + } +} + +bool String::isValidXMPPCharacter(std::uint32_t codepoint) { + // Special accepted characters: + if (codepoint == '\t' || codepoint == '\r' || codepoint == '\n') + return true; + // Discouraged characters: + if (codepoint >= 0x7Fu && codepoint <= 0x84u) + return false; + if (codepoint >= 0x86u && codepoint <= 0x9Fu) + return false; + if (codepoint >= 0xFDD0u && codepoint <= 0xFDEFu) + return false; + if (((codepoint & 0xFFFEu) == 0xFFEEu) || ((codepoint & 0xFFFFu) == 0xFFFFu)) + return false; + // Other valid characters (after filtering for discouraged ones above) + if (codepoint >= 0x20u && codepoint <= 0xD7FFu) + return true; + if (codepoint >= 0xE000u && codepoint <= 0xFFFDu) + return true; + if (codepoint >= 0x10000u && codepoint <= 0x10FFFFu) + return true; + return false; +} + +std::string String::sanitizeXMPPString(const std::string& input) { + std::string result; + result.reserve(input.length()); + + auto it = input.data(); + const auto end = it + input.length(); + + std::size_t consumed; + bool status = UTF8_ACCEPT; + + while (it < end) { + const auto codepoint = getNextCodepoint(it, end, consumed, status); + if (status) { + if (isValidXMPPCharacter(codepoint)) { + std::copy(it, it + consumed, std::back_inserter(result)); + } + it += consumed; + } + else { + ++it; + } + } + result.shrink_to_fit(); + return result; } std::vector<std::string> String::split(const std::string& s, char c) { - assert((c & 0x80) == 0); - std::vector<std::string> result; - std::string accumulator; - for (size_t i = 0; i < s.size(); ++i) { - if (s[i] == c) { - result.push_back(accumulator); - accumulator = ""; - } - else { - accumulator += s[i]; - } - } - result.push_back(accumulator); - return result; + assert((c & 0x80) == 0); + std::vector<std::string> result; + std::string accumulator; + for (char i : s) { + if (i == c) { + result.push_back(accumulator); + accumulator = ""; + } + else { + accumulator += i; + } + } + result.push_back(accumulator); + return result; } std::string String::convertIntToHexString(int h) { - std::stringstream ss; - ss << std::setbase(16); - ss << h; - return ss.str(); + std::stringstream ss; + ss << std::setbase(16); + ss << h; + return ss.str(); } int String::convertHexStringToInt(const std::string& s) { - std::stringstream ss; - int h; - ss << std::setbase(16); - ss << s; - ss >> h; - return h; + std::stringstream ss; + int h; + ss << std::setbase(16); + ss << s; + ss >> h; + return h; } - #ifdef SWIFTEN_PLATFORM_WINDOWS std::string convertWStringToString(const std::wstring& s) { - int utf8Size = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, NULL, 0, NULL, NULL); - if (utf8Size < 0) { - throw std::runtime_error("Conversion error"); - } - std::vector<char> utf8Data(utf8Size); - int result = WideCharToMultiByte( - CP_UTF8, 0, s.c_str(), -1, vecptr(utf8Data), utf8Data.size(), NULL, NULL); - if (result < 0) { - throw std::runtime_error("Conversion error"); - } - return std::string(vecptr(utf8Data), utf8Size-1 /* trailing 0 character */); + int utf8Size = WideCharToMultiByte(CP_UTF8, 0, s.c_str(), -1, NULL, 0, NULL, NULL); + if (utf8Size < 0) { + throw std::runtime_error("Conversion error"); + } + std::vector<char> utf8Data(utf8Size); + int result = WideCharToMultiByte( + CP_UTF8, 0, s.c_str(), -1, vecptr(utf8Data), utf8Data.size(), NULL, NULL); + if (result < 0) { + throw std::runtime_error("Conversion error"); + } + return std::string(vecptr(utf8Data), utf8Size-1 /* trailing 0 character */); } std::wstring convertStringToWString(const std::string& s) { - int utf16Size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, NULL, 0); - if (utf16Size < 0) { - throw std::runtime_error("Conversion error"); - } - std::vector<wchar_t> utf16Data(utf16Size); - int result = MultiByteToWideChar( - CP_UTF8, 0, s.c_str(), -1, vecptr(utf16Data), utf16Data.size()); - if (result < 0) { - throw std::runtime_error("Conversion error"); - } - return std::wstring(vecptr(utf16Data), utf16Size-1 /* trailing 0 character */); + int utf16Size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, NULL, 0); + if (utf16Size < 0) { + throw std::runtime_error("Conversion error"); + } + std::vector<wchar_t> utf16Data(utf16Size); + int result = MultiByteToWideChar( + CP_UTF8, 0, s.c_str(), -1, vecptr(utf16Data), utf16Data.size()); + if (result < 0) { + throw std::runtime_error("Conversion error"); + } + return std::wstring(vecptr(utf16Data), utf16Size-1 /* trailing 0 character */); } #endif diff --git a/Swiften/Base/String.h b/Swiften/Base/String.h index 5a5642e..3a7ca65 100644 --- a/Swiften/Base/String.h +++ b/Swiften/Base/String.h @@ -1,58 +1,60 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <cstdint> +#include <sstream> #include <string> #include <vector> -#include <sstream> #include <Swiften/Base/API.h> #include <Swiften/Base/Platform.h> - #define SWIFTEN_STRING_TO_CFSTRING(a) \ - CFStringCreateWithBytes(NULL, reinterpret_cast<const UInt8*>(a.c_str()), a.size(), kCFStringEncodingUTF8, false) + CFStringCreateWithBytes(NULL, reinterpret_cast<const UInt8*>(a.c_str()), a.size(), kCFStringEncodingUTF8, false) namespace Swift { - namespace String { - SWIFTEN_API std::vector<unsigned int> getUnicodeCodePoints(const std::string&); - SWIFTEN_API std::pair<std::string, std::string> getSplittedAtFirst(const std::string&, char c); - SWIFTEN_API std::vector<std::string> split(const std::string&, char c); - SWIFTEN_API void replaceAll(std::string&, char c, const std::string& s); + namespace String { + SWIFTEN_API std::vector<unsigned int> getUnicodeCodePoints(const std::string&); + SWIFTEN_API std::pair<std::string, std::string> getSplittedAtFirst(const std::string&, char c); + SWIFTEN_API std::vector<std::string> split(const std::string&, char c); + SWIFTEN_API void replaceAll(std::string&, char c, const std::string& s); + SWIFTEN_API bool isValidXMPPCharacter(std::uint32_t codepoint); + SWIFTEN_API std::string sanitizeXMPPString(const std::string& input); - inline bool beginsWith(const std::string& s, char c) { - return s.size() > 0 && s[0] == c; - } + inline bool beginsWith(const std::string& s, char c) { + return s.size() > 0 && s[0] == c; + } - inline bool endsWith(const std::string& s, char c) { - return s.size() > 0 && s[s.size()-1] == c; - } + inline bool endsWith(const std::string& s, char c) { + return s.size() > 0 && s[s.size()-1] == c; + } - std::string convertIntToHexString(int h); - int convertHexStringToInt(const std::string& s); + std::string convertIntToHexString(int h); + int convertHexStringToInt(const std::string& s); - } + } #ifdef SWIFTEN_PLATFORM_WINDOWS - SWIFTEN_API std::string convertWStringToString(const std::wstring& s); - SWIFTEN_API std::wstring convertStringToWString(const std::string& s); + SWIFTEN_API std::string convertWStringToString(const std::wstring& s); + SWIFTEN_API std::wstring convertStringToWString(const std::string& s); #endif - class SWIFTEN_API makeString { - public: - template <typename T> makeString& operator<<(T const& v) { - stream << v; - return *this; - } + class SWIFTEN_API makeString { + public: + template <typename T> makeString& operator<<(T const& v) { + stream << v; + return *this; + } - operator std::string() const { - return stream.str(); - } + operator std::string() const { + return stream.str(); + } - private: - std::ostringstream stream; - }; + private: + std::ostringstream stream; + }; } diff --git a/Swiften/Base/Tristate.h b/Swiften/Base/Tristate.h new file mode 100644 index 0000000..edb7444 --- /dev/null +++ b/Swiften/Base/Tristate.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +namespace Swift { + +enum Tristate {Yes, No, Maybe}; + +} diff --git a/Swiften/Base/URL.cpp b/Swiften/Base/URL.cpp index 866cd45..5c0f0d7 100644 --- a/Swiften/Base/URL.cpp +++ b/Swiften/Base/URL.cpp @@ -1,114 +1,141 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/URL.h> +#include <algorithm> #include <iostream> namespace Swift { -int URL::getPortOrDefaultPort(const URL& url) { - if (url.getPort()) { - return *url.getPort(); - } - else if (url.getScheme() == "http") { - return 80; - } - else if (url.getScheme() == "https") { - return 443; - } - else { - std::cerr << "Unknown scheme: " + url.getScheme() << std::endl; - return 80; - } +unsigned short URL::getPortOrDefaultPort(const URL& url) { + if (url.getPort()) { + return *url.getPort(); + } + else if (url.getScheme() == "http") { + return 80; + } + else if (url.getScheme() == "https") { + return 443; + } + else { + std::cerr << "Unknown scheme: " + url.getScheme() << std::endl; + return 80; + } } URL URL::fromString(const std::string& urlString) { - size_t colonIndex = urlString.find(':'); - if (colonIndex == std::string::npos) { - return URL(); - } - std::string scheme = urlString.substr(0, colonIndex); + size_t colonIndex = urlString.find(':'); + if (colonIndex == std::string::npos) { + return URL(); + } + std::string scheme = urlString.substr(0, colonIndex); - // Authority - if (urlString.size() > colonIndex + 2 && urlString[colonIndex+1] == '/' && urlString[colonIndex+2] == '/') { - size_t authorityIndex = colonIndex + 3; - size_t slashIndex = urlString.find('/', authorityIndex); - std::string authority; - std::string path; - if (slashIndex == std::string::npos) { - authority = urlString.substr(authorityIndex); - path = ""; - } - else { - authority = urlString.substr(authorityIndex, slashIndex - authorityIndex); - path = unescape(urlString.substr(slashIndex)); - } + // Authority + if (urlString.size() > colonIndex + 2 && urlString[colonIndex+1] == '/' && urlString[colonIndex+2] == '/') { + size_t authorityIndex = colonIndex + 3; + size_t slashIndex = urlString.find('/', authorityIndex); + std::string authority; + std::string path; + if (slashIndex == std::string::npos) { + authority = urlString.substr(authorityIndex); + path = ""; + } + else { + authority = urlString.substr(authorityIndex, slashIndex - authorityIndex); + path = unescape(urlString.substr(slashIndex)); + } - size_t atIndex = authority.find('@'); - std::string userInfo; - std::string hostAndPort; - if (atIndex != std::string::npos) { - userInfo = authority.substr(0, atIndex); - hostAndPort = authority.substr(atIndex + 1); - } - else { - userInfo = ""; - hostAndPort = authority; - } + size_t atIndex = authority.find('@'); + std::string userInfo; + std::string hostAndPort; + if (atIndex != std::string::npos) { + userInfo = authority.substr(0, atIndex); + hostAndPort = authority.substr(atIndex + 1); + } + else { + userInfo = ""; + hostAndPort = authority; + } - std::string host; - boost::optional<int> port; - colonIndex = hostAndPort.find(':'); - if (colonIndex != std::string::npos) { - host = unescape(hostAndPort.substr(0, colonIndex)); - try { - port = boost::lexical_cast<int>(hostAndPort.substr(colonIndex + 1)); - } - catch (const boost::bad_lexical_cast&) { - return URL(); - } - } - else { - host = unescape(hostAndPort); - } + std::string host; + boost::optional<unsigned short> port; + if (hostAndPort[0] == '[') { + // handle IPv6 address literals + size_t addressEndIndex = hostAndPort.find(']'); + if (addressEndIndex != std::string::npos) { + host = hostAndPort.substr(1, addressEndIndex - 1); + colonIndex = hostAndPort.find(':', addressEndIndex); + if (colonIndex != std::string::npos) { + try { + port = boost::numeric_cast<unsigned short>(boost::lexical_cast<int>(hostAndPort.substr(colonIndex + 1))); + } + catch (...) { + return URL(); + } + } + } + else { + return URL(); + } + } + else { + colonIndex = hostAndPort.find(':'); + if (colonIndex != std::string::npos) { + host = unescape(hostAndPort.substr(0, colonIndex)); + try { + port = boost::numeric_cast<unsigned short>(boost::lexical_cast<int>(hostAndPort.substr(colonIndex + 1))); + } + catch (const boost::bad_lexical_cast&) { + return URL(); + } + } + else { + host = unescape(hostAndPort); + } + } - if (port) { - return URL(scheme, host, *port, path); - } - else { - return URL(scheme, host, path); - } - } - else { - // We don't support URLs without authorities yet - return URL(); - } + if (port) { + return URL(scheme, host, *port, path); + } + else { + return URL(scheme, host, path); + } + } + else { + // We don't support URLs without authorities yet + return URL(); + } } // FIXME: Escape non-ascii characters std::string URL::toString() const { - if (empty) { - return ""; - } - std::string result = scheme + "://"; - if (!user.empty()) { - result += user; - if (!password.empty()) { - result += ":" + password; - } - result += "@"; - } - result += host; - if (port) { - result += ":"; - result += boost::lexical_cast<std::string>(*port); - } - result += path; - return result; + if (empty) { + return ""; + } + std::string result = scheme + "://"; + if (!user.empty()) { + result += user; + if (!password.empty()) { + result += ":" + password; + } + result += "@"; + } + if (host.find(':') != std::string::npos) { + result += "[" + host + "]"; + } + else { + result += host; + } + if (port) { + result += ":"; + result += std::to_string(*port); + } + result += path; + return result; } // Disabling this code for now, since GCC4.5+boost1.42 (on ubuntu) seems to @@ -118,72 +145,72 @@ std::string URL::toString() const { struct PercentEncodedCharacterFinder { template<typename Iterator> boost::iterator_range<Iterator> operator()(Iterator begin, Iterator end) { - boost::iterator_range<Iterator> r = boost::first_finder("%")(begin, end); - if (r.end() == end) { - return r; - } - else { - if (r.end() + 1 == end || r.end() + 2 == end) { - throw std::runtime_error("Incomplete escape character"); - } - else { - r.advance_end(2); - return r; - } - } + boost::iterator_range<Iterator> r = boost::first_finder("%")(begin, end); + if (r.end() == end) { + return r; + } + else { + if (r.end() + 1 == end || r.end() + 2 == end) { + throw std::runtime_error("Incomplete escape character"); + } + else { + r.advance_end(2); + return r; + } + } } }; struct PercentUnencodeFormatter { template<typename FindResult> std::string operator()(const FindResult& match) const { - std::stringstream s; - s << std::hex << std::string(match.begin() + 1, match.end()); - unsigned int value; - s >> value; - if (s.fail() || s.bad()) { - throw std::runtime_error("Invalid escape character"); - } - unsigned char charValue = static_cast<unsigned char>(value); - return std::string(reinterpret_cast<const char*>(&charValue), 1); + std::stringstream s; + s << std::hex << std::string(match.begin() + 1, match.end()); + unsigned int value; + s >> value; + if (s.fail() || s.bad()) { + throw std::runtime_error("Invalid escape character"); + } + unsigned char charValue = static_cast<unsigned char>(value); + return std::string(reinterpret_cast<const char*>(&charValue), 1); } }; std::string unescape(const std::string& s) { - try { - return boost::find_format_all_copy(s, PercentEncodedCharacterFinder(), PercentUnencodeFormatter()); - } - catch (const std::exception&) { - return ""; - } + try { + return boost::find_format_all_copy(s, PercentEncodedCharacterFinder(), PercentUnencodeFormatter()); + } + catch (const std::exception&) { + return ""; + } } #endif std::string URL::unescape(const std::string& str) { - std::string result; - for (size_t i = 0; i < str.size(); ++i) { - if (str[i] == '%') { - if (i + 3 < str.size()) { - std::stringstream s; - s << std::hex << str.substr(i+1, 2); - unsigned int value; - s >> value; - if (s.fail() || s.bad()) { - return ""; - } - unsigned char charValue = static_cast<unsigned char>(value); - result += std::string(reinterpret_cast<const char*>(&charValue), 1); - i += 2; - } - else { - return ""; - } - } - else { - result += str[i]; - } - } - return result; + std::string result; + for (size_t i = 0; i < str.size(); ++i) { + if (str[i] == '%') { + if (i + 3 < str.size()) { + std::stringstream s; + s << std::hex << str.substr(i+1, 2); + unsigned int value; + s >> value; + if (s.fail() || s.bad()) { + return ""; + } + unsigned char charValue = static_cast<unsigned char>(value); + result += std::string(reinterpret_cast<const char*>(&charValue), 1); + i += 2; + } + else { + return ""; + } + } + else { + result += str[i]; + } + } + return result; } } diff --git a/Swiften/Base/URL.h b/Swiften/Base/URL.h index 75cf1a6..8fdb018 100644 --- a/Swiften/Base/URL.h +++ b/Swiften/Base/URL.h @@ -1,79 +1,81 @@ /* - * Copyright (c) 2011 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <string> + #include <boost/lexical_cast.hpp> #include <boost/optional.hpp> + #include <Swiften/Base/API.h> namespace Swift { class SWIFTEN_API URL { - public: - - URL() : scheme(""), user(""), password(""), host(""), path(""), empty(true) { - } - - URL(const std::string& scheme, const std::string& host, int port, const std::string& path) : scheme(scheme), user(), password(), host(host), port(port), path(path), empty(false) { - } - - URL(const std::string& scheme, const std::string& host, const std::string& path) : scheme(scheme), user(), password(), host(host), path(path), empty(false) { - } - - /** - * Whether the URL is empty. - */ - bool isEmpty() const { - return empty; - } - - /** - * Scheme used for the URL (http, https etc.) - */ - const std::string& getScheme() const { - return scheme; - } - - /** - * Hostname - */ - const std::string& getHost() const { - return host; - } - - /** - * Port number - */ - boost::optional<int> getPort() const { - return port; - } - - /** - * Path - */ - const std::string& getPath() const { - return path; - } - - std::string toString() const; - - static int getPortOrDefaultPort(const URL& url); - static URL fromString(const std::string&); - static std::string unescape(const std::string&); - - - private: - std::string scheme; - std::string user; - std::string password; - std::string host; - boost::optional<int> port; - std::string path; - bool empty; - }; + public: + + URL() : scheme(""), user(""), password(""), host(""), path(""), empty(true) { + } + + URL(const std::string& scheme, const std::string& host, unsigned short port, const std::string& path) : scheme(scheme), user(), password(), host(host), port(port), path(path), empty(false) { + } + + URL(const std::string& scheme, const std::string& host, const std::string& path) : scheme(scheme), user(), password(), host(host), path(path), empty(false) { + } + + /** + * Whether the URL is empty. + */ + bool isEmpty() const { + return empty; + } + + /** + * Scheme used for the URL (http, https etc.) + */ + const std::string& getScheme() const { + return scheme; + } + + /** + * Hostname + */ + const std::string& getHost() const { + return host; + } + + /** + * Port number + */ + boost::optional<unsigned short> getPort() const { + return port; + } + + /** + * Path + */ + const std::string& getPath() const { + return path; + } + + std::string toString() const; + + static unsigned short getPortOrDefaultPort(const URL& url); + static URL fromString(const std::string&); + static std::string unescape(const std::string&); + + + private: + std::string scheme; + std::string user; + std::string password; + std::string host; + boost::optional<unsigned short> port; + std::string path; + bool empty; + }; } diff --git a/Swiften/Base/UnitTest/ByteArrayTest.cpp b/Swiften/Base/UnitTest/ByteArrayTest.cpp index ecd0439..f1732ae 100644 --- a/Swiften/Base/UnitTest/ByteArrayTest.cpp +++ b/Swiften/Base/UnitTest/ByteArrayTest.cpp @@ -1,56 +1,43 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> - -#include <Swiften/Base/ByteArray.h> #include <boost/lexical_cast.hpp> -using namespace Swift; +#include <gtest/gtest.h> -class ByteArrayTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ByteArrayTest); - CPPUNIT_TEST(testGetData_NoData); - CPPUNIT_TEST(testToString); - CPPUNIT_TEST(testToString_NullTerminated); - CPPUNIT_TEST(testToString_TwoNullTerminated); - CPPUNIT_TEST(testToString_AllNull); - CPPUNIT_TEST_SUITE_END(); +#include <Swiften/Base/ByteArray.h> - public: - void testGetData_NoData() { - ByteArray testling; +using namespace Swift; - CPPUNIT_ASSERT_EQUAL(reinterpret_cast<const char*>(NULL), reinterpret_cast<const char*>(vecptr(testling))); - } +TEST(ByteArrayTest, testGetData_NoData) { + ByteArray testling; - void testToString() { - ByteArray testling(createByteArray("abcde")); + ASSERT_EQ(reinterpret_cast<const char*>(NULL), reinterpret_cast<const char*>(vecptr(testling))); +} - CPPUNIT_ASSERT_EQUAL(std::string("abcde"), byteArrayToString(testling)); - } +TEST(ByteArrayTest, testToString) { + ByteArray testling(createByteArray("abcde")); - void testToString_NullTerminated() { - ByteArray testling(createByteArray("abcde\0", 6)); + ASSERT_EQ(std::string("abcde"), byteArrayToString(testling)); +} - CPPUNIT_ASSERT_EQUAL(std::string("abcde"), byteArrayToString(testling)); - } +TEST(ByteArrayTest, testToString_NullTerminated) { + ByteArray testling(createByteArray("abcde\0", 6)); - void testToString_TwoNullTerminated() { - ByteArray testling(createByteArray("abcde\0\0", 7)); + ASSERT_EQ(std::string("abcde"), byteArrayToString(testling)); +} - CPPUNIT_ASSERT_EQUAL(std::string("abcde"), byteArrayToString(testling)); - } +TEST(ByteArrayTest, testToString_TwoNullTerminated) { + ByteArray testling(createByteArray("abcde\0\0", 7)); - void testToString_AllNull() { - ByteArray testling(createByteArray("\0\0", 2)); + ASSERT_EQ(std::string("abcde"), byteArrayToString(testling)); +} - CPPUNIT_ASSERT_EQUAL(std::string(""), byteArrayToString(testling)); - } -}; +TEST(ByteArrayTest, testToString_AllNull) { + ByteArray testling(createByteArray("\0\0", 2)); -CPPUNIT_TEST_SUITE_REGISTRATION(ByteArrayTest); + ASSERT_EQ(std::string(""), byteArrayToString(testling)); +} diff --git a/Swiften/Base/UnitTest/DateTimeTest.cpp b/Swiften/Base/UnitTest/DateTimeTest.cpp index 8c3903a..6a82d96 100644 --- a/Swiften/Base/UnitTest/DateTimeTest.cpp +++ b/Swiften/Base/UnitTest/DateTimeTest.cpp @@ -1,43 +1,52 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> #include <string> + #include <boost/date_time/posix_time/posix_time.hpp> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + #include <Swiften/Base/DateTime.h> using namespace Swift; class DateTimeTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(DateTimeTest); - CPPUNIT_TEST(testStringToDateTime_UTC); - CPPUNIT_TEST(testStringToDateTime_WithTimezone); - CPPUNIT_TEST(testDateTimeToString); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(DateTimeTest); + CPPUNIT_TEST(testStringToDateTime_UTC); + CPPUNIT_TEST(testStringToDateTime_WithTimezone); + CPPUNIT_TEST(testDateTimeToString); + CPPUNIT_TEST(testDateTimeToLocalStringNotThrowingException); + CPPUNIT_TEST_SUITE_END(); + + public: + void testStringToDateTime_UTC() { + boost::posix_time::ptime time = stringToDateTime("1969-07-21T02:56:15Z"); + + CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15"), boost::posix_time::to_iso_extended_string(time)); + } - public: - void testStringToDateTime_UTC() { - boost::posix_time::ptime time = stringToDateTime("1969-07-21T02:56:15Z"); + void testStringToDateTime_WithTimezone() { + boost::posix_time::ptime time = stringToDateTime("1969-07-20T21:56:15-05:00"); - CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15"), boost::posix_time::to_iso_extended_string(time)); - } + CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15"), boost::posix_time::to_iso_extended_string(time)); + } - void testStringToDateTime_WithTimezone() { - boost::posix_time::ptime time = stringToDateTime("1969-07-20T21:56:15-05:00"); + void testDateTimeToString() { + boost::posix_time::ptime time = stringToDateTime("1969-07-20T21:56:15-05:00"); - CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15"), boost::posix_time::to_iso_extended_string(time)); - } + CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15Z"), dateTimeToString(time)); + } - void testDateTimeToString() { - boost::posix_time::ptime time = stringToDateTime("1969-07-20T21:56:15-05:00"); + void testDateTimeToLocalStringNotThrowingException() { + boost::posix_time::ptime time = stringToDateTime("1954-07-20T21:56:15-05:00"); - CPPUNIT_ASSERT_EQUAL(std::string("1969-07-21T02:56:15Z"), dateTimeToString(time)); - } + CPPUNIT_ASSERT_EQUAL(std::string(""), dateTimeToLocalString(time)); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(DateTimeTest); diff --git a/Swiften/Base/UnitTest/IDGeneratorTest.cpp b/Swiften/Base/UnitTest/IDGeneratorTest.cpp index 610138f..08bd48b 100644 --- a/Swiften/Base/UnitTest/IDGeneratorTest.cpp +++ b/Swiften/Base/UnitTest/IDGeneratorTest.cpp @@ -1,12 +1,13 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <set> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <set> #include <Swiften/Base/IDGenerator.h> @@ -14,27 +15,27 @@ using namespace Swift; class IDGeneratorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IDGeneratorTest); - CPPUNIT_TEST(testGenerate); - CPPUNIT_TEST_SUITE_END(); - - public: - IDGeneratorTest() {} - - void setUp() { - generatedIDs_.clear(); - } - - void testGenerate() { - IDGenerator testling; - for (unsigned int i = 0; i < 26*4; ++i) { - std::string id = testling.generateID(); - CPPUNIT_ASSERT(generatedIDs_.insert(id).second); - } - } - - private: - std::set<std::string> generatedIDs_; + CPPUNIT_TEST_SUITE(IDGeneratorTest); + CPPUNIT_TEST(testGenerate); + CPPUNIT_TEST_SUITE_END(); + + public: + IDGeneratorTest() {} + + void setUp() { + generatedIDs_.clear(); + } + + void testGenerate() { + IDGenerator testling; + for (unsigned int i = 0; i < 26*4; ++i) { + std::string id = testling.generateID(); + CPPUNIT_ASSERT(generatedIDs_.insert(id).second); + } + } + + private: + std::set<std::string> generatedIDs_; }; CPPUNIT_TEST_SUITE_REGISTRATION(IDGeneratorTest); diff --git a/Swiften/Base/UnitTest/LRUCacheTest.cpp b/Swiften/Base/UnitTest/LRUCacheTest.cpp new file mode 100644 index 0000000..7d54c5c --- /dev/null +++ b/Swiften/Base/UnitTest/LRUCacheTest.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <string> + +#include <boost/optional.hpp> + +#include <Swiften/Base/LogSerializers.h> +#include <Swiften/Base/LRUCache.h> + +#include <gtest/gtest.h> // This has to go after Swiften/Base/LogSerializers.h. + +using namespace Swift; +namespace b = boost; + +TEST(LRUCacheTest, testCacheLimit) { + LRUCache<std::string, std::string, 3> testling; + + testling.insert("A", "AA"); + testling.insert("B", "BB"); + testling.insert("C", "CC"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>(), testling.get("D")); + + testling.insert("D", "DD"); + + ASSERT_EQ(b::optional<std::string>(), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>("DD"), testling.get("D")); +} + +TEST(LRUCacheTest, testMoveRecentToFrontOnGet) { + LRUCache<std::string, std::string, 3> testling; + + testling.insert("A", "AA"); + testling.insert("B", "BB"); + testling.insert("C", "CC"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>(), testling.get("D")); + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + + testling.insert("D", "DD"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>(), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>("DD"), testling.get("D")); +} + +TEST(LRUCacheTest, testMoveRecentToFrontOnReinsert) { + LRUCache<std::string, std::string, 3> testling; + + testling.insert("A", "AA"); + testling.insert("B", "BB"); + testling.insert("C", "CC"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>(), testling.get("D")); + + testling.insert("B", "BB"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>(), testling.get("D")); + + testling.insert("D", "DD"); + + ASSERT_EQ(b::optional<std::string>(), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + ASSERT_EQ(b::optional<std::string>("DD"), testling.get("D")); +} + +TEST(LRUCacheTest, testCacheReturnsValuesPreviouslyInserted) { + LRUCache<std::string, std::string, 3> testling; + + testling.insert("A", "AA"); + testling.insert("B", "BB"); + testling.insert("C", "CC"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); +} + +TEST(LRUCacheTest, testCacheMissFunctionIsUsedOnCacheMiss) { + LRUCache<std::string, std::string, 3> testling; + + testling.insert("A", "AA"); + testling.insert("B", "BB"); + + ASSERT_EQ(b::optional<std::string>("AA"), testling.get("A")); + ASSERT_EQ(b::optional<std::string>("BB"), testling.get("B")); + + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C", [](const std::string&) { + return boost::optional<std::string>(std::string("CC")); + })); + ASSERT_EQ(b::optional<std::string>("CC"), testling.get("C")); + + ASSERT_EQ(b::optional<std::string>(), testling.get("D", [](const std::string&) { + return boost::optional<std::string>(); + })); + ASSERT_EQ(b::optional<std::string>(), testling.get("D")); +} diff --git a/Swiften/Base/UnitTest/LogTest.cpp b/Swiften/Base/UnitTest/LogTest.cpp new file mode 100644 index 0000000..5d710db --- /dev/null +++ b/Swiften/Base/UnitTest/LogTest.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2019 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <vector> + +#include <boost/algorithm/string/predicate.hpp> + +#include <gtest/gtest.h> + +#include <Swiften/Base/Log.h> + +using namespace Swift; + +struct LogEntry { + LogEntry(Log::Severity severity, std::string file, int line, std::string function, std::string message) : severity(severity), file(std::move(file)), line(line), function(std::move(function)), message(std::move(message)) {} + + Log::Severity severity; + std::string file; + int line; + std::string function; + std::string message; +}; + +// Helper class to set the logging callback. Using this class to set it will ensure the +// logCallback is reset to empty (its default state) after each test. +class LogCallbackSetter { +public: + LogCallbackSetter(Log::Callback callback) { + Log::setLogCallback(callback); + } + ~LogCallbackSetter() { + Log::setLogCallback({}); + } +}; + +TEST(LogTest, testCallback) { + std::vector<LogEntry> logEntries; + LogCallbackSetter callbackSetter = {[&](Log::Severity severity, const std::string& file, int line, const std::string& function, const std::string& message) { + logEntries.emplace_back(severity, file, line, function, message); + }}; + + SWIFT_LOG(error) << "An error"; + ASSERT_EQ(1, logEntries.size()); + ASSERT_EQ(Log::error, logEntries[0].severity); + ASSERT_EQ("An error", logEntries[0].message); +} diff --git a/Swiften/Base/UnitTest/PathTest.cpp b/Swiften/Base/UnitTest/PathTest.cpp index f5f99e7..dd2233b 100644 --- a/Swiften/Base/UnitTest/PathTest.cpp +++ b/Swiften/Base/UnitTest/PathTest.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <cppunit/extensions/HelperMacros.h> @@ -13,23 +13,23 @@ using namespace Swift; class PathTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(PathTest); - CPPUNIT_TEST(testStringToPath); - CPPUNIT_TEST(testPathToString); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(PathTest); + CPPUNIT_TEST(testStringToPath); + CPPUNIT_TEST(testPathToString); + CPPUNIT_TEST_SUITE_END(); - public: - void testStringToPath() { + public: + void testStringToPath() { #ifdef SWIFTEN_PLATFORM_WINDOWS - CPPUNIT_ASSERT(std::wstring(L"tron\xe7on") == stringToPath("tron\xc3\xa7on").native()); + CPPUNIT_ASSERT(std::wstring(L"tron\xe7on") == stringToPath("tron\xc3\xa7on").native()); #else - CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), stringToPath("tron\xc3\xa7on").native()); + CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), stringToPath("tron\xc3\xa7on").native()); #endif - } + } - void testPathToString() { - CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), pathToString(stringToPath("tron\xc3\xa7on"))); - } + void testPathToString() { + CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), pathToString(stringToPath("tron\xc3\xa7on"))); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(PathTest); diff --git a/Swiften/Base/UnitTest/SimpleIDGeneratorTest.cpp b/Swiften/Base/UnitTest/SimpleIDGeneratorTest.cpp index 80aff02..9b49c0a 100644 --- a/Swiften/Base/UnitTest/SimpleIDGeneratorTest.cpp +++ b/Swiften/Base/UnitTest/SimpleIDGeneratorTest.cpp @@ -1,40 +1,41 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <set> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <set> -#include "Swiften/Base/SimpleIDGenerator.h" +#include <Swiften/Base/SimpleIDGenerator.h> using namespace Swift; class SimpleIDGeneratorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SimpleIDGeneratorTest); - CPPUNIT_TEST(testGenerate); - CPPUNIT_TEST_SUITE_END(); - - public: - SimpleIDGeneratorTest() {} - - void setUp() { - generatedIDs_.clear(); - } - - void testGenerate() { - SimpleIDGenerator testling; - for (unsigned int i = 0; i < 26*4; ++i) { - std::string id = testling.generateID(); - CPPUNIT_ASSERT(generatedIDs_.insert(id).second); - } - } - - private: - std::set<std::string> generatedIDs_; + CPPUNIT_TEST_SUITE(SimpleIDGeneratorTest); + CPPUNIT_TEST(testGenerate); + CPPUNIT_TEST_SUITE_END(); + + public: + SimpleIDGeneratorTest() {} + + void setUp() { + generatedIDs_.clear(); + } + + void testGenerate() { + SimpleIDGenerator testling; + for (unsigned int i = 0; i < 26*4; ++i) { + std::string id = testling.generateID(); + CPPUNIT_ASSERT(generatedIDs_.insert(id).second); + } + } + + private: + std::set<std::string> generatedIDs_; }; CPPUNIT_TEST_SUITE_REGISTRATION(SimpleIDGeneratorTest); diff --git a/Swiften/Base/UnitTest/StringTest.cpp b/Swiften/Base/UnitTest/StringTest.cpp index ffca98a..889c9c7 100644 --- a/Swiften/Base/UnitTest/StringTest.cpp +++ b/Swiften/Base/UnitTest/StringTest.cpp @@ -1,128 +1,171 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <string> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <string> -#include <Swiften/Base/String.h> #include <Swiften/Base/Platform.h> +#include <Swiften/Base/String.h> + +#include <boost/format.hpp> using namespace Swift; -class StringTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(StringTest); - CPPUNIT_TEST(testGetUnicodeCodePoints); - CPPUNIT_TEST(testGetSplittedAtFirst); - CPPUNIT_TEST(testGetSplittedAtFirst_CharacterAtBegin); - CPPUNIT_TEST(testGetSplittedAtFirst_CharacterAtEnd); - CPPUNIT_TEST(testGetSplittedAtFirst_NoSuchCharacter); - CPPUNIT_TEST(testReplaceAll); - CPPUNIT_TEST(testReplaceAll_LastChar); - CPPUNIT_TEST(testReplaceAll_ConsecutiveChars); - CPPUNIT_TEST(testReplaceAll_MatchingReplace); - CPPUNIT_TEST(testSplit); + class StringTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(StringTest); + CPPUNIT_TEST(testGetUnicodeCodePoints); + CPPUNIT_TEST(testGetSplittedAtFirst); + CPPUNIT_TEST(testGetSplittedAtFirst_CharacterAtBegin); + CPPUNIT_TEST(testGetSplittedAtFirst_CharacterAtEnd); + CPPUNIT_TEST(testGetSplittedAtFirst_NoSuchCharacter); + CPPUNIT_TEST(testReplaceAll); + CPPUNIT_TEST(testReplaceAll_LastChar); + CPPUNIT_TEST(testReplaceAll_ConsecutiveChars); + CPPUNIT_TEST(testReplaceAll_MatchingReplace); + CPPUNIT_TEST(testIsValidXMPPCharacter); + CPPUNIT_TEST(testSanitizeXMPPString); + CPPUNIT_TEST(testSplit); #ifdef SWIFTEN_PLATFORM_WINDOWS - CPPUNIT_TEST(testConvertWStringToString); - CPPUNIT_TEST(testConvertStringToWString); + CPPUNIT_TEST(testConvertWStringToString); + CPPUNIT_TEST(testConvertStringToWString); #endif - CPPUNIT_TEST_SUITE_END(); - - public: - void testGetUnicodeCodePoints() { - std::string testling("$\xc2\xa2\xe2\x82\xac\xf4\x8a\xaf\x8d"); - std::vector<unsigned int> points = String::getUnicodeCodePoints(testling); - - CPPUNIT_ASSERT_EQUAL(0x24U, points[0]); - CPPUNIT_ASSERT_EQUAL(0xA2U, points[1]); - CPPUNIT_ASSERT_EQUAL(0x20ACU, points[2]); - CPPUNIT_ASSERT_EQUAL(0x10ABCDU, points[3]); - } - - void testGetSplittedAtFirst() { - std::string testling("ab@cd@ef"); - - std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, '@'); - CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.first); - CPPUNIT_ASSERT_EQUAL(std::string("cd@ef"), result.second); - } - - void testGetSplittedAtFirst_CharacterAtBegin() { - std::string testling(" ab"); - - std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, ' '); - CPPUNIT_ASSERT(result.first.empty()); - CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.second); - } - - void testGetSplittedAtFirst_CharacterAtEnd() { - std::string testling("ab@"); - - std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, '@'); - CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.first); - CPPUNIT_ASSERT(result.second.empty()); - } - - void testGetSplittedAtFirst_NoSuchCharacter() { - std::string testling("ab"); - - std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, '@'); - CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.first); - CPPUNIT_ASSERT(result.second.empty()); - } - - void testReplaceAll() { - std::string testling("abcbd"); - - String::replaceAll(testling, 'b', "xyz"); - - CPPUNIT_ASSERT_EQUAL(std::string("axyzcxyzd"), testling); - } - - void testReplaceAll_LastChar() { - std::string testling("abc"); - - String::replaceAll(testling, 'c', "xyz"); - - CPPUNIT_ASSERT_EQUAL(std::string("abxyz"), testling); - } - - void testReplaceAll_ConsecutiveChars() { - std::string testling("abbc"); - - String::replaceAll(testling, 'b',"xyz"); - - CPPUNIT_ASSERT_EQUAL(std::string("axyzxyzc"), testling); - } - - void testReplaceAll_MatchingReplace() { - std::string testling("abc"); - - String::replaceAll(testling, 'b',"bbb"); - - CPPUNIT_ASSERT_EQUAL(std::string("abbbc"), testling); - } - - void testSplit() { - std::vector<std::string> result = String::split("abc def ghi", ' '); + CPPUNIT_TEST_SUITE_END(); - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(result.size())); - CPPUNIT_ASSERT_EQUAL(std::string("abc"), result[0]); - CPPUNIT_ASSERT_EQUAL(std::string("def"), result[1]); - CPPUNIT_ASSERT_EQUAL(std::string("ghi"), result[2]); - } + public: + void testGetUnicodeCodePoints() { + std::string testling("$\xc2\xa2\xe2\x82\xac\xf4\x8a\xaf\x8d"); + std::vector<unsigned int> points = String::getUnicodeCodePoints(testling); + + CPPUNIT_ASSERT_EQUAL(0x24U, points[0]); + CPPUNIT_ASSERT_EQUAL(0xA2U, points[1]); + CPPUNIT_ASSERT_EQUAL(0x20ACU, points[2]); + CPPUNIT_ASSERT_EQUAL(0x10ABCDU, points[3]); + } + + void testGetSplittedAtFirst() { + std::string testling("ab@cd@ef"); + + std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, '@'); + CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.first); + CPPUNIT_ASSERT_EQUAL(std::string("cd@ef"), result.second); + } + + void testGetSplittedAtFirst_CharacterAtBegin() { + std::string testling(" ab"); + + std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, ' '); + CPPUNIT_ASSERT(result.first.empty()); + CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.second); + } + + void testGetSplittedAtFirst_CharacterAtEnd() { + std::string testling("ab@"); + + std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, '@'); + CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.first); + CPPUNIT_ASSERT(result.second.empty()); + } + + void testGetSplittedAtFirst_NoSuchCharacter() { + std::string testling("ab"); + + std::pair<std::string,std::string> result = String::getSplittedAtFirst(testling, '@'); + CPPUNIT_ASSERT_EQUAL(std::string("ab"), result.first); + CPPUNIT_ASSERT(result.second.empty()); + } + + void testReplaceAll() { + std::string testling("abcbd"); + + String::replaceAll(testling, 'b', "xyz"); + + CPPUNIT_ASSERT_EQUAL(std::string("axyzcxyzd"), testling); + } + + void testReplaceAll_LastChar() { + std::string testling("abc"); + + String::replaceAll(testling, 'c', "xyz"); + + CPPUNIT_ASSERT_EQUAL(std::string("abxyz"), testling); + } + + void testReplaceAll_ConsecutiveChars() { + std::string testling("abbc"); + + String::replaceAll(testling, 'b',"xyz"); + + CPPUNIT_ASSERT_EQUAL(std::string("axyzxyzc"), testling); + } + + void testReplaceAll_MatchingReplace() { + std::string testling("abc"); + + String::replaceAll(testling, 'b',"bbb"); + + CPPUNIT_ASSERT_EQUAL(std::string("abbbc"), testling); + } + + void testIsValidXMPPCharacter() { + const std::uint32_t testCharacters[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x7F, 0x80, 0x84, 0x85, 0xFF }; + const auto testLength = sizeof(testCharacters) / sizeof(std::uint32_t); + const bool expectedValid[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 1 }; + static_assert(testLength == sizeof(expectedValid), "size of test data must match"); + + for (std::size_t i = 0; i != testLength; ++i) { + const auto c = testCharacters[i]; + CPPUNIT_ASSERT_EQUAL_MESSAGE(boost::str(boost::format("While testing at idx=%d: 0x%02x") % i % c), expectedValid[i], String::isValidXMPPCharacter(c)); + } + } + + void testSanitizeXMPPString() { + std::vector<std::pair<std::string, std::string>> testData = { + { "\0", "" }, + { std::string("\0\t", 3), "\t" }, + { "", "" }, + { std::string("\0", 1) , std::string() }, + { std::string("\0blah\0", 6) , std::string("blah", 4) }, + { "z\xC3\x9F\xE6\xB0\xB4\xF0\x9D\x84\x8B" , "z\xC3\x9F\xE6\xB0\xB4\xF0\x9D\x84\x8B" }, // or in u8 notation: u8"z\u00df\u6c34\U0001d10b" + { "\x7FT\t\x0c\xff\xfeT", "T\tT" }, + { "\x01Q\x0BW\x81T", "QWT" }, + { "\xF0\x9F\x98\x83" "ABC" "\xE2\xBE\xA6", "\xF0\x9F\x98\x83" "ABC" "\xE2\xBE\xA6" } + }; + + for (std::size_t i = 0; i != testData.size(); ++i) { + const auto & t = testData[i]; + const auto actual = String::sanitizeXMPPString(t.first); + CPPUNIT_ASSERT_EQUAL_MESSAGE(boost::str(boost::format("While testing string idx=%d") % i), std::string(actual), t.second); + } + } + + void testSplit() { + std::vector<std::string> result = String::split("abc def ghi", ' '); + + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(result.size())); + CPPUNIT_ASSERT_EQUAL(std::string("abc"), result[0]); + CPPUNIT_ASSERT_EQUAL(std::string("def"), result[1]); + CPPUNIT_ASSERT_EQUAL(std::string("ghi"), result[2]); + } #ifdef SWIFTEN_PLATFORM_WINDOWS - void testConvertWStringToString() { - CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), convertWStringToString(std::wstring(L"tron\xe7on"))); - } + void testConvertWStringToString() { + CPPUNIT_ASSERT_EQUAL(std::string("tron\xc3\xa7on"), convertWStringToString(std::wstring(L"tron\xe7on"))); + } - void testConvertStringToWString() { - CPPUNIT_ASSERT(std::wstring(L"tron\xe7on") == convertStringToWString(std::string("tron\xc3\xa7on"))); - } + void testConvertStringToWString() { + CPPUNIT_ASSERT(std::wstring(L"tron\xe7on") == convertStringToWString(std::string("tron\xc3\xa7on"))); + } #endif }; diff --git a/Swiften/Base/UnitTest/URLTest.cpp b/Swiften/Base/UnitTest/URLTest.cpp index e82321f..da9f15c 100644 --- a/Swiften/Base/UnitTest/URLTest.cpp +++ b/Swiften/Base/UnitTest/URLTest.cpp @@ -1,114 +1,238 @@ /* - * Copyright (c) 2012 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ +#include <boost/lexical_cast.hpp> + #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <Swiften/Base/URL.h> -#include <boost/lexical_cast.hpp> using namespace Swift; class URLTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(URLTest); - CPPUNIT_TEST(testFromString); - CPPUNIT_TEST(testFromString_WithoutPath); - CPPUNIT_TEST(testFromString_WithRootPath); - CPPUNIT_TEST(testFromString_WithPort); - CPPUNIT_TEST(testFromString_WithPortOnePartPath); - CPPUNIT_TEST(testFromString_WithPortWithoutPath); - CPPUNIT_TEST(testFromString_WithUserInfo); - CPPUNIT_TEST(testFromString_NonASCIIHost); - CPPUNIT_TEST(testFromString_NonASCIIPath); - CPPUNIT_TEST(testToString); - CPPUNIT_TEST(testToString_WithPort); - CPPUNIT_TEST_SUITE_END(); - - public: - void testFromString() { - URL url = URL::fromString("http://foo.bar/baz/bam"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT(!url.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string("/baz/bam"), url.getPath()); - } - - void testFromString_WithoutPath() { - URL url = URL::fromString("http://foo.bar"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT(!url.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string(""), url.getPath()); - } - - void testFromString_WithRootPath() { - URL url = URL::fromString("http://foo.bar/"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT(!url.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string("/"), url.getPath()); - } - - void testFromString_WithPort() { - URL url = URL::fromString("http://foo.bar:1234/baz/bam"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT_EQUAL(1234, *url.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string("/baz/bam"), url.getPath()); - } - - void testFromString_WithPortOnePartPath() { - URL url = URL::fromString("http://foo.bar:11440/http-bind/"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT_EQUAL(11440, *url.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string("/http-bind/"), url.getPath()); - } - - void testFromString_WithPortWithoutPath() { - URL url = URL::fromString("http://foo.bar:1234"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT_EQUAL(1234, *url.getPort()); - CPPUNIT_ASSERT_EQUAL(std::string(""), url.getPath()); - } - - void testFromString_WithUserInfo() { - URL url = URL::fromString("http://user:pass@foo.bar/baz/bam"); - - CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); - CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); - CPPUNIT_ASSERT_EQUAL(std::string("/baz/bam"), url.getPath()); - } - - void testFromString_NonASCIIHost() { - URL url = URL::fromString("http://www.tron%C3%A7on.be/baz/bam"); - - CPPUNIT_ASSERT_EQUAL(std::string("www.tron\xc3\xa7on.be"), url.getHost()); - } - - void testFromString_NonASCIIPath() { - URL url = URL::fromString("http://foo.bar/baz/tron%C3%A7on/bam"); - - CPPUNIT_ASSERT_EQUAL(std::string("/baz/tron\xc3\xa7on/bam"), url.getPath()); - } - - void testToString() { - CPPUNIT_ASSERT_EQUAL(std::string("http://foo.bar/baz/bam"), URL("http", "foo.bar", "/baz/bam").toString()); - } - - void testToString_WithPort() { - CPPUNIT_ASSERT_EQUAL(std::string("http://foo.bar:1234/baz/bam"), URL("http", "foo.bar", 1234, "/baz/bam").toString()); - } + CPPUNIT_TEST_SUITE(URLTest); + CPPUNIT_TEST(testFromString); + CPPUNIT_TEST(testFromString_WithoutPath); + CPPUNIT_TEST(testFromString_WithRootPath); + CPPUNIT_TEST(testFromString_WithPort); + CPPUNIT_TEST(testFromString_WithPortOnePartPath); + CPPUNIT_TEST(testFromString_WithPortWithoutPath); + CPPUNIT_TEST(testFromString_WithUserInfo); + CPPUNIT_TEST(testFromString_NonASCIIHost); + CPPUNIT_TEST(testFromString_NonASCIIPath); + CPPUNIT_TEST(testFromString_IPv4Address); + CPPUNIT_TEST(testFromString_IPv4AddressWithPort); + CPPUNIT_TEST(testFromString_IPv6Address); + CPPUNIT_TEST(testFromString_IPv6AddressWithPort); + CPPUNIT_TEST(testToString); + CPPUNIT_TEST(testToString_WithPort); + CPPUNIT_TEST(test_FromString_ToString_IPv6RFC2732); + CPPUNIT_TEST_SUITE_END(); + + public: + void testFromString() { + URL url = URL::fromString("http://foo.bar/baz/bam"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT(!url.getPort()); + CPPUNIT_ASSERT_EQUAL(std::string("/baz/bam"), url.getPath()); + } + + void testFromString_WithoutPath() { + URL url = URL::fromString("http://foo.bar"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT(!url.getPort()); + CPPUNIT_ASSERT_EQUAL(std::string(""), url.getPath()); + } + + void testFromString_WithRootPath() { + URL url = URL::fromString("http://foo.bar/"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT(!url.getPort()); + CPPUNIT_ASSERT_EQUAL(std::string("/"), url.getPath()); + } + + void testFromString_WithPort() { + URL url = URL::fromString("http://foo.bar:1234/baz/bam"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(1234), *url.getPort()); + CPPUNIT_ASSERT_EQUAL(std::string("/baz/bam"), url.getPath()); + } + + void testFromString_WithPortOnePartPath() { + URL url = URL::fromString("http://foo.bar:11440/http-bind/"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(11440), *url.getPort()); + CPPUNIT_ASSERT_EQUAL(std::string("/http-bind/"), url.getPath()); + } + + void testFromString_WithPortWithoutPath() { + URL url = URL::fromString("http://foo.bar:1234"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(1234), *url.getPort()); + CPPUNIT_ASSERT_EQUAL(std::string(""), url.getPath()); + } + + void testFromString_WithUserInfo() { + URL url = URL::fromString("http://user:pass@foo.bar/baz/bam"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("foo.bar"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(std::string("/baz/bam"), url.getPath()); + } + + void testFromString_NonASCIIHost() { + URL url = URL::fromString("http://www.tron%C3%A7on.be/baz/bam"); + + CPPUNIT_ASSERT_EQUAL(std::string("www.tron\xc3\xa7on.be"), url.getHost()); + } + + void testFromString_NonASCIIPath() { + URL url = URL::fromString("http://foo.bar/baz/tron%C3%A7on/bam"); + + CPPUNIT_ASSERT_EQUAL(std::string("/baz/tron\xc3\xa7on/bam"), url.getPath()); + } + + void testFromString_IPv4Address() { + URL url = URL::fromString("http://127.0.0.1/foobar"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("127.0.0.1"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(std::string("/foobar"), url.getPath()); + } + + void testFromString_IPv4AddressWithPort() { + URL url = URL::fromString("http://127.0.0.1:12345/foobar"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("127.0.0.1"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(12345), url.getPort().get_value_or(0)); + CPPUNIT_ASSERT_EQUAL(std::string("/foobar"), url.getPath()); + } + + void testFromString_IPv6Address() { + URL url = URL::fromString("http://[fdf8:f53b:82e4::53]/foobar"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("fdf8:f53b:82e4::53"), url.getHost()); + } + + void testFromString_IPv6AddressWithPort() { + URL url = URL::fromString("http://[fdf8:f53b:82e4::53]:12435/foobar"); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("fdf8:f53b:82e4::53"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(12435), url.getPort().get_value_or(0)); + } + + void test_FromString_ToString_IPv6RFC2732() { + { + const char* testVector = "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("FEDC:BA98:7654:3210:FEDC:BA98:7654:3210"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(80), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string("/index.html"), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + + { + const char* testVector = "http://[1080:0:0:0:8:800:200C:417A]/index.html"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("1080:0:0:0:8:800:200C:417A"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(2), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string("/index.html"), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + + { + const char* testVector = "http://[3ffe:2a00:100:7031::1]"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("3ffe:2a00:100:7031::1"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(2), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string(""), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + + { + const char* testVector = "http://[1080::8:800:200C:417A]/foo"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("1080::8:800:200C:417A"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(2), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string("/foo"), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + + { + const char* testVector = "http://[::192.9.5.5]/ipng"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("::192.9.5.5"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(2), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string("/ipng"), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + + { + const char* testVector = "http://[::FFFF:129.144.52.38]:80/index.html"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("::FFFF:129.144.52.38"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(80), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string("/index.html"), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + + { + const char* testVector = "http://[2010:836B:4179::836B:4179]"; + URL url = URL::fromString(testVector); + + CPPUNIT_ASSERT_EQUAL(std::string("http"), url.getScheme()); + CPPUNIT_ASSERT_EQUAL(std::string("2010:836B:4179::836B:4179"), url.getHost()); + CPPUNIT_ASSERT_EQUAL(static_cast<unsigned short>(2), url.getPort().get_value_or(2)); + CPPUNIT_ASSERT_EQUAL(std::string(), url.getPath()); + + CPPUNIT_ASSERT_EQUAL(std::string(testVector), url.toString()); + } + } + + void testToString() { + CPPUNIT_ASSERT_EQUAL(std::string("http://foo.bar/baz/bam"), URL("http", "foo.bar", "/baz/bam").toString()); + } + + void testToString_WithPort() { + CPPUNIT_ASSERT_EQUAL(std::string("http://foo.bar:1234/baz/bam"), URL("http", "foo.bar", 1234, "/baz/bam").toString()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(URLTest); diff --git a/Swiften/Base/WindowsRegistry.h b/Swiften/Base/WindowsRegistry.h index 11a26b3..6243dd2 100644 --- a/Swiften/Base/WindowsRegistry.h +++ b/Swiften/Base/WindowsRegistry.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2012 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2012 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,49 +9,49 @@ #include <windows.h> namespace Swift { - class WindowsRegistry { - public: - static bool isFIPSEnabled() { - char* pathForXP = "System\\CurrentControlSet\\Control\\Lsa"; - char* pathSinceVista = "System\\CurrentControlSet\\Control\\Lsa\\FIPSAlgorithmPolicy"; - char* keyForXP = "FIPSAlgorithmPolicy"; - char* keySinceVista = "Enabled"; - - OSVERSIONINFO osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - - char* keyForOS = osvi.dwMajorVersion < 6 ? keyForXP : keySinceVista; - char* pathForOS = osvi.dwMajorVersion < 6 ? pathForXP : pathSinceVista; - - /* http://support.microsoft.com/kb/811833 */ - /* http://msdn.microsoft.com/en-us/library/ms724911%28VS.85%29.aspx */ - HKEY key; - bool result = false; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, - pathForOS, - 0, - KEY_READ, - &key) != ERROR_SUCCESS) { - /* If we can't find the key that says we're FIPS, we're not FIPS */ - return result; - } - DWORD keyType = REG_DWORD; - DWORD data; - DWORD length = sizeof(data); - - if (RegQueryValueEx(key, - keyForOS, - NULL, - &keyType, - (LPBYTE)&data, - &length) == ERROR_SUCCESS) { - result = data != 0; - } - - RegCloseKey(key); - return result; - } - }; + class WindowsRegistry { + public: + static bool isFIPSEnabled() { + char* pathForXP = "System\\CurrentControlSet\\Control\\Lsa"; + char* pathSinceVista = "System\\CurrentControlSet\\Control\\Lsa\\FIPSAlgorithmPolicy"; + char* keyForXP = "FIPSAlgorithmPolicy"; + char* keySinceVista = "Enabled"; + + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + + char* keyForOS = osvi.dwMajorVersion < 6 ? keyForXP : keySinceVista; + char* pathForOS = osvi.dwMajorVersion < 6 ? pathForXP : pathSinceVista; + + /* http://support.microsoft.com/kb/811833 */ + /* http://msdn.microsoft.com/en-us/library/ms724911%28VS.85%29.aspx */ + HKEY key; + bool result = false; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, + pathForOS, + 0, + KEY_READ, + &key) != ERROR_SUCCESS) { + /* If we can't find the key that says we're FIPS, we're not FIPS */ + return result; + } + DWORD keyType = REG_DWORD; + DWORD data; + DWORD length = sizeof(data); + + if (RegQueryValueEx(key, + keyForOS, + NULL, + &keyType, + (LPBYTE)&data, + &length) == ERROR_SUCCESS) { + result = data != 0; + } + + RegCloseKey(key); + return result; + } + }; } diff --git a/Swiften/Base/boost_bsignals.h b/Swiften/Base/boost_bsignals.h deleted file mode 100644 index 7609c94..0000000 --- a/Swiften/Base/boost_bsignals.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -// Work around for the boost::signals / Qt signals keyword clash. -// Based on an example from Frank Hess, improved by Niels Dekker - -#pragma once - -#if defined(signals) && defined(Q_SIGNALS) && !defined(QT_MOC_CPP) -#undef signals -#define signals signals -#endif - -#include <boost/signal.hpp> - -namespace boost { - namespace bsignals = signals; -} - -#if defined(signals) && defined(Q_SIGNALS) && !defined(QT_MOC_CPP) -#undef signals -#define signals Q_SIGNALS -#endif diff --git a/Swiften/Base/foreach.h b/Swiften/Base/foreach.h deleted file mode 100644 index 3ad506d..0000000 --- a/Swiften/Base/foreach.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include <boost/foreach.hpp> - -#undef foreach -#define foreach BOOST_FOREACH -#define reverse_foreach BOOST_REVERSE_FOREACH diff --git a/Swiften/Base/format.h b/Swiften/Base/format.h index 0e49eaa..e5696b0 100644 --- a/Swiften/Base/format.h +++ b/Swiften/Base/format.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once -#include <boost/format.hpp> #include <iostream> +#include <boost/format.hpp> + namespace Swift { - inline boost::format format(const std::string& s) { - using namespace boost::io; - try { - boost::format fmter(s); - fmter.exceptions(no_error_bits); - return fmter; - } - catch (...) { - std::cerr << "Error: Invalid translation: " << s << std::endl; - throw; - } - } + inline boost::format format(const std::string& s) { + using namespace boost::io; + try { + boost::format fmter(s); + fmter.exceptions(no_error_bits); + return fmter; + } + catch (...) { + std::cerr << "Error: Invalid translation: " << s << std::endl; + throw; + } + } } diff --git a/Swiften/Base/sleep.cpp b/Swiften/Base/sleep.cpp index 0f1937b..48eae51 100644 --- a/Swiften/Base/sleep.cpp +++ b/Swiften/Base/sleep.cpp @@ -1,25 +1,18 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/Base/sleep.h> -#include <boost/thread.hpp> -#include <boost/version.hpp> +#include <chrono> +#include <thread> namespace Swift { void sleep(unsigned int msecs) { - boost::xtime xt; -#if BOOST_VERSION >= 105000 - boost::xtime_get(&xt, boost::TIME_UTC_); -#else - boost::xtime_get(&xt, boost::TIME_UTC); -#endif - xt.nsec += msecs*1000000; - boost::thread::sleep(xt); + std::this_thread::sleep_for(std::chrono::milliseconds(msecs)); } } diff --git a/Swiften/Base/sleep.h b/Swiften/Base/sleep.h index afcf6c7..744e19f 100644 --- a/Swiften/Base/sleep.h +++ b/Swiften/Base/sleep.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -9,5 +9,5 @@ #include <Swiften/Base/API.h> namespace Swift { - SWIFTEN_API void sleep(unsigned int msecs); + SWIFTEN_API void sleep(unsigned int msecs); } |