Commit 685668f7 authored by jshin@chromium.org's avatar jshin@chromium.org

Use UTS46 API to convert IDN in Unicode to punycode

When upgrading ICU to 52, I removed the stringprep data for IDNA 2003 because Chrome/Blink switched to UTS46/IDNA 2008. I overlooked that Blink email form handling still uses IDNA 2003 API that fails without stringprep data for IDNA 2003. 

This CL changes Blink to use UTS46 API. 

BUG=132145,376587
TEST=LayoutTest: fast/forms/email-idn-conversion.html

Review URL: https://codereview.chromium.org/326453002

git-svn-id: svn://svn.chromium.org/blink/trunk@175869 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 8369d467
......@@ -34,7 +34,8 @@
#include "public/platform/Platform.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/text/StringBuilder.h"
#include <unicode/uidna.h>
#include <unicode/idna.h>
#include <unicode/unistr.h>
namespace WebCore {
......@@ -49,8 +50,9 @@ static const char emailPattern[] =
"(?:\\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*";
// RFC5321 says the maximum total length of a domain name is 255 octets.
static const size_t maximumDomainNameLength = 255;
static const int32_t idnaConversionOption = UIDNA_ALLOW_UNASSIGNED;
static const int32_t maximumDomainNameLength = 255;
// Use the same option as in url/url_canon_icu.cc
static const int32_t idnaConversionOption = UIDNA_CHECK_BIDI;
static String convertEmailAddressToASCII(const String& address)
{
......@@ -61,15 +63,24 @@ static String convertEmailAddressToASCII(const String& address)
if (atPosition == kNotFound)
return address;
UErrorCode error = U_ZERO_ERROR;
UChar domainNameBuffer[maximumDomainNameLength];
int32_t domainNameLength = uidna_IDNToASCII(address.charactersWithNullTermination().data() + atPosition + 1, address.length() - atPosition - 1, domainNameBuffer, WTF_ARRAY_LENGTH(domainNameBuffer), idnaConversionOption, 0, &error);
if (error != U_ZERO_ERROR || domainNameLength <= 0)
// UnicodeString ctor for copy-on-write does not work reliably (in debug
// build.) TODO(jshin): In an unlikely case this is a perf-issue, treat
// 8bit and non-8bit strings separately.
icu::UnicodeString idnDomainName(address.charactersWithNullTermination().data() + atPosition + 1, address.length() - atPosition - 1);
icu::UnicodeString domainName;
// Leak |idna| at the end.
UErrorCode errorCode = U_ZERO_ERROR;
static icu::IDNA *idna = icu::IDNA::createUTS46Instance(idnaConversionOption, errorCode);
ASSERT(idna);
icu::IDNAInfo idnaInfo;
idna->nameToASCII(idnDomainName, domainName, idnaInfo, errorCode);
if (U_FAILURE(errorCode) || idnaInfo.hasErrors() || domainName.length() > maximumDomainNameLength)
return address;
StringBuilder builder;
builder.append(address, 0, atPosition + 1);
builder.append(domainNameBuffer, domainNameLength);
builder.append(domainName.getBuffer(), domainName.length());
return builder.toString();
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment