/src/gdal/port/cpl_base64.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | int CPLBase64DecodeInPlace(GByte *pszBase64) |
91 | 0 | { |
92 | 0 | if (pszBase64 && *pszBase64) |
93 | 0 | { |
94 | 0 | unsigned char *p = pszBase64; |
95 | 0 | int offset_1 = 0; |
96 | 0 | int offset_2 = 0; |
97 | | |
98 | | // Drop illegal chars first. |
99 | 0 | for (; pszBase64[offset_1]; ++offset_1) |
100 | 0 | { |
101 | 0 | unsigned char c = pszBase64[offset_1]; |
102 | 0 | if ((CPLBase64DecodeChar[c] != 64) || (c == '=')) |
103 | 0 | { |
104 | 0 | pszBase64[offset_2++] = c; |
105 | 0 | } |
106 | 0 | } |
107 | |
|
108 | 0 | for (int idx = 0; idx < offset_2; idx += 4) |
109 | 0 | { |
110 | 0 | unsigned char b1 = CPLBase64DecodeChar[pszBase64[idx]]; |
111 | 0 | unsigned char b2 = 0; |
112 | 0 | unsigned char c3 = 'A'; |
113 | 0 | unsigned char c4 = 'A'; |
114 | |
|
115 | 0 | if (idx + 3 < offset_2) |
116 | 0 | { |
117 | 0 | b2 = CPLBase64DecodeChar[pszBase64[idx + 1]]; |
118 | 0 | c3 = pszBase64[idx + 2]; |
119 | 0 | c4 = pszBase64[idx + 3]; |
120 | 0 | } |
121 | 0 | else if (idx + 2 < offset_2) |
122 | 0 | { |
123 | 0 | b2 = CPLBase64DecodeChar[pszBase64[idx + 1]]; |
124 | 0 | c3 = pszBase64[idx + 2]; |
125 | 0 | } |
126 | 0 | else if (idx + 1 < offset_2) |
127 | 0 | { |
128 | 0 | b2 = CPLBase64DecodeChar[pszBase64[idx + 1]]; |
129 | | // c3 = 'A'; |
130 | 0 | } // Else: Use the default values. |
131 | |
|
132 | 0 | const unsigned char b3 = CPLBase64DecodeChar[c3]; |
133 | 0 | const unsigned char b4 = CPLBase64DecodeChar[c4]; |
134 | |
|
135 | 0 | *p++ = ((b1 << 2) | (b2 >> 4)); |
136 | 0 | if (p - pszBase64 == offset_1) |
137 | 0 | break; |
138 | 0 | if (c3 != '=') |
139 | 0 | { |
140 | 0 | *p++ = (((b2 & 0xf) << 4) | (b3 >> 2)); |
141 | 0 | if (p - pszBase64 == offset_1) |
142 | 0 | break; |
143 | 0 | } |
144 | 0 | if (c4 != '=') |
145 | 0 | { |
146 | 0 | *p++ = (((b3 & 0x3) << 6) | b4); |
147 | 0 | if (p - pszBase64 == offset_1) |
148 | 0 | break; |
149 | 0 | } |
150 | 0 | } |
151 | 0 | return static_cast<int>(p - pszBase64); |
152 | 0 | } |
153 | 0 | return 0; |
154 | 0 | } |
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 | | char *CPLBase64Encode(int nDataLen, const GByte *pabyBytesToEncode) |
197 | 0 | { |
198 | 0 | constexpr char base64Chars[] = |
199 | 0 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
200 | |
|
201 | 0 | const int kCharArray3Size = 3; |
202 | 0 | const int kCharArray4Size = 4; |
203 | 0 | unsigned char charArray3[kCharArray3Size] = {}; |
204 | |
|
205 | 0 | std::string result(""); |
206 | 0 | int array3_idx = 0; |
207 | 0 | while (nDataLen--) |
208 | 0 | { |
209 | 0 | charArray3[array3_idx++] = *(pabyBytesToEncode++); |
210 | |
|
211 | 0 | if (array3_idx == kCharArray3Size) |
212 | 0 | { |
213 | 0 | const unsigned char charArray4[kCharArray4Size] = { |
214 | 0 | static_cast<unsigned char>((charArray3[0] & 0xfc) >> 2), |
215 | 0 | static_cast<unsigned char>(((charArray3[0] & 0x03) << 4) + |
216 | 0 | ((charArray3[1] & 0xf0) >> 4)), |
217 | 0 | static_cast<unsigned char>(((charArray3[1] & 0x0f) << 2) + |
218 | 0 | ((charArray3[2] & 0xc0) >> 6)), |
219 | 0 | static_cast<unsigned char>(charArray3[2] & 0x3f)}; |
220 | |
|
221 | 0 | for (int idx = 0; idx < kCharArray4Size; ++idx) |
222 | 0 | { |
223 | 0 | result += base64Chars[charArray4[idx]]; |
224 | 0 | } |
225 | |
|
226 | 0 | array3_idx = 0; |
227 | 0 | } |
228 | 0 | } |
229 | |
|
230 | 0 | if (array3_idx) |
231 | 0 | { |
232 | 0 | for (int idx = array3_idx; idx < kCharArray3Size; ++idx) |
233 | 0 | { |
234 | 0 | charArray3[idx] = '\0'; |
235 | 0 | } |
236 | |
|
237 | 0 | const unsigned char charArray4[kCharArray4Size] = { |
238 | 0 | static_cast<unsigned char>((charArray3[0] & 0xfc) >> 2), |
239 | 0 | static_cast<unsigned char>(((charArray3[0] & 0x03) << 4) + |
240 | 0 | ((charArray3[1] & 0xf0) >> 4)), |
241 | 0 | static_cast<unsigned char>(((charArray3[1] & 0x0f) << 2) + |
242 | 0 | ((charArray3[2] & 0xc0) >> 6)), |
243 | 0 | static_cast<unsigned char>(charArray3[2] & 0x3f)}; |
244 | |
|
245 | 0 | for (int idx = 0; idx < (array3_idx + 1); ++idx) |
246 | 0 | { |
247 | 0 | result += base64Chars[charArray4[idx]]; |
248 | 0 | } |
249 | |
|
250 | 0 | while (array3_idx++ < kCharArray3Size) |
251 | 0 | result += '='; |
252 | 0 | } |
253 | |
|
254 | 0 | return CPLStrdup(result.c_str()); |
255 | 0 | } |