]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
9f95a23c | 2 | // vim: ts=8 sw=2 smarttab ft=cpp |
7c673cae FG |
3 | |
4 | #ifndef RGW_B64_H | |
5 | #define RGW_B64_H | |
6 | ||
7c673cae FG |
7 | #include <boost/archive/iterators/base64_from_binary.hpp> |
8 | #include <boost/archive/iterators/binary_from_base64.hpp> | |
9 | #include <boost/archive/iterators/insert_linebreaks.hpp> | |
10 | #include <boost/archive/iterators/transform_width.hpp> | |
11 | #include <boost/archive/iterators/remove_whitespace.hpp> | |
12 | #include <limits> | |
f67539c2 TL |
13 | #include <string> |
14 | #include <string_view> | |
7c673cae FG |
15 | |
16 | namespace rgw { | |
17 | ||
18 | /* | |
19 | * A header-only Base64 encoder built on boost::archive. The | |
20 | * formula is based on a class poposed for inclusion in boost in | |
21 | * 2011 by Denis Shevchenko (abandoned), updated slightly | |
f67539c2 | 22 | * (e.g., uses std::string_view). |
7c673cae FG |
23 | * |
24 | * Also, wrap_width added as template argument, based on | |
25 | * feedback from Marcus. | |
26 | */ | |
27 | ||
28 | template<int wrap_width = std::numeric_limits<int>::max()> | |
f67539c2 | 29 | inline std::string to_base64(std::string_view sview) |
7c673cae FG |
30 | { |
31 | using namespace boost::archive::iterators; | |
32 | ||
33 | // output must be =padded modulo 3 | |
31f18b77 | 34 | auto psize = sview.size(); |
7c673cae FG |
35 | while ((psize % 3) != 0) { |
36 | ++psize; | |
37 | } | |
38 | ||
39 | /* RFC 2045 requires linebreaks to be present in the output | |
40 | * sequence every at-most 76 characters (MIME-compliance), | |
41 | * but we could likely omit it. */ | |
42 | typedef | |
43 | insert_linebreaks< | |
44 | base64_from_binary< | |
45 | transform_width< | |
f67539c2 | 46 | std::string_view::const_iterator |
7c673cae FG |
47 | ,6,8> |
48 | > | |
49 | ,wrap_width | |
50 | > b64_iter; | |
51 | ||
31f18b77 FG |
52 | std::string outstr(b64_iter(sview.data()), |
53 | b64_iter(sview.data() + sview.size())); | |
7c673cae FG |
54 | |
55 | // pad outstr with '=' to a length that is a multiple of 3 | |
31f18b77 | 56 | for (size_t ix = 0; ix < (psize-sview.size()); ++ix) |
7c673cae FG |
57 | outstr.push_back('='); |
58 | ||
59 | return outstr; | |
60 | } | |
61 | ||
f67539c2 | 62 | inline std::string from_base64(std::string_view sview) |
7c673cae FG |
63 | { |
64 | using namespace boost::archive::iterators; | |
31f18b77 | 65 | if (sview.empty()) |
7c673cae FG |
66 | return std::string(); |
67 | /* MIME-compliant input will have line-breaks, so we have to | |
68 | * filter WS */ | |
69 | typedef | |
70 | transform_width< | |
71 | binary_from_base64< | |
72 | remove_whitespace< | |
f67539c2 | 73 | std::string_view::const_iterator>> |
7c673cae FG |
74 | ,8,6 |
75 | > b64_iter; | |
76 | ||
31f18b77 FG |
77 | while (sview.back() == '=') |
78 | sview.remove_suffix(1); | |
7c673cae | 79 | |
31f18b77 FG |
80 | std::string outstr(b64_iter(sview.data()), |
81 | b64_iter(sview.data() + sview.size())); | |
7c673cae FG |
82 | |
83 | return outstr; | |
84 | } | |
7c673cae FG |
85 | } /* namespace */ |
86 | ||
87 | #endif /* RGW_B64_H */ |