asn1-ut-string.cpp revision 30d5bd8604e5b514b0e4f6360c0384ab1c7851fe
/* $Id$ */
/** @file
* IPRT - ASN.1, XXX STRING Types.
*/
/*
* Copyright (C) 2006-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
/*******************************************************************************
* Global Variables *
*******************************************************************************/
static uint8_t const g_acbStringTags[] =
{
/* [ASN1_TAG_EOC] = */ 0,
/* [ASN1_TAG_BOOLEAN] = */ 0,
/* [ASN1_TAG_INTEGER] = */ 0,
/* [ASN1_TAG_BIT_STRING] = */ 0,
/* [ASN1_TAG_OCTET_STRING] = */ 0,
/* [ASN1_TAG_NULL] = */ 0,
/* [ASN1_TAG_OID] = */ 0,
/* [ASN1_TAG_OBJECT_DESCRIPTOR] = */ 0,
/* [ASN1_TAG_EXTERNAL] = */ 0,
/* [ASN1_TAG_REAL] = */ 0,
/* [ASN1_TAG_ENUMERATED] = */ 0,
/* [ASN1_TAG_EMBEDDED_PDV] = */ 0,
/* [ASN1_TAG_UTF8_STRING] = */ 1,
/* [ASN1_TAG_RELATIVE_OID] = */ 0,
/* [ASN1_TAG_RESERVED_14] = */ 0,
/* [ASN1_TAG_RESERVED_15] = */ 0,
/* [ASN1_TAG_SEQUENCE] = */ 0,
/* [ASN1_TAG_SET] = */ 0,
/* [ASN1_TAG_NUMERIC_STRING] = */ 1,
/* [ASN1_TAG_PRINTABLE_STRING] = */ 1,
/* [ASN1_TAG_T61_STRING] = */ 1,
/* [ASN1_TAG_VIDEOTEX_STRING] = */ 1,
/* [ASN1_TAG_IA5_STRING] = */ 1,
/* [ASN1_TAG_UTC_TIME] = */ 0,
/* [ASN1_TAG_GENERALIZED_TIME] = */ 0,
/* [ASN1_TAG_GRAPHIC_STRING] = */ 1,
/* [ASN1_TAG_VISIBLE_STRING] = */ 1,
/* [ASN1_TAG_GENERAL_STRING] = */ 1,
/* [ASN1_TAG_UNIVERSAL_STRING] = */ 4,
/* [ASN1_TAG_CHARACTER_STRING] = */ 1,
/* [ASN1_TAG_BMP_STRING] = */ 2,
};
/*
*/
/**
* ISO-2022 codepoint mappings.
*/
typedef struct RTISO2022MAP
{
/** The number of bytes per character. */
/** The registration number. */
/** The size of the pauToUni table. */
/** Pointer to the convertion table from ISO-2022 to Unicode.
* ASSUMES that unicode chars above 0xffff won't be required. */
/** Escape sequence for loading into G0 or C0 or C1 depending on the type (sans
* ESC). */
/** Escape sequence for loading into G1 (sans ESC). */
/** Escape sequence for loading into G2 (sans ESC). */
/** Escape sequence for loading into G3 (sans ESC). */
} RTISO2022MAP;
/** Pointer to const ISO-2022 mappings. */
typedef RTISO2022MAP const *PCRTISO2022MAP;
/** Unused codepoint value. */
/** Dummy mappings to avoid dealing with NULL pointers in the decoder
* registers. */
static const RTISO2022MAP g_DummyMap =
{
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* No escape into G0 */,
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* No escape into G1 */,
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* No escape into G2 */,
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* No escape into G3 */
};
/** GL mappings for ISO-IR-168 (Japanese, update of #87), with space and
* delete. */
static const RTISO2022MAP g_IsoIr168Map =
{
//2, 168, RT_ELEMENTS(g_awcIsoIr168Decode), g_awcIsoIr168Decode,
{ 0x26, 0x40, 0x2b, 0x24, 0x42, 0xff } /* Esc into G0 */,
{ 0x26, 0x40, 0x2b, 0x24, 0x29, 0x42 } /* Esc into G1 */,
{ 0x26, 0x40, 0x2b, 0x24, 0x2a, 0x42 } /* Esc into G2 */,
{ 0x26, 0x40, 0x2b, 0x24, 0x2b, 0x42 } /* Esc into G3 */,
};
/** GL mappings for ISO-IR-165 (Chinese), with space and delete. */
static const RTISO2022MAP g_IsoIr165Map =
{
//2, 165, RT_ELEMENTS(g_awcIsoIr165Decode), g_awcIsoIr165Decode,
{ 0x24, 0x28, 0x45, 0xff, 0xff, 0xff } /* Esc into G0 */,
{ 0x24, 0x29, 0x45, 0xff, 0xff, 0xff } /* Esc into G1 */,
{ 0x24, 0x2a, 0x45, 0xff, 0xff, 0xff } /* Esc into G2 */,
{ 0x24, 0x2b, 0x45, 0xff, 0xff, 0xff } /* Esc into G3 */,
};
/** GL mappings for ISO-IR-150 (Greek), with space and delete. */
static const RTISO2022MAP g_IsoIr150Map =
{
//1, 150, RT_ELEMENTS(g_awcIsoIr150Decode), g_awcIsoIr150Decode,
{ 0x28, 0x21, 0x40, 0xff, 0xff, 0xff } /* Esc into G0 */,
{ 0x29, 0x21, 0x40, 0xff, 0xff, 0xff } /* Esc into G1 */,
{ 0x2a, 0x21, 0x40, 0xff, 0xff, 0xff } /* Esc into G2 */,
{ 0x2b, 0x21, 0x40, 0xff, 0xff, 0xff } /* Esc into G3 */,
};
/** GL mappings for ISO-IR-103 (Teletex supplementary), with space and
* delete. */
static const RTISO2022MAP g_IsoIr103Map =
{
//1, 103, RT_ELEMENTS(g_awcIsoIr103Decode), g_awcIsoIr103Decode,
{ 0x28, 0x76, 0xff, 0xff, 0xff, 0xff } /* Esc into G0 */,
{ 0x29, 0x76, 0xff, 0xff, 0xff, 0xff } /* Esc into G1 */,
{ 0x2a, 0x76, 0xff, 0xff, 0xff, 0xff } /* Esc into G2 */,
{ 0x2b, 0x76, 0xff, 0xff, 0xff, 0xff } /* Esc into G3 */,
};
/**
* GL mapping from ISO-IR-102 (Teletex primary) to unicode, with space and
* delete.
*
* Mostly 1:1, except that (a) what would be dollar is currency sign, (b)
* positions 0x5c, 0x5e, 0x7b, 0x7d and 0x7e are defined not to be used.
*/
{
0x0020, 0x0021, 0x0022, 0x0023, 0x00A4, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0xffff, 0x005d, 0xffff, 0x005f,
0xffff, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0xffff, 0x007c, 0xffff, 0xffff, 0x007f,
};
/** GL mappings for ISO-IR-102, with space and delete. */
static const RTISO2022MAP g_IsoIr102Map =
{
{ 0x28, 0x75, 0xff, 0xff, 0xff, 0xff } /* Esc into G0 */,
{ 0x29, 0x75, 0xff, 0xff, 0xff, 0xff } /* Esc into G1 */,
{ 0x2a, 0x75, 0xff, 0xff, 0xff, 0xff } /* Esc into G2 */,
{ 0x2b, 0x75, 0xff, 0xff, 0xff, 0xff } /* Esc into G3 */,
};
/** GL mappings for ISO-IR-87 (Japanese), with space and delete. */
static const RTISO2022MAP g_IsoIr87Map =
{
//1, 87, RT_ELEMENTS(g_awcIsoIr87Decode), g_awcIsoIr97Decode,
{ 0x24, 0x42, 0xff, 0xff, 0xff, 0xff } /* Esc into G0 */,
{ 0x24, 0x29, 0x42, 0xff, 0xff, 0xff } /* Esc into G1 */,
{ 0x24, 0x2a, 0x42, 0xff, 0xff, 0xff } /* Esc into G2 */,
{ 0x24, 0x2b, 0x42, 0xff, 0xff, 0xff } /* Esc into G3 */,
};
/**
* GL mapping from ISO-IR-6 (ASCII) to unicode, with space and delete.
*
* Completely 1:1.
*/
{
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x006b, 0x007c, 0x007d, 0x007e, 0x007f,
};
/** GL mappings for ISO-IR-6 (ASCII), with space and delete. */
static const RTISO2022MAP g_IsoIr6Map =
{
{ 0x28, 0x42, 0xff, 0xff, 0xff, 0xff } /* Esc into G0 */,
{ 0x29, 0x42, 0xff, 0xff, 0xff, 0xff } /* Esc into G1 */,
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* Esc into G2 */,
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* Esc into G3 */,
};
/** GL maps. */
static PCRTISO2022MAP g_paGLMaps[] =
{
};
/** GR mappings for ISO-IR-164 (Hebrew supplementary). */
static const RTISO2022MAP g_IsoIr164Map =
{
//1, 164, RT_ELEMENTS(g_awcIsoIr164Decode), g_awcIsoIr164Decode
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* Esc into G0 */,
{ 0x2d, 0x53, 0xff, 0xff, 0xff, 0xff } /* Esc into G1 */,
{ 0x2e, 0x53, 0xff, 0xff, 0xff, 0xff } /* Esc into G2 */,
{ 0x2f, 0x53, 0xff, 0xff, 0xff, 0xff } /* Esc into G3 */,
};
/** GR mappings for ISO-IR-156 (Supplementary for ASCII (#6)). */
static const RTISO2022MAP g_IsoIr156Map =
{
//1, 156, RT_ELEMENTS(g_awcIsoIr156Decode), g_awcIsoIr156Decode
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* Esc into G0 */,
{ 0x2d, 0x52, 0xff, 0xff, 0xff, 0xff } /* Esc into G1 */,
{ 0x2e, 0x52, 0xff, 0xff, 0xff, 0xff } /* Esc into G2 */,
{ 0x2f, 0x52, 0xff, 0xff, 0xff, 0xff } /* Esc into G3 */,
};
/** GR mappings for ISO-IR-153 (Basic Cyrillic). */
static const RTISO2022MAP g_IsoIr153Map =
{
//1, 153, RT_ELEMENTS(g_awcIsoIr153Decode), g_awcIsoIr153Decode
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* Esc into G0 */,
{ 0x2d, 0x4f, 0xff, 0xff, 0xff, 0xff } /* Esc into G1 */,
{ 0x2e, 0x4f, 0xff, 0xff, 0xff, 0xff } /* Esc into G2 */,
{ 0x2f, 0x4f, 0xff, 0xff, 0xff, 0xff } /* Esc into G3 */,
};
static const RTISO2022MAP g_IsoIr144Map =
{
//1, 144, RT_ELEMENTS(g_awcIsoIr144Decode), g_awcIsoIr144Decode
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* Esc into G0 */,
{ 0x2d, 0x4f, 0xff, 0xff, 0xff, 0xff } /* Esc into G1 */,
{ 0x2e, 0x4f, 0xff, 0xff, 0xff, 0xff } /* Esc into G2 */,
{ 0x2f, 0x4f, 0xff, 0xff, 0xff, 0xff } /* Esc into G3 */,
};
static const RTISO2022MAP g_IsoIr126Map =
{
//1, 126, RT_ELEMENTS(g_awcIsoIr126Decode), g_awcIsoIr126Decode
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* Esc into G0 */,
{ 0x2d, 0x46, 0xff, 0xff, 0xff, 0xff } /* Esc into G1 */,
{ 0x2e, 0x46, 0xff, 0xff, 0xff, 0xff } /* Esc into G2 */,
{ 0x2f, 0x46, 0xff, 0xff, 0xff, 0xff } /* Esc into G3 */,
};
/** GR maps. */
static PCRTISO2022MAP g_paGRMaps[] =
{
};
/** C0 mapping from ISO-IR-106 to unicode. */
{
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0008, 0xffff, 0x000a, 0xffff, 0x000c, 0x000d, 0x000e, 0x000f,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x008e, 0x000a, 0x001b, 0xffff, 0x008f, 0xffff, 0xffff,
};
/** C0 mappings for ISO-IR-106. */
static const RTISO2022MAP g_IsoIr106Map =
{
{ 0x21, 0x45, 0xff, 0xff, 0xff, 0xff } /* Esc into C0 */,
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* N/A */,
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* N/A */,
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* N/A */,
};
/** C0 maps. */
static PCRTISO2022MAP g_paC0Maps[] =
{
};
/** C1 mapping from ISO-IR-107 to unicode. */
{
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x008b, 0x008c, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x009b, 0xffff, 0xffff, 0xffff, 0xffff,
};
/** C1 mappings for ISO-IR-107. */
static const RTISO2022MAP g_IsoIr107Map =
{
{ 0x22, 0x48, 0xff, 0xff, 0xff, 0xff } /* Esc into C1 */,
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* N/A */,
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* N/A */,
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } /* N/A */,
};
/** C1 maps. */
static PCRTISO2022MAP g_paC1Maps[] =
{
};
static int rtIso2022Decoder_LookupAndSet(PCRTISO2022MAP *ppMapRet, uint16_t uRegistration, PCRTISO2022MAP *papMaps, uint32_t cMaps)
{
while (i-- > 0)
{
/** @todo skip non-Teletex codesets if we ever add more than we need for it. */
return VINF_SUCCESS;
}
}
/**
* ISO-2022 decoder state.
*/
typedef struct RTISO2022DECODERSTATE
{
/** Pointer to the string */
/** The string size. */
/** The current string position. */
/** The GL mapping. */
/** The GR mapping. */
/** The lower control set (C0) mapping. */
/** The higher control set (C1) mapping. */
/** The G0, G1, G2, and G3 mappings. */
/** Used by SS2 & SS3 to store the orignal GL value that is to be restored. */
/** Pointer to extended error info buffer, optional. */
/** Pointer to a const ISO-2022 decoder state. */
typedef RTISO2022DECODERSTATE *PRTISO2022DECODERSTATE;
{
return VINF_SUCCESS;
}
{
return VINF_SUCCESS;
}
{
return VINF_SUCCESS;
}
{
return rtIso2022Decoder_LookupAndSet(&pThis->pMapC0, uRegistration, g_paC0Maps, RT_ELEMENTS(g_paC0Maps));
}
{
return rtIso2022Decoder_LookupAndSet(&pThis->pMapC1, uRegistration, g_paC1Maps, RT_ELEMENTS(g_paC1Maps));
}
/**
* Worker for rtIso2022Decoder_FindEscAndSet.
*
* @returns true if match, false if not.
* @param pabLeft Pointer to the first string byte after the ESC.
* @param cbLeft The number of bytes left in the string.
* @param pabRight Pointer to the abEscLoad* byte array to match with.
* @param cbRight Size of the mapping sequence (fixed).
* @param pcchMatch Where to return the length of the escape sequence (sans
* ESC) on success.
*/
{
uint32_t i = 1;
while (i < cbRight)
{
if (pabRight[i] == 0xff)
break;
return false;
i++;
}
*pcchMatch = i;
return true;
}
/**
* Finds a the set with a matching abEscLoad* escape sequence and loads it into
* the designated register.
*
* @returns The length of the sequence on success, negative error status code on
* failure.
* @param pThis The decoder instance.
* @param ppMapRet Used to specify C0 or C1 maps when processing
* escape sequences for loading these. Only the
* abEscLoadXX arrays will be searched if this is
* not NULL. For loading {G0,...,G3} pass NULL.
* @param pb Pointer to the start of the escape sequence.
* @param cb The number of bytes remaining in the string.
* @param papMaps The maps to search.
* @param cMaps The number of maps @a papMaps points to.
*/
{
/* Skip the ESC.*/
/* Cache the first char. */
/* Scan the array of maps for matching sequences. */
while (i-- > 0)
{
/** @todo skip non-Teletex codesets if we ever add more than we need for it. */
&& rtIso2022Decoder_MatchEscSeqFrom2ndByte(pb, cb, pMap->abEscLoadXX, sizeof(pMap->abEscLoadXX), &cchMatch) )
{
if (ppMapRet)
else
return cchMatch + 1;
}
else if (!ppMapRet) /* ppMapRet is NULL if Gn. */
{
&& rtIso2022Decoder_MatchEscSeqFrom2ndByte(pb, cb, pMap->abEscLoadG1, sizeof(pMap->abEscLoadG1), &cchMatch))
iGn = 1;
&& rtIso2022Decoder_MatchEscSeqFrom2ndByte(pb, cb, pMap->abEscLoadG2, sizeof(pMap->abEscLoadG2), &cchMatch))
iGn = 2;
&& rtIso2022Decoder_MatchEscSeqFrom2ndByte(pb, cb, pMap->abEscLoadG3, sizeof(pMap->abEscLoadG3), &cchMatch))
iGn = 3;
else
iGn = UINT32_MAX;
if (iGn != UINT32_MAX)
{
return cchMatch + 1;
}
}
}
}
/**
* Interprets an escape sequence.
*
* @returns The length of the sequence on success, negative error status code on
* failure.
* @param pThis The decoder instance. The offString must be
* pointing to the escape byte.
*/
{
/* the first escape byte. */
"@%u: Unexpected EOS parsing ESC...", offString);
int rc;
{
/*
* GL selection:
*/
case 0x6e: /* Lock shift two: G2 -> GL */
break;
case 0x6f: /* Lock shift three: G3 -> GL */
break;
case 0x4e: /* Single shift two: G2 -> GL for one char. */
break;
case 0x4f: /* Single shift three: G3 -> GL for one char. */
break;
/*
* GR selection:
*/
case 0x7e: /* Locking shift one right: G1 -> GR. */
break;
case 0x7d: /* Locking shift two right: G2 -> GR. */
break;
case 0x7c: /* Locking shift three right: G3 -> GR. */
break;
/*
* Cx selection:
*/
case 0x21: /* C0-designate */
case 0x22: /* C1-designate */
/*
* Single-byte character set selection.
*/
case 0x28: /* G0-designate, 94 chars. */
case 0x29: /* G1-designate, 94 chars. */
case 0x2a: /* G2-designate, 94 chars. */
case 0x2b: /* G3-designate, 94 chars. */
case 0x2c: /* G0-designate, 96 chars. */
case 0x2d: /* G1-designate, 96 chars. */
case 0x2e: /* G2-designate, 96 chars. */
case 0x2f: /* G3-designate, 96 chars. */
/*
* Multibyte character set selection.
*/
case 0x24:
{
case 0x28: /* G0-designate, 94^n chars. */
case 0x29: /* G1-designate, 94^n chars. */
case 0x2a: /* G2-designate, 94^n chars. */
case 0x2b: /* G3-designate, 94^n chars. */
default: /* G0-designate that skips the 0x28? (See japanese ones.) */
case 0x2c: /* G0-designate, 96^n chars. */
case 0x2d: /* G1-designate, 96^n chars. */
case 0x2e: /* G2-designate, 96^n chars. */
case 0x2f: /* G3-designate, 96^n chars. */
} \
break;
case 0x26: /* Special escape prefix for #168. */
/*
*/
case 0x25: /* Designate other coding system. */
"@%u: ESC DOCS not supported\n", offString);
default:
}
/* Only single byte escapes sequences for shifting ends up here. */
if (RT_SUCCESS(rc))
return 1;
return rc;
}
{
int rc;
switch (wcControl)
{
case 0x000e: /* Locking shift zero: G0 -> GL. */
break;
case 0x000f: /* Locking shift one: G1 -> GL. */
break;
case 0x008e: /* Single shift two: G2 -> GL for one char. */
break;
case 0x008f: /* Single shift three: G3 -> GL for one char. */
break;
case 0x002b: /* Escape should be handled by the caller. */
break;
default:
return 0;
}
}
static int rtIso2022Decoder_Init(PRTISO2022DECODERSTATE pThis, const char *pchString, uint32_t cchString,
{
int rc = VINF_SUCCESS;
if (uGL != UINT32_MAX)
return rc;
}
{
{
if (!(b & 0x80))
{
if (b >= 0x20)
{
/*
* GL range.
*/
b -= 0x20;
/* Single byte character map. */
{
{
{
return VINF_SUCCESS;
}
"@%u: GL b=%#x is marked unused in map #u range %u.",
}
"@%u: GL b=%#x is outside map #u range %u.",
}
/* Double byte character set. */
{
b2 -= 0x20;
{
{
{
return VINF_SUCCESS;
}
"@%u: GL b=%#x is marked unused in map #u.",
}
if (u16 >= 0x7f00)
{
return VINF_SUCCESS;
}
"@%u: GL u16=%#x (b0=%#x b1=%#x) is outside map #u range %u.",
}
"@%u: 2nd GL byte outside GL range: b0=%#x b1=%#x (map #u)",
}
"@%u: EOS reading 2nd byte for GL b=%#x (map #u).",
}
else
{
/*
* C0 range.
*/
if (wc != RTISO2022_UNUSED)
{
int rc;
else
if (RT_SUCCESS(rc))
{
if (rc == 0)
{
return VINF_SUCCESS;
}
}
else
return rc;
}
else
"@%u: C0 b=%#x is marked unused in map #u.",
}
}
else
{
if (b >= 0xa0)
{
/*
* GR range.
*/
b -= 0xa0;
/* Single byte character map. */
{
/** @todo 0xa0 = SPACE and 0xff = DELETE if it's a 94 charater map... */
{
{
return VINF_SUCCESS;
}
"@%u: GR b=%#x is marked unused in map #u.",
}
"@%u: GR b=%#x is outside map #u range %u",
}
/* Double byte character set. */
{
b2 -= 0xa0;
{
{
{
return VINF_SUCCESS;
}
"@%u: GR b=%#x is marked unused in map #u.",
}
"@%u: GR u16=%#x (b0=%#x b1=%#x) is outside map #u range %u.",
}
"@%u: 2nd GR byte outside GR range: b0=%#x b1=%#x (map #u).",
}
"@%u: EOS reading 2nd byte for GR b=%#x (map #u).",
}
else
{
/*
* C2 range.
*/
b -= 0x80;
if (wc != RTISO2022_UNUSED)
{
if (RT_SUCCESS(rc))
{
if (rc == 0)
{
return VINF_SUCCESS;
}
}
else
return rc;
}
else
"@%u: C1 b=%#x is marked unused in map #u.",
}
}
}
/* End of string. */
return VERR_END_OF_STRING;
}
{
/*
* Deal with single byte GL.
*/
{
{
{
if (wc != RTISO2022_UNUSED)
{
return VINF_SUCCESS;
}
}
}
/*
* Deal with complications in the non-inline function.
*/
}
return VERR_END_OF_STRING;
}
static int rtIso2022ValidateString(uint32_t uProfile, const char *pch, uint32_t cch, size_t *pcchUtf8, PRTERRINFO pErrInfo)
{
AssertReturn(uProfile == ASN1_TAG_T61_STRING, VERR_INVALID_PARAMETER); /* just a place holder for now. */
if (RT_SUCCESS(rc))
{
for (;;)
{
if (RT_SUCCESS(rc))
else
{
{
return VINF_SUCCESS;
}
return rc;
}
}
}
return rc;
}
static int rtIso2022RecodeAsUtf8(uint32_t uProfile, const char *pchSrc, uint32_t cchSrc, char *pszDst, size_t cbDst)
{
AssertReturn(uProfile == ASN1_TAG_T61_STRING, VERR_INVALID_PARAMETER); /* just a place holder for now. */
if (RT_SUCCESS(rc))
{
for (;;)
{
if (RT_SUCCESS(rc))
{
{
cbDst--;
}
else
{
{
}
else
{
*pszDst = '\0';
return VERR_BUFFER_OVERFLOW;
}
}
}
{
*pszDst = '\0';
return VINF_SUCCESS;
}
else
return rc;
}
}
return rc;
}
/** The unicode mapping of the C1 area of windows codepage 1252.
* The rest of the code page is 1:1 with unicode. */
{
0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,
0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178,
};
{
while (cch-- > 0)
{
if (b < 0x80)
cchUtf8 += 1;
else if (b >= 0xa0)
cchUtf8 += 2;
else
{
}
}
return cchUtf8;
}
{
while (cchSrc-- > 0)
{
if (b < 0x80)
{
if (cbDst <= 1)
return VERR_BUFFER_OVERFLOW;
*pszDst++ = (char)b;
}
else
{
return VERR_BUFFER_OVERFLOW;
}
}
if (!cbDst)
return VERR_BUFFER_OVERFLOW;
*pszDst = '\0';
return VINF_SUCCESS;
}
/*
* ASN.1 STRING - Specific Methods.
*/
/** rtAsn1String_IsTeletexLatin1 results. */
typedef enum RTASN1TELETEXVARIANT
{
/** Couldn't find hard evidence of either. */
/** Pretty certain that it's real teletex. */
/** Pretty sure it's latin-1 or Windows-1252. */
/** Pretty sure it's Windows-1252. */
/**
* Takes a guess as whether TELETEX STRING (T61 STRING) is actually is Latin-1
* or the real thing.
*
* According to RFC-2459, section 4.1.2.4, various libraries, certificate
* authorities and others have perverted the TeletexString/T61String tag by
* ISO-8859-1 (aka latin-1) strings (more probably these are actually Windows
* CP-1252 rather than latin-1). We'll try detect incompatible latin-1
* perversions by:
* - The use of GR (0xf0-0xff) chars.
* - The lack of ESC sequences and shifts (LS0,LS1,SS2,SS3)
*
* An ASSUMTION here is that GR is not loaded with anything at the start of a
* teletex string, as per table 3 in section 8.23.5.2 in T-REC-X.590.200811.
*
* @retval @c true if chances are good that it's LATIN-1.
* @retval @c false if changes are very good that it's real teletex.
* @param pch The first char in the string.
* @param cch The string length.
*
*/
{
while (cch-- > 0)
{
if (b >= 0x20 && b <= 0x7f)
{
}
else
{
if ( b == 0x1b /* ESC */
|| b == 0x0e /* LS0 / SI */
|| b == 0x0f /* LS1 / SO */
|| b == 0x19 /* SS2 */
|| b == 0x1d /* SS3 */ )
return RTASN1TELETEXVARIANT_TELETEX;
if (b >= 0xa0)
else if (b >= 0x80 && b <= 0x9f)
{
/* Any use of C1 characters defined by windows cp-1252 will
lead us to believe it's the windows code rather than the
much of a difference, because we're gonna treat it as the
windows codepage, anyways.) */
if ( b != 0x81
&& b != 0x8d
&& b != 0x8f
&& b != 0x90
&& b != 0x9d)
return RTASN1TELETEXVARIANT_WIN_1252;
}
}
}
return RTASN1TELETEXVARIANT_UNDECIDED;
}
/**
* Checks the encoding of an ASN.1 string according to it's tag.
*
* @returns IPRT status code.
* @param pThis The string to santity check.
* @param pErrInfo Where to store extra error info. Optional.
* @param pcchUtf8 Where to return the UTF-8 string length. Optional.
*/
static int rtAsn1String_CheckSanity(PCRTASN1STRING pThis, PRTERRINFO pErrInfo, const char *pszErrorTag, size_t *pcchUtf8)
{
int rc;
switch (uTag)
{
case ASN1_TAG_UTF8_STRING:
if (RT_SUCCESS(rc))
break;
case ASN1_TAG_NUMERIC_STRING:
while (cch-- > 0)
{
if ( !RT_C_IS_DIGIT(ch)
&& ch != ' ')
}
break;
while (cch-- > 0)
{
if ( !RT_C_IS_ALNUM(ch)
&& ch != ' '
&& ch != '\''
&& ch != '('
&& ch != ')'
&& ch != '+'
&& ch != ','
&& ch != '-'
&& ch != '.'
&& ch != '/'
&& ch != ':'
&& ch != '='
&& ch != '?'
)
}
break;
case ASN1_TAG_IA5_STRING: /* ASCII */
while (cch-- > 0)
{
}
break;
case ASN1_TAG_T61_STRING:
{
default:
if (RT_FAILURE(rc))
return rc;
break;
break;
}
break;
case ASN1_TAG_VIDEOTEX_STRING:
case ASN1_TAG_GRAPHIC_STRING:
case ASN1_TAG_VISIBLE_STRING:
while (cch-- > 0)
{
}
break;
case ASN1_TAG_GENERAL_STRING:
if (!(cch & 3))
{
cchUtf8 = 0;
while (cch > 0)
{
if (!RTUniCpIsValid(uc))
/* next */
pb += 4;
cch -= 4;
}
break;
}
case ASN1_TAG_BMP_STRING:
if (!(cch & 1))
{
cchUtf8 = 0;
while (cch > 0)
{
if (!RTUniCpIsValid(uc))
/* next */
pb += 2;
cch -= 2;
}
break;
}
default:
}
if (pcchUtf8)
return VINF_SUCCESS;
}
{
}
{
Assert(pLeft && (!RTAsn1String_IsPresent(pLeft) || pLeft->Asn1Core.pOps == &g_RTAsn1String_Vtable));
Assert(pRight && (!RTAsn1String_IsPresent(pRight) || pRight->Asn1Core.pOps == &g_RTAsn1String_Vtable));
int iDiff;
if (RTAsn1String_IsPresent(pLeft))
{
if (RTAsn1String_IsPresent(pRight))
{
else
}
else
iDiff = 1;
}
else
return iDiff;
}
RTDECL(int) RTAsn1String_CompareWithString(PCRTASN1STRING pThis, const char *pszString, size_t cchString)
{
Assert(pThis && (!RTAsn1String_IsPresent(pThis) || pThis->Asn1Core.pOps == &g_RTAsn1String_Vtable));
int iDiff;
if (RTAsn1String_IsPresent(pThis))
{
/*
* If there is a UTF-8 conversion available already, use it.
*/
{
}
else
{
/*
* Some types are UTF-8 compatible, so try do the compare without
* RTAsn1String_QueryUtf8.
*/
{
case ASN1_TAG_UTF8_STRING:
case ASN1_TAG_NUMERIC_STRING:
case ASN1_TAG_IA5_STRING:
break;
/** @todo Implement compating ASN1_TAG_BMP_STRING, ASN1_TAG_UNIVERSAL_STRING and
* ASN1_TAG_T61_STRING with UTF-8 strings without conversion. */
default:
{
if (RT_SUCCESS(rc))
{
}
else
iDiff = -1;
break;
}
}
}
/* Reduce the strcmp return value. */
if (iDiff != 0)
}
else
iDiff = -1;
return iDiff;
}
{
if (!psz)
{
/*
* Convert the first time around. Start by validating the encoding and
* calculating the length.
*/
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
/*
* Got memory, now do the actual convertion to UTF-8 / copying.
*/
{
case ASN1_TAG_UTF8_STRING:
case ASN1_TAG_NUMERIC_STRING:
case ASN1_TAG_IA5_STRING:
case ASN1_TAG_VISIBLE_STRING:
break;
case ASN1_TAG_T61_STRING:
{
default:
break;
break;
}
break;
/* case ASN1_TAG_VIDEOTEX_STRING: */
/* case ASN1_TAG_GRAPHIC_STRING: */
/* case ASN1_TAG_GENERAL_STRING: */
{
while (cchSrc > 0)
{
AssertReturnStmt(RTUniCpIsValid(uc), RTAsn1MemFree(&pThisNC->Allocation, psz), VERR_INTERNAL_ERROR_2);
/* next */
pbSrc += 4;
cchSrc -= 4;
}
break;
}
case ASN1_TAG_BMP_STRING:
{
while (cchSrc > 0)
{
AssertReturnStmt(RTUniCpIsValid(uc), RTAsn1MemFree(&pThisNC->Allocation, psz), VERR_INTERNAL_ERROR_2);
/* next */
pbSrc += 2;
cchSrc -= 2;
}
break;
}
default:
}
/*
* Successfully produced UTF-8. Save it in the object.
*/
}
else
return rc;
}
else
return rc;
}
/*
* Success.
*/
if (ppsz)
if (pcch)
return VINF_SUCCESS;
}
{
{
if (RT_FAILURE(rc))
return rc;
}
return VINF_SUCCESS;
}
RTDECL(int) RTAsn1String_InitEx(PRTASN1STRING pThis, uint32_t uTag, void const *pvValue, size_t cbValue,
{
AssertMsgReturn(uTag < RT_ELEMENTS(g_acbStringTags) && g_acbStringTags[uTag] > 0, ("uTag=%#x\n", uTag),
uTag,
if (cbValue > 0)
{
if (RT_FAILURE(rc))
return rc;
}
return VINF_SUCCESS;
}
RTDECL(int) RTAsn1String_InitWithValue(PRTASN1STRING pThis, const char *pszUtf8Value, PCRTASN1ALLOCATORVTABLE pAllocator)
{
return RTAsn1String_InitEx(pThis, ASN1_TAG_UTF8_STRING, pszUtf8Value, strlen(pszUtf8Value), pAllocator);
}
{
/*
* Query the UTF-8 string. Do this even if it's already an
* ASN1_TAG_UTF8_STRING object as it makes sure we've got a valid UTF-8
* string upon successful return.
*/
if (RT_SUCCESS(rc))
{
{
/*
* Resize the content, copy the UTF-8 bytes in there, and change
* the tag.
*/
if (RT_SUCCESS(rc))
{
}
}
}
return rc;
}
/*
* ASN.1 STRING - Standard Methods.
*/
{
"RTAsn1String",
sizeof(RTASN1STRING),
0,
NULL,
NULL,
};
{
return RTAsn1String_InitEx(pThis, ASN1_TAG_UTF8_STRING, NULL /*pvValue*/, 0 /*cbValue*/, pAllocator);
}
RTDECL(int) RTAsn1String_Clone(PRTASN1STRING pThis, PCRTASN1STRING pSrc, PCRTASN1ALLOCATORVTABLE pAllocator)
{
if (RTAsn1String_IsPresent(pSrc))
{
if (RT_SUCCESS(rc))
{
/* Don't copy the UTF-8 representation, decode it when queried. */
return VINF_SUCCESS;
}
}
return VINF_SUCCESS;
}
{
if ( pThis
{
}
}
RTDECL(int) RTAsn1String_Enum(PRTASN1STRING pThis, PFNRTASN1ENUMCALLBACK pfnCallback, uint32_t uDepth, void *pvUser)
{
Assert(pThis && (!RTAsn1String_IsPresent(pThis) || pThis->Asn1Core.pOps == &g_RTAsn1String_Vtable));
/* No children to enumerate. */
return VINF_SUCCESS;
}
{
/* Compare tag and binary value. */
}
RTDECL(int) RTAsn1String_CheckSanity(PCRTASN1STRING pThis, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag)
{
}
/*
* Generate code for the tag specific methods.
* Note! This is very similar to what we're doing in asn1-ut-time.cpp.
*/
\
{ \
} \
\
RTDECL(int) RT_CONCAT(a_Api,_Clone)(PRTASN1STRING pThis, PCRTASN1STRING pSrc, PCRTASN1ALLOCATORVTABLE pAllocator) \
{ \
} \
\
{ \
|| !RTAsn1String_IsPresent(pThis) \
} \
\
RTDECL(int) RT_CONCAT(a_Api,_Enum)(PRTASN1STRING pThis, PFNRTASN1ENUMCALLBACK pfnCallback, uint32_t uDepth, void *pvUser) \
{ \
&& ( !RTAsn1String_IsPresent(pThis) \
/* No children to enumerate. */ \
return VINF_SUCCESS; \
} \
\
{ \
return iDiff; \
} \
\
{ \
}
#include "asn1-ut-string-template2.h"
/*
* Generate code for the associated collection types.
*/
#define RTASN1TMPL_TEMPLATE_FILE "../common/asn1/asn1-ut-string-template.h"
#include <iprt/asn1-generator-internal-header.h>
#include <iprt/asn1-generator-core.h>
#include <iprt/asn1-generator-init.h>
#include <iprt/asn1-generator-sanity.h>