omadrm/drmengine/dm/src/b64.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 16 Apr 2010 15:14:55 +0300
changeset 23 493788a4a8a4
parent 0 95b198f216e5
permissions -rw-r--r--
Revision: 201011 Kit: 201015

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