Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: Common Portability Library
4 : * Purpose: Encoding/Decoding Base64 strings
5 : * Author: Paul Ramsey <pramsey@cleverelephant.ca>
6 : * Dave Blasby <dblasby@gmail.com>
7 : * René Nyffenegger
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2008 Paul Ramsey
11 : * Copyright (c) 2002 Refractions Research
12 : * Copyright (C) 2004-2008 René Nyffenegger
13 : * Copyright (c) 2010-2013, Even Rouault <even dot rouault at spatialys.com>
14 : *
15 : * (see also part way down the file for license terms for René's code)
16 : *
17 : * Permission is hereby granted, free of charge, to any person obtaining a
18 : * copy of this software and associated documentation files (the "Software"),
19 : * to deal in the Software without restriction, including without limitation
20 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
21 : * and/or sell copies of the Software, and to permit persons to whom the
22 : * Software is furnished to do so, subject to the following conditions:
23 : *
24 : * The above copyright notice and this permission notice shall be included in
25 : * all copies of this Software or works derived from this Software.
26 : *
27 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
28 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33 : * DEALINGS IN THE SOFTWARE.
34 : ****************************************************************************/
35 :
36 : #include "cpl_port.h"
37 : #include "cpl_string.h"
38 :
39 : #include <string>
40 :
41 : #include "cpl_conv.h"
42 :
43 : // Derived from MapServer's mappostgis.c.
44 :
45 : /*
46 : ** Decode a base64 character.
47 : */
48 : constexpr unsigned char CPLBase64DecodeChar[256] = {
49 : // Not Base64 characters.
50 : 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
51 : 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
52 : 64, 64, 64, 64, 64,
53 : // +
54 : 62,
55 : // Not Base64 characters.
56 : 64, 64, 64,
57 : // /
58 : 63,
59 : // 0-9
60 : 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
61 : // Not Base64 characters.
62 : 64, 64, 64, 64, 64, 64, 64,
63 : // A-Z
64 : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
65 : 21, 22, 23, 24, 25,
66 : // Not Base64 characters.
67 : 64, 64, 64, 64, 64, 64,
68 : // a-z
69 : 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
70 : 45, 46, 47, 48, 49, 50, 51,
71 : // Not Base64 characters.
72 : 64, 64, 64, 64, 64,
73 : // Not Base64 characters (upper 128 characters).
74 : 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
75 : 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
76 : 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
77 : 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
78 : 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
79 : 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
80 : 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64};
81 :
82 : /************************************************************************/
83 : /* CPLBase64DecodeInPlace() */
84 : /************************************************************************/
85 :
86 : /** Decode base64 string "pszBase64" (null terminated) in place.
87 : *
88 : * Returns length of decoded array or 0 on failure.
89 : */
90 1291 : int CPLBase64DecodeInPlace(GByte *pszBase64)
91 : {
92 1291 : if (pszBase64 && *pszBase64)
93 : {
94 1291 : unsigned char *p = pszBase64;
95 1291 : int offset_1 = 0;
96 1291 : int offset_2 = 0;
97 :
98 : // Drop illegal chars first.
99 849959 : for (; pszBase64[offset_1]; ++offset_1)
100 : {
101 848668 : unsigned char c = pszBase64[offset_1];
102 848668 : if ((CPLBase64DecodeChar[c] != 64) || (c == '='))
103 : {
104 848255 : pszBase64[offset_2++] = c;
105 : }
106 : }
107 :
108 213357 : for (int idx = 0; idx < offset_2; idx += 4)
109 : {
110 212066 : unsigned char b1 = CPLBase64DecodeChar[pszBase64[idx]];
111 212066 : unsigned char b2 = 0;
112 212066 : unsigned char c3 = 'A';
113 212066 : unsigned char c4 = 'A';
114 :
115 212066 : if (idx + 3 < offset_2)
116 : {
117 212063 : b2 = CPLBase64DecodeChar[pszBase64[idx + 1]];
118 212063 : c3 = pszBase64[idx + 2];
119 212063 : c4 = pszBase64[idx + 3];
120 : }
121 3 : else if (idx + 2 < offset_2)
122 : {
123 0 : b2 = CPLBase64DecodeChar[pszBase64[idx + 1]];
124 0 : c3 = pszBase64[idx + 2];
125 : }
126 3 : else if (idx + 1 < offset_2)
127 : {
128 0 : b2 = CPLBase64DecodeChar[pszBase64[idx + 1]];
129 : // c3 = 'A';
130 : } // Else: Use the default values.
131 :
132 212066 : const unsigned char b3 = CPLBase64DecodeChar[c3];
133 212066 : const unsigned char b4 = CPLBase64DecodeChar[c4];
134 :
135 212066 : *p++ = ((b1 << 2) | (b2 >> 4));
136 212066 : if (p - pszBase64 == offset_1)
137 0 : break;
138 212066 : if (c3 != '=')
139 : {
140 212051 : *p++ = (((b2 & 0xf) << 4) | (b3 >> 2));
141 212051 : if (p - pszBase64 == offset_1)
142 0 : break;
143 : }
144 212066 : if (c4 != '=')
145 : {
146 212036 : *p++ = (((b3 & 0x3) << 6) | b4);
147 212036 : if (p - pszBase64 == offset_1)
148 0 : break;
149 : }
150 : }
151 1291 : return static_cast<int>(p - pszBase64);
152 : }
153 0 : return 0;
154 : }
155 :
156 : /*
157 : * This function was extracted from the base64 cpp utility published by
158 : * René Nyffenegger. The code was modified into a form suitable for use in
159 : * CPL. The original code can be found at:
160 : *
161 : * http://www.adp-gmbh.ch/cpp/common/base64.html.
162 : *
163 : * The following is the original notice of this function.
164 : *
165 : * base64.cpp and base64.h
166 : *
167 : * Copyright (C) 2004-2008 René Nyffenegger
168 : *
169 : * This source code is provided 'as-is', without any express or implied
170 : * warranty. In no event will the author be held liable for any damages
171 : * arising from the use of this software.
172 : *
173 : * Permission is granted to anyone to use this software for any purpose,
174 : * including commercial applications, and to alter it and redistribute it
175 : * freely, subject to the following restrictions:
176 : *
177 : * 1. The origin of this source code must not be misrepresented; you must not
178 : * claim that you wrote the original source code. If you use this source
179 : * code in a product, an acknowledgment in the product documentation would
180 : * be appreciated but is not required.
181 : *
182 : * 2. Altered source versions must be plainly marked as such, and must not be
183 : * misrepresented as being the original source code.
184 : *
185 : * 3. This notice may not be removed or altered from any source distribution.
186 : *
187 : * René Nyffenegger rene.nyffenegger@adp-gmbh.ch
188 : */
189 :
190 : /************************************************************************/
191 : /* CPLBase64Encode() */
192 : /************************************************************************/
193 :
194 : /** Base64 encode a buffer. */
195 :
196 395 : char *CPLBase64Encode(int nDataLen, const GByte *pabyBytesToEncode)
197 : {
198 395 : constexpr char base64Chars[] =
199 : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
200 :
201 395 : const int kCharArray3Size = 3;
202 395 : const int kCharArray4Size = 4;
203 395 : unsigned char charArray3[kCharArray3Size] = {};
204 :
205 790 : std::string result("");
206 395 : int array3_idx = 0;
207 1243590 : while (nDataLen--)
208 : {
209 1243190 : charArray3[array3_idx++] = *(pabyBytesToEncode++);
210 :
211 1243190 : if (array3_idx == kCharArray3Size)
212 : {
213 : const unsigned char charArray4[kCharArray4Size] = {
214 414153 : static_cast<unsigned char>((charArray3[0] & 0xfc) >> 2),
215 414153 : static_cast<unsigned char>(((charArray3[0] & 0x03) << 4) +
216 414153 : ((charArray3[1] & 0xf0) >> 4)),
217 414153 : static_cast<unsigned char>(((charArray3[1] & 0x0f) << 2) +
218 414153 : ((charArray3[2] & 0xc0) >> 6)),
219 414153 : static_cast<unsigned char>(charArray3[2] & 0x3f)};
220 :
221 2070760 : for (int idx = 0; idx < kCharArray4Size; ++idx)
222 : {
223 1656610 : result += base64Chars[charArray4[idx]];
224 : }
225 :
226 414153 : array3_idx = 0;
227 : }
228 : }
229 :
230 395 : if (array3_idx)
231 : {
232 801 : for (int idx = array3_idx; idx < kCharArray3Size; ++idx)
233 : {
234 417 : charArray3[idx] = '\0';
235 : }
236 :
237 : const unsigned char charArray4[kCharArray4Size] = {
238 384 : static_cast<unsigned char>((charArray3[0] & 0xfc) >> 2),
239 384 : static_cast<unsigned char>(((charArray3[0] & 0x03) << 4) +
240 384 : ((charArray3[1] & 0xf0) >> 4)),
241 384 : static_cast<unsigned char>(((charArray3[1] & 0x0f) << 2) +
242 384 : ((charArray3[2] & 0xc0) >> 6)),
243 384 : static_cast<unsigned char>(charArray3[2] & 0x3f)};
244 :
245 1503 : for (int idx = 0; idx < (array3_idx + 1); ++idx)
246 : {
247 1119 : result += base64Chars[charArray4[idx]];
248 : }
249 :
250 801 : while (array3_idx++ < kCharArray3Size)
251 417 : result += '=';
252 : }
253 :
254 790 : return CPLStrdup(result.c_str());
255 : }
|