From: Matt Benjamin Date: Thu, 18 Feb 2016 16:14:42 +0000 (-0500) Subject: rgw: add a pure c++, header-only base64 encode/decode X-Git-Tag: v10.1.0~127^2~5 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=87ca3efe23dd8a6a51c2c904034a0e4dcc6d5982;p=ceph.git rgw: add a pure c++, header-only base64 encode/decode interface is based on strings, but takes boost::string_ref when encoding, column-wrap is controlled by the template argument, which defaults to int-max Signed-off-by: Matt Benjamin --- diff --git a/src/rgw/Makefile.am b/src/rgw/Makefile.am index beb6ab25b417..37e92a1e03ce 100644 --- a/src/rgw/Makefile.am +++ b/src/rgw/Makefile.am @@ -172,6 +172,7 @@ noinst_HEADERS += \ rgw/rgw_acl.h \ rgw/rgw_acl_s3.h \ rgw/rgw_acl_swift.h \ + rgw/rgw_b64.h \ rgw/rgw_client_io.h \ rgw/rgw_coroutine.h \ rgw/rgw_cr_rados.h \ diff --git a/src/rgw/rgw_b64.h b/src/rgw/rgw_b64.h new file mode 100644 index 000000000000..8a9e8adafe7a --- /dev/null +++ b/src/rgw/rgw_b64.h @@ -0,0 +1,87 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef RGW_B64_H +#define RGW_B64_H + +#include +#include +#include +#include +#include +#include +#include + +namespace rgw { + + /* + * A header-only Base64 encoder built on boost::archive. The + * formula is based on a class poposed for inclusion in boost in + * 2011 by Denis Shevchenko (abandoned), updated slightly + * (e.g., uses boost::string_ref). + * + * Also, wrap_width added as template argument, based on + * feedback from Marcus. + */ + + template::max()> + inline std::string to_base64(boost::string_ref sref) + { + using namespace boost::archive::iterators; + std::string ostr; + + // output must be =padded modulo 3 + auto psize = sref.size(); + while ((psize % 3) != 0) { + ++psize; + } + + /* RFC 2045 requires linebreaks to be present in the output + * sequence every at-most 76 characters (MIME-compliance), + * but we could likely omit it. */ + typedef + insert_linebreaks< + base64_from_binary< + transform_width< + boost::string_ref::const_iterator + ,6,8> + > + ,wrap_width + > b64_iter; + + std::string outstr(b64_iter(sref.data()), + b64_iter(sref.data() + sref.size())); + + // pad ostr with '=' to a length that is a multiple of 3 + for (size_t ix = 0; ix < (psize-sref.size()); ++ix) + outstr.push_back('='); + + return std::move(outstr); + } + + inline std::string from_base64(boost::string_ref sref) + { + using namespace boost::archive::iterators; + + /* MIME-compliant input will have line-breaks, so we have to + * filter WS */ + typedef + transform_width< + binary_from_base64< + remove_whitespace< + boost::string_ref::const_iterator>> + ,8,6 + > b64_iter; + + while (sref.back() == '=') + sref.remove_suffix(1); + + std::string outstr(b64_iter(sref.data()), + b64_iter(sref.data() + sref.size())); + + return std::move(outstr); + } + +} /* namespace */ + +#endif /* RGW_B64_H */