diff --git a/lib/remote/base64.cpp b/lib/remote/base64.cpp index d487cb2d3..f818b8bb7 100644 --- a/lib/remote/base64.cpp +++ b/lib/remote/base64.cpp @@ -18,44 +18,50 @@ ******************************************************************************/ #include "remote/base64.hpp" -#include -#include -#include -#include -#include +#include +#include +#include #include using namespace icinga; -const String base64_padding[] = {"", "==", "="}; - -String Base64::Encode(const String& data) +String Base64::Encode(const String& input) { - typedef boost::archive::iterators::base64_from_binary > base64_encode; + BIO *biomem = BIO_new(BIO_s_mem()); + BIO *bio64 = BIO_new(BIO_f_base64()); + BIO_push(bio64, biomem); + BIO_set_flags(bio64, BIO_FLAGS_BASE64_NO_NL); + BIO_write(bio64, input.CStr(), input.GetLength()); + BIO_flush(bio64); - std::ostringstream msgbuf; - std::copy(base64_encode(data.CStr()), base64_encode(data.CStr() + data.GetLength()), std::ostream_iterator(msgbuf)); - msgbuf << base64_padding[data.GetLength() % 3]; - return msgbuf.str(); + char *outbuf; + long len = BIO_get_mem_data(biomem, &outbuf); + + String ret = String(outbuf, outbuf + len); + BIO_free_all(bio64); + + return ret; } -String Base64::Decode(const String& data) +String Base64::Decode(const String& input) { - typedef boost::archive::iterators::transform_width, 8, 6> base64_decode; + BIO *biomem = BIO_new_mem_buf( + const_cast(input.CStr()), input.GetLength()); + BIO *bio64 = BIO_new(BIO_f_base64()); + BIO_push(bio64, biomem); + BIO_set_flags(bio64, BIO_FLAGS_BASE64_NO_NL); - String::SizeType size = data.GetLength(); + char *outbuf = new char[input.GetLength()]; + + size_t rc, len = 0; + while (rc = BIO_read(bio64, outbuf + len, input.GetLength() - len)) + len += rc; - if (size && data[size - 1] == '=') { - --size; + String ret = String(outbuf, outbuf + len); + BIO_free_all(bio64); + + if (ret.IsEmpty() && !input.IsEmpty()) + throw std::invalid_argument("Not a valid base64 string"); - if (size && data[size - 1] == '=') - --size; - } - - if (size == 0) - return String(); - - std::ostringstream msgbuf; - std::copy(base64_decode(data.CStr()), base64_decode(data.CStr() + size), std::ostream_iterator(msgbuf)); - return msgbuf.str(); + return ret; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 37c17093a..3757274a1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -24,7 +24,7 @@ set(base_test_SOURCES base-stream.cpp base-string.cpp base-timer.cpp base-type.cpp base-value.cpp config-ops.cpp icinga-macros.cpp icinga-perfdata.cpp test.cpp - remote-url.cpp + remote-base64.cpp remote-url.cpp ) set(livestatus_test_SOURCES @@ -107,6 +107,7 @@ add_boost_test(base icinga_perfdata/ignore_invalid_warn_crit_min_max icinga_perfdata/invalid icinga_perfdata/multi + remote_base64/base64 remote_url/id_and_path remote_url/parameters remote_url/get_and_set diff --git a/test/remote-base64.cpp b/test/remote-base64.cpp new file mode 100644 index 000000000..573d533e1 --- /dev/null +++ b/test/remote-base64.cpp @@ -0,0 +1,66 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#include "remote/base64.hpp" +#include +#include + +#include + +using namespace icinga; + +BOOST_AUTO_TEST_SUITE(remote_base64) + +BOOST_AUTO_TEST_CASE(base64) +{ + std::vector clearText; + clearText.push_back(""); + clearText.push_back("1"); + clearText.push_back("12"); + clearText.push_back("123"); + clearText.push_back("1234"); + clearText.push_back( + "VsowLvPqEiAeITDmo-5L_NB-k7fsT3sT2d3K9O4iC2uBk41hvCPAxrgGSxrdeX5s" + "Zo0Z9b1kxDZlzf8GHQ9ARW6YLeGODMtiZo8cKkUzfSbxyZ_wlE9u6pCTTg9kODCM" + "Ve-X_a3jWkOy89RoDkT5ahKBY-8S25L6wlvWt8ZyQ2bLxfplzEzuHgEknTMKKp2K" + "jRlwI2p3gF4FYeQM7dx0E5O782Lh1P3IC6jPNqiZgTgWmsRYZbAN8oU2V626bQxD" + "n8prQ0Xr_3aPdP7VIVgxNZMnF0NJrQvB_rzq1Dip1UM_xH_9nansbX25E64OQU-r" + "q54EdO-vb_9FvyqdeVTJ3UTgXIP7OXtz4K8xlEHWdb1-hJChVvDc0KSnN5HVN2NJ" + "yJrAofVyHBxXGRnGMdN8cOwvxzBFsz2Hih_lIqm1NVULm9_J9GoesY-aN8JzGocU" + "U3hbhFQBiUlzliuodhwg4RXRcfmPHQRo7kWKaohpySkvqmWcXEAt2LPJ8nH70fW7" + "vudgzwwWTnNcMlf0Wa-nKL4xXNNPQD0obDCfogN8uKuGqi0DltOUmFK62Zkkb0_d" + "45grssnD5q89MjDGBkGMXuLY_JLOqc7Y9VV6H48vzoTNK1a2kOGV2TrAD8syuA5Z" + "o8RLKjTqAYjKTUqEJjg0MflpiBnbDQvRqiSXs1cJuFNXRLpEC5GoqGqMd0zAGn4u" + "5J3OurVd0SFp8_vkYUI6YwNUe00y8_Dn6DOBh_0KKADphZBgple82_8HrnQNreQn" + "GkB2TpIsjwWud0yuhI-jQZEMNNlhEYMLwx7B-xTGhn0LFC1pLEXn_kZ2NOgDgUHd" + "bdj906o3N2Jjo9Fb5GXkCrt-fNEYBjeXvIu73yeTGmsiAzfiICNHi_PmGkgq8fYQ" + "O9lQgyRHCMic8zU7ffWuSoUPRgHsqztLHaCDbYIrNmgrn2taxcXSb57Xm_l-1xBH" + "bZqdMvBziapJXaLJmhUg03lgdsIc_OuJmzt-sytDLVGIuNqpa4dETdhLsI7qis4B" + ); + + // 1024 chars + + BOOST_FOREACH(const String str, clearText) { + String enc = Base64::Encode(str); + String dec = Base64::Decode(enc); + BOOST_CHECK(str == dec); + } +} + +BOOST_AUTO_TEST_SUITE_END()