blob: 3d802bc4dcffdeb15666a9182498637020d60510 [file] [log] [blame]
/**
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string.h>
#include <ImsMediaBinaryFormat.h>
#include <ImsMediaTrace.h>
// Default value for non-printable characters
#define NP 0xFF
// Carriage-Return (\r)
#define CR 0x0D
// Line-Feed (\n)
#define LF 0x0A
// Padding character for Base64
#define BASE64_PAD '='
// Constant table for Base64 value encoding / decoding
static const char BASE64_ENCODING_TABLE[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const uint8_t BASE64_DECODING_TABLE[] = {
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 0 ~ 9
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 10 ~ 19
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 20 ~ 29
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 30 ~ 39
NP, NP, NP, 62, NP, NP, NP, 63, 52, 53, // 40 ~ 49
54, 55, 56, 57, 58, 59, 60, 61, NP, NP, // 50 ~ 59
NP, NP, NP, NP, NP, 0, 1, 2, 3, 4, // 60 ~ 69
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 70 ~ 79
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 80 ~ 89
25, NP, NP, NP, NP, NP, NP, 26, 27, 28, // 90 ~ 99
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // 100 ~ 109
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // 110 ~ 119
49, 50, 51, NP, NP, NP, NP, NP, NP, NP, // 120 ~ 129
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 130 ~ 139
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 140 ~ 149
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 150 ~ 159
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 160 ~ 169
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 170 ~ 179
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 180 ~ 189
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 190 ~ 199
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 200 ~ 209
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 210 ~ 219
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 220 ~ 229
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 230 ~ 239
NP, NP, NP, NP, NP, NP, NP, NP, NP, NP, // 240 ~ 249
NP, NP, NP, NP, NP, NP // 250 ~ 256
};
static bool BinaryToBase16(char* pszDst, uint32_t nDstBuffSize, uint8_t* pbSrc, uint32_t nSrcSize)
{
if (((nDstBuffSize - 1) >> 1) < nSrcSize)
return false;
if (nSrcSize > 0)
{
uint32_t m, n;
for (m = 0, n = 0; m < nSrcSize; m++)
{
int8_t c, h, l;
c = (int8_t)pbSrc[m];
h = (c >> 4) & 0x0F;
l = c & 0x0F;
if (h < 10)
h += '0';
else
h += 'A' - 10;
if (l < 10)
l += '0';
else
l += 'A' - 10;
pszDst[n++] = h;
pszDst[n++] = l;
}
pszDst[n] = 0;
}
return true;
}
static bool Base16ToBinary(uint8_t* pbDst, uint32_t* pnDstSize, uint32_t nDstBuffSize, char* pszSrc)
{
uint32_t nSrcLen;
uint32_t src_pos, dst_pos;
nSrcLen = strlen(pszSrc);
if (nSrcLen & 0x1)
nSrcLen++;
if (nDstBuffSize < (nSrcLen >> 1))
return false;
for (src_pos = 0, dst_pos = 0; src_pos < nSrcLen; src_pos += 2, dst_pos++)
{
char h, l;
h = pszSrc[src_pos];
l = pszSrc[src_pos + 1];
if (h >= '0' && h <= '9')
h = h - '0';
else if (h >= 'a' && h <= 'f')
h = h - 'a' + 10;
else if (h >= 'A' && h <= 'F')
h = h - 'A' + 10;
if (l >= '0' && l <= '9')
l = l - '0';
else if (l >= 'a' && l <= 'f')
l = l - 'a' + 10;
else if (l >= 'A' && l <= 'F')
l = l - 'A' + 10;
pbDst[dst_pos] = (h << 4) | l;
}
*pnDstSize = dst_pos;
return true;
}
static bool BinaryToBase64(char* pszDst, uint32_t nDstBuffSize, uint8_t* pbSrc, uint32_t nSrcSize)
{
uint8_t c6bit;
char* pEncBuffer = pszDst;
if ((nDstBuffSize - 1) < ((nSrcSize + 2) / 3 * 4))
return false;
for (int32_t nPos = 0; nPos < nSrcSize; ++nPos)
{
c6bit = (pbSrc[nPos] >> 2) & 0x3F;
(*pEncBuffer) = BASE64_ENCODING_TABLE[(uint8_t)c6bit];
pEncBuffer++;
c6bit = (pbSrc[nPos] << 4) & 0x3F;
if (++nPos < nSrcSize)
c6bit |= (pbSrc[nPos] >> 4) & 0x0F;
(*pEncBuffer) = BASE64_ENCODING_TABLE[(uint8_t)c6bit];
pEncBuffer++;
if (nPos < nSrcSize)
{
c6bit = (pbSrc[nPos] << 2) & 0x3F;
if (++nPos < nSrcSize)
c6bit |= (pbSrc[nPos] >> 6) & 0x03;
(*pEncBuffer) = BASE64_ENCODING_TABLE[(uint8_t)c6bit];
pEncBuffer++;
}
else
{
++nPos;
(*pEncBuffer) = BASE64_PAD;
pEncBuffer++;
}
if (nPos < nSrcSize)
{
c6bit = pbSrc[nPos] & 0x3F;
(*pEncBuffer) = BASE64_ENCODING_TABLE[(uint8_t)c6bit];
pEncBuffer++;
}
else
{
(*pEncBuffer) = BASE64_PAD;
pEncBuffer++;
}
}
(*pEncBuffer) = 0x00;
return true;
}
static bool Base64ToBinary(uint8_t* pbDst, uint32_t* pnDstSize, uint32_t nDstBuffSize, char* pszSrc)
{
char c8bit;
char c8bit1;
uint8_t* pDecBuffer = pbDst;
uint32_t nSrcLen;
nSrcLen = strlen(pszSrc);
if (nDstBuffSize < ((nSrcLen >> 2) * 3 + (nSrcLen & 0x3)))
return false;
for (int32_t nPos = 0; nPos < nSrcLen; ++nPos)
{
if (pszSrc[nPos] == LF)
nPos += 1;
if (pszSrc[nPos] == CR)
nPos += 2;
c8bit = (char)BASE64_DECODING_TABLE[(uint8_t)pszSrc[nPos]];
++nPos;
if (pszSrc[nPos] == LF)
nPos += 1;
if (pszSrc[nPos] == CR)
nPos += 2;
c8bit1 = (char)BASE64_DECODING_TABLE[(uint8_t)pszSrc[nPos]];
c8bit = (c8bit << 2) | ((c8bit1 >> 4) & 0x03);
(*pDecBuffer) = c8bit;
pDecBuffer++;
if (++nPos < nSrcLen)
{
if (pszSrc[nPos] == LF)
nPos += 1;
if (pszSrc[nPos] == CR)
nPos += 2;
c8bit = pszSrc[nPos];
if (c8bit == BASE64_PAD)
break;
c8bit = (char)BASE64_DECODING_TABLE[(uint8_t)pszSrc[nPos]];
c8bit1 = ((c8bit1 << 4) & 0xF0) | ((c8bit >> 2) & 0x0F);
(*pDecBuffer) = c8bit1;
pDecBuffer++;
}
if (++nPos < nSrcLen)
{
if (pszSrc[nPos] == LF)
nPos += 1;
if (pszSrc[nPos] == CR)
nPos += 2;
c8bit1 = pszSrc[nPos];
if (c8bit1 == BASE64_PAD)
break;
c8bit1 = (char)BASE64_DECODING_TABLE[(uint8_t)pszSrc[nPos]];
c8bit = ((c8bit << 6) & 0xC0) | c8bit1;
(*pDecBuffer) = c8bit;
pDecBuffer++;
}
}
*pnDstSize = (uint32_t)(pDecBuffer - pbDst);
return true;
}
bool ImsMediaBinaryFormat::BinaryToBase00(
char* pszDst, uint32_t nDstBuffSize, uint8_t* pbSrc, uint32_t nSrcSize, uint32_t eFormat)
{
switch (eFormat)
{
case BINARY_FORMAT_BASE16:
return BinaryToBase16(pszDst, nDstBuffSize, pbSrc, nSrcSize);
case BINARY_FORMAT_BASE64:
return BinaryToBase64(pszDst, nDstBuffSize, pbSrc, nSrcSize);
case BINARY_FORMAT_BASE32:
default:
IMLOGE1("[BinaryToBase00] not supported binary format %d", eFormat);
return false;
}
}
bool ImsMediaBinaryFormat::Base00ToBinary(
uint8_t* pbDst, uint32_t* pnDstSize, uint32_t nDstBuffSize, char* pszSrc, uint32_t eFormat)
{
switch (eFormat)
{
case BINARY_FORMAT_BASE16:
return Base16ToBinary(pbDst, pnDstSize, nDstBuffSize, pszSrc);
case BINARY_FORMAT_BASE64:
return Base64ToBinary(pbDst, pnDstSize, nDstBuffSize, pszSrc);
case BINARY_FORMAT_BASE32:
default:
IMLOGE1("[Base00ToBinary] not supported binary format %d", eFormat);
return false;
}
}