1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
3 #include "kwsysPrivate.h"
4 #include KWSYS_HEADER(Base64.h)
5
6 /* Work-around CMake dependency scanning limitation. This must
7 duplicate the above list of headers. */
8 #if 0
9 # include "Base64.h.in"
10 #endif
11
12 static const unsigned char kwsysBase64EncodeTable[65] =
13 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
14 "abcdefghijklmnopqrstuvwxyz"
15 "0123456789+/";
16
17 static const unsigned char kwsysBase64DecodeTable[256] = {
18 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
19 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
20 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
21 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F, 0x34, 0x35, 0x36, 0x37,
22 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
23 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
24 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
25 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
26 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D,
27 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
28 /*------------------------------------*/
29 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
30 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
31 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
32 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
33 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
34 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
35 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
36 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
37 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
38 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
39 };
40
kwsysBase64EncodeChar(int c)41 static unsigned char kwsysBase64EncodeChar(int c)
42 {
43 return kwsysBase64EncodeTable[(unsigned char)c];
44 }
45
kwsysBase64DecodeChar(unsigned char c)46 static unsigned char kwsysBase64DecodeChar(unsigned char c)
47 {
48 return kwsysBase64DecodeTable[c];
49 }
50
51 /* Encode 3 bytes into a 4 byte string. */
kwsysBase64_Encode3(const unsigned char * src,unsigned char * dest)52 void kwsysBase64_Encode3(const unsigned char* src, unsigned char* dest)
53 {
54 dest[0] = kwsysBase64EncodeChar((src[0] >> 2) & 0x3F);
55 dest[1] =
56 kwsysBase64EncodeChar(((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0F));
57 dest[2] =
58 kwsysBase64EncodeChar(((src[1] << 2) & 0x3C) | ((src[2] >> 6) & 0x03));
59 dest[3] = kwsysBase64EncodeChar(src[2] & 0x3F);
60 }
61
62 /* Encode 2 bytes into a 4 byte string. */
kwsysBase64_Encode2(const unsigned char * src,unsigned char * dest)63 void kwsysBase64_Encode2(const unsigned char* src, unsigned char* dest)
64 {
65 dest[0] = kwsysBase64EncodeChar((src[0] >> 2) & 0x3F);
66 dest[1] =
67 kwsysBase64EncodeChar(((src[0] << 4) & 0x30) | ((src[1] >> 4) & 0x0F));
68 dest[2] = kwsysBase64EncodeChar(((src[1] << 2) & 0x3C));
69 dest[3] = '=';
70 }
71
72 /* Encode 1 bytes into a 4 byte string. */
kwsysBase64_Encode1(const unsigned char * src,unsigned char * dest)73 void kwsysBase64_Encode1(const unsigned char* src, unsigned char* dest)
74 {
75 dest[0] = kwsysBase64EncodeChar((src[0] >> 2) & 0x3F);
76 dest[1] = kwsysBase64EncodeChar(((src[0] << 4) & 0x30));
77 dest[2] = '=';
78 dest[3] = '=';
79 }
80
81 /* Encode 'length' bytes from the input buffer and store the
82 encoded stream into the output buffer. Return the length of the encoded
83 buffer (output). Note that the output buffer must be allocated by the caller
84 (length * 1.5 should be a safe estimate). If 'mark_end' is true than an
85 extra set of 4 bytes is added to the end of the stream if the input is a
86 multiple of 3 bytes. These bytes are invalid chars and therefore they will
87 stop the decoder thus enabling the caller to decode a stream without
88 actually knowing how much data to expect (if the input is not a multiple of
89 3 bytes then the extra padding needed to complete the encode 4 bytes will
90 stop the decoding anyway). */
kwsysBase64_Encode(const unsigned char * input,size_t length,unsigned char * output,int mark_end)91 size_t kwsysBase64_Encode(const unsigned char* input, size_t length,
92 unsigned char* output, int mark_end)
93 {
94 const unsigned char* ptr = input;
95 const unsigned char* end = input + length;
96 unsigned char* optr = output;
97
98 /* Encode complete triplet */
99
100 while ((end - ptr) >= 3) {
101 kwsysBase64_Encode3(ptr, optr);
102 ptr += 3;
103 optr += 4;
104 }
105
106 /* Encodes a 2-byte ending into 3 bytes and 1 pad byte and writes. */
107
108 if (end - ptr == 2) {
109 kwsysBase64_Encode2(ptr, optr);
110 optr += 4;
111 }
112
113 /* Encodes a 1-byte ending into 2 bytes and 2 pad bytes */
114
115 else if (end - ptr == 1) {
116 kwsysBase64_Encode1(ptr, optr);
117 optr += 4;
118 }
119
120 /* Do we need to mark the end */
121
122 else if (mark_end) {
123 optr[0] = optr[1] = optr[2] = optr[3] = '=';
124 optr += 4;
125 }
126
127 return (size_t)(optr - output);
128 }
129
130 /* Decode 4 bytes into a 3 byte string. */
kwsysBase64_Decode3(const unsigned char * src,unsigned char * dest)131 int kwsysBase64_Decode3(const unsigned char* src, unsigned char* dest)
132 {
133 unsigned char d0;
134 unsigned char d1;
135 unsigned char d2;
136 unsigned char d3;
137
138 d0 = kwsysBase64DecodeChar(src[0]);
139 d1 = kwsysBase64DecodeChar(src[1]);
140 d2 = kwsysBase64DecodeChar(src[2]);
141 d3 = kwsysBase64DecodeChar(src[3]);
142
143 /* Make sure all characters were valid */
144
145 if (d0 == 0xFF || d1 == 0xFF || d2 == 0xFF || d3 == 0xFF) {
146 return 0;
147 }
148
149 /* Decode the 3 bytes */
150
151 dest[0] = (unsigned char)(((d0 << 2) & 0xFC) | ((d1 >> 4) & 0x03));
152 dest[1] = (unsigned char)(((d1 << 4) & 0xF0) | ((d2 >> 2) & 0x0F));
153 dest[2] = (unsigned char)(((d2 << 6) & 0xC0) | ((d3 >> 0) & 0x3F));
154
155 /* Return the number of bytes actually decoded */
156
157 if (src[2] == '=') {
158 return 1;
159 }
160 if (src[3] == '=') {
161 return 2;
162 }
163 return 3;
164 }
165
166 /* Decode bytes from the input buffer and store the decoded stream
167 into the output buffer until 'length' bytes have been decoded. Return the
168 real length of the decoded stream (which should be equal to 'length'). Note
169 that the output buffer must be allocated by the caller. If
170 'max_input_length' is not null, then it specifies the number of encoded
171 bytes that should be at most read from the input buffer. In that case the
172 'length' parameter is ignored. This enables the caller to decode a stream
173 without actually knowing how much decoded data to expect (of course, the
174 buffer must be large enough). */
kwsysBase64_Decode(const unsigned char * input,size_t length,unsigned char * output,size_t max_input_length)175 size_t kwsysBase64_Decode(const unsigned char* input, size_t length,
176 unsigned char* output, size_t max_input_length)
177 {
178 const unsigned char* ptr = input;
179 unsigned char* optr = output;
180
181 /* Decode complete triplet */
182
183 if (max_input_length) {
184 const unsigned char* end = input + max_input_length;
185 while (ptr < end) {
186 int len = kwsysBase64_Decode3(ptr, optr);
187 optr += len;
188 if (len < 3) {
189 return (size_t)(optr - output);
190 }
191 ptr += 4;
192 }
193 } else {
194 unsigned char* oend = output + length;
195 while ((oend - optr) >= 3) {
196 int len = kwsysBase64_Decode3(ptr, optr);
197 optr += len;
198 if (len < 3) {
199 return (size_t)(optr - output);
200 }
201 ptr += 4;
202 }
203
204 /* Decode the last triplet */
205
206 if (oend - optr == 2) {
207 unsigned char temp[3];
208 int len = kwsysBase64_Decode3(ptr, temp);
209 if (len >= 2) {
210 optr[0] = temp[0];
211 optr[1] = temp[1];
212 optr += 2;
213 } else if (len > 0) {
214 optr[0] = temp[0];
215 optr += 1;
216 }
217 } else if (oend - optr == 1) {
218 unsigned char temp[3];
219 int len = kwsysBase64_Decode3(ptr, temp);
220 if (len > 0) {
221 optr[0] = temp[0];
222 optr += 1;
223 }
224 }
225 }
226
227 return (size_t)(optr - output);
228 }
229