comparison nspr/lib/libc/src/base64.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "plbase64.h"
7 #include "prlog.h" /* For PR_NOT_REACHED */
8 #include "prmem.h" /* for malloc / PR_MALLOC */
9
10 #include <string.h> /* for strlen */
11
12 static unsigned char *base = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
13
14 static void
15 encode3to4
16 (
17 const unsigned char *src,
18 unsigned char *dest
19 )
20 {
21 PRUint32 b32 = (PRUint32)0;
22 PRIntn i, j = 18;
23
24 for( i = 0; i < 3; i++ )
25 {
26 b32 <<= 8;
27 b32 |= (PRUint32)src[i];
28 }
29
30 for( i = 0; i < 4; i++ )
31 {
32 dest[i] = base[ (PRUint32)((b32>>j) & 0x3F) ];
33 j -= 6;
34 }
35
36 return;
37 }
38
39 static void
40 encode2to4
41 (
42 const unsigned char *src,
43 unsigned char *dest
44 )
45 {
46 dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
47 dest[1] = base[ (PRUint32)(((src[0] & 0x03) << 4) | ((src[1] >> 4) & 0x0F)) ];
48 dest[2] = base[ (PRUint32)((src[1] & 0x0F) << 2) ];
49 dest[3] = (unsigned char)'=';
50 return;
51 }
52
53 static void
54 encode1to4
55 (
56 const unsigned char *src,
57 unsigned char *dest
58 )
59 {
60 dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ];
61 dest[1] = base[ (PRUint32)((src[0] & 0x03) << 4) ];
62 dest[2] = (unsigned char)'=';
63 dest[3] = (unsigned char)'=';
64 return;
65 }
66
67 static void
68 encode
69 (
70 const unsigned char *src,
71 PRUint32 srclen,
72 unsigned char *dest
73 )
74 {
75 while( srclen >= 3 )
76 {
77 encode3to4(src, dest);
78 src += 3;
79 dest += 4;
80 srclen -= 3;
81 }
82
83 switch( srclen )
84 {
85 case 2:
86 encode2to4(src, dest);
87 break;
88 case 1:
89 encode1to4(src, dest);
90 break;
91 case 0:
92 break;
93 default:
94 PR_NOT_REACHED("coding error");
95 }
96
97 return;
98 }
99
100 /*
101 * PL_Base64Encode
102 *
103 * If the destination argument is NULL, a return buffer is
104 * allocated, and the data therein will be null-terminated.
105 * If the destination argument is not NULL, it is assumed to
106 * be of sufficient size, and the contents will not be null-
107 * terminated by this routine.
108 *
109 * Returns null if the allocation fails.
110 */
111
112 PR_IMPLEMENT(char *)
113 PL_Base64Encode
114 (
115 const char *src,
116 PRUint32 srclen,
117 char *dest
118 )
119 {
120 if( 0 == srclen )
121 {
122 size_t len = strlen(src);
123 srclen = len;
124 /* Detect truncation. */
125 if( srclen != len )
126 {
127 return (char *)0;
128 }
129 }
130
131 if( (char *)0 == dest )
132 {
133 PRUint32 destlen;
134 /* Ensure all PRUint32 values stay within range. */
135 if( srclen > (PR_UINT32_MAX/4) * 3 )
136 {
137 return (char *)0;
138 }
139 destlen = ((srclen + 2)/3) * 4;
140 dest = (char *)PR_MALLOC(destlen + 1);
141 if( (char *)0 == dest )
142 {
143 return (char *)0;
144 }
145 dest[ destlen ] = (char)0; /* null terminate */
146 }
147
148 encode((const unsigned char *)src, srclen, (unsigned char *)dest);
149 return dest;
150 }
151
152 static PRInt32
153 codetovalue
154 (
155 unsigned char c
156 )
157 {
158 if( (c >= (unsigned char)'A') && (c <= (unsigned char)'Z') )
159 {
160 return (PRInt32)(c - (unsigned char)'A');
161 }
162 else if( (c >= (unsigned char)'a') && (c <= (unsigned char)'z') )
163 {
164 return ((PRInt32)(c - (unsigned char)'a') +26);
165 }
166 else if( (c >= (unsigned char)'0') && (c <= (unsigned char)'9') )
167 {
168 return ((PRInt32)(c - (unsigned char)'0') +52);
169 }
170 else if( (unsigned char)'+' == c )
171 {
172 return (PRInt32)62;
173 }
174 else if( (unsigned char)'/' == c )
175 {
176 return (PRInt32)63;
177 }
178 else
179 {
180 return -1;
181 }
182 }
183
184 static PRStatus
185 decode4to3
186 (
187 const unsigned char *src,
188 unsigned char *dest
189 )
190 {
191 PRUint32 b32 = (PRUint32)0;
192 PRInt32 bits;
193 PRIntn i;
194
195 for( i = 0; i < 4; i++ )
196 {
197 bits = codetovalue(src[i]);
198 if( bits < 0 )
199 {
200 return PR_FAILURE;
201 }
202
203 b32 <<= 6;
204 b32 |= bits;
205 }
206
207 dest[0] = (unsigned char)((b32 >> 16) & 0xFF);
208 dest[1] = (unsigned char)((b32 >> 8) & 0xFF);
209 dest[2] = (unsigned char)((b32 ) & 0xFF);
210
211 return PR_SUCCESS;
212 }
213
214 static PRStatus
215 decode3to2
216 (
217 const unsigned char *src,
218 unsigned char *dest
219 )
220 {
221 PRUint32 b32 = (PRUint32)0;
222 PRInt32 bits;
223 PRUint32 ubits;
224
225 bits = codetovalue(src[0]);
226 if( bits < 0 )
227 {
228 return PR_FAILURE;
229 }
230
231 b32 = (PRUint32)bits;
232 b32 <<= 6;
233
234 bits = codetovalue(src[1]);
235 if( bits < 0 )
236 {
237 return PR_FAILURE;
238 }
239
240 b32 |= (PRUint32)bits;
241 b32 <<= 4;
242
243 bits = codetovalue(src[2]);
244 if( bits < 0 )
245 {
246 return PR_FAILURE;
247 }
248
249 ubits = (PRUint32)bits;
250 b32 |= (ubits >> 2);
251
252 dest[0] = (unsigned char)((b32 >> 8) & 0xFF);
253 dest[1] = (unsigned char)((b32 ) & 0xFF);
254
255 return PR_SUCCESS;
256 }
257
258 static PRStatus
259 decode2to1
260 (
261 const unsigned char *src,
262 unsigned char *dest
263 )
264 {
265 PRUint32 b32;
266 PRUint32 ubits;
267 PRInt32 bits;
268
269 bits = codetovalue(src[0]);
270 if( bits < 0 )
271 {
272 return PR_FAILURE;
273 }
274
275 ubits = (PRUint32)bits;
276 b32 = (ubits << 2);
277
278 bits = codetovalue(src[1]);
279 if( bits < 0 )
280 {
281 return PR_FAILURE;
282 }
283
284 ubits = (PRUint32)bits;
285 b32 |= (ubits >> 4);
286
287 dest[0] = (unsigned char)b32;
288
289 return PR_SUCCESS;
290 }
291
292 static PRStatus
293 decode
294 (
295 const unsigned char *src,
296 PRUint32 srclen,
297 unsigned char *dest
298 )
299 {
300 PRStatus rv;
301
302 while( srclen >= 4 )
303 {
304 rv = decode4to3(src, dest);
305 if( PR_SUCCESS != rv )
306 {
307 return PR_FAILURE;
308 }
309
310 src += 4;
311 dest += 3;
312 srclen -= 4;
313 }
314
315 switch( srclen )
316 {
317 case 3:
318 rv = decode3to2(src, dest);
319 break;
320 case 2:
321 rv = decode2to1(src, dest);
322 break;
323 case 1:
324 rv = PR_FAILURE;
325 break;
326 case 0:
327 rv = PR_SUCCESS;
328 break;
329 default:
330 PR_NOT_REACHED("coding error");
331 }
332
333 return rv;
334 }
335
336 /*
337 * PL_Base64Decode
338 *
339 * If the destination argument is NULL, a return buffer is
340 * allocated and the data therein will be null-terminated.
341 * If the destination argument is not null, it is assumed
342 * to be of sufficient size, and the data will not be null-
343 * terminated by this routine.
344 *
345 * Returns null if the allocation fails, or if the source string is
346 * not well-formed.
347 */
348
349 PR_IMPLEMENT(char *)
350 PL_Base64Decode
351 (
352 const char *src,
353 PRUint32 srclen,
354 char *dest
355 )
356 {
357 PRStatus status;
358 PRBool allocated = PR_FALSE;
359
360 if( (char *)0 == src )
361 {
362 return (char *)0;
363 }
364
365 if( 0 == srclen )
366 {
367 size_t len = strlen(src);
368 srclen = len;
369 /* Detect truncation. */
370 if( srclen != len )
371 {
372 return (char *)0;
373 }
374 }
375
376 if( srclen && (0 == (srclen & 3)) )
377 {
378 if( (char)'=' == src[ srclen-1 ] )
379 {
380 if( (char)'=' == src[ srclen-2 ] )
381 {
382 srclen -= 2;
383 }
384 else
385 {
386 srclen -= 1;
387 }
388 }
389 }
390
391 if( (char *)0 == dest )
392 {
393 /* The following computes ((srclen * 3) / 4) without overflow. */
394 PRUint32 destlen = (srclen / 4) * 3 + ((srclen % 4) * 3) / 4;
395 dest = (char *)PR_MALLOC(destlen + 1);
396 if( (char *)0 == dest )
397 {
398 return (char *)0;
399 }
400 dest[ destlen ] = (char)0; /* null terminate */
401 allocated = PR_TRUE;
402 }
403
404 status = decode((const unsigned char *)src, srclen, (unsigned char *)dest);
405 if( PR_SUCCESS != status )
406 {
407 if( PR_TRUE == allocated )
408 {
409 PR_DELETE(dest);
410 }
411
412 return (char *)0;
413 }
414
415 return dest;
416 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)