📄 ccoder.c
字号:
/*
* Copyright (C) Obigo AB, 2002-2005.
* All rights reserved.
*
* This software is covered by the license agreement between
* the end user and Obigo AB, and may be
* used and copied only in accordance with the terms of the
* said agreement.
*
* Obigo AB assumes no responsibility or
* liability for any errors or inaccuracies in this software,
* or any consequential, incidental or indirect damage arising
* out of the use of the software.
*
*/
#include "cansilib.h"
#include "cmnconf.h"
#include "cmntypes.h"
#include "aapicmn.h"
#include "chartype.h"
#include "gmem.h"
#include "cutils.h"
#include "ccoder.h"
typedef struct
{
const char *str;
CmnCharset charset;
} CmnCharsetTable;
static const char base64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const CmnCharsetTable charsetTable[] =
{
{ "us-ascii", CMN_CHARSET_US_ASCII},
{ "iso-8859-1", CMN_CHARSET_LATIN_1},
{ "latin-1", CMN_CHARSET_LATIN_1},
{ "utf-8", CMN_CHARSET_UTF_8},
{ "iso-10646-ucs-2", CMN_CHARSET_UCS_2},
{ "utf-16be", CMN_CHARSET_UTF_16BE},
{ "utf-16le", CMN_CHARSET_UTF_16LE},
{ "utf-16", CMN_CHARSET_UTF_16},
{ NULL, CMN_CHARSET_UNKNOWN},
};
static INT8 cmnBase64DecodeChar(UINT8 ch);
static INT8 cmnHexDecodeChar(UINT8 ch);
CMN_BOOL cmnBase64Decode( CmnClientId client, char **to, INT32 *toSize,
const char *from, INT32 fromSize)
{
char b;
INT8 cb;
UINT8 tmp = 0;
UINT8 savedBits = 0;
INT32 srcPos;
INT32 size = 0;
*toSize = cmnBase64DecodedLength( from, fromSize);
if (*toSize <= 0)
{
*to = NULL;
return FALSE;
}
*to = G_CALLOC( client, (UINT32)*toSize);
for (srcPos = 0; srcPos < fromSize; ++srcPos)
{
b = from[srcPos];
if (b == '=')
{
break;
}
else if (b == ' ' || b == '\t' || b == '\r' || b == '\n')
{
continue;
}
cb = cmnBase64DecodeChar((UINT8)b);
if (cb < 0)
{
CMN_LOG_I(("%s(%d): Illegal char %d\n", __FILE__, __LINE__, (int)b));
G_FREE( client, *to);
*to = NULL;
*toSize = 0;
return FALSE;
}
if (savedBits > 0)
{
(*to)[size] = (char)(tmp | ((UINT8)cb >> (savedBits - 2)));
++size;
}
savedBits = (UINT8)((savedBits == 0) ? 6 : savedBits - 2);
if (savedBits > 0)
{
tmp = (UINT8)(((UINT8)cb << (8 - savedBits)) & 0xff);
}
}
*toSize = size;
return TRUE;
}
static INT8 cmnBase64DecodeChar(UINT8 ch)
{
if (ch & 0x80)
{
return -1;
}
else if (CMN_ISUPPER(ch))
{
return (INT8)(ch - 'A');
}
else if (CMN_ISLOWER(ch))
{
return (INT8)(ch - 'a' + 26);
}
else if (CMN_ISDIGIT(ch))
{
return (INT8)(ch - '0' + 52);
}
else if (ch == '+')
{
return 62;
}
else if (ch == '/')
{
return 63;
}
else
{
return -1;
}
}
INT32 cmnBase64DecodedLength( const char *str, INT32 len)
{
INT32 newLen = (len / 4) * 3;
if (len > 0 && newLen > 0 && str[len - 1] == '=')
{
--newLen;
}
if (len > 1 && newLen > 0 && str[len - 2] == '=')
{
--newLen;
}
return newLen;
}
CMN_BOOL cmnBase64Encode( CmnClientId client, char **to, INT32 *toSize,
const char *from, INT32 fromSize)
{
int i;
char *p;
UINT8 *uFrom = (UINT8 *)from;
CMN_BOOL isError = FALSE;
*toSize = cmnBase64EncodedLength(fromSize);
*to = G_CALLOC( client, (UINT32)*toSize + 1);
p = *to;
for (i = 0; (i + 2) < fromSize; i += 3)
{
if (((p + 3) - *to) > *toSize)
{
isError = TRUE;
break;
}
*p++ = base64[(uFrom[i] >> 2) & 0x3f];
*p++ = base64[((uFrom[i] << 4) & 0x30) | ((uFrom[i + 1] >> 4) & 0x0f)];
*p++ = base64[((uFrom[i + 1] << 2) & 0x3c) | ((uFrom[i + 2] >> 6) & 0x03)];
*p++ = base64[uFrom[i + 2] & 0x3f];
}
if (i < fromSize)
{
if (((p + 3) - *to) > *toSize)
{
isError = TRUE;
}
else
{
*p++ = base64[(uFrom[i] >> 2) & 0x3f];
if (i + 1 < fromSize)
{
*p++ = base64[((uFrom[i] << 4) & 0x30) | ((uFrom[i + 1] >> 4) & 0x0f)];
*p++ = base64[(uFrom[i + 1] << 2) & 0x3c];
}
else
{
*p++ = base64[(uFrom[i] << 4) & 0x30];
*p++ = '=';
}
*p++ = '=';
}
}
if (isError || p - *to > *toSize)
{
CMN_LOG_I(("%s(%d): Out of bounds %d. Emergency exit.\n",
__FILE__, __LINE__, *toSize));
G_FREE( client, *to);
*to = NULL;
*toSize = 0;
return FALSE;
}
*p = '\0';
return TRUE;
}
INT32 cmnBase64EncodedLength( INT32 fromSize)
{
return (INT32)((fromSize + 2) / 3 * 4);
}
CmnCharset cmnCharsetStr2Enum( const char *str)
{
int i;
for ( i = 0; charsetTable[i].str != NULL; ++i)
{
if (cmnStrcmpNc( str, charsetTable[i].str) == 0)
{
return charsetTable[i].charset;
}
}
return CMN_CHARSET_UNKNOWN;
}
CMN_BOOL cmnHexDecode( CmnClientId client, char **to, INT32 *toSize,
const char *from, INT32 fromSize)
{
INT32 size;
char *p;
*to = NULL;
*toSize = 0;
if (fromSize % 2 != 0)
{
CMN_LOG_I(("%s(%d): Uneven number of bytes in 'from' string.\n",
__FILE__, __LINE__));
return FALSE;
}
size = fromSize / 2 + 1;
*toSize = size;
*to = G_CALLOC( client, (UINT32)size);
p = *to;
while (*from && size > 0)
{
if (cmnHexDecodeByte( p, from) != TRUE)
{
CMN_LOG_I(("%s(%d): Hex decoding failed.\n",
__FILE__, __LINE__));
G_FREE( client, *to);
*to = NULL;
*toSize = 0;
return FALSE;
}
++p;
from += 2;
--size;
}
return TRUE;
}
CMN_BOOL cmnHexDecodeByte( char *to, const char *from)
{
INT8 low;
INT8 high;
high = cmnHexDecodeChar((UINT8)*from++);
if (*from == '\0')
{
CMN_LOG_I(("%s(%d): Mismatch in actual strlen and in fromSize.\n",
__FILE__, __LINE__));
return FALSE;
}
low = cmnHexDecodeChar((UINT8)*from);
if (high == -1 || low == -1)
{
CMN_LOG_I(("%s(%d): Illegal hex character in 'from' string.\n",
__FILE__, __LINE__));
return FALSE;
}
*to = (char)(((UINT8)high << 4) | low);
return TRUE;
}
static INT8 cmnHexDecodeChar( UINT8 ch)
{
if (CMN_ISDIGIT(ch))
{
return (INT8)(ch - '0');
}
else if (CMN_ISUPPER(ch) && CMN_ISHEXLETTER(ch))
{
return (INT8)(10 + ch - 'A');
}
else if (CMN_ISLOWER(ch) && CMN_ISHEXLETTER(ch))
{
return (INT8)(10 + ch - 'a');
}
else
{
return -1;
}
}
CMN_BOOL cmnQuotedPrintableDecode( CmnClientId client, char **to, INT32 *toSize,
const char *from)
{
char hex;
char *offset;
*toSize = cmnQuotedPrintableDecodedLength(from);
if (*toSize <= 0)
{
CMN_LOG_I(("%s(%d): Length is %ld\n", __FILE__, __LINE__, *toSize));
*to = NULL;
*toSize = 0;
return TRUE;
}
*to = G_CALLOC( client, (UINT32)*toSize);
offset = *to;
while (*from)
{
switch (*from)
{
case '=':
++from;
if (*from == '\r')
{
if (*(from + 1) == '\n')
{
++from;
}
continue;
}
if ( cmnHexDecodeByte( &hex, from) != TRUE)
{
CMN_LOG_I(("%s(%d): Couldn't hexDecode %d, %d\n",
__FILE__, __LINE__, from, *from));
G_FREE( client, *to);
*to = NULL;
return FALSE;
}
*offset++ = hex;
++from;
break;
default:
*offset++ = *from;
break;
}
++from;
}
return TRUE;
}
INT32 cmnQuotedPrintableDecodedLength( const char *buf)
{
INT32 size = 0;
while (*buf)
{
if (*buf == '=')
{
++buf;
if (*buf == '\r')
{
if (*(buf + 1) == '\n')
{
++buf;
}
continue;
}
else if (*buf == '\0')
{
break;
}
++buf;
}
++size;
++buf;
}
return ++size;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -