Files
microser/mmslib/asn1/ard_vstr.c
2026-06-15 15:48:16 +08:00

215 lines
8.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/************************************************************************/
/* SISCO SOFTWARE MODULE HEADER *****************************************/
/************************************************************************/
/* (c) Copyright Systems Integration Specialists Company, Inc., */
/* 1986 - 2004, All Rights Reserved. */
/* */
/* PROPRIETARY AND CONFIDENTIAL */
/* */
/* MODULE NAME : ard_vstr.c */
/* PRODUCT(S) : ASN1DE */
/* */
/* MODULE DESCRIPTION : */
/* */
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
/* */
/* MODIFICATION LOG : */
/* Date Who Rev Comments */
/* -------- --- ------ ------------------------------------------- */
/* 12/05/05 JRB 09 Add asn1r_get_vstr_maxlen. */
/* 03/22/05 JRB 08 Fix cast in log macro. */
/* 01/16/04 EJV 07 Added typecast to elim warning on AIX. */
/* 09/24/03 JRB 06 Fix to properly decode 0-length UTF8string. */
/* 04/22/03 JRB 05 Allow fixed len UTF8 only if local fmt=UTF16.*/
/* 04/02/03 JRB 04 Add UTF8string support (asn1r_get_utf8) */
/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_DEC_CTXT. */
/* 09/13/99 MDE 02 Added SD_CONST modifiers */
/* 07/26/99 MDE 01 New module, derived from ad_vstr.c */
/************************************************************************/
#include "glbtypes.h"
#include "sysincs.h"
#include <ctype.h>
#include "asn1r.h"
#include "asn1log.h"
/************************************************************************/
/* For debug version, use a static pointer to avoid duplication of */
/* __FILE__ strings. */
#ifdef DEBUG_SISCO
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
#endif
/************************************************************************/
/* asn1r_get_vstr_maxlen */
/* Just like asn1r_get_vstr but checks the string length. */
/* NOTE: caller's buffer must be 1 byte bigger than max_len to allow */
/* room for NULL terminator. */
/************************************************************************/
ST_RET asn1r_get_vstr_maxlen (ASN1_DEC_CTXT *aCtx, ST_CHAR *ptr, ST_INT max_len)
{
if (aCtx->asn1r_elmnt_len > max_len)
{
ALOG_ERR0("ASN.1 decode: visible string too long");
return (SD_FAILURE);
}
else
return (asn1r_get_vstr (aCtx, ptr));
}
/************************************************************************/
/* get_vstr */
/* Reads visible character data from message into selected buffer. If */
/* character is encountered which is not valid for ASN.1 VisibleString */
/* type, error code will be returned as function return value. Other- */
/* wise, function return value will be zero. The calling function must */
/* verify that buffer is big enough. Conversion from ASCII to local */
/* character representation is not necessary for MS-DOS. */
/************************************************************************/
ST_RET asn1r_get_vstr (ASN1_DEC_CTXT *ac, ST_CHAR *ptr)
{
ST_INT i;
#ifdef DEBUG_ASN1_DECODE
if (!ptr)
{
slogCallStack (sLogCtrl,
"get_vstr: attempt to reference through a NULL pointer");
return(SD_FAILURE);
}
#endif
for (i = ac->asn1r_elmnt_len; i; --i)
{
*ptr = (ST_CHAR) *(ac->asn1r_field_ptr++); /* Move character to user buffer. */
if (*ptr < ' ') /* Check that character is not a control char. */
{
ALOG_NERR1 ("ASN.1 decode: invalid character (0x%02x) in visible string",
(ST_UINT)(ST_UCHAR) *ptr); /* 2 casts to avoid sign extension*/
return (SD_FAILURE);
}
ptr++;
}
*ptr = '\x00'; /* Null terminate the visible string. */
return(SD_SUCCESS); /* If no problelms, return success. */
}
/************************************************************************/
/* asn1r_get_utf8 */
/* Reads Unicode UTF8 string data from message into selected buffer. If */
/* character is encountered which is not valid for ASN.1 UTF8string */
/* type, error code will be returned as function return value. Other- */
/* wise, function return value will be zero. The calling function must */
/* verify that buffer is big enough. */
/************************************************************************/
ST_RET asn1r_get_utf8 (ASN1_DEC_CTXT *aCtx, ST_CHAR *ptr, ST_INT el_len)
{
ST_INT dst_len, local_len;
#ifdef DEBUG_ASN1_DECODE
if (!ptr)
{
slogCallStack (sLogCtrl,
"get_utf8: attempt to reference through a NULL pointer");
return(SD_FAILURE);
}
#endif
/* Convert from UTF8 to local format. Input is NOT NULL terminated.
* abs (el_len) = maximum number of Unicode "characters".
* Multiply by the maximum size of each Unicode "character".
*/
#if (UNICODE_LOCAL_FORMAT==UNICODE_UTF16)
dst_len = abs(el_len)*2;
#else /* default is UTF8 */
dst_len = abs(el_len)*4;
#endif
local_len = asn1r_utf8_to_local (ptr, dst_len, (ST_CHAR *) aCtx->asn1r_field_ptr, aCtx->asn1r_elmnt_len);
if (local_len < 0)
{
ALOG_NERR0 ("ASN.1 decode: UTF8 to local conversion failed");
return(SD_FAILURE);
}
/* If this is "fixed length" (el_len>0), length must match. */
#if (UNICODE_LOCAL_FORMAT==UNICODE_UTF16)
if (el_len > 0 && el_len*2 != local_len) /* Fixed len string */
{
ALOG_NERR2 ("ASN.1 decode: expected UTF8string%d, received UTF8string%d",
el_len, local_len/2);
return (SD_FAILURE);
}
*(ST_UINT16*)(ptr+local_len) = 0; /* add "2 byte" NULL */
#else /* default is UTF8 */
if (el_len > 0) /* Fixed len string */
{
/* This error should never occur because no way to define fixed len UTF8.*/
ALOG_ERR0 ("ASN.1 decode: 'FIXED LENGTH' UTF8string not supported on this platform");
return (SD_FAILURE);
}
ptr[local_len] = '\0'; /* add NULL */
#endif
aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; /* Update decode ptr*/
return(SD_SUCCESS);
}
#if (UNICODE_LOCAL_FORMAT==UNICODE_UTF16)
#if defined(_WIN32)
#include <windows.h>
/************************************************************************/
/* On Windows, the local format is UTF16, so this function converts */
/* from UTF8 string to UTF16 string. */
/* CRITICAL: "dst" is NOT automatically NULL terminated, so calling */
/* function must do so if necessary. */
/* dst_len = num bytes in dst "UTF16" string. */
/* src_len = num bytes in src "UTF8" string. */
/************************************************************************/
ST_INT asn1r_utf8_to_local (ST_CHAR *dst, ST_INT dst_len, ST_CHAR *src, ST_INT src_len)
{
int ret;
ST_UINT16 *dst_utf16 = (ST_UINT16 *) dst;
/* This function expects the max number of UTF16 chars (2 bytes per char)
* in the last arg, so divide "dst_len" by 2.
* It does NOT automatically NULL terminate, so neither does this function.
* It returns the number of UTF16 chars converted, so we multiply the
* return value by 2 to return the number of bytes.
*/
/*renxiaobao UTF8<46><38><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD>޸<EFBFBD>*/
#ifdef WIN32
memcpy(dst,src,src_len); return src_len;
#else
ret = MultiByteToWideChar (CP_UTF8, 0,
src, src_len, dst_utf16, dst_len/2);
if (ret >= 0)
return (ret*2); /* success */
return (-1); /* error */
#endif
}
#else /* All other systems */
#error Unicode UTF16 currently only supported on Windows
#endif
#else /* UNICODE_LOCAL_FORMAT==UNICODE_UTF8 */
/************************************************************************/
/* This function should work on any system where the local Unicode */
/* format is UTF8. The ASN.1 format is also UTF8, so this function */
/* basically just copies the string. */
/* CRITICAL: dst_len must be >= src_len */
/************************************************************************/
ST_INT asn1r_utf8_to_local (ST_CHAR *dst, ST_INT dst_len, ST_CHAR *src, ST_INT src_len)
{
if (dst_len >= src_len) /* make sure dst has room */
{
if (src_len > 0)
memcpy (dst, src, src_len);
return (src_len); /* success */
}
return (-1); /* error */
}
#endif /* UNICODE_LOCAL_FORMAT==UNICODE_UTF8 */