📄 crfc2047.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 "codecvt.h"
#include "cmntypes.h"
#include "aapicmn.h"
#include "gmem.h"
#include "chartype.h"
#include "crfc2047.h"
#include "ccoder.h"
#define RFC2047_BEGIN "=?UTF-8?"
#define RFC2047_BASE64 "B?"
#define RFC2047_END "?="
#define CMN_CHAR_CONV_TYPE codecvt_convert_t
#define CMN_CHAR_CONV_FUNC_FIND codecvt_find_function
static INT32 cmnCharsetDecodedTextLength( char *charset, const char *from,
INT32 fromLen);
static CMN_BOOL cmnCharsetDecodeText( char *charset, char *to, INT32 *toLen,
const char *from, INT32 fromLen);
static CMN_BOOL cmnDecodeText( CmnClientId client, char encoding,
char **to, INT32 *toLen, const char *from, INT32 fromLen);
static void cmnRfc2047LocateTags( char *from, char **charset, char *encoding,
char **encodedText);
static INT32 cmnCharsetDecodedTextLength( char *charset, const char *from,
INT32 fromLen)
{
INT32 length = -1;
if (cmnCharsetDecodeText( charset, NULL, &length, from, fromLen) == FALSE)
{
CMN_LOG_I(("%s(%d): Couldn't determine length\n", __FILE__, __LINE__));
length = -1;
}
return length;
}
static CMN_BOOL cmnCharsetDecodeText( char *charset, char *to, INT32 *toLen,
const char *from, INT32 fromLen)
{
int mibEnum = -1;
int ret = 0;
int iDestLen = (int)*toLen;
int iSrcLen = (int)fromLen;
char *p = charset;
CMN_CHAR_CONV_TYPE *cvtFunction = NULL;
while (*p)
{
*p = (char)CMN_TOLOWER(*p);
++p;
}
mibEnum = cmnCharsetStr2Enum(charset);
if (mibEnum == CMN_CHARSET_UNKNOWN)
{
mibEnum = CHARSET_LATIN_1;
}
if (mibEnum == CHARSET_UTF_8)
{
if (to)
{
memcpy( to, from, (UINT32)fromLen);
to[fromLen] = 0x00;
}
*toLen = fromLen;
return TRUE;
}
else
{
cvtFunction = CMN_CHAR_CONV_FUNC_FIND( mibEnum, CMN_CHARSET_UTF_8);
if (cvtFunction == NULL)
{
CMN_LOG_I(("%s(%d): Unknown encoding %d\n",
__FILE__, __LINE__, mibEnum));
return FALSE;
}
ret = cvtFunction( from, &iSrcLen, to, &iDestLen);
*toLen = (INT32)iDestLen;
return ret == 0;
}
}
static CMN_BOOL cmnDecodeText( CmnClientId client, char encoding,
char **to, INT32 *toLen, const char *from, INT32 fromLen)
{
CMN_BOOL retVal = FALSE;
switch (encoding)
{
case 'b':
case 'B':
retVal = cmnBase64Decode( client, to, toLen, from, fromLen);
break;
case 'q':
case 'Q':
retVal = cmnQuotedPrintableDecode( client, to, toLen, from);
break;
default:
CMN_LOG_I(("%s(%d): Unknown encoding %d\n", __FILE__, __LINE__, encoding));
retVal = FALSE;
break;
}
return retVal;
}
static void cmnRfc2047LocateTags( char *str, char **charset, char *encoding,
char **encodedText)
{
if (cmnRfc2047IsEncoded(str) != TRUE)
{
CMN_LOG_I(("%s(%d): %s isn't RFC 2047 encoded\n", __FILE__, __LINE__, str));
return;
}
str += 2;
*charset = str;
while (*str != '?')
{
++str;
}
*str = '\0';
++str;
*encoding = *str;
str += 2;
*encodedText = str;
while (str[0] != '\0')
{
if (str[0] == '?' && str[1] == '=')
{
*str = '\0';
return;
}
++str;
}
}
CMN_BOOL cmnRfc2047Decode( CmnClientId client, char **to, INT32 *toSize,
const char *from, INT32 fromLen)
{
CMN_BOOL retVal = FALSE;
char *fromCopy = NULL;
char *charset = NULL;
char encoding = 0x00;
char *encodedText = NULL;
INT32 decodedLen = 0;
UINT32 textLen;
char *decodedText;
if (cmnRfc2047IsEncoded(from) == FALSE)
{
CMN_LOG_I(("%s(%d): %s isn't RFC 2047 encoded\n",
__FILE__, __LINE__, from));
return FALSE;
}
fromCopy = G_CALLOC( client, (UINT32)(fromLen + 1));
if (fromCopy)
{
memcpy( fromCopy, from, (UINT32)(fromLen + 1));
cmnRfc2047LocateTags( fromCopy, &charset, &encoding, &encodedText);
textLen = strlen(encodedText);
if (cmnDecodeText( client, encoding, &decodedText,
&decodedLen, encodedText, (INT32)textLen))
{
*toSize = cmnCharsetDecodedTextLength( charset, decodedText,
decodedLen) + 1;
if (to != NULL)
{
*to = G_CALLOC( client, (UINT32)*toSize);
retVal = cmnCharsetDecodeText( charset, *to, toSize,
decodedText, decodedLen);
if (retVal != TRUE)
{
CMN_LOG_I(("%s(%d): charset decoding failed\n",
__FILE__, __LINE__));
G_FREE( client, *to);
*to = NULL;
*toSize = 0;
}
}
G_FREE( client, decodedText);
}
G_FREE( client, fromCopy);
}
return retVal;
}
INT32 cmnRfc2047DecodedLength( const char *src)
{
INT32 destSize = 0;
if (cmnRfc2047Decode( 0, NULL, &destSize, src, (INT32)strlen(src)) == FALSE)
{
return -1;
}
return (INT32)destSize;
}
CMN_BOOL cmnRfc2047Encode( CmnClientId client, char **to, const char *from)
{
INT32 toSize;
INT32 destLen;
INT32 srcLen = (INT32)strlen(from);
char *tmp;
destLen = cmnBase64EncodedLength(srcLen) + (INT32)strlen(RFC2047_BEGIN) +
(INT32)strlen(RFC2047_BASE64) + (INT32)strlen(RFC2047_END) + 1;
*to = G_CALLOC( client, (UINT32)destLen);
strcpy( *to, RFC2047_BEGIN);
strcat( *to, RFC2047_BASE64);
if (cmnBase64Encode( client, &tmp, &toSize, from, srcLen) == FALSE)
{
CMN_LOG_I(("%s(%d): Base64 encoding failed\n", __FILE__, __LINE__));
G_FREE( client, *to);
*to = NULL;
return FALSE;
}
strcat( *to, tmp);
strcat( *to, RFC2047_END);
G_FREE( client, tmp);
return TRUE;
}
CMN_BOOL cmnRfc2047IsEncoded( const char *str)
{
UINT32 strLen = strlen(str);
if (strLen < 7)
{
CMN_LOG_I(("%s(%d): RFC 2047 string is too short %d\n",
__FILE__, __LINE__, (int)strLen));
return FALSE;
}
if (str[0] != '=' || str[1] != '?')
{
CMN_LOG_I(("%s(%d): RFC 2047 start is wrong %d, %d\n",
__FILE__, __LINE__, (int)str[0], (int)str[1]));
return FALSE;
}
str += 2;
while (*str && *str != '?')
{
++str;
}
if (*str == 0x00)
{
return FALSE;
}
++str;
if (str[0] == 0x00 || str[0] == '?' ||
str[1] == 0x00 || str[1] != '?')
{
return FALSE;
}
str += 2;
while (str[0] != '\0')
{
if (str[0] == '?' && str[1] == '=')
{
return TRUE;
}
++str;
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -