b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync/* $Id$ */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync/** @file
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * IPRT - Base64, MIME content transfer encoding.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2009-2012 Oracle Corporation
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync *
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * available from http://www.virtualbox.org. This file is free software;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * General Public License (GPL) as published by the Free Software
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync *
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * The contents of this file may alternatively be used under the terms
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * of the Common Development and Distribution License Version 1.0
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * VirtualBox OSE distribution, in which case the provisions of the
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * CDDL are applicable instead of those of the GPL.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync *
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * You may elect to license modified versions of this file under the
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * terms and conditions of either the GPL or the CDDL or both.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync/*******************************************************************************
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync* Header Files *
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync*******************************************************************************/
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync#include <iprt/base64.h>
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync#include "internal/iprt.h"
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync#include <iprt/assert.h>
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync#include <iprt/err.h>
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync#include <iprt/ctype.h>
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync#include <iprt/string.h>
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync#ifdef RT_STRICT
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync# include <iprt/asm.h>
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync#endif
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync/*******************************************************************************
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync* Defined Constants And Macros *
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync*******************************************************************************/
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync/** The line length used for encoding. */
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync#define RTBASE64_LINE_LEN 64
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync/** @name Special g_au8CharToVal values
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * @{ */
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync#define BASE64_SPACE 0xc0
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync#define BASE64_PAD 0xe0
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync#define BASE64_INVALID 0xff
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync/** @} */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync/*******************************************************************************
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync* Global Variables *
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync*******************************************************************************/
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync/** Base64 character to value. (RFC 2045)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * ASSUMES ASCII / UTF-8. */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsyncstatic const uint8_t g_au8CharToVal[256] =
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync{
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xff, 0xff, /* 0x00..0x0f */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x10..0x1f */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 62, 0xff, 0xff, 0xff, 63, /* 0x20..0x2f */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, /* 0x30..0x3f */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 0xff, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40..0x4f */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x50..0x5f */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 0xff, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60..0x6f */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x70..0x7f */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x80..0x8f */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x90..0x9f */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xa0..0xaf */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0..0xbf */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xc0..0xcf */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd0..0xdf */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xe0..0xef */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* 0xf0..0xff */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync};
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync/** Value to Base64 character. (RFC 2045) */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsyncstatic const char g_szValToChar[64+1] =
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync#ifdef RT_STRICT
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync/**
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Perform table sanity checks on the first call.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsyncstatic void rtBase64Sanity(void)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync{
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync static bool s_fSane = false;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (RT_UNLIKELY(!s_fSane))
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync for (unsigned i = 0; i < 64; i++)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync unsigned ch = g_szValToChar[i];
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync Assert(ch);
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync Assert(g_au8CharToVal[ch] == i);
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync for (unsigned i = 0; i < 256; i++)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync uint8_t u8 = g_au8CharToVal[i];
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync Assert( ( u8 == BASE64_INVALID
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync && !RT_C_IS_ALNUM(i)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync && !RT_C_IS_SPACE(i))
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync || ( u8 == BASE64_PAD
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync && i == '=')
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync || ( u8 == BASE64_SPACE
51d08d098f20a2d43e3a72258e9082cee8a88784vboxsync && RT_C_IS_SPACE(i))
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync || ( u8 < 64
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync && (unsigned)g_szValToChar[u8] == i));
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync ASMAtomicWriteBool(&s_fSane, true);
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync}
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync#endif /* RT_STRICT */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(ssize_t) RTBase64DecodedSizeEx(const char *pszString, size_t cchStringMax, char **ppszEnd)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync{
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync#ifdef RT_STRICT
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync rtBase64Sanity();
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync#endif
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /*
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Walk the string until a non-encoded or non-space character is encountered.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync uint32_t c6Bits = 0;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync uint8_t u8 = BASE64_INVALID;
40678526ebfcafa6de6ce3e1e279e344b042e8a5vboxsync unsigned ch = 0;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync AssertCompile(sizeof(char) == sizeof(uint8_t));
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (cchStringMax > 0 && (ch = *pszString))
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync u8 = g_au8CharToVal[ch];
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (u8 < 64)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync c6Bits++;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync else if (RT_UNLIKELY(u8 != BASE64_SPACE))
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync break;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /* advance */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pszString++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchStringMax--;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /*
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Padding can only be found at the end and there is
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * only 1 or 2 padding chars. Deal with it first.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync unsigned cbPad = 0;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (u8 == BASE64_PAD)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cbPad = 1;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync c6Bits++;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pszString++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchStringMax--;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync while (cchStringMax > 0 && (ch = *pszString))
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync u8 = g_au8CharToVal[ch];
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (u8 != BASE64_SPACE)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (u8 != BASE64_PAD)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync break;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync c6Bits++;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cbPad++;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pszString++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchStringMax--;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (cbPad >= 3)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return -1;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /*
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Invalid char and no where to indicate where the
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Base64 text ends? Return failure.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if ( u8 == BASE64_INVALID
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync && !ppszEnd
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync && ch)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return -1;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /*
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Recalc 6-bit to 8-bit and adjust for padding.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync size_t cb;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (c6Bits * 3 / 3 == c6Bits)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if ((c6Bits * 3 % 4) != 0)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return -1;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cb = c6Bits * 3 / 4;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync else
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if ((c6Bits * (uint64_t)3 % 4) != 0)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return -1;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cb = c6Bits * (uint64_t)3 / 4;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (cb < cbPad)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return -1;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cb -= cbPad;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (ppszEnd)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync *ppszEnd = (char *)pszString;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return cb;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRT_EXPORT_SYMBOL(RTBase64DecodedSizeEx);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(ssize_t) RTBase64DecodedSize(const char *pszString, char **ppszEnd)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTBase64DecodedSizeEx(pszString, RTSTR_MAX, ppszEnd);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncRT_EXPORT_SYMBOL(RTBase64DecodedSize);
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(int) RTBase64DecodeEx(const char *pszString, size_t cchStringMax, void *pvData, size_t cbData,
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync size_t *pcbActual, char **ppszEnd)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync{
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync#ifdef RT_STRICT
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync rtBase64Sanity();
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync#endif
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /*
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Process input in groups of 4 input / 3 output chars.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
710a6316a22868b04400caf79719f96c18163cd3vboxsync uint8_t u8Trio[3] = { 0, 0, 0 }; /* shuts up gcc */
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync uint8_t *pbData = (uint8_t *)pvData;
2d7bbced35e18187687ac5810ff77d00b3423455vboxsync unsigned ch;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync uint8_t u8;
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync unsigned c6Bits = 0;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync AssertCompile(sizeof(char) == sizeof(uint8_t));
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync for (;;)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /* The first 6-bit group. */
ab68e23ea892b1bbcc90d441a1e9afd259089dfcvboxsync while ((u8 = g_au8CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pszString++, cchStringMax--;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (u8 >= 64)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync c6Bits = 0;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync break;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync u8Trio[0] = u8 << 2;
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync pszString++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchStringMax--;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /* The second 6-bit group. */
ab68e23ea892b1bbcc90d441a1e9afd259089dfcvboxsync while ((u8 = g_au8CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pszString++, cchStringMax--;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (u8 >= 64)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync c6Bits = 1;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync break;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync u8Trio[0] |= u8 >> 4;
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync u8Trio[1] = u8 << 4;
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync pszString++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchStringMax--;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /* The third 6-bit group. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync u8 = BASE64_INVALID;
ab68e23ea892b1bbcc90d441a1e9afd259089dfcvboxsync while ((u8 = g_au8CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pszString++, cchStringMax--;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (u8 >= 64)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync c6Bits = 2;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync break;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync u8Trio[1] |= u8 >> 2;
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync u8Trio[2] = u8 << 6;
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync pszString++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchStringMax--;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /* The fourth 6-bit group. */
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync u8 = BASE64_INVALID;
ab68e23ea892b1bbcc90d441a1e9afd259089dfcvboxsync while ((u8 = g_au8CharToVal[ch = cchStringMax > 0 ? (uint8_t)*pszString : 0]) == BASE64_SPACE)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync pszString++, cchStringMax--;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (u8 >= 64)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync c6Bits = 3;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync break;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync u8Trio[2] |= u8;
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync pszString++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchStringMax--;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /* flush the trio */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (cbData < 3)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return VERR_BUFFER_OVERFLOW;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cbData -= 3;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pbData[0] = u8Trio[0];
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pbData[1] = u8Trio[1];
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pbData[2] = u8Trio[2];
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pbData += 3;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /*
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Padding can only be found at the end and there is
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * only 1 or 2 padding chars. Deal with it first.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync unsigned cbPad = 0;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (u8 == BASE64_PAD)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cbPad = 1;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pszString++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchStringMax--;
ab68e23ea892b1bbcc90d441a1e9afd259089dfcvboxsync while (cchStringMax > 0 && (ch = (uint8_t)*pszString))
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync u8 = g_au8CharToVal[ch];
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (u8 != BASE64_SPACE)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (u8 != BASE64_PAD)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync break;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cbPad++;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pszString++;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync cchStringMax--;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (cbPad >= 3)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return VERR_INVALID_BASE64_ENCODING;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /*
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Invalid char and no where to indicate where the
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Base64 text ends? Return failure.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if ( u8 == BASE64_INVALID
4ca402de19f8fba11f023409e3903f52100d1515vboxsync && !ppszEnd
4ca402de19f8fba11f023409e3903f52100d1515vboxsync && ch != '\0')
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return VERR_INVALID_BASE64_ENCODING;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /*
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Check padding vs. pending sextets, if anything left to do finish it off.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync if (c6Bits || cbPad)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync if (c6Bits + cbPad != 4)
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync return VERR_INVALID_BASE64_ENCODING;
909b49e9391c03444e8aadbc0d9b5ff78669cfb2vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync switch (c6Bits)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync case 1:
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync u8Trio[1] = u8Trio[2] = 0;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync break;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync case 2:
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync u8Trio[2] = 0;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync break;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync case 3:
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync default:
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync break;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync switch (3 - cbPad)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync case 1:
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (cbData < 1)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return VERR_BUFFER_OVERFLOW;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cbData--;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pbData[0] = u8Trio[0];
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pbData++;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync break;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync case 2:
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (cbData < 2)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return VERR_BUFFER_OVERFLOW;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cbData -= 2;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pbData[0] = u8Trio[0];
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pbData[1] = u8Trio[1];
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync pbData += 2;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync break;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync default:
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync break;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync /*
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Set optional return values and return successfully.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (ppszEnd)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync *ppszEnd = (char *)pszString;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (pcbActual)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync *pcbActual = pbData - (uint8_t *)pvData;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return VINF_SUCCESS;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync}
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRT_EXPORT_SYMBOL(RTBase64DecodeEx);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsyncRTDECL(int) RTBase64Decode(const char *pszString, void *pvData, size_t cbData, size_t *pcbActual, char **ppszEnd)
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync{
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync return RTBase64DecodeEx(pszString, RTSTR_MAX, pvData, cbData, pcbActual, ppszEnd);
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync}
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncRT_EXPORT_SYMBOL(RTBase64Decode);
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync/**
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Calculates the length of the Base64 encoding of a given number of bytes of
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * data.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync *
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * This will assume line breaks every 64 chars. A RTBase64EncodedLengthEx
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * function can be added if closer control over the output is found to be
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * required.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync *
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * @returns The Base64 string length.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * @param cbData The number of bytes to encode.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsyncRTDECL(size_t) RTBase64EncodedLength(size_t cbData)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync{
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync if (cbData * 8 / 8 != cbData)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync {
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync AssertReturn(sizeof(size_t) == sizeof(uint64_t), ~(size_t)0);
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync uint64_t cch = cbData * (uint64_t)8;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync while (cch % 24)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cch += 8;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cch /= 6;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
2400ef9ff1502b88791bf36bc8aeac8dfa57c91cvboxsync cch += ((cch - 1) / RTBASE64_LINE_LEN) * RTBASE64_EOL_SIZE;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return cch;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync }
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync size_t cch = cbData * 8;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync while (cch % 24)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cch += 8;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync cch /= 6;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
2400ef9ff1502b88791bf36bc8aeac8dfa57c91cvboxsync cch += ((cch - 1) / RTBASE64_LINE_LEN) * RTBASE64_EOL_SIZE;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync return cch;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync}
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncRT_EXPORT_SYMBOL(RTBase64EncodedLength);
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync/**
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * Encodes the specifed data into a Base64 string, the caller supplies the
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * output buffer.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync *
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * This will make the same assumptions about line breaks and EOL size as
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * RTBase64EncodedLength() does. A RTBase64EncodeEx function can be added if
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * more strict control over the output formatting is found necessary.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync *
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * @returns IRPT status code.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * may contain an invalid Base64 string.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync *
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * @param pvData The data to encode.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync * @param cbData The number of bytes to encode.
df5f1b4303be82a000284349e9392beb9f1b6f11vboxsync * @param pszBuf Where to put the Base64 string.
df5f1b4303be82a000284349e9392beb9f1b6f11vboxsync * @param cbBuf The size of the output buffer, including the terminator.
df5f1b4303be82a000284349e9392beb9f1b6f11vboxsync * @param pcchActual The actual number of characters returned.
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync */
df5f1b4303be82a000284349e9392beb9f1b6f11vboxsyncRTDECL(int) RTBase64Encode(const void *pvData, size_t cbData, char *pszBuf, size_t cbBuf, size_t *pcchActual)
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync{
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync /*
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync * Process whole "trios" of input data.
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync */
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync uint8_t u8A;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync uint8_t u8B;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync uint8_t u8C;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync size_t cbLineFeed = cbBuf - RTBASE64_LINE_LEN;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync const uint8_t *pbSrc = (const uint8_t *)pvData;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync char *pchDst = pszBuf;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync while (cbData >= 3)
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync {
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync if (cbBuf < 4 + 1)
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync return VERR_BUFFER_OVERFLOW;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync /* encode */
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync u8A = pbSrc[0];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst[0] = g_szValToChar[u8A >> 2];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync u8B = pbSrc[1];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst[1] = g_szValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync u8C = pbSrc[2];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst[2] = g_szValToChar[((u8B << 2) & 0x3f) | (u8C >> 6)];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst[3] = g_szValToChar[u8C & 0x3f];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync /* advance */
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync cbBuf -= 4;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst += 4;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync cbData -= 3;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pbSrc += 3;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync
c0e1b51d9d294f2826624ff25a2b759aab3ef5f9vboxsync /* deal out linefeeds */
c0e1b51d9d294f2826624ff25a2b759aab3ef5f9vboxsync if (cbBuf == cbLineFeed && cbData)
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync {
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync if (cbBuf < RTBASE64_EOL_SIZE + 1)
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync return VERR_BUFFER_OVERFLOW;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync cbBuf -= RTBASE64_EOL_SIZE;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync if (RTBASE64_EOL_SIZE == 2)
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync *pchDst++ = '\r';
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync *pchDst++ = '\n';
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync cbLineFeed = cbBuf - RTBASE64_LINE_LEN;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync }
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync }
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync /*
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync * Deal with the odd bytes and string termination.
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync */
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync if (cbData)
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync {
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync if (cbBuf < 4 + 1)
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync return VERR_BUFFER_OVERFLOW;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync switch (cbData)
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync {
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync case 1:
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync u8A = pbSrc[0];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst[0] = g_szValToChar[u8A >> 2];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst[1] = g_szValToChar[(u8A << 4) & 0x3f];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst[2] = '=';
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst[3] = '=';
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync break;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync case 2:
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync u8A = pbSrc[0];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst[0] = g_szValToChar[u8A >> 2];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync u8B = pbSrc[1];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst[1] = g_szValToChar[((u8A << 4) & 0x3f) | (u8B >> 4)];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst[2] = g_szValToChar[(u8B << 2) & 0x3f];
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst[3] = '=';
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync break;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync }
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync pchDst += 4;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync }
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync *pchDst = '\0';
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync if (pcchActual)
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync *pcchActual = pchDst - pszBuf;
9f9488dd30b14c1591d8bcad931ab508095217c9vboxsync return VINF_SUCCESS;
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync}
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncRT_EXPORT_SYMBOL(RTBase64Encode);
b0ab7e3ff45cca3c9755432dde464562cdde61f0vboxsync