/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  | }  |