Mercurial > trustbridge > nss-cmake-static
view nspr/lib/libc/src/base64.c @ 4:b513267f632f tip
Build DBM module
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Tue, 05 Aug 2014 18:58:03 +0200 |
parents | 1e5118fa0cb1 |
children |
line wrap: on
line source
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plbase64.h" #include "prlog.h" /* For PR_NOT_REACHED */ #include "prmem.h" /* for malloc / PR_MALLOC */ #include <string.h> /* for strlen */ static unsigned char *base = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static void encode3to4 ( const unsigned char *src, unsigned char *dest ) { PRUint32 b32 = (PRUint32)0; PRIntn i, j = 18; for( i = 0; i < 3; i++ ) { b32 <<= 8; b32 |= (PRUint32)src[i]; } for( i = 0; i < 4; i++ ) { dest[i] = base[ (PRUint32)((b32>>j) & 0x3F) ]; j -= 6; } return; } static void encode2to4 ( const unsigned char *src, unsigned char *dest ) { dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ]; dest[1] = base[ (PRUint32)(((src[0] & 0x03) << 4) | ((src[1] >> 4) & 0x0F)) ]; dest[2] = base[ (PRUint32)((src[1] & 0x0F) << 2) ]; dest[3] = (unsigned char)'='; return; } static void encode1to4 ( const unsigned char *src, unsigned char *dest ) { dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ]; dest[1] = base[ (PRUint32)((src[0] & 0x03) << 4) ]; dest[2] = (unsigned char)'='; dest[3] = (unsigned char)'='; return; } static void encode ( const unsigned char *src, PRUint32 srclen, unsigned char *dest ) { while( srclen >= 3 ) { encode3to4(src, dest); src += 3; dest += 4; srclen -= 3; } switch( srclen ) { case 2: encode2to4(src, dest); break; case 1: encode1to4(src, dest); break; case 0: break; default: PR_NOT_REACHED("coding error"); } return; } /* * PL_Base64Encode * * If the destination argument is NULL, a return buffer is * allocated, and the data therein will be null-terminated. * If the destination argument is not NULL, it is assumed to * be of sufficient size, and the contents will not be null- * terminated by this routine. * * Returns null if the allocation fails. */ PR_IMPLEMENT(char *) PL_Base64Encode ( const char *src, PRUint32 srclen, char *dest ) { if( 0 == srclen ) { size_t len = strlen(src); srclen = len; /* Detect truncation. */ if( srclen != len ) { return (char *)0; } } if( (char *)0 == dest ) { PRUint32 destlen; /* Ensure all PRUint32 values stay within range. */ if( srclen > (PR_UINT32_MAX/4) * 3 ) { return (char *)0; } destlen = ((srclen + 2)/3) * 4; dest = (char *)PR_MALLOC(destlen + 1); if( (char *)0 == dest ) { return (char *)0; } dest[ destlen ] = (char)0; /* null terminate */ } encode((const unsigned char *)src, srclen, (unsigned char *)dest); return dest; } static PRInt32 codetovalue ( unsigned char c ) { if( (c >= (unsigned char)'A') && (c <= (unsigned char)'Z') ) { return (PRInt32)(c - (unsigned char)'A'); } else if( (c >= (unsigned char)'a') && (c <= (unsigned char)'z') ) { return ((PRInt32)(c - (unsigned char)'a') +26); } else if( (c >= (unsigned char)'0') && (c <= (unsigned char)'9') ) { return ((PRInt32)(c - (unsigned char)'0') +52); } else if( (unsigned char)'+' == c ) { return (PRInt32)62; } else if( (unsigned char)'/' == c ) { return (PRInt32)63; } else { return -1; } } static PRStatus decode4to3 ( const unsigned char *src, unsigned char *dest ) { PRUint32 b32 = (PRUint32)0; PRInt32 bits; PRIntn i; for( i = 0; i < 4; i++ ) { bits = codetovalue(src[i]); if( bits < 0 ) { return PR_FAILURE; } b32 <<= 6; b32 |= bits; } dest[0] = (unsigned char)((b32 >> 16) & 0xFF); dest[1] = (unsigned char)((b32 >> 8) & 0xFF); dest[2] = (unsigned char)((b32 ) & 0xFF); return PR_SUCCESS; } static PRStatus decode3to2 ( const unsigned char *src, unsigned char *dest ) { PRUint32 b32 = (PRUint32)0; PRInt32 bits; PRUint32 ubits; bits = codetovalue(src[0]); if( bits < 0 ) { return PR_FAILURE; } b32 = (PRUint32)bits; b32 <<= 6; bits = codetovalue(src[1]); if( bits < 0 ) { return PR_FAILURE; } b32 |= (PRUint32)bits; b32 <<= 4; bits = codetovalue(src[2]); if( bits < 0 ) { return PR_FAILURE; } ubits = (PRUint32)bits; b32 |= (ubits >> 2); dest[0] = (unsigned char)((b32 >> 8) & 0xFF); dest[1] = (unsigned char)((b32 ) & 0xFF); return PR_SUCCESS; } static PRStatus decode2to1 ( const unsigned char *src, unsigned char *dest ) { PRUint32 b32; PRUint32 ubits; PRInt32 bits; bits = codetovalue(src[0]); if( bits < 0 ) { return PR_FAILURE; } ubits = (PRUint32)bits; b32 = (ubits << 2); bits = codetovalue(src[1]); if( bits < 0 ) { return PR_FAILURE; } ubits = (PRUint32)bits; b32 |= (ubits >> 4); dest[0] = (unsigned char)b32; return PR_SUCCESS; } static PRStatus decode ( const unsigned char *src, PRUint32 srclen, unsigned char *dest ) { PRStatus rv; while( srclen >= 4 ) { rv = decode4to3(src, dest); if( PR_SUCCESS != rv ) { return PR_FAILURE; } src += 4; dest += 3; srclen -= 4; } switch( srclen ) { case 3: rv = decode3to2(src, dest); break; case 2: rv = decode2to1(src, dest); break; case 1: rv = PR_FAILURE; break; case 0: rv = PR_SUCCESS; break; default: PR_NOT_REACHED("coding error"); } return rv; } /* * PL_Base64Decode * * If the destination argument is NULL, a return buffer is * allocated and the data therein will be null-terminated. * If the destination argument is not null, it is assumed * to be of sufficient size, and the data will not be null- * terminated by this routine. * * Returns null if the allocation fails, or if the source string is * not well-formed. */ PR_IMPLEMENT(char *) PL_Base64Decode ( const char *src, PRUint32 srclen, char *dest ) { PRStatus status; PRBool allocated = PR_FALSE; if( (char *)0 == src ) { return (char *)0; } if( 0 == srclen ) { size_t len = strlen(src); srclen = len; /* Detect truncation. */ if( srclen != len ) { return (char *)0; } } if( srclen && (0 == (srclen & 3)) ) { if( (char)'=' == src[ srclen-1 ] ) { if( (char)'=' == src[ srclen-2 ] ) { srclen -= 2; } else { srclen -= 1; } } } if( (char *)0 == dest ) { /* The following computes ((srclen * 3) / 4) without overflow. */ PRUint32 destlen = (srclen / 4) * 3 + ((srclen % 4) * 3) / 4; dest = (char *)PR_MALLOC(destlen + 1); if( (char *)0 == dest ) { return (char *)0; } dest[ destlen ] = (char)0; /* null terminate */ allocated = PR_TRUE; } status = decode((const unsigned char *)src, srclen, (unsigned char *)dest); if( PR_SUCCESS != status ) { if( PR_TRUE == allocated ) { PR_DELETE(dest); } return (char *)0; } return dest; }