omadrm/drmengine/dm/src/b64.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:52:27 +0200
changeset 0 95b198f216e5
child 18 8a03a285ab14
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  This class implements the base64 en/decoding.
*
*/


#include <e32base.h>
#include "base64.h"

/*  6    LOCAL DEFINITIONS */

/*  6.1    Local include files */

/*  6.2    Local constants */

LOCAL_C const TUint8 pBase64[] = 
	{                   
	0x3e, 0x7f, 0x7f, 0x7f, 0x3f, 0x34, 0x35, 0x36,
	0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x7f,
	0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x01,
	0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
	0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
	0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
	0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x1a, 0x1b,
	0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
	0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
	0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
	};

/*  6.3    Local macros */
#define b64blocks(l) (((l) + 2) / 3 * 4)
/* #define b64octets(l)  ((l) / 4  * 3) */

/*  6.4    Local data types */

/*  6.5    Local data structures */

/*  6.6    Local function prototypes */

LOCAL_C TInt b64valid(TUint8 *);

/*  7    MODULE CODE */

/* ========================================================================= */

/*  7.2 */

/* Functional description
 *
 * This function does base64 decoding. As the outputted buffer is always 33% shorter than 
 * the input buffer, the caller may want to reallocate the buffer after calling this function.
 *
 * Parameters
 *
 * Pointer to source containing data to decode
 *
 source
 *
 * Length of source buffer
 *
 length
 *
 * pointer to the destination buffer
 * Note: the user must allocate memory for this buffer that its length at least can not be shorter than
 *       the length of source. The user also can use same buffer for both source and destination.
 *
 destination
 *
 * length of the buffer allocated
 *
 destination_length
 *
 * Return values
 *
 *	byte 0 if OK else > 0
 */

/* ---------------------------------------------------------------------- */

TInt b64decode(TUint8 *source, TUint32 length, TUint8 *destination, TUint32 *destination_length)
	{
	/* Data structures */

	/*  Code  */
    
	TUint8   *buf/*, *pbuf*/;     /* Decoding buffer pointers. */
	register TUint32 x = 0;          /* General purpose integers. */
	TUint32 buf_index = 0;  /* current index in destination buffer */

	
	/* buffer to avoid allocating wholly new buffer for output */
	TUint8 localBuffer[4] = {0,0,0,0}; 
	TUint8* pLocalBufferOutPointer = 0;
	
	register TUint32 i = 0;
	TUint32 num;

    TUint8   c = 0;          /* Character to decode. */
    TUint8 localBufferIndex = 0;

    /*	int32 buf_length = 0; */ /* new length of destination buf */
	const TUint8 pad = 0x3d; /* '=' */

	if(!source || length == 0 || !destination || !destination_length)
		{
		return KErrArgument;
		}

	/* Collating sequence independant "===". */

	/* Calculate the amount of '=' in the end of the source */
	for(x=0, buf=source + (length-1); *buf == pad; buf --)
		{
		x++;
		}

	/* max allow 3 "===" in the end of content */
	if (x > 3)
		{                                       
		return KErrArgument;
		}

	/* Save the encoded string pointer. */
	// pbuf = destination; 

	/* save address for first output block */
	pLocalBufferOutPointer = destination;
	x = 0; /* Initialize index. */

	localBufferIndex = 0;


	Mem::Copy(localBuffer, source, 4);

	for (i = length; i != 0; i-- ) /* Decode every byte of the base 64 string */
		{
		/* c = *pbuf++; */
		c = localBuffer[localBufferIndex++];

		if(localBufferIndex == 4)
			{
			localBufferIndex = 0;
			
			source = source + 4;

			/* INPUT: copy next input block to local buffer */
			num = i > 4 ? 4 : i - 1;
			if(num > 0)
				{
				Mem::Copy(localBuffer, source, num);
				}
			}

		/* Ignore "=". */
		if  (c == pad)
			{
			break; /* this must be the end of the buffer, or else ve have a invalid character */
			}
		
		if  (c == '\n' || c == '\r' || c == '\t') /* ignore linefeed tab and cr */
			{
			continue;
			}
		
		/* Valid Base64 Index? */
		if (!b64valid(&c))
			{
			/* b64free(buf); */
			return KErrArgument;
			}
        
		/* Decode 4 byte words into 3 byte octets.*/
		switch(x % 4)
			{
			case 0: /* Byte 0 of word.*/
				pLocalBufferOutPointer[buf_index] = (TInt8)(c << 2);
				break;                          
			case 1: /* Byte 1 of word. */
				pLocalBufferOutPointer[buf_index] |= c >> 4;
				buf_index ++;
				pLocalBufferOutPointer[buf_index] = (TInt8)( (c & 0x0f) << 4 );
				break;
			case 2: /* Byte 2 of word. */
				pLocalBufferOutPointer[buf_index] |= c >> 2;
				buf_index ++;
				pLocalBufferOutPointer[buf_index] = (TInt8)( (c & 0x03) << 6 );
				break;
			case 3: /* Byte 3 of word. */
				pLocalBufferOutPointer[buf_index] |= c;
				buf_index ++;
				break;
			default: /* useless, just to depress warnings */
				break;
			}
		
		x++; /* Increment word byte. */
		

		} /* while */


	/* make sure that there is zero at the end of the buffer
	   though buf[buf_index] shoule be zero after decoding
	*/

	
	/* pbuf[buf_index+1] = 0; */

	/*buf[buf_index+1]=0*/
	/* don't return the size of the buffer (buf_length), but the data size we put in (buf_index)*/
	*destination_length = buf_index; 
	return KErrNone;
	}

/*  7.3 */

/* Functional description
 *
 * This function validates the character according to the base64 rules,
 * and changes it to the corresponding value in the table.
 *
 * Parameters
 *
 * Pointer to character to validate
 *
 c
 *
 * Return values
 *
 *	TRUE if character is valid else FALSE.
 */

/* ---------------------------------------------------------------------- */

LOCAL_C TInt b64valid(TUint8 *c)
	{
	/* Data structures */

	/*  Code  */

	/* If not within the range of the table, return false. */
	if ((*c < 0x2b) || (*c > 0x7a))
		{
		return 0;
		}
	/* If it falls within one of the gaps, return false. */
	if ((*c = pBase64[*c - 0x2b]) == 0x7f)
		{
		return 0;
		}
	
	return 1; /* Otherwise, return true. */
	}

/*  7.4 */

/* Functional description
 *
 * This function allocates a buffer in the size of the parameter.
 *
 * Parameters
 *
 * Size of buffer to allocate
 *
 length
 *
 * Return values
 *
 *	pointer to buffer
 */

/* ---------------------------------------------------------------------- */
#ifdef BUILD_BASE64_ENCODE

LOCAL TUint8 *b64buffer(TUint32 length)
	{
	/* Data structures */

	/*  Code  */

	TUint8 *buf; /* buffer pointers. */
	
	if  (!length) /* dont allow buf size  0 */
		{
		return  NULL;
		}
	
	buf = (TUint8 *) DRM_BLOCK_ALLOC(length); 
	
	return buf; /* Return the pointer or null. */
	}
#endif /* #ifdef BUILD_BASE64_ENCODE */

/* End of File */