diff --git a/mozilla/xpcom/io/nsLocalFileOSX.cpp b/mozilla/xpcom/io/nsLocalFileOSX.cpp index a56132f6298..62f851c04c9 100644 --- a/mozilla/xpcom/io/nsLocalFileOSX.cpp +++ b/mozilla/xpcom/io/nsLocalFileOSX.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Conrad Carlen + * Jungshik Shin * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -68,6 +69,7 @@ static nsresult MacErrorMapper(OSErr inErr); static OSErr FindRunningAppBySignature(OSType aAppSig, ProcessSerialNumber& outPsn); +static void CopyUTF8toUTF16NFC(nsACString& aSrc, nsAString& aResult); //***************************************************************************** // Local Helper Classes @@ -516,7 +518,7 @@ NS_IMETHODIMP nsLocalFile::GetLeafName(nsAString& aLeafName) nsresult rv = GetNativeLeafName(nativeString); if (NS_FAILED(rv)) return rv; - CopyUTF8toUTF16(nativeString, aLeafName); + CopyUTF8toUTF16NFC(nativeString, aLeafName); return NS_OK; } @@ -815,7 +817,7 @@ NS_IMETHODIMP nsLocalFile::GetPath(nsAString& aPath) nsresult rv = GetNativePath(nativeString); if (NS_FAILED(rv)) return rv; - CopyUTF8toUTF16(nativeString, aPath); + CopyUTF8toUTF16NFC(nativeString, aPath); return NS_OK; } @@ -2176,3 +2178,63 @@ static OSErr FindRunningAppBySignature(OSType aAppSig, ProcessSerialNumber& outP } return procNotFound; } + +// Convert a UTF-8 string to a UTF-16 string while normalizing to +// Normalization Form C (composed Unicode). We need this because +// Mac OS X file system uses NFD (Normalization Form D : decomposed Unicode) +// while most other OS', server-side programs usually expect NFC. + +typedef void (*UnicodeNormalizer) (CFMutableStringRef, CFStringNormalizationForm); +static void CopyUTF8toUTF16NFC(nsACString& aSrc, nsAString& aResult) +{ + static PRBool sChecked = PR_FALSE; + static UnicodeNormalizer sUnicodeNormalizer = NULL; + + // CFStringNormalize was not introduced until Mac OS 10.2 + if (!sChecked) { + CFBundleRef carbonBundle = + CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Carbon")); + if (carbonBundle) + sUnicodeNormalizer = (UnicodeNormalizer) + ::CFBundleGetFunctionPointerForName(carbonBundle, + CFSTR("CFStringNormalize")); + sChecked = PR_TRUE; + } + + if (!sUnicodeNormalizer) { // OS X 10.2 or earlier + CopyUTF8toUTF16(aSrc, aResult); + return; + } + + const nsAFlatCString &inFlatSrc = PromiseFlatCString(aSrc); + + // The number of 16bit code units in a UTF-16 string will never be + // larger than the number of bytes in the corresponding UTF-8 string. + CFMutableStringRef inStr = + ::CFStringCreateMutable(NULL, inFlatSrc.Length()); + + if (!inStr) { + CopyUTF8toUTF16(aSrc, aResult); + return; + } + + ::CFStringAppendCString(inStr, inFlatSrc.get(), kCFStringEncodingUTF8); + + sUnicodeNormalizer(inStr, kCFStringNormalizationFormC); + + CFIndex length = CFStringGetLength(inStr); + const UniChar* chars = CFStringGetCharactersPtr(inStr); + + if (chars) + aResult.Assign(chars, length); + else { + StBuffer buffer; + if (!buffer.EnsureElemCapacity(length)) + CopyUTF8toUTF16(aSrc, aResult); + else { + CFStringGetCharacters(inStr, CFRangeMake(0, length), buffer.get()); + aResult.Assign(buffer.get(), length); + } + } + CFRelease(inStr); +} diff --git a/mozilla/xpcom/io/nsLocalFileOSX.h b/mozilla/xpcom/io/nsLocalFileOSX.h index 21d160beeb4..2b207888280 100644 --- a/mozilla/xpcom/io/nsLocalFileOSX.h +++ b/mozilla/xpcom/io/nsLocalFileOSX.h @@ -49,9 +49,10 @@ class nsDirEnumerator; // // The native charset of this implementation is UTF-8. The Unicode used by the // Mac OS file system is decomposed, so "Native" versions of these routines will -// always use decomposed Unicode. Their "non-Native" counterparts are intended -// to be simple wrappers which call the "Native" version and convert between -// UTF-8 and UCS-2. All the work is done on the "Native" side. +// always use decomposed Unicode (NFD). Their "non-Native" counterparts are +// intended to be simple wrappers which call the "Native" version and convert +// between UTF-8 and UTF-16. All the work is done on the "Native" side except +// for the conversion to NFC (composed Unicode) done in "non-Native" getters. //***************************************************************************** class NS_COM nsLocalFile : public nsILocalFileMac