FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
uap-cpp/base64.cpp at master · aitech-lab/uap-cpp · GitHub
aitech-lab
uap-cpp
Repository navigation
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
uap-cpp
/
base64.cpp
Copy path
More file actions
More file actions
Latest commit
History
History
History
282 lines (220 loc) · 8.68 KB
Breadcrumbs
uap-cpp
/
base64.cpp
Copy path
File metadata and controls
282 lines (220 loc) · 8.68 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
/*
base64.cpp and base64.h
base64 encoding and decoding with C++.
More information at
https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp
Version: 2.rc.09 (release candidate)
Copyright (C) 2004-2017, 2020-2022 René Nyffenegger
This source code is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this source code must not be misrepresented; you must not
claim that you wrote the original source code. If you use this source code
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original source code.
3. This notice may not be removed or altered from any source distribution.
René Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/
#
include
"
base64.h
"
#
include
<
algorithm
>
#
include
<
stdexcept
>
//
//
Depending on the url parameter in base64_chars, one of
//
two sets of base64 characters needs to be chosen.
//
They differ in their last two characters.
//
static
const
char
* base64_chars[
2
] = {
"
ABCDEFGHIJKLMNOPQRSTUVWXYZ
"
"
abcdefghijklmnopqrstuvwxyz
"
"
0123456789
"
"
+/
"
,
"
ABCDEFGHIJKLMNOPQRSTUVWXYZ
"
"
abcdefghijklmnopqrstuvwxyz
"
"
0123456789
"
"
-_
"
};
static
unsigned
int
pos_of_char
(
const
unsigned
char
chr) {
//
//
Return the position of chr within base64_encode()
//
if
(chr >=
'
A
'
&& chr <=
'
Z
'
)
return
chr -
'
A
'
;
else
if
(chr >=
'
a
'
&& chr <=
'
z
'
)
return
chr -
'
a
'
+ (
'
Z
'
-
'
A
'
) +
1
;
else
if
(chr >=
'
0
'
&& chr <=
'
9
'
)
return
chr -
'
0
'
+ (
'
Z
'
-
'
A
'
) + (
'
z
'
-
'
a
'
) +
2
;
else
if
(chr ==
'
+
'
|| chr ==
'
-
'
)
return
62
;
//
Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters (
else
if
(chr ==
'
/
'
|| chr ==
'
_
'
)
return
63
;
//
Ditto for '/' and '_'
else
//
//
2020-10-23: Throw std::exception rather than const char*
//
(Pablo Martin-Gomez, https://github.com/Bouska)
//
throw
std::runtime_error
(
"
Input is not valid base64-encoded data.
"
);
}
static
std::string
insert_linebreaks
(std::string str,
size_t
distance) {
//
//
Provided by https://github.com/JomaCorpFX, adapted by me.
//
if
(!str.
length
()) {
return
"
"
;
}
size_t
pos = distance;
while
(pos < str.
size
()) {
str.
insert
(pos,
"
\n
"
);
pos += distance +
1
;
}
return
str;
}
template
<
typename
String,
unsigned
int
line_length>
static
std::string
encode_with_line_breaks
(String s) {
return
insert_linebreaks
(
base64_encode
(s,
false
), line_length);
}
template
<
typename
String>
static
std::string
encode_pem
(String s) {
return
encode_with_line_breaks<String,
64
>(s);
}
template
<
typename
String>
static
std::string
encode_mime
(String s) {
return
encode_with_line_breaks<String,
76
>(s);
}
template
<
typename
String>
static
std::string
encode
(String s,
bool
url) {
return
base64_encode
(
reinterpret_cast
<
const
unsigned
char
*>(s.
data
()), s.
length
(), url);
}
std::string
base64_encode
(
unsigned
char
const
* bytes_to_encode,
size_t
in_len,
bool
url) {
size_t
len_encoded = (in_len +
2
) /
3
*
4
;
unsigned
char
trailing_char = url ?
'
.
'
:
'
=
'
;
//
//
Choose set of base64 characters. They differ
//
for the last two positions, depending on the url
//
parameter.
//
A bool (as is the parameter url) is guaranteed
//
to evaluate to either 0 or 1 in C++ therefore,
//
the correct character set is chosen by subscripting
//
base64_chars with url.
//
const
char
* base64_chars_ = base64_chars[url];
std::string ret;
ret.
reserve
(len_encoded);
unsigned
int
pos =
0
;
while
(pos < in_len) {
ret.
push_back
(base64_chars_[(bytes_to_encode[pos +
0
] &
0xfc
) >>
2
]);
if
(pos+
1
< in_len) {
ret.
push_back
(base64_chars_[((bytes_to_encode[pos +
0
] &
0x03
) <<
4
) + ((bytes_to_encode[pos +
1
] &
0xf0
) >>
4
)]);
if
(pos+
2
< in_len) {
ret.
push_back
(base64_chars_[((bytes_to_encode[pos +
1
] &
0x0f
) <<
2
) + ((bytes_to_encode[pos +
2
] &
0xc0
) >>
6
)]);
ret.
push_back
(base64_chars_[ bytes_to_encode[pos +
2
] &
0x3f
]);
}
else
{
ret.
push_back
(base64_chars_[(bytes_to_encode[pos +
1
] &
0x0f
) <<
2
]);
ret.
push_back
(trailing_char);
}
}
else
{
ret.
push_back
(base64_chars_[(bytes_to_encode[pos +
0
] &
0x03
) <<
4
]);
ret.
push_back
(trailing_char);
ret.
push_back
(trailing_char);
}
pos +=
3
;
}
return
ret;
}
template
<
typename
String>
static
std::string
decode
(String
const
& encoded_string,
bool
remove_linebreaks) {
//
//
decode(…) is templated so that it can be used with String = const std::string&
//
or std::string_view (requires at least C++17)
//
if
(encoded_string.
empty
())
return
std::string
();
if
(remove_linebreaks) {
std::string
copy
(encoded_string);
copy.
erase
(
std::remove
(copy.
begin
(), copy.
end
(),
'
\n
'
), copy.
end
());
return
base64_decode
(copy,
false
);
}
size_t
length_of_string = encoded_string.
length
();
size_t
pos =
0
;
//
//
The approximate length (bytes) of the decoded string might be one or
//
two bytes smaller, depending on the amount of trailing equal signs
//
in the encoded string. This approximation is needed to reserve
//
enough space in the string to be returned.
//
size_t
approx_length_of_decoded_string = length_of_string /
4
*
3
;
std::string ret;
ret.
reserve
(approx_length_of_decoded_string);
while
(pos < length_of_string) {
//
//
Iterate over encoded input string in chunks. The size of all
//
chunks except the last one is 4 bytes.
//
//
The last chunk might be padded with equal signs or dots
//
in order to make it 4 bytes in size as well, but this
//
is not required as per RFC 2045.
//
//
All chunks except the last one produce three output bytes.
//
//
The last chunk produces at least one and up to three bytes.
//
size_t
pos_of_char_1 =
pos_of_char
(encoded_string.
at
(pos+
1
) );
//
//
Emit the first output byte that is produced in each chunk:
//
ret.
push_back
(
static_cast
<std::string::value_type>( ( (
pos_of_char
(encoded_string.
at
(pos+
0
)) ) <<
2
) + ( (pos_of_char_1 &
0x30
) >>
4
)));
if
( ( pos +
2
< length_of_string ) &&
//
Check for data that is not padded with equal signs (which is allowed by RFC 2045)
encoded_string.
at
(pos+
2
) !=
'
=
'
&&
encoded_string.
at
(pos+
2
) !=
'
.
'
//
accept URL-safe base 64 strings, too, so check for '.' also.
)
{
//
//
Emit a chunk's second byte (which might not be produced in the last chunk).
//
unsigned
int
pos_of_char_2 =
pos_of_char
(encoded_string.
at
(pos+
2
) );
ret.
push_back
(
static_cast
<std::string::value_type>( (( pos_of_char_1 &
0x0f
) <<
4
) + (( pos_of_char_2 &
0x3c
) >>
2
)));
if
( ( pos +
3
< length_of_string ) &&
encoded_string.
at
(pos+
3
) !=
'
=
'
&&
encoded_string.
at
(pos+
3
) !=
'
.
'
)
{
//
//
Emit a chunk's third byte (which might not be produced in the last chunk).
//
ret.
push_back
(
static_cast
<std::string::value_type>( ( (pos_of_char_2 &
0x03
) <<
6
) +
pos_of_char
(encoded_string.
at
(pos+
3
)) ));
}
}
pos +=
4
;
}
return
ret;
}
std::string
base64_decode
(std::string
const
& s,
bool
remove_linebreaks) {
return
decode
(s, remove_linebreaks);
}
std::string
base64_encode
(std::string
const
& s,
bool
url) {
return
encode
(s, url);
}
std::string
base64_encode_pem
(std::string
const
& s) {
return
encode_pem
(s);
}
std::string
base64_encode_mime
(std::string
const
& s) {
return
encode_mime
(s);
}
#
if
__cplusplus >= 201703L
//
//
Interface with std::string_view rather than const std::string&
//
Requires C++17
//
Provided by Yannic Bonenberger (https://github.com/Yannic)
//
std::string
base64_encode
(std::string_view s,
bool
url) {
return
encode
(s, url);
}
std::string
base64_encode_pem
(std::string_view s) {
return
encode_pem
(s);
}
std::string
base64_encode_mime
(std::string_view s) {
return
encode_mime
(s);
}
std::string
base64_decode
(std::string_view s,
bool
remove_linebreaks) {
return
decode
(s, remove_linebreaks);
}
#
endif
//
__cplusplus >= 201703L
Back
|
FazBrowse Home
|
New Git URL