Apache Mesos
base64.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_BASE64_HPP__
14 #define __STOUT_BASE64_HPP__
15 
16 #include <cctype>
17 #include <functional>
18 #include <string>
19 
20 #include <stout/foreach.hpp>
21 #include <stout/stringify.hpp>
22 #include <stout/try.hpp>
23 
24 namespace base64 {
25 
26 namespace internal {
27 
28 // This slightly modified base64 implementation from
29 // cplusplus.com answer by modoran can be found at:
30 // http://www.cplusplus.com/forum/beginner/51572/
31 
32 constexpr char STANDARD_CHARS[] =
33  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
34  "abcdefghijklmnopqrstuvwxyz"
35  "0123456789+/";
36 
37 constexpr char URL_SAFE_CHARS[] =
38  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
39  "abcdefghijklmnopqrstuvwxyz"
40  "0123456789-_";
41 
42 
43 inline std::string encode(
44  const std::string& s,
45  const std::string& chars,
46  bool padding)
47 {
48  std::string result;
49  int i = 0;
50  int j = 0;
51  unsigned char array3[3];
52  unsigned char array4[4];
53  const char* bytesToEncode = s.c_str();
54  size_t length = s.size();
55 
56  while (length--) {
57  array3[i++] = *(bytesToEncode++);
58  if (i == 3) {
59  array4[0] = (array3[0] & 0xfc) >> 2;
60  array4[1] = ((array3[0] & 0x03) << 4) + ((array3[1] & 0xf0) >> 4);
61  array4[2] = ((array3[1] & 0x0f) << 2) + ((array3[2] & 0xc0) >> 6);
62  array4[3] = array3[2] & 0x3f;
63  for (i = 0; i < 4; i++) {
64  result += chars[array4[i]];
65  }
66  i = 0;
67  }
68  }
69 
70  if (i != 0) {
71  for (j = i; j < 3; j++) {
72  array3[j] = '\0';
73  }
74  array4[0] = (array3[0] & 0xfc) >> 2;
75  array4[1] = ((array3[0] & 0x03) << 4) + ((array3[1] & 0xf0) >> 4);
76  array4[2] = ((array3[1] & 0x0f) << 2) + ((array3[2] & 0xc0) >> 6);
77  array4[3] = array3[2] & 0x3f;
78  for (j = 0; j < i + 1; j++) {
79  result += chars[array4[j]];
80  }
81  if (padding) {
82  while (i++ < 3) {
83  result += '=';
84  }
85  }
86  }
87 
88  return result;
89 }
90 
91 
92 inline Try<std::string> decode(const std::string& s, const std::string& chars)
93 {
94  auto isBase64 = [&chars](unsigned char c) -> bool {
95  return (isalnum(c) || (c == chars[62]) || (c == chars[63]));
96  };
97 
98  size_t i = 0;
99  unsigned char array3[3];
100  unsigned char array4[4];
101  std::string result;
102 
103  foreach (unsigned char c, s) {
104  if (c == '=') {
105  // TODO(bmahler): Note that this does not validate that
106  // there are the correct number of '=' characters!
107  break; // Reached the padding.
108  }
109 
110  if (!isBase64(c)) {
111  return Error("Invalid character '" + stringify(c) + "'");
112  }
113 
114  array4[i++] = c;
115 
116  if (i == 4) {
117  for (i = 0; i < 4; i++) {
118  array4[i] = static_cast<unsigned char>(chars.find(array4[i]));
119  }
120  array3[0] = (array4[0] << 2) + ((array4[1] & 0x30) >> 4);
121  array3[1] = ((array4[1] & 0xf) << 4) + ((array4[2] & 0x3c) >> 2);
122  array3[2] = ((array4[2] & 0x3) << 6) + array4[3];
123  for (i = 0; i < 3; i++) {
124  result += array3[i];
125  }
126  i = 0;
127  }
128  }
129 
130  if (i != 0) {
131  size_t j;
132 
133  for (j = i; j < 4; j++) {
134  array4[j] = 0;
135  }
136  for (j = 0; j < 4; j++) {
137  array4[j] = static_cast<unsigned char>(chars.find(array4[j]));
138  }
139  array3[0] = (array4[0] << 2) + ((array4[1] & 0x30) >> 4);
140  array3[1] = ((array4[1] & 0xf) << 4) + ((array4[2] & 0x3c) >> 2);
141  array3[2] = ((array4[2] & 0x3) << 6) + array4[3];
142  for (j = 0; (j < i - 1); j++) {
143  result += array3[j];
144  }
145  }
146 
147  return result;
148 }
149 
150 } // namespace internal {
151 
152 
159 inline std::string encode(const std::string& s)
160 {
162 }
163 
164 
172 inline Try<std::string> decode(const std::string& s)
173 {
175 }
176 
177 
185 inline std::string encode_url_safe(const std::string& s, bool padding = true)
186 {
187  return internal::encode(s, internal::URL_SAFE_CHARS, padding);
188 }
189 
190 
198 inline Try<std::string> decode_url_safe(const std::string& s)
199 {
201 }
202 
203 } // namespace base64 {
204 
205 #endif // __STOUT_BASE64_HPP__
Try< std::string > decode(const std::string &s)
Decode a string that is Base64-encoded with the standard Base64 alphabet.
Definition: base64.hpp:172
Definition: errorbase.hpp:35
Definition: try.hpp:34
std::string encode(const std::string &s, const std::string &chars, bool padding)
Definition: base64.hpp:43
constexpr char URL_SAFE_CHARS[]
Definition: base64.hpp:37
std::string encode(const std::string &s)
Encode a string to Base64 with the standard Base64 alphabet.
Definition: base64.hpp:159
std::string encode_url_safe(const std::string &s, bool padding=true)
Encode a string to Base64 with a URL and filename safe alphabet.
Definition: base64.hpp:185
Try< std::string > decode_url_safe(const std::string &s)
Decode a string that is Base64-encoded with a URL and filename safe alphabet.
Definition: base64.hpp:198
std::string stringify(int flags)
constexpr char STANDARD_CHARS[]
Definition: base64.hpp:32
Try< std::string > decode(const std::string &s, const std::string &chars)
Definition: base64.hpp:92