#include <stdexcept>
#include <algorithm>
#include <cmath> // for round()
+#include <climits>
#include <wchar.h>
#include <stdlib.h>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/foreach.hpp>
+#include <boost/assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+
#include <stringfunc.hxx>
using namespace std;
return result;
} // eo join_string(const std::vector< std::string >&,const std::string&)
+std::string join_string (
+ const char *const parts[], /* assumed NULL-terminated */
+ const std::string& delimiter
+)
+{
+ std::string result;
+
+ if (parts != NULL)
+ {
+ const char *const *cur = parts;
+
+ if (*cur != NULL) {
+ result = std::string (*cur);
+
+ while (*++cur != NULL) {
+ result += delimiter;
+ result += std::string (*cur);
+ }
+ }
+ }
+
+ return result;
+}
+
/*
return output;
}
+typedef boost::shared_ptr<BIO> BIO_Ptr;
+
+/**
+* @brief Converts openssl generic input/output to std::string
+*
+* Code adapted from keymakerd.
+*
+* @param bio Openssl's generic input/output
+* @return :string STL string
+**/
+static std::string _convert_BIO_to_string(BIO *input)
+{
+ std::string rtn;
+
+ char *output = NULL;
+ long written = BIO_get_mem_data(input, &output);
+ if (written <= 0 || output == NULL)
+ return rtn;
+
+ rtn.assign(output, written); //lint !e534 !e732
+ return rtn;
+} //lint !e1764
+
+/**
+ * @brief base64 encode a string using OpenSSL base64 functions
+ *
+ * Data size limit is 2GB on 32 bit (LONG_MAX)
+ *
+ * @param input String to encode
+ * @param one_line Encode all data as one line, no wrapping with line feeds
+ * @return base64 encoded string
+ */
+std::string base64_encode(const std::string &input, bool one_line)
+{
+ // check for empty buffer
+ if (input.empty())
+ return input;
+
+ // safety check to ensure our check afer BIO_write() works
+ if (input.size() >= LONG_MAX)
+ throw runtime_error("base64 encode: Too much data");
+
+ // setup encoder. Note: BIO_free_all frees both BIOs.
+ BIO_Ptr base64_encoder(BIO_new(BIO_f_base64()), BIO_free_all);
+ BIO *encoder_bio = base64_encoder.get();
+ if (one_line)
+ BIO_set_flags(encoder_bio, BIO_FLAGS_BASE64_NO_NL);
+
+ // chain output buffer and encoder together
+ BIO *encoded_result = BIO_new(BIO_s_mem());
+ BIO_push(encoder_bio, encoded_result);
+
+ // encode
+ long written = BIO_write(encoder_bio, input.c_str(), input.size());
+ if ((unsigned)written != input.size())
+ {
+ ostringstream out;
+ out << "base64 encoding failed: input size: "
+ << input.size() << " vs. output size: " << written;
+ throw runtime_error(out.str());
+ }
+ if (BIO_flush(encoder_bio) != 1)
+ throw runtime_error("base64 encode: BIO_flush() failed");
+
+ return _convert_BIO_to_string(encoded_result);
+}
+
+/**
+ * @brief base64 decode a string using OpenSSL base64 functions
+ *
+ * @param input String to decode
+ * @param one_line Expect all base64 data in one line. Input with line feeds will fail.
+ * @return base64 decoded string
+ */
+std::string base64_decode(const std::string &input, bool one_line)
+{
+ // check for empty buffer
+ if (input.empty())
+ return input;
+
+ // safety check for BIO_new_mem_buf()
+ if (input.size() >= INT_MAX)
+ throw runtime_error("base64 decode: Too much data");
+
+ // setup encoder. Note: BIO_free_all frees both BIOs.
+ BIO_Ptr base64_decoder(BIO_new(BIO_f_base64()), BIO_free_all);
+ BIO *bio_base64 = base64_decoder.get();
+ if (one_line)
+ BIO_set_flags(bio_base64, BIO_FLAGS_BASE64_NO_NL);
+
+ // chain input buffer and decoder together
+ BIO *bio_input = BIO_new_mem_buf((void*)input.c_str(), input.size());
+ bio_input = BIO_push(bio_base64, bio_input);
+
+ BIO_Ptr decoded_result(BIO_new(BIO_s_mem()), BIO_free_all);
+ BIO *bio_decoded = decoded_result.get();
+ const int convbuf_size = 512;
+ char convbuf[convbuf_size];
+
+ long read_bytes = 0;
+ while((read_bytes = BIO_read(bio_input, convbuf, convbuf_size)) > 0)
+ {
+ BOOST_ASSERT(read_bytes <= convbuf_size);
+ long written_bytes = BIO_write(bio_decoded, convbuf, read_bytes);
+ if (written_bytes != read_bytes)
+ {
+ ostringstream out;
+ out << "base64 decoding failed: read_bytes: "
+ << read_bytes << " vs. written_bytes: " << written_bytes;
+ throw runtime_error(out.str());
+ }
+ }
+ if (read_bytes == -2 || read_bytes == -1)
+ throw runtime_error("base64 decode: Error during decoding");
+
+ return _convert_BIO_to_string(bio_decoded);
+}
+
} // eo namespace I2n