diff options
author | jgmyers%speakeasy.net <devnull@localhost> | 2004-01-15 06:23:14 +0000 |
---|---|---|
committer | jgmyers%speakeasy.net <devnull@localhost> | 2004-01-15 06:23:14 +0000 |
commit | cbb0b657eb8b6715a688b308dd5b24b7c23c153c (patch) | |
tree | 4e1aea62d0ce344ec8528a3ed649892e04795267 | |
parent | 1f308d745f87b7f98f12fa6745633a6631534478 (diff) | |
download | nss-hg-cbb0b657eb8b6715a688b308dd5b24b7c23c153c.tar.gz |
Convert T61String-labeled ISO-8859-1 to UTF-8: bug 53133 r=nelsonb a=wtc
-rw-r--r-- | security/nss/lib/certdb/secname.c | 68 | ||||
-rw-r--r-- | security/nss/lib/util/secport.c | 9 | ||||
-rw-r--r-- | security/nss/lib/util/secport.h | 16 | ||||
-rw-r--r-- | security/nss/lib/util/utf8.c | 97 |
4 files changed, 161 insertions, 29 deletions
diff --git a/security/nss/lib/certdb/secname.c b/security/nss/lib/certdb/secname.c index 5a40249da..d1abab4fa 100644 --- a/security/nss/lib/certdb/secname.c +++ b/security/nss/lib/certdb/secname.c @@ -17,6 +17,7 @@ * Rights Reserved. * * Contributor(s): + * John Gardiner Myers <jgmyers@speakeasy.net> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -603,8 +604,7 @@ CERT_DecodeAVAValue(const SECItem *derAVAValue) { SECItem *retItem; const SEC_ASN1Template *theTemplate = NULL; - PRBool convertUCS4toUTF8 = PR_FALSE; - PRBool convertUCS2toUTF8 = PR_FALSE; + enum { conv_none, conv_ucs4, conv_ucs2, conv_iso88591 } convert = conv_none; SECItem avaValue = {siBuffer, 0}; PLArenaPool *newarena = NULL; @@ -614,7 +614,7 @@ CERT_DecodeAVAValue(const SECItem *derAVAValue) switch(derAVAValue->data[0]) { case SEC_ASN1_UNIVERSAL_STRING: - convertUCS4toUTF8 = PR_TRUE; + convert = conv_ucs4; theTemplate = SEC_UniversalStringTemplate; break; case SEC_ASN1_IA5_STRING: @@ -624,10 +624,15 @@ CERT_DecodeAVAValue(const SECItem *derAVAValue) theTemplate = SEC_PrintableStringTemplate; break; case SEC_ASN1_T61_STRING: + /* + * Per common practice, we're not decoding actual T.61, but instead + * treating T61-labeled strings as containing ISO-8859-1. + */ + convert = conv_iso88591; theTemplate = SEC_T61StringTemplate; break; case SEC_ASN1_BMP_STRING: - convertUCS2toUTF8 = PR_TRUE; + convert = conv_ucs2; theTemplate = SEC_BMPStringTemplate; break; case SEC_ASN1_UTF8_STRING: @@ -649,36 +654,41 @@ CERT_DecodeAVAValue(const SECItem *derAVAValue) return NULL; } - if (convertUCS4toUTF8) { + if (convert != conv_none) { unsigned int utf8ValLen = avaValue.len * 3; unsigned char *utf8Val = (unsigned char*) PORT_ArenaZAlloc(newarena, utf8ValLen); - if(avaValue.len % 4 != 0 || - !PORT_UCS4_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, - utf8Val, utf8ValLen, &utf8ValLen)) { - PORT_FreeArena(newarena, PR_FALSE); - PORT_SetError(SEC_ERROR_INVALID_AVA); - return NULL; + switch (convert) { + case conv_ucs4: + if(avaValue.len % 4 != 0 || + !PORT_UCS4_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, + utf8Val, utf8ValLen, &utf8ValLen)) { + PORT_FreeArena(newarena, PR_FALSE); + PORT_SetError(SEC_ERROR_INVALID_AVA); + return NULL; + } + break; + case conv_ucs2: + if(avaValue.len % 2 != 0 || + !PORT_UCS2_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, + utf8Val, utf8ValLen, &utf8ValLen)) { + PORT_FreeArena(newarena, PR_FALSE); + PORT_SetError(SEC_ERROR_INVALID_AVA); + return NULL; + } + break; + case conv_iso88591: + if(!PORT_ISO88591_UTF8Conversion(avaValue.data, avaValue.len, + utf8Val, utf8ValLen, &utf8ValLen)) { + PORT_FreeArena(newarena, PR_FALSE); + PORT_SetError(SEC_ERROR_INVALID_AVA); + return NULL; + } + break; + case conv_none: ; } - - avaValue.data = utf8Val; - avaValue.len = utf8ValLen; - - } else if (convertUCS2toUTF8) { - - unsigned int utf8ValLen = avaValue.len * 3; - unsigned char *utf8Val = (unsigned char*) - PORT_ArenaZAlloc(newarena, utf8ValLen); - - if(avaValue.len % 2 != 0 || - !PORT_UCS2_UTF8Conversion(PR_FALSE, avaValue.data, avaValue.len, - utf8Val, utf8ValLen, &utf8ValLen)) { - PORT_FreeArena(newarena, PR_FALSE); - PORT_SetError(SEC_ERROR_INVALID_AVA); - return NULL; - } - + avaValue.data = utf8Val; avaValue.len = utf8ValLen; } diff --git a/security/nss/lib/util/secport.c b/security/nss/lib/util/secport.c index 7d276f9b7..1abf5c030 100644 --- a/security/nss/lib/util/secport.c +++ b/security/nss/lib/util/secport.c @@ -542,6 +542,15 @@ PORT_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf, } PRBool +PORT_ISO88591_UTF8Conversion(const unsigned char *inBuf, + unsigned int inBufLen, unsigned char *outBuf, + unsigned int maxOutBufLen, unsigned int *outBufLen) +{ + return sec_port_iso88591_utf8_conversion_function(inBuf, inBufLen, + outBuf, maxOutBufLen, outBufLen); +} + +PRBool PORT_UCS2_ASCIIConversion(PRBool toUnicode, unsigned char *inBuf, unsigned int inBufLen, unsigned char *outBuf, unsigned int maxOutBufLen, unsigned int *outBufLen, diff --git a/security/nss/lib/util/secport.h b/security/nss/lib/util/secport.h index 5cfdbd19d..693b35110 100644 --- a/security/nss/lib/util/secport.h +++ b/security/nss/lib/util/secport.h @@ -255,6 +255,11 @@ PRBool PORT_UCS2_UTF8Conversion(PRBool toUnicode, unsigned char *inBuf, unsigned int inBufLen, unsigned char *outBuf, unsigned int maxOutBufLen, unsigned int *outBufLen); +/* One-way conversion from ISO-8859-1 to UTF-8 */ +PRBool PORT_ISO88591_UTF8Conversion(const unsigned char *inBuf, + unsigned int inBufLen, unsigned char *outBuf, + unsigned int maxOutBufLen, unsigned int *outBufLen); + PR_EXTERN(PRBool) sec_port_ucs4_utf8_conversion_function ( @@ -277,6 +282,17 @@ sec_port_ucs2_utf8_conversion_function unsigned int *outBufLen ); +/* One-way conversion from ISO-8859-1 to UTF-8 */ +extern PRBool +sec_port_iso88591_utf8_conversion_function +( + const unsigned char *inBuf, + unsigned int inBufLen, + unsigned char *outBuf, + unsigned int maxOutBufLen, + unsigned int *outBufLen +); + extern int NSS_PutEnv(const char * envVarName, const char * envValue); SEC_END_PROTOS diff --git a/security/nss/lib/util/utf8.c b/security/nss/lib/util/utf8.c index 013f202a9..f418233eb 100644 --- a/security/nss/lib/util/utf8.c +++ b/security/nss/lib/util/utf8.c @@ -17,6 +17,7 @@ * Rights Reserved. * * Contributor(s): + * John Gardiner Myers <jgmyers@speakeasy.net> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -553,6 +554,56 @@ sec_port_ucs2_utf8_conversion_function } } +PRBool +sec_port_iso88591_utf8_conversion_function +( + const unsigned char *inBuf, + unsigned int inBufLen, + unsigned char *outBuf, + unsigned int maxOutBufLen, + unsigned int *outBufLen +) +{ +#ifndef TEST_UTF8 + PORT_Assert((unsigned int *)NULL != outBufLen); +#endif /* TEST_UTF8 */ + + unsigned int i, len = 0; + + for( i = 0; i < inBufLen; i++) { + if( (inBuf[i] & 0x80) == 0x00 ) len += 1; + else len += 2; + } + + if( len > maxOutBufLen ) { + *outBufLen = len; + return PR_FALSE; + } + + len = 0; + + for( i = 0; i < inBufLen; i++) { + if( (inBuf[i] & 0x80) == 0x00 ) { + /* 7F -> 0xxxxxx */ + /* 0abcdefg -> 0abcdefg */ + + outBuf[len] = inBuf[i]; + len += 1; + } else { + /* 80-FF <- 110xxxxx 10xxxxxx */ + /* 00000000 abcdefgh -> 110000ab 10cdefgh */ + + outBuf[len+0] = 0xC0 | ((inBuf[i] & 0xC0) >> 6); + outBuf[len+1] = 0x80 | ((inBuf[i] & 0x3F) >> 0); + + len += 2; + } + } + + *outBufLen = len; + return PR_TRUE; +} + #ifdef TEST_UTF8 #include <stdio.h> @@ -1743,6 +1794,51 @@ test_utf16_chars #endif /* UTF16 */ static PRBool +test_iso88591_chars +( + void +) +{ + PRBool rv = PR_TRUE; + int i; + + for( i = 0; i < sizeof(ucs2)/sizeof(ucs2[0]); i++ ) { + struct ucs2 *e = &ucs2[i]; + PRBool result; + unsigned char iso88591; + unsigned char utf8[8]; + unsigned int len = 0; + + if (e->c > 0xFF) continue; + + (void)memset(utf8, 0, sizeof(utf8)); + iso88591 = e->c; + + result = sec_port_iso88591_utf8_conversion_function(&iso88591, + 1, utf8, sizeof(utf8), &len); + + if( !result ) { + fprintf(stdout, "Failed to convert ISO-8859-1 0x%02.2x to UTF-8\n", iso88591); + rv = PR_FALSE; + continue; + } + + if( (len >= sizeof(utf8)) || + (strlen(e->utf8) != len) || + (utf8[len] = '\0', 0 != strcmp(e->utf8, utf8)) ) { + fprintf(stdout, "Wrong conversion of ISO-8859-1 0x%02.2x to UTF-8: ", iso88591); + dump_utf8("expected", e->utf8, ", "); + dump_utf8("received", utf8, "\n"); + rv = PR_FALSE; + continue; + } + + } + + return rv; +} + +static PRBool test_zeroes ( void @@ -2057,6 +2153,7 @@ main #ifdef UTF16 test_utf16_chars() && #endif /* UTF16 */ + test_iso88591_chars() && test_zeroes() && test_multichars() && PR_TRUE ) { |