-
Notifications
You must be signed in to change notification settings - Fork 3
/
base64.cpp
160 lines (110 loc) · 4.55 KB
/
base64.cpp
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
/**
--------------------------------------------------------------------------------
- Module : base64.h
- Description : Just another Base64 encoding/decoding class
- Author : Tim Zaman, 18-FEB-2016
--------------------------------------------------------------------------------
*/
#include "base64.h"
static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'};
static int mod_table[] = {0, 2, 1};
void b64::build_decoding_table() {
this->decoding_table = (char *) malloc(256);
for (int i = 0; i < 64; i++){
this->decoding_table[(unsigned char) encoding_table[i]] = i;
}
}
void b64::base64_cleanup() {
free(this->decoding_table);
}
b64::b64(){ //c'tor
build_decoding_table();
}
b64::~b64(){ //d'tor
base64_cleanup();
}
std::string b64::base64_encode(std::string src_str){
//Public interface
unsigned int dst_len = 0;
char * dst_data = base64_encode((const unsigned char *)src_str.c_str(), src_str.size(), &dst_len);
std::string ret(dst_data, dst_len);
delete dst_data;
return ret;
}
std::string b64::base64_decode(std::string src_str){
//Public interface
unsigned int dst_len = 0;
unsigned char * dst_data = base64_decode(src_str.c_str(), src_str.size(), &dst_len);
std::string ret((char*)dst_data, dst_len);
delete dst_data;
return ret;
}
std::string b64::base64_encode(unsigned char const* src_data, unsigned int src_len){
//Public interface
unsigned int dst_len = 0;
char * dst_data = base64_encode(src_data, src_len, &dst_len);
std::string ret(dst_data, dst_len);
delete dst_data;
return ret;
}
std::string b64::base64_decode(char const* src_data, unsigned int src_len){
//Public interface
unsigned int dst_len = 0;
unsigned char * dst_data = base64_decode(src_data, src_len, &dst_len);
std::string ret((char*)dst_data, dst_len);
delete dst_data;
return ret;
}
char * b64::base64_encode(const unsigned char *data,
unsigned int input_length,
unsigned int *output_length) {
*output_length = 4 * ((input_length + 2) / 3);
char *encoded_data = (char *)malloc(*output_length);
if (encoded_data == NULL) return NULL;
for (int i = 0, j = 0; i < input_length;) {
uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
}
for (int i = 0; i < mod_table[input_length % 3]; i++){
encoded_data[*output_length - 1 - i] = '=';
}
return encoded_data;
}
unsigned char * b64::base64_decode(const char *data,
unsigned int input_length,
unsigned int *output_length) {
if (this->decoding_table == NULL) build_decoding_table();
if (input_length % 4 != 0) return NULL;
*output_length = input_length / 4 * 3;
if (data[input_length - 1] == '=') (*output_length)--;
if (data[input_length - 2] == '=') (*output_length)--;
unsigned char *decoded_data = (unsigned char *) malloc(*output_length);
if (decoded_data == NULL) return NULL;
for (int i = 0, j = 0; i < input_length;) {
uint32_t sextet_a = data[i] == '=' ? 0 & i++ : this->decoding_table[data[i++]];
uint32_t sextet_b = data[i] == '=' ? 0 & i++ : this->decoding_table[data[i++]];
uint32_t sextet_c = data[i] == '=' ? 0 & i++ : this->decoding_table[data[i++]];
uint32_t sextet_d = data[i] == '=' ? 0 & i++ : this->decoding_table[data[i++]];
uint32_t triple = (sextet_a << 3 * 6)
+ (sextet_b << 2 * 6)
+ (sextet_c << 1 * 6)
+ (sextet_d << 0 * 6);
if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
}
return decoded_data;
}