updated build system
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				BlockStorage/repertory/pipeline/head There was a failure building this commit
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	BlockStorage/repertory/pipeline/head There was a failure building this commit
				
			This commit is contained in:
		| @@ -24,6 +24,8 @@ | |||||||
|  |  | ||||||
| #include "utils/config.hpp" | #include "utils/config.hpp" | ||||||
|  |  | ||||||
|  | #include "utils/string.hpp" | ||||||
|  |  | ||||||
| namespace repertory::utils::collection { | namespace repertory::utils::collection { | ||||||
| template <typename col_t> | template <typename col_t> | ||||||
| [[nodiscard]] inline auto | [[nodiscard]] inline auto | ||||||
| @@ -94,21 +96,6 @@ inline auto remove_element(col_t &collection, | |||||||
|   return collection; |   return collection; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename col_t, typename string_t> |  | ||||||
| [[nodiscard]] inline auto to_hex_string_t(const col_t &collection) -> string_t { |  | ||||||
|   static_assert(sizeof(typename col_t::value_type) == 1U, |  | ||||||
|                 "value_type must be 1 byte in size"); |  | ||||||
|   static constexpr const auto mask = 0xFF; |  | ||||||
|  |  | ||||||
|   std::basic_stringstream<typename string_t::value_type> stream{}; |  | ||||||
|   for (auto &&val : collection) { |  | ||||||
|     stream << std::setfill('0') << std::setw(2) << std::hex |  | ||||||
|            << (static_cast<std::uint32_t>(val) & mask); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return stream.str(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename val_t> | template <typename val_t> | ||||||
| inline auto from_hex_string(std::string_view str, val_t &val) -> bool { | inline auto from_hex_string(std::string_view str, val_t &val) -> bool { | ||||||
|   return from_hex_string_t<val_t, std::string>(str, val); |   return from_hex_string_t<val_t, std::string>(str, val); | ||||||
| @@ -121,12 +108,22 @@ inline auto from_hex_string(std::wstring_view str, val_t &val) -> bool { | |||||||
|  |  | ||||||
| template <typename col_t> | template <typename col_t> | ||||||
| inline auto to_hex_string(const col_t &collection) -> std::string { | inline auto to_hex_string(const col_t &collection) -> std::string { | ||||||
|   return to_hex_string_t<col_t, std::string>(collection); |   static_assert(sizeof(typename col_t::value_type) == 1U, | ||||||
|  |                 "value_type must be 1 byte in size"); | ||||||
|  |   static constexpr const auto mask = 0xFF; | ||||||
|  |  | ||||||
|  |   std::stringstream stream{}; | ||||||
|  |   for (auto &&val : collection) { | ||||||
|  |     stream << std::setfill('0') << std::setw(2) << std::hex | ||||||
|  |            << (static_cast<std::uint32_t>(val) & mask); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return stream.str(); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename col_t> | template <typename col_t> | ||||||
| inline auto to_hex_wstring(const col_t &collection) -> std::wstring { | inline auto to_hex_wstring(const col_t &collection) -> std::wstring { | ||||||
|   return to_hex_string_t<col_t, std::wstring>(collection); |   return utils::string::from_utf8(to_hex_string<col_t>(collection)); | ||||||
| } | } | ||||||
| } // namespace repertory::utils::collection | } // namespace repertory::utils::collection | ||||||
|  |  | ||||||
|   | |||||||
| @@ -90,10 +90,6 @@ get_next_available_port(std::uint16_t first_port, | |||||||
|                         std::uint16_t &available_port) -> bool; |                         std::uint16_t &available_port) -> bool; | ||||||
| #endif // defined(PROJECT_ENABLE_BOOST) | #endif // defined(PROJECT_ENABLE_BOOST) | ||||||
|  |  | ||||||
| [[nodiscard]] auto resolve_variables(std::string str) -> std::string; |  | ||||||
|  |  | ||||||
| [[nodiscard]] auto resolve_variables(std::wstring_view str) -> std::wstring; |  | ||||||
|  |  | ||||||
| template <typename result_t, typename data_t> | template <typename result_t, typename data_t> | ||||||
| inline constexpr auto divide_with_ceiling(result_t numerator, | inline constexpr auto divide_with_ceiling(result_t numerator, | ||||||
|                                           data_t denominator) -> result_t { |                                           data_t denominator) -> result_t { | ||||||
|   | |||||||
| @@ -25,31 +25,46 @@ | |||||||
|  |  | ||||||
| #include "utils/config.hpp" | #include "utils/config.hpp" | ||||||
|  |  | ||||||
| namespace repertory::utils::encryption { | #include "utils/hash.hpp" | ||||||
| using hash_256_t = std::array<unsigned char, 32U>; |  | ||||||
| using hash_256_func_t = std::function<hash_256_t(std::string_view)>; |  | ||||||
| using key_type = std::array<unsigned char, 32U>; |  | ||||||
|  |  | ||||||
|  | namespace repertory::utils::encryption { | ||||||
| inline constexpr const std::uint32_t encryption_header_size{ | inline constexpr const std::uint32_t encryption_header_size{ | ||||||
|     crypto_aead_xchacha20poly1305_IETF_NPUBBYTES + |     crypto_aead_xchacha20poly1305_IETF_NPUBBYTES + | ||||||
|         crypto_aead_xchacha20poly1305_IETF_ABYTES, |         crypto_aead_xchacha20poly1305_IETF_ABYTES, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| [[nodiscard]] auto generate_key(std::string_view encryption_token) -> key_type; | template <typename hash_t> | ||||||
|  | [[nodiscard]] inline auto default_create_hash(std::string_view) -> hash_t; | ||||||
|  |  | ||||||
|  | template <typename hash_t> | ||||||
|  | [[nodiscard]] inline auto default_create_hash(std::wstring_view) -> hash_t; | ||||||
|  |  | ||||||
|  | template <typename hash_t> | ||||||
|  | inline auto generate_key( | ||||||
|  |     std::string_view password, | ||||||
|  |     std::optional< | ||||||
|  |         std::function<hash_t(const unsigned char *data, std::size_t size)>> | ||||||
|  |         hasher = std::nullopt) -> hash_t; | ||||||
|  |  | ||||||
|  | template <typename hash_t> | ||||||
|  | inline auto generate_key( | ||||||
|  |     std::wstring_view password, | ||||||
|  |     std::optional< | ||||||
|  |         std::function<hash_t(const unsigned char *data, std::size_t size)>> | ||||||
|  |         hasher = std::nullopt) -> hash_t; | ||||||
|  |  | ||||||
| #if defined(PROJECT_ENABLE_BOOST) | #if defined(PROJECT_ENABLE_BOOST) | ||||||
| [[nodiscard]] auto decrypt_data( | [[nodiscard]] auto decrypt_data(std::string_view password, | ||||||
|     std::string_view data, std::string_view password, |                                 std::string_view data) -> data_buffer; | ||||||
|     std::optional<hash_256_func_t> hasher = std::nullopt) -> data_buffer; |  | ||||||
|  |  | ||||||
| [[nodiscard]] auto encrypt_data( | [[nodiscard]] auto encrypt_data(std::string_view password, | ||||||
|     std::string_view data, std::string_view password, |                                 std::string_view data) -> data_buffer; | ||||||
|     std::optional<hash_256_func_t> hasher = std::nullopt) -> data_buffer; |  | ||||||
|  |  | ||||||
| template <typename result> | template <typename result, typename arr_t, std::size_t arr_size> | ||||||
| [[nodiscard]] inline auto | [[nodiscard]] inline auto decrypt_data(const std::array<arr_t, arr_size> &key, | ||||||
| decrypt_data(const key_type &key, const unsigned char *buffer, |                                        const unsigned char *buffer, | ||||||
|              std::size_t buffer_size, result &res) -> bool { |                                        std::size_t buffer_size, | ||||||
|  |                                        result &res) -> bool { | ||||||
|   if (buffer_size > encryption_header_size) { |   if (buffer_size > encryption_header_size) { | ||||||
|     const std::uint32_t size = |     const std::uint32_t size = | ||||||
|         boost::endian::native_to_big(static_cast<std::uint32_t>(buffer_size)); |         boost::endian::native_to_big(static_cast<std::uint32_t>(buffer_size)); | ||||||
| @@ -65,34 +80,43 @@ decrypt_data(const key_type &key, const unsigned char *buffer, | |||||||
|   return false; |   return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename buffer, typename result> | template <typename buffer, typename result, typename arr_t, | ||||||
| [[nodiscard]] inline auto decrypt_data(const key_type &key, const buffer &buf, |           std::size_t arr_size> | ||||||
|                                        result &res) -> bool { | [[nodiscard]] inline auto decrypt_data(const std::array<arr_t, arr_size> &key, | ||||||
|  |                                        const buffer &buf, result &res) -> bool { | ||||||
|   return decrypt_data<result>( |   return decrypt_data<result>( | ||||||
|       key, reinterpret_cast<const unsigned char *>(buf.data()), buf.size(), |       key, reinterpret_cast<const unsigned char *>(buf.data()), buf.size(), | ||||||
|       res); |       res); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename buffer, typename result> | template <typename buffer, typename result, typename hash_t = hash_256_t> | ||||||
| [[nodiscard]] inline auto decrypt_data(std::string_view encryption_token, | [[nodiscard]] inline auto decrypt_data( | ||||||
|                                        const buffer &buf, result &res) -> bool { |     std::string_view password, const buffer &buf, result &res, | ||||||
|   return decrypt_data<buffer, result>(generate_key(encryption_token), buf, res); |     std::optional< | ||||||
|  |         std::function<hash_t(const unsigned char *data, std::size_t size)>> | ||||||
|  |         hasher = std::nullopt) -> bool { | ||||||
|  |   return decrypt_data<buffer, result>(generate_key(password, hasher), buf, res); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename result> | template <typename result, typename hash_t = hash_256_t> | ||||||
| [[nodiscard]] inline auto | [[nodiscard]] inline auto decrypt_data( | ||||||
| decrypt_data(std::string_view encryption_token, const unsigned char *buffer, |     std::string_view password, const unsigned char *buffer, | ||||||
|              std::size_t buffer_size, result &res) -> bool { |     std::size_t buffer_size, result &res, | ||||||
|   return decrypt_data<result>(generate_key(encryption_token), buffer, |  | ||||||
|  |     std::optional< | ||||||
|  |         std::function<hash_t(const unsigned char *data, std::size_t size)>> | ||||||
|  |         hasher = std::nullopt) -> bool { | ||||||
|  |   return decrypt_data<result>(generate_key(password, hasher), buffer, | ||||||
|                               buffer_size, res); |                               buffer_size, res); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename result> | template <typename result, typename arr_t, std::size_t arr_size> | ||||||
| inline void | inline void | ||||||
| encrypt_data(const std::array<unsigned char, | encrypt_data(const std::array<unsigned char, | ||||||
|                               crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> &iv, |                               crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> &iv, | ||||||
|              const key_type &key, const unsigned char *buffer, |              const std::array<arr_t, arr_size> &key, | ||||||
|              std::size_t buffer_size, result &res) { |              const unsigned char *buffer, std::size_t buffer_size, | ||||||
|  |              result &res) { | ||||||
|   std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_ABYTES> mac{}; |   std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_ABYTES> mac{}; | ||||||
|  |  | ||||||
|   const std::uint32_t size = boost::endian::native_to_big( |   const std::uint32_t size = boost::endian::native_to_big( | ||||||
| @@ -113,47 +137,116 @@ encrypt_data(const std::array<unsigned char, | |||||||
|   std::memcpy(&res[iv.size()], mac.data(), mac.size()); |   std::memcpy(&res[iv.size()], mac.data(), mac.size()); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename result> | template <typename result, typename s, std::size_t t> | ||||||
| inline void encrypt_data(const key_type &key, const unsigned char *buffer, | inline void encrypt_data(const std::array<s, t> &key, | ||||||
|                          std::size_t buffer_size, result &res) { |                          const unsigned char *buffer, std::size_t buffer_size, | ||||||
|  |                          result &res) { | ||||||
|   std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> iv{}; |   std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> iv{}; | ||||||
|   randombytes_buf(iv.data(), iv.size()); |   randombytes_buf(iv.data(), iv.size()); | ||||||
|  |  | ||||||
|   encrypt_data<result>(iv, key, buffer, buffer_size, res); |   encrypt_data<result>(iv, key, buffer, buffer_size, res); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename result> | template <typename result, typename hash_t = hash_256_t> | ||||||
| inline void encrypt_data(std::string_view encryption_token, | inline void encrypt_data( | ||||||
|                          const unsigned char *buffer, std::size_t buffer_size, |     std::string_view password, const unsigned char *buffer, | ||||||
|                          result &res) { |     std::size_t buffer_size, result &res, | ||||||
|   encrypt_data<result>(generate_key(encryption_token), buffer, buffer_size, |     std::optional< | ||||||
|  |         std::function<hash_t(const unsigned char *data, std::size_t size)>> | ||||||
|  |         hasher = std::nullopt) { | ||||||
|  |   encrypt_data<result>(generate_key(password, hasher), buffer, buffer_size, | ||||||
|                        res); |                        res); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename buffer, typename result> | template <typename buffer, typename result, typename hash_t = hash_256_t> | ||||||
| inline void encrypt_data(std::string_view encryption_token, const buffer &buf, | inline void encrypt_data( | ||||||
|                          result &res) { |     std::string_view password, const buffer &buf, result &res, | ||||||
|   encrypt_data<result>(generate_key(encryption_token), |     std::optional< | ||||||
|  |         std::function<hash_t(const unsigned char *data, std::size_t size)>> | ||||||
|  |         hasher = std::nullopt) { | ||||||
|  |   encrypt_data<result>(generate_key(password, hasher), | ||||||
|                        reinterpret_cast<const unsigned char *>(buf.data()), |                        reinterpret_cast<const unsigned char *>(buf.data()), | ||||||
|                        buf.size(), res); |                        buf.size(), res); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename buffer, typename result> | template <typename buffer, typename result, typename s, std::size_t t> | ||||||
| inline void encrypt_data(const key_type &key, const buffer &buf, result &res) { | inline void encrypt_data(const std::array<s, t> &key, const buffer &buf, | ||||||
|  |                          result &res) { | ||||||
|   encrypt_data<result>(key, reinterpret_cast<const unsigned char *>(buf.data()), |   encrypt_data<result>(key, reinterpret_cast<const unsigned char *>(buf.data()), | ||||||
|                        buf.size(), res); |                        buf.size(), res); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename buffer, typename result> | template <typename buffer, typename result, typename s, std::size_t t> | ||||||
| inline void | inline void | ||||||
| encrypt_data(const std::array<unsigned char, | encrypt_data(const std::array<unsigned char, | ||||||
|                               crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> &iv, |                               crypto_aead_xchacha20poly1305_IETF_NPUBBYTES> &iv, | ||||||
|              const key_type &key, const buffer &buf, result &res) { |              const std::array<s, t> &key, const buffer &buf, result &res) { | ||||||
|   encrypt_data<result>(iv, key, |   encrypt_data<result>(iv, key, | ||||||
|                        reinterpret_cast<const unsigned char *>(buf.data()), |                        reinterpret_cast<const unsigned char *>(buf.data()), | ||||||
|                        buf.size(), res); |                        buf.size(), res); | ||||||
| } | } | ||||||
| #endif // defined(PROJECT_ENABLE_BOOST) | #endif // defined(PROJECT_ENABLE_BOOST) | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | inline auto | ||||||
|  | default_create_hash<hash_256_t>(std::string_view data) -> hash_256_t { | ||||||
|  |   return create_hash_sha256(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | inline auto | ||||||
|  | default_create_hash<hash_256_t>(std::wstring_view data) -> hash_256_t { | ||||||
|  |   return create_hash_sha256(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | inline auto | ||||||
|  | default_create_hash<hash_384_t>(std::string_view data) -> hash_384_t { | ||||||
|  |   return create_hash_blake2b_384(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | inline auto | ||||||
|  | default_create_hash<hash_384_t>(std::wstring_view data) -> hash_384_t { | ||||||
|  |   return create_hash_blake2b_384(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | inline auto | ||||||
|  | default_create_hash<hash_512_t>(std::string_view data) -> hash_512_t { | ||||||
|  |   return create_hash_sha512(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | inline auto | ||||||
|  | default_create_hash<hash_512_t>(std::wstring_view data) -> hash_512_t { | ||||||
|  |   return create_hash_sha512(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename hash_t> | ||||||
|  | inline auto generate_key( | ||||||
|  |     std::string_view password, | ||||||
|  |     std::optional< | ||||||
|  |         std::function<hash_t(const unsigned char *data, std::size_t size)>> | ||||||
|  |         hasher) -> hash_t { | ||||||
|  |   return hasher.has_value() ? (*hasher)(reinterpret_cast<const unsigned char *>( | ||||||
|  |                                             password.data()), | ||||||
|  |                                         password.size()) | ||||||
|  |                             : default_create_hash<hash_t>(password); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename hash_t> | ||||||
|  | inline auto generate_key( | ||||||
|  |     std::wstring_view password, | ||||||
|  |     std::optional< | ||||||
|  |         std::function<hash_t(const unsigned char *data, std::size_t size)>> | ||||||
|  |         hasher) -> hash_t { | ||||||
|  |   return hasher.has_value() | ||||||
|  |              ? (*hasher)( | ||||||
|  |                    reinterpret_cast<const unsigned char *>(password.data()), | ||||||
|  |                    password.size() * sizeof(std::wstring_view::value_type)) | ||||||
|  |              : default_create_hash<hash_t>(password); | ||||||
|  | } | ||||||
| } // namespace repertory::utils::encryption | } // namespace repertory::utils::encryption | ||||||
|  |  | ||||||
| #endif // defined(PROJECT_ENABLE_LIBSODIUM) | #endif // defined(PROJECT_ENABLE_LIBSODIUM) | ||||||
|   | |||||||
| @@ -74,21 +74,21 @@ public: | |||||||
|  |  | ||||||
|   [[nodiscard]] auto truncate(std::size_t size) -> bool; |   [[nodiscard]] auto truncate(std::size_t size) -> bool; | ||||||
|  |  | ||||||
| #if defined(PROJECT_ENABLE_JSON) |  | ||||||
|   [[nodiscard]] auto write(const nlohmann::json &data, |  | ||||||
|                            std::size_t *total_written = nullptr) -> bool { |  | ||||||
|     auto str_data = data.dump(); |  | ||||||
|     return write_(reinterpret_cast<const unsigned char *>(str_data.c_str()), |  | ||||||
|                   str_data.size(), 0U, total_written); |  | ||||||
|   } |  | ||||||
| #endif // defined(PROJECT_ENABLE_JSON) |  | ||||||
|  |  | ||||||
|   [[nodiscard]] auto write(const data_buffer &data, std::uint64_t offset, |   [[nodiscard]] auto write(const data_buffer &data, std::uint64_t offset, | ||||||
|                            std::size_t *total_written = nullptr) -> bool { |                            std::size_t *total_written = nullptr) -> bool { | ||||||
|     return write_(reinterpret_cast<const unsigned char *>(data.data()), |     return write_(reinterpret_cast<const unsigned char *>(data.data()), | ||||||
|                   data.size(), offset, total_written); |                   data.size(), offset, total_written); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | #if defined(PROJECT_ENABLE_JSON) | ||||||
|  |   [[nodiscard]] auto write_json(const nlohmann::json &data, | ||||||
|  |                                 std::size_t *total_written = nullptr) -> bool { | ||||||
|  |     auto str_data = data.dump(); | ||||||
|  |     return write_(reinterpret_cast<const unsigned char *>(str_data.c_str()), | ||||||
|  |                   str_data.size(), 0U, total_written); | ||||||
|  |   } | ||||||
|  | #endif // defined(PROJECT_ENABLE_JSON) | ||||||
|  |  | ||||||
|   [[nodiscard]] operator bool() const { return stream_.is_open(); } |   [[nodiscard]] operator bool() const { return stream_.is_open(); } | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   | |||||||
							
								
								
									
										255
									
								
								support/include/utils/hash.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								support/include/utils/hash.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,255 @@ | |||||||
|  | /* | ||||||
|  |   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||||
|  |  | ||||||
|  |   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |   of this software and associated documentation files (the "Software"), to deal | ||||||
|  |   in the Software without restriction, including without limitation the rights | ||||||
|  |   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |   copies of the Software, and to permit persons to whom the Software is | ||||||
|  |   furnished to do so, subject to the following conditions: | ||||||
|  |  | ||||||
|  |   The above copyright notice and this permission notice shall be included in all | ||||||
|  |   copies or substantial portions of the Software. | ||||||
|  |  | ||||||
|  |   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |   SOFTWARE. | ||||||
|  | */ | ||||||
|  | #ifndef REPERTORY_INCLUDE_UTILS_HASH_HPP_ | ||||||
|  | #define REPERTORY_INCLUDE_UTILS_HASH_HPP_ | ||||||
|  | #if defined(PROJECT_ENABLE_LIBSODIUM) | ||||||
|  |  | ||||||
|  | #include "utils/config.hpp" | ||||||
|  |  | ||||||
|  | namespace repertory::utils::encryption { | ||||||
|  | using hash_256_t = std::array<unsigned char, 32U>; | ||||||
|  | using hash_384_t = std::array<unsigned char, 48U>; | ||||||
|  | using hash_512_t = std::array<unsigned char, 64U>; | ||||||
|  |  | ||||||
|  | [[nodiscard]] auto create_hash_blake2b_256(std::string_view data) -> hash_256_t; | ||||||
|  |  | ||||||
|  | [[nodiscard]] auto | ||||||
|  | create_hash_blake2b_256(std::wstring_view data) -> hash_256_t; | ||||||
|  |  | ||||||
|  | [[nodiscard]] auto create_hash_blake2b_384(std::string_view data) -> hash_384_t; | ||||||
|  |  | ||||||
|  | [[nodiscard]] auto | ||||||
|  | create_hash_blake2b_384(std::wstring_view data) -> hash_384_t; | ||||||
|  |  | ||||||
|  | [[nodiscard]] auto create_hash_blake2b_512(std::string_view data) -> hash_512_t; | ||||||
|  |  | ||||||
|  | [[nodiscard]] auto | ||||||
|  | create_hash_blake2b_512(std::wstring_view data) -> hash_512_t; | ||||||
|  |  | ||||||
|  | template <typename char_t, typename hash_t> | ||||||
|  | [[nodiscard]] auto | ||||||
|  | create_hash_blake2b_t(std::basic_string_view<char_t> data) -> hash_t; | ||||||
|  |  | ||||||
|  | template <typename hash_t> | ||||||
|  | [[nodiscard]] auto create_hash_blake2b_t(const data_buffer &data) -> hash_t; | ||||||
|  |  | ||||||
|  | template <typename char_t, typename hash_t> | ||||||
|  | [[nodiscard]] auto create_hash_blake2b_t( | ||||||
|  |     const std::vector<std::basic_string<char_t>> &data) -> hash_t; | ||||||
|  |  | ||||||
|  | template <typename arr_t, std::size_t arr_size> | ||||||
|  | [[nodiscard]] auto | ||||||
|  | create_hash_blake2b_t(const std::vector<std::array<arr_t, arr_size>> &data) | ||||||
|  |     -> std::array<arr_t, arr_size>; | ||||||
|  |  | ||||||
|  | [[nodiscard]] auto create_hash_sha256(std::string_view data) -> hash_256_t; | ||||||
|  |  | ||||||
|  | [[nodiscard]] auto create_hash_sha256(std::wstring_view data) -> hash_256_t; | ||||||
|  |  | ||||||
|  | [[nodiscard]] auto create_hash_sha512(std::string_view data) -> hash_512_t; | ||||||
|  |  | ||||||
|  | [[nodiscard]] auto create_hash_sha512(std::wstring_view data) -> hash_512_t; | ||||||
|  |  | ||||||
|  | template <typename char_t> | ||||||
|  | [[nodiscard]] auto | ||||||
|  | create_hash_sha256_t(std::basic_string_view<char_t> data) -> hash_256_t; | ||||||
|  |  | ||||||
|  | template <typename char_t> | ||||||
|  | [[nodiscard]] auto create_hash_sha512_t(std::basic_string_view<char_t> data) | ||||||
|  |     -> repertory::utils::encryption::hash_512_t; | ||||||
|  |  | ||||||
|  | template <typename hash_t> | ||||||
|  | auto create_hash_blake2b_t(const data_buffer &data) -> hash_t { | ||||||
|  |   hash_t hash{}; | ||||||
|  |  | ||||||
|  |   crypto_generichash_blake2b_state state{}; | ||||||
|  |   auto res = crypto_generichash_blake2b_init(&state, nullptr, 0U, hash.size()); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to initialize blake2b|" + | ||||||
|  |                              std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   res = crypto_generichash_blake2b_update( | ||||||
|  |       &state, reinterpret_cast<const unsigned char *>(data.data()), | ||||||
|  |       data.size() * sizeof(data_buffer::value_type)); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to update blake2b|" + std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   res = crypto_generichash_blake2b_final(&state, hash.data(), hash.size()); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to finalize blake2b|" + | ||||||
|  |                              std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return hash; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename arr_t, std::size_t arr_size> | ||||||
|  | auto create_hash_blake2b_t(const std::vector<std::array<arr_t, arr_size>> &data) | ||||||
|  |     -> std::array<arr_t, arr_size> { | ||||||
|  |   using hash_t = std::array<arr_t, arr_size>; | ||||||
|  |   hash_t hash{}; | ||||||
|  |  | ||||||
|  |   crypto_generichash_blake2b_state state{}; | ||||||
|  |   auto res = crypto_generichash_blake2b_init(&state, nullptr, 0U, hash.size()); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to initialize blake2b|" + | ||||||
|  |                              std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   for (const auto &item : data) { | ||||||
|  |     res = crypto_generichash_blake2b_update( | ||||||
|  |         &state, reinterpret_cast<const unsigned char *>(item.data()), | ||||||
|  |         item.size()); | ||||||
|  |     if (res != 0) { | ||||||
|  |       throw std::runtime_error("failed to update blake2b|" + | ||||||
|  |                                std::to_string(res)); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   res = crypto_generichash_blake2b_final(&state, hash.data(), hash.size()); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to finalize blake2b|" + | ||||||
|  |                              std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return hash; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename char_t, typename hash_t> | ||||||
|  | auto create_hash_blake2b_t(const std::vector<std::basic_string<char_t>> &data) | ||||||
|  |     -> hash_t { | ||||||
|  |   hash_t hash{}; | ||||||
|  |  | ||||||
|  |   crypto_generichash_blake2b_state state{}; | ||||||
|  |   auto res = crypto_generichash_blake2b_init(&state, nullptr, 0U, hash.size()); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to initialize blake2b|" + | ||||||
|  |                              std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   for (const auto &item : data) { | ||||||
|  |     res = crypto_generichash_blake2b_update( | ||||||
|  |         &state, reinterpret_cast<const unsigned char *>(item.data()), | ||||||
|  |         item.size() * sizeof(char_t)); | ||||||
|  |     if (res != 0) { | ||||||
|  |       throw std::runtime_error("failed to update blake2b|" + | ||||||
|  |                                std::to_string(res)); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   res = crypto_generichash_blake2b_final(&state, hash.data(), hash.size()); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to finalize blake2b|" + | ||||||
|  |                              std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return hash; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename char_t, typename hash_t> | ||||||
|  | auto create_hash_blake2b_t(std::basic_string_view<char_t> data) -> hash_t { | ||||||
|  |   hash_t hash{}; | ||||||
|  |  | ||||||
|  |   crypto_generichash_blake2b_state state{}; | ||||||
|  |   auto res = crypto_generichash_blake2b_init(&state, nullptr, 0U, hash.size()); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to initialize blake2b|" + | ||||||
|  |                              std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   res = crypto_generichash_blake2b_update( | ||||||
|  |       &state, reinterpret_cast<const unsigned char *>(data.data()), | ||||||
|  |       data.size() * sizeof(char_t)); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to update blake2b|" + std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   res = crypto_generichash_blake2b_final(&state, hash.data(), hash.size()); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to finalize blake2b|" + | ||||||
|  |                              std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return hash; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename char_t> | ||||||
|  | auto create_hash_sha256_t(std::basic_string_view<char_t> data) | ||||||
|  |     -> repertory::utils::encryption::hash_256_t { | ||||||
|  |   repertory::utils::encryption::hash_256_t hash{}; | ||||||
|  |  | ||||||
|  |   crypto_hash_sha256_state state{}; | ||||||
|  |   auto res = crypto_hash_sha256_init(&state); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to initialize sha256|" + | ||||||
|  |                              std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   res = crypto_hash_sha256_update( | ||||||
|  |       &state, reinterpret_cast<const unsigned char *>(data.data()), | ||||||
|  |       data.size() * sizeof(char_t)); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to update sha256|" + std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   res = crypto_hash_sha256_final(&state, hash.data()); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to finalize sha256|" + | ||||||
|  |                              std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return hash; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename char_t> | ||||||
|  | auto create_hash_sha512_t(std::basic_string_view<char_t> data) | ||||||
|  |     -> repertory::utils::encryption::hash_512_t { | ||||||
|  |   repertory::utils::encryption::hash_512_t hash{}; | ||||||
|  |  | ||||||
|  |   crypto_hash_sha512_state state{}; | ||||||
|  |   auto res = crypto_hash_sha512_init(&state); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to initialize sha512|" + | ||||||
|  |                              std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   res = crypto_hash_sha512_update( | ||||||
|  |       &state, reinterpret_cast<const unsigned char *>(data.data()), | ||||||
|  |       data.size() * sizeof(char_t)); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to update sha512|" + std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   res = crypto_hash_sha512_final(&state, hash.data()); | ||||||
|  |   if (res != 0) { | ||||||
|  |     throw std::runtime_error("failed to finalize sha512|" + | ||||||
|  |                              std::to_string(res)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return hash; | ||||||
|  | } | ||||||
|  | } // namespace repertory::utils::encryption | ||||||
|  |  | ||||||
|  | #endif // defined(PROJECT_ENABLE_LIBSODIUM) | ||||||
|  | #endif // REPERTORY_INCLUDE_UTILS_HASH_HPP_ | ||||||
| @@ -86,12 +86,21 @@ auto create_uuid_wstring() -> std::wstring { | |||||||
| #if defined(PROJECT_ENABLE_LIBSODIUM) | #if defined(PROJECT_ENABLE_LIBSODIUM) | ||||||
| auto generate_random_string(std::size_t length) -> std::string { | auto generate_random_string(std::size_t length) -> std::string { | ||||||
|   std::string ret; |   std::string ret; | ||||||
|  |   if (length == 0U) { | ||||||
|  |     return ret; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   ret.resize(length); |   ret.resize(length); | ||||||
|   for (std::size_t i = 0U; i < length; i++) { |   for (auto &ch : ret) { | ||||||
|     do { |     std::array<unsigned int, 3U> random_list{ | ||||||
|       ret[i] = static_cast<char>(generate_random<std::uint8_t>() % 74 + 48); |         generate_random_between(0U, 57U), | ||||||
|     } while (((ret.at(i) >= 91) && (ret.at(i) <= 96)) || |         generate_random_between(65U, 90U), | ||||||
|              ((ret.at(i) >= 58) && (ret.at(i) <= 64))); |         generate_random_between(97U, 255U), | ||||||
|  |     }; | ||||||
|  |     ch = static_cast<char>( | ||||||
|  |         random_list.at(repertory::utils::generate_random_between(0U, 2U)) % | ||||||
|  |             74U + | ||||||
|  |         48U); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   return ret; |   return ret; | ||||||
| @@ -118,6 +127,10 @@ auto get_environment_variable(std::wstring_view variable) -> std::wstring { | |||||||
| #if defined(PROJECT_ENABLE_BOOST) | #if defined(PROJECT_ENABLE_BOOST) | ||||||
| auto get_next_available_port(std::uint16_t first_port, | auto get_next_available_port(std::uint16_t first_port, | ||||||
|                              std::uint16_t &available_port) -> bool { |                              std::uint16_t &available_port) -> bool { | ||||||
|  |   if (first_port == 0U) { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   using namespace boost::asio; |   using namespace boost::asio; | ||||||
|   using ip::tcp; |   using ip::tcp; | ||||||
|  |  | ||||||
| @@ -141,13 +154,4 @@ auto get_next_available_port(std::uint16_t first_port, | |||||||
|   return not error_code; |   return not error_code; | ||||||
| } | } | ||||||
| #endif // defined(PROJECT_ENABLE_BOOST) | #endif // defined(PROJECT_ENABLE_BOOST) | ||||||
|  |  | ||||||
| auto resolve_variables(std::string str) -> std::string { |  | ||||||
|   return utils::path::absolute(str); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| auto resolve_variables(std::wstring_view str) -> std::wstring { |  | ||||||
|   return utils::string::from_utf8( |  | ||||||
|       resolve_variables(utils::string::to_utf8(str))); |  | ||||||
| } |  | ||||||
| } // namespace repertory::utils | } // namespace repertory::utils | ||||||
|   | |||||||
| @@ -22,33 +22,11 @@ | |||||||
| #include "utils/encryption.hpp" | #include "utils/encryption.hpp" | ||||||
|  |  | ||||||
| #if defined(PROJECT_ENABLE_LIBSODIUM) | #if defined(PROJECT_ENABLE_LIBSODIUM) | ||||||
| namespace { |  | ||||||
| using nonce_t = |  | ||||||
|     std::array<unsigned char, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES>; |  | ||||||
|  |  | ||||||
| static constexpr const auto nonce_size{sizeof(nonce_t)}; |  | ||||||
|  |  | ||||||
| [[nodiscard]] static auto create_hash_256(std::string_view data) |  | ||||||
|     -> repertory::utils::encryption::hash_256_t { |  | ||||||
|   repertory::utils::encryption::hash_256_t hash{}; |  | ||||||
|  |  | ||||||
|   crypto_generichash_blake2b_state state{}; |  | ||||||
|   crypto_generichash_blake2b_init(&state, nullptr, 0U, hash.size()); |  | ||||||
|   crypto_generichash_blake2b_update( |  | ||||||
|       &state, reinterpret_cast<const unsigned char *>(data.data()), |  | ||||||
|       data.size()); |  | ||||||
|   crypto_generichash_blake2b_final(&state, hash.data(), hash.size()); |  | ||||||
|  |  | ||||||
|   return hash; |  | ||||||
| } |  | ||||||
| } // namespace |  | ||||||
|  |  | ||||||
| namespace repertory::utils::encryption { | namespace repertory::utils::encryption { | ||||||
| #if defined(PROJECT_ENABLE_BOOST) | #if defined(PROJECT_ENABLE_BOOST) | ||||||
| auto decrypt_data(std::string_view data, std::string_view password, | auto decrypt_data(std::string_view password, | ||||||
|                   std::optional<hash_256_func_t> hasher) -> data_buffer { |                   std::string_view data) -> data_buffer { | ||||||
|   auto key = |   auto key = generate_key<hash_256_t>(password); | ||||||
|       hasher.has_value() ? (*hasher)(password) : create_hash_256(password); |  | ||||||
|  |  | ||||||
|   data_buffer buf{}; |   data_buffer buf{}; | ||||||
|   if (not decrypt_data(key, |   if (not decrypt_data(key, | ||||||
| @@ -60,10 +38,9 @@ auto decrypt_data(std::string_view data, std::string_view password, | |||||||
|   return buf; |   return buf; | ||||||
| } | } | ||||||
|  |  | ||||||
| auto encrypt_data(std::string_view data, std::string_view password, | auto encrypt_data(std::string_view password, | ||||||
|                   std::optional<hash_256_func_t> hasher) -> data_buffer { |                   std::string_view data) -> data_buffer { | ||||||
|   auto key = |   auto key = generate_key<hash_256_t>(password); | ||||||
|       hasher.has_value() ? (*hasher)(password) : create_hash_256(password); |  | ||||||
|  |  | ||||||
|   data_buffer buf{}; |   data_buffer buf{}; | ||||||
|   encrypt_data(key, reinterpret_cast<const unsigned char *>(data.data()), |   encrypt_data(key, reinterpret_cast<const unsigned char *>(data.data()), | ||||||
| @@ -72,30 +49,6 @@ auto encrypt_data(std::string_view data, std::string_view password, | |||||||
|   return buf; |   return buf; | ||||||
| } | } | ||||||
| #endif // defined(PROJECT_ENABLE_BOOST) | #endif // defined(PROJECT_ENABLE_BOOST) | ||||||
|  |  | ||||||
| auto generate_key(std::string_view encryption_token) -> key_type { |  | ||||||
|   crypto_hash_sha256_state state{}; |  | ||||||
|   auto res = crypto_hash_sha256_init(&state); |  | ||||||
|   if (res != 0) { |  | ||||||
|     throw std::runtime_error("failed to initialize sha256|" + |  | ||||||
|                              std::to_string(res)); |  | ||||||
|   } |  | ||||||
|   res = crypto_hash_sha256_update( |  | ||||||
|       &state, reinterpret_cast<const unsigned char *>(encryption_token.data()), |  | ||||||
|       encryption_token.size()); |  | ||||||
|   if (res != 0) { |  | ||||||
|     throw std::runtime_error("failed to update sha256|" + std::to_string(res)); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   key_type ret{}; |  | ||||||
|   res = crypto_hash_sha256_final(&state, ret.data()); |  | ||||||
|   if (res != 0) { |  | ||||||
|     throw std::runtime_error("failed to finalize sha256|" + |  | ||||||
|                              std::to_string(res)); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return ret; |  | ||||||
| } |  | ||||||
| } // namespace repertory::utils::encryption | } // namespace repertory::utils::encryption | ||||||
|  |  | ||||||
| #endif // defined(PROJECT_ENABLE_LIBSODIUM) | #endif // defined(PROJECT_ENABLE_LIBSODIUM) | ||||||
|   | |||||||
| @@ -276,7 +276,7 @@ auto read_json_file(std::string_view path, nlohmann::json &data) -> bool { | |||||||
| #if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) | #if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) | ||||||
|       if (password.has_value()) { |       if (password.has_value()) { | ||||||
|         auto decrypted_data = |         auto decrypted_data = | ||||||
|             utils::encryption::decrypt_data(json_text, *password); |             utils::encryption::decrypt_data(*password, json_text); | ||||||
|         json_text = {decrypted_data.begin(), decrypted_data.end()}; |         json_text = {decrypted_data.begin(), decrypted_data.end()}; | ||||||
|       } |       } | ||||||
| #endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) | #endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) | ||||||
| @@ -322,7 +322,7 @@ auto write_json_file(std::string_view path, | |||||||
|  |  | ||||||
| #if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) | #if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) | ||||||
|     if (password.has_value()) { |     if (password.has_value()) { | ||||||
|       return file.write(utils::encryption::encrypt_data(data.dump(), *password), |       return file.write(utils::encryption::encrypt_data(*password, data.dump()), | ||||||
|                         0U); |                         0U); | ||||||
|     } |     } | ||||||
| #endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) | #endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) | ||||||
|   | |||||||
							
								
								
									
										70
									
								
								support/src/utils/hash.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								support/src/utils/hash.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | /* | ||||||
|  |   Copyright <2018-2024> <scott.e.graves@protonmail.com> | ||||||
|  |  | ||||||
|  |   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |   of this software and associated documentation files (the "Software"), to deal | ||||||
|  |   in the Software without restriction, including without limitation the rights | ||||||
|  |   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |   copies of the Software, and to permit persons to whom the Software is | ||||||
|  |   furnished to do so, subject to the following conditions: | ||||||
|  |  | ||||||
|  |   The above copyright notice and this permission notice shall be included in all | ||||||
|  |   copies or substantial portions of the Software. | ||||||
|  |  | ||||||
|  |   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |   SOFTWARE. | ||||||
|  | */ | ||||||
|  | #include "utils/hash.hpp" | ||||||
|  |  | ||||||
|  | #if defined(PROJECT_ENABLE_LIBSODIUM) | ||||||
|  |  | ||||||
|  | namespace {} // namespace | ||||||
|  |  | ||||||
|  | namespace repertory::utils::encryption { | ||||||
|  | auto create_hash_blake2b_256(std::string_view data) -> hash_256_t { | ||||||
|  |   return create_hash_blake2b_t<char, hash_256_t>(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | auto create_hash_blake2b_256(std::wstring_view data) -> hash_256_t { | ||||||
|  |   return create_hash_blake2b_t<wchar_t, hash_256_t>(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | auto create_hash_blake2b_384(std::string_view data) -> hash_384_t { | ||||||
|  |   return create_hash_blake2b_t<char, hash_384_t>(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | auto create_hash_blake2b_384(std::wstring_view data) -> hash_384_t { | ||||||
|  |   return create_hash_blake2b_t<wchar_t, hash_384_t>(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | auto create_hash_blake2b_512(std::string_view data) -> hash_512_t { | ||||||
|  |   return create_hash_blake2b_t<char, hash_512_t>(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | auto create_hash_blake2b_512(std::wstring_view data) -> hash_512_t { | ||||||
|  |   return create_hash_blake2b_t<wchar_t, hash_512_t>(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | auto create_hash_sha256(std::string_view data) -> hash_256_t { | ||||||
|  |   return create_hash_sha256_t<char>(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | auto create_hash_sha256(std::wstring_view data) -> hash_256_t { | ||||||
|  |   return create_hash_sha256_t<wchar_t>(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | auto create_hash_sha512(std::string_view data) -> hash_512_t { | ||||||
|  |   return create_hash_sha512_t<char>(data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | auto create_hash_sha512(std::wstring_view data) -> hash_512_t { | ||||||
|  |   return create_hash_sha512_t<wchar_t>(data); | ||||||
|  | } | ||||||
|  | } // namespace repertory::utils::encryption | ||||||
|  |  | ||||||
|  | #endif // defined(PROJECT_ENABLE_LIBSODIUM) | ||||||
| @@ -20,10 +20,12 @@ | |||||||
|   SOFTWARE. |   SOFTWARE. | ||||||
| */ | */ | ||||||
| #include "gtest/gtest.h" | #include "gtest/gtest.h" | ||||||
| #include <utils/collection.hpp> |  | ||||||
|  |  | ||||||
| #include "utils/common.hpp" | #include "utils/common.hpp" | ||||||
|  |  | ||||||
|  | #include "utils/collection.hpp" | ||||||
|  | #include "utils/string.hpp" | ||||||
|  |  | ||||||
| namespace repertory { | namespace repertory { | ||||||
| TEST(utils_common, calculate_read_size) { | TEST(utils_common, calculate_read_size) { | ||||||
|   auto read_size = utils::calculate_read_size(0U, 0U, 0U); |   auto read_size = utils::calculate_read_size(0U, 0U, 0U); | ||||||
| @@ -240,4 +242,72 @@ TEST(utils_common, generate_random_between_throws_error_on_invalid_range) { | |||||||
|       }, |       }, | ||||||
|       std::range_error); |       std::range_error); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #if defined(PROJECT_ENABLE_LIBSODIUM) | ||||||
|  | TEST(utils_common, generate_random_string) { | ||||||
|  |   static constexpr const auto max_iterations{10000L}; | ||||||
|  |  | ||||||
|  |   const auto test_string = [](auto str) { | ||||||
|  |     static std::vector<decltype(str)> list{}; | ||||||
|  |  | ||||||
|  |     EXPECT_FALSE(utils::collection::includes(list, str)); | ||||||
|  |     list.push_back(str); | ||||||
|  |  | ||||||
|  |     EXPECT_EQ(16U, str.size()); | ||||||
|  |     for (auto &&ch : str) { | ||||||
|  |       auto ch_int = static_cast<std::uint32_t>(ch); | ||||||
|  |       EXPECT_GE(ch_int, 48U); | ||||||
|  |       EXPECT_LE(ch_int, 73U + 48U); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   for (std::size_t idx = 0U; idx < max_iterations; ++idx) { | ||||||
|  |     test_string(utils::generate_random_string(16U)); | ||||||
|  |     test_string(utils::generate_random_wstring(16U)); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST(utils_common, generate_random_string_for_zero_length) { | ||||||
|  |   EXPECT_TRUE(utils::generate_random_string(0U).empty()); | ||||||
|  |   EXPECT_TRUE(utils::generate_random_wstring(0U).empty()); | ||||||
|  | } | ||||||
|  | #endif // defined(PROJECT_ENABLE_LIBSODIUM) | ||||||
|  |  | ||||||
|  | TEST(utils_common, get_environment_variable) { | ||||||
|  |   static constexpr const std::string path_env{"PATH"}; | ||||||
|  |   std::string path; | ||||||
|  |  | ||||||
|  | #if defined(_WIN32) | ||||||
|  |   path.resize(MAX_PATH + 1U); | ||||||
|  |   auto size = ::GetEnvironmentVariableA(path_env.c_str(), path.data(), 0U); | ||||||
|  |  | ||||||
|  |   path.resize(size); | ||||||
|  |   ::GetEnvironmentVariableA(path_env.c_str(), path.data(), | ||||||
|  |                             static_cast<DWORD>(path.size())); | ||||||
|  | #else  // !defined(_WIN32) | ||||||
|  |   path = std::getenv(path_env.c_str()); | ||||||
|  | #endif // defined(_WIN32) | ||||||
|  |  | ||||||
|  |   EXPECT_STREQ(path.c_str(), utils::get_environment_variable(path_env).c_str()); | ||||||
|  |   EXPECT_STREQ( | ||||||
|  |       utils::string::from_utf8(path).c_str(), | ||||||
|  |       utils::get_environment_variable(utils::string::from_utf8(path_env)) | ||||||
|  |           .c_str()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #if defined(PROJECT_ENABLE_BOOST) | ||||||
|  | TEST(utils_common, get_next_available_port) { | ||||||
|  |   std::uint16_t available_port{}; | ||||||
|  |   for (std::uint16_t port = 1U; port < 65535; ++port) { | ||||||
|  |     EXPECT_TRUE(utils::get_next_available_port(port, available_port)); | ||||||
|  |     EXPECT_GE(available_port, port); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST(utils_common, get_next_available_port_fails_if_starting_point_is_zero) { | ||||||
|  |   std::uint16_t available_port{}; | ||||||
|  |   EXPECT_FALSE(utils::get_next_available_port(0U, available_port)); | ||||||
|  |   EXPECT_EQ(0U, available_port); | ||||||
|  | } | ||||||
|  | #endif // defined(PROJECT_ENABLE_BOOST) | ||||||
| } // namespace repertory | } // namespace repertory | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ | |||||||
|  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  SOFTWARE. |  SOFTWARE. | ||||||
| */ | */ | ||||||
| #if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) | #if defined(PROJECT_ENABLE_LIBSODIUM) | ||||||
|  |  | ||||||
| #include "gtest/gtest.h" | #include "gtest/gtest.h" | ||||||
|  |  | ||||||
| @@ -27,8 +27,117 @@ | |||||||
| #include "utils/encryption.hpp" | #include "utils/encryption.hpp" | ||||||
|  |  | ||||||
| namespace repertory { | namespace repertory { | ||||||
|  | static const std::string token{"moose"}; | ||||||
|  | static const std::wstring token_w{L"moose"}; | ||||||
|  |  | ||||||
|  | TEST(utils_encryption, generate_key) { | ||||||
|  |   auto key1 = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>(token); | ||||||
|  |   EXPECT_STREQ( | ||||||
|  |       "182072537ada59e4d6b18034a80302ebae935f66adbdf0f271d3d36309c2d481", | ||||||
|  |       utils::collection::to_hex_string(key1).c_str()); | ||||||
|  |  | ||||||
|  |   auto key2 = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>("moose"); | ||||||
|  |   auto key3 = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>("moose"); | ||||||
|  |   EXPECT_EQ(key2, key3); | ||||||
|  |  | ||||||
|  |   auto key4 = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>("moose2"); | ||||||
|  |   EXPECT_NE(key2, key4); | ||||||
|  |  | ||||||
|  |   auto key1_w = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>(token_w); | ||||||
|  |   EXPECT_NE(key1, key1_w); | ||||||
|  |   EXPECT_STREQ( | ||||||
|  |       L"590ac70125bec4501172937f6a2cbdeb22a87b5e40d5595eccd06b2b20548d8f", | ||||||
|  |       utils::collection::to_hex_wstring(key1_w).c_str()); | ||||||
|  |  | ||||||
|  |   auto key2_w = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>(L"moose"); | ||||||
|  |   auto key3_w = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>(L"moose"); | ||||||
|  |   EXPECT_EQ(key2_w, key3_w); | ||||||
|  |   EXPECT_NE(key2_w, key2); | ||||||
|  |   EXPECT_NE(key3_w, key3); | ||||||
|  |  | ||||||
|  |   auto key4_w = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>(L"moose2"); | ||||||
|  |   EXPECT_NE(key2_w, key4_w); | ||||||
|  |   EXPECT_NE(key4_w, key4); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST(utils_encryption, generate_key_default_hasher_is_sha256) { | ||||||
|  |   auto key1 = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>(token); | ||||||
|  |   auto key2 = utils::encryption::generate_key<utils::encryption::hash_256_t>( | ||||||
|  |       token, [](auto &&data, auto &&size) -> auto { | ||||||
|  |         return utils::encryption::create_hash_sha256( | ||||||
|  |             std::string_view(reinterpret_cast<const char *>(data), size)); | ||||||
|  |       }); | ||||||
|  |   EXPECT_EQ(key1, key2); | ||||||
|  |  | ||||||
|  |   auto key1_w = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>(token_w); | ||||||
|  |   auto key2_w = utils::encryption::generate_key<utils::encryption::hash_256_t>( | ||||||
|  |       token_w, [](auto &&data, auto &&size) -> auto { | ||||||
|  |         return utils::encryption::create_hash_sha256(std::wstring_view( | ||||||
|  |             reinterpret_cast<const wchar_t *>(data), size / sizeof(wchar_t))); | ||||||
|  |       }); | ||||||
|  |   EXPECT_EQ(key1_w, key2_w); | ||||||
|  |  | ||||||
|  |   EXPECT_NE(key1_w, key1); | ||||||
|  |   EXPECT_NE(key2_w, key2); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST(utils_encryption, generate_key_with_hasher) { | ||||||
|  |   auto key1 = utils::encryption::generate_key<utils::encryption::hash_256_t>( | ||||||
|  |       token, [](auto &&data, auto &&size) -> auto { | ||||||
|  |         return utils::encryption::create_hash_sha256( | ||||||
|  |             std::string_view(reinterpret_cast<const char *>(data), size)); | ||||||
|  |       }); | ||||||
|  |   EXPECT_STREQ( | ||||||
|  |       "182072537ada59e4d6b18034a80302ebae935f66adbdf0f271d3d36309c2d481", | ||||||
|  |       utils::collection::to_hex_string(key1).c_str()); | ||||||
|  |  | ||||||
|  |   auto key2 = utils::encryption::generate_key<utils::encryption::hash_256_t>( | ||||||
|  |       token, [](auto &&data, auto &&size) -> auto { | ||||||
|  |         return utils::encryption::create_hash_blake2b_256( | ||||||
|  |             std::string_view(reinterpret_cast<const char *>(data), size)); | ||||||
|  |       }); | ||||||
|  |   EXPECT_NE(key1, key2); | ||||||
|  |  | ||||||
|  |   EXPECT_STREQ( | ||||||
|  |       "ab4a0b004e824962913f7c0f79582b6ec7a3b8726426ca61d1a0a28ce5049e96", | ||||||
|  |       utils::collection::to_hex_string(key2).c_str()); | ||||||
|  |  | ||||||
|  |   auto key1_w = utils::encryption::generate_key<utils::encryption::hash_256_t>( | ||||||
|  |       token_w, [](auto &&data, auto &&size) -> auto { | ||||||
|  |         return utils::encryption::create_hash_sha256(std::wstring_view( | ||||||
|  |             reinterpret_cast<const wchar_t *>(data), size / sizeof(wchar_t))); | ||||||
|  |       }); | ||||||
|  |   EXPECT_STREQ( | ||||||
|  |       L"590ac70125bec4501172937f6a2cbdeb22a87b5e40d5595eccd06b2b20548d8f", | ||||||
|  |       utils::collection::to_hex_wstring(key1_w).c_str()); | ||||||
|  |  | ||||||
|  |   auto key2_w = utils::encryption::generate_key<utils::encryption::hash_256_t>( | ||||||
|  |       token_w, [](auto &&data, auto &&size) -> auto { | ||||||
|  |         return utils::encryption::create_hash_blake2b_256(std::wstring_view( | ||||||
|  |             reinterpret_cast<const wchar_t *>(data), size / sizeof(wchar_t))); | ||||||
|  |       }); | ||||||
|  |   EXPECT_NE(key1_w, key2_w); | ||||||
|  |  | ||||||
|  |   EXPECT_STREQ( | ||||||
|  |       L"0392d95ed3eee9772fbb9af68fedf829a8eb0adbe8575d9691cc9a752196766a", | ||||||
|  |       utils::collection::to_hex_wstring(key2_w).c_str()); | ||||||
|  |  | ||||||
|  |   EXPECT_NE(key1_w, key1); | ||||||
|  |   EXPECT_NE(key2_w, key2); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #if defined(PROJECT_ENABLE_BOOST) | ||||||
| static const std::string buffer = "cow moose dog chicken"; | static const std::string buffer = "cow moose dog chicken"; | ||||||
| static const std::string token = "moose"; |  | ||||||
|  |  | ||||||
| static void test_encrypted_result(const data_buffer &result) { | static void test_encrypted_result(const data_buffer &result) { | ||||||
|   EXPECT_EQ(buffer.size() + utils::encryption::encryption_header_size, |   EXPECT_EQ(buffer.size() + utils::encryption::encryption_header_size, | ||||||
| @@ -39,14 +148,6 @@ static void test_encrypted_result(const data_buffer &result) { | |||||||
|   EXPECT_STREQ(buffer.c_str(), data.c_str()); |   EXPECT_STREQ(buffer.c_str(), data.c_str()); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(utils_encryption, generate_key) { |  | ||||||
|   const auto key = utils::encryption::generate_key(token); |  | ||||||
|   const auto str = utils::collection::to_hex_string(key); |  | ||||||
|   EXPECT_STREQ( |  | ||||||
|       "182072537ada59e4d6b18034a80302ebae935f66adbdf0f271d3d36309c2d481", |  | ||||||
|       str.c_str()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| TEST(utils_encryption, encrypt_data_buffer) { | TEST(utils_encryption, encrypt_data_buffer) { | ||||||
|   data_buffer result; |   data_buffer result; | ||||||
|   utils::encryption::encrypt_data(token, buffer, result); |   utils::encryption::encrypt_data(token, buffer, result); | ||||||
| @@ -54,7 +155,8 @@ TEST(utils_encryption, encrypt_data_buffer) { | |||||||
| } | } | ||||||
|  |  | ||||||
| TEST(utils_encryption, encrypt_data_buffer_with_key) { | TEST(utils_encryption, encrypt_data_buffer_with_key) { | ||||||
|   const auto key = utils::encryption::generate_key(token); |   const auto key = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>(token); | ||||||
|   data_buffer result; |   data_buffer result; | ||||||
|   utils::encryption::encrypt_data(key, buffer, result); |   utils::encryption::encrypt_data(key, buffer, result); | ||||||
|   test_encrypted_result(result); |   test_encrypted_result(result); | ||||||
| @@ -69,7 +171,8 @@ TEST(utils_encryption, encrypt_data_pointer) { | |||||||
| } | } | ||||||
|  |  | ||||||
| TEST(utils_encryption, encrypt_data_pointer_with_key) { | TEST(utils_encryption, encrypt_data_pointer_with_key) { | ||||||
|   const auto key = utils::encryption::generate_key(token); |   const auto key = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>(token); | ||||||
|   data_buffer result; |   data_buffer result; | ||||||
|   utils::encryption::encrypt_data( |   utils::encryption::encrypt_data( | ||||||
|       key, reinterpret_cast<const unsigned char *>(buffer.data()), |       key, reinterpret_cast<const unsigned char *>(buffer.data()), | ||||||
| @@ -78,7 +181,8 @@ TEST(utils_encryption, encrypt_data_pointer_with_key) { | |||||||
| } | } | ||||||
|  |  | ||||||
| TEST(utils_encryption, decrypt_data_pointer) { | TEST(utils_encryption, decrypt_data_pointer) { | ||||||
|   const auto key = utils::encryption::generate_key(token); |   const auto key = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>(token); | ||||||
|   data_buffer result; |   data_buffer result; | ||||||
|   utils::encryption::encrypt_data( |   utils::encryption::encrypt_data( | ||||||
|       key, reinterpret_cast<const unsigned char *>(buffer.data()), |       key, reinterpret_cast<const unsigned char *>(buffer.data()), | ||||||
| @@ -93,7 +197,8 @@ TEST(utils_encryption, decrypt_data_pointer) { | |||||||
| } | } | ||||||
|  |  | ||||||
| TEST(utils_encryption, decrypt_data_buffer_with_key) { | TEST(utils_encryption, decrypt_data_buffer_with_key) { | ||||||
|   const auto key = utils::encryption::generate_key(token); |   const auto key = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>(token); | ||||||
|   data_buffer result; |   data_buffer result; | ||||||
|   utils::encryption::encrypt_data( |   utils::encryption::encrypt_data( | ||||||
|       key, reinterpret_cast<const unsigned char *>(buffer.data()), |       key, reinterpret_cast<const unsigned char *>(buffer.data()), | ||||||
| @@ -107,7 +212,8 @@ TEST(utils_encryption, decrypt_data_buffer_with_key) { | |||||||
| } | } | ||||||
|  |  | ||||||
| TEST(utils_encryption, decrypt_data_pointer_with_key) { | TEST(utils_encryption, decrypt_data_pointer_with_key) { | ||||||
|   const auto key = utils::encryption::generate_key(token); |   const auto key = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>(token); | ||||||
|   data_buffer result; |   data_buffer result; | ||||||
|   utils::encryption::encrypt_data( |   utils::encryption::encrypt_data( | ||||||
|       key, reinterpret_cast<const unsigned char *>(buffer.data()), |       key, reinterpret_cast<const unsigned char *>(buffer.data()), | ||||||
| @@ -122,7 +228,8 @@ TEST(utils_encryption, decrypt_data_pointer_with_key) { | |||||||
| } | } | ||||||
|  |  | ||||||
| TEST(utils_encryption, decryption_failure) { | TEST(utils_encryption, decryption_failure) { | ||||||
|   const auto key = utils::encryption::generate_key(token); |   const auto key = | ||||||
|  |       utils::encryption::generate_key<utils::encryption::hash_256_t>(token); | ||||||
|   data_buffer result; |   data_buffer result; | ||||||
|   utils::encryption::encrypt_data( |   utils::encryption::encrypt_data( | ||||||
|       key, reinterpret_cast<const unsigned char *>(buffer.data()), |       key, reinterpret_cast<const unsigned char *>(buffer.data()), | ||||||
| @@ -134,6 +241,7 @@ TEST(utils_encryption, decryption_failure) { | |||||||
|   std::string data; |   std::string data; | ||||||
|   EXPECT_FALSE(utils::encryption::decrypt_data(key, result, data)); |   EXPECT_FALSE(utils::encryption::decrypt_data(key, result, data)); | ||||||
| } | } | ||||||
|  | #endif // defined(PROJECT_ENABLE_BOOST) | ||||||
| } // namespace repertory | } // namespace repertory | ||||||
|  |  | ||||||
| #endif // defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST) | #endif // defined(PROJECT_ENABLE_LIBSODIUM) | ||||||
|   | |||||||
| @@ -304,4 +304,31 @@ TEST(utils_path, absolute) { | |||||||
|  |  | ||||||
|   // path = utils::path::absolute("~/.local"); |   // path = utils::path::absolute("~/.local"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | TEST(utils_path, absolute_can_resolve_path_variables) { | ||||||
|  |   std::string home{}; | ||||||
|  |  | ||||||
|  | #if defined(_WIN32) | ||||||
|  |   home.resize(MAX_PATH + 1U); | ||||||
|  |   auto size = ::GetEnvironmentVariableA("USERPROFILE", home.data(), 0U); | ||||||
|  |  | ||||||
|  |   home.resize(size); | ||||||
|  |   ::GetEnvironmentVariableA("USERPROFILE", home.data(), | ||||||
|  |                             static_cast<DWORD>(home.size())); | ||||||
|  |   home = utils::path::absolute(home); | ||||||
|  |  | ||||||
|  |   auto expanded_str = utils::path::absolute("%USERPROFILE%"); | ||||||
|  |   EXPECT_STREQ(home.c_str(), expanded_str.c_str()); | ||||||
|  |  | ||||||
|  |   expanded_str = utils::path::absolute("~"); | ||||||
|  |   EXPECT_STREQ(home.c_str(), expanded_str.c_str()); | ||||||
|  |   EXPECT_STREQ((home + home).c_str(), expanded_str.c_str()); | ||||||
|  | #else  // !defined(_WIN32) | ||||||
|  |   home = std::getenv("HOME"); | ||||||
|  |   home = utils::path::absolute(home); | ||||||
|  |  | ||||||
|  |   auto expanded_str = utils::path::absolute("~"); | ||||||
|  |   EXPECT_STREQ(home.c_str(), expanded_str.c_str()); | ||||||
|  | #endif // defined(_WIN32) | ||||||
|  | } | ||||||
| } // namespace repertory | } // namespace repertory | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user