186 lines
5.1 KiB
C++
186 lines
5.1 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include <locale.h>
|
|
|
|
#include "mozilla/ArrayUtils.h"
|
|
|
|
#include "nsIPlatformCharset.h"
|
|
#include "nsUConvPropertySearch.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsReadableUtils.h"
|
|
#include "nsEncoderDecoderUtils.h"
|
|
#if HAVE_GNU_LIBC_VERSION_H
|
|
#include <gnu/libc-version.h>
|
|
#endif
|
|
#ifdef HAVE_NL_TYPES_H
|
|
#include <nl_types.h>
|
|
#endif
|
|
#if HAVE_LANGINFO_CODESET
|
|
#include <langinfo.h>
|
|
#endif
|
|
#include "nsPlatformCharset.h"
|
|
#include "prinit.h"
|
|
#include "nsUnicharUtils.h"
|
|
#include "mozilla/dom/EncodingUtils.h"
|
|
|
|
using mozilla::dom::EncodingUtils;
|
|
using namespace mozilla;
|
|
|
|
static const nsUConvProp kUnixCharsets[] = {
|
|
#include "unixcharset.properties.h"
|
|
};
|
|
|
|
NS_IMPL_ISUPPORTS(nsPlatformCharset, nsIPlatformCharset)
|
|
|
|
nsPlatformCharset::nsPlatformCharset()
|
|
{
|
|
}
|
|
|
|
static nsresult
|
|
ConvertLocaleToCharsetUsingDeprecatedConfig(const nsACString& locale,
|
|
nsACString& oResult)
|
|
{
|
|
if (!(locale.IsEmpty())) {
|
|
if (NS_SUCCEEDED(nsUConvPropertySearch::SearchPropertyValue(kUnixCharsets,
|
|
ArrayLength(kUnixCharsets), locale, oResult))) {
|
|
return NS_OK;
|
|
}
|
|
}
|
|
NS_ERROR("unable to convert locale to charset using deprecated config");
|
|
oResult.AssignLiteral("ISO-8859-1");
|
|
return NS_SUCCESS_USING_FALLBACK_LOCALE;
|
|
}
|
|
|
|
nsPlatformCharset::~nsPlatformCharset()
|
|
{
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsPlatformCharset::GetCharset(nsPlatformCharsetSel selector, nsACString& oResult)
|
|
{
|
|
oResult = mCharset;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsPlatformCharset::GetDefaultCharsetForLocale(const nsAString& localeName, nsACString &oResult)
|
|
{
|
|
//
|
|
// if this locale is the user's locale then use the charset
|
|
// we already determined at initialization
|
|
//
|
|
if (mLocale.Equals(localeName) ||
|
|
// support the 4.x behavior
|
|
(mLocale.LowerCaseEqualsLiteral("en_us") &&
|
|
localeName.LowerCaseEqualsLiteral("c"))) {
|
|
oResult = mCharset;
|
|
return NS_OK;
|
|
}
|
|
|
|
#if HAVE_LANGINFO_CODESET
|
|
//
|
|
// This locale appears to be a different locale from the user's locale.
|
|
// To do this we would need to lock the global resource we are currently
|
|
// using or use a library that provides multi locale support.
|
|
// ICU is a possible example of a multi locale library.
|
|
// http://oss.software.ibm.com/icu/
|
|
//
|
|
// A more common cause of hitting this warning than the above is that
|
|
// Mozilla is launched under an ll_CC.UTF-8 locale. In xpLocale,
|
|
// we only store the language and the region (ll-CC) losing 'UTF-8', which
|
|
// leads |mLocale| to be different from |localeName|. Although we lose
|
|
// 'UTF-8', we init'd |mCharset| with the value obtained via
|
|
// |nl_langinfo(CODESET)| so that we're all right here.
|
|
//
|
|
NS_WARNING("GetDefaultCharsetForLocale: need to add multi locale support");
|
|
#ifdef DEBUG_jungshik
|
|
printf("localeName=%s mCharset=%s\n", NS_ConvertUTF16toUTF8(localeName).get(),
|
|
mCharset.get());
|
|
#endif
|
|
// until we add multi locale support: use the the charset of the user's locale
|
|
oResult = mCharset;
|
|
return NS_SUCCESS_USING_FALLBACK_LOCALE;
|
|
#else
|
|
//
|
|
// convert from locale to charset
|
|
// using the deprecated locale to charset mapping
|
|
//
|
|
NS_LossyConvertUTF16toASCII localeStr(localeName);
|
|
return ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oResult);
|
|
#endif
|
|
}
|
|
|
|
nsresult
|
|
nsPlatformCharset::InitGetCharset(nsACString &oString)
|
|
{
|
|
#if HAVE_LANGINFO_CODESET
|
|
char* nl_langinfo_codeset = nullptr;
|
|
nsCString aCharset;
|
|
nsresult res;
|
|
|
|
nl_langinfo_codeset = nl_langinfo(CODESET);
|
|
NS_ASSERTION(nl_langinfo_codeset, "cannot get nl_langinfo(CODESET)");
|
|
|
|
//
|
|
// see if we can use nl_langinfo(CODESET) directly
|
|
//
|
|
if (nl_langinfo_codeset) {
|
|
aCharset.Assign(nl_langinfo_codeset);
|
|
res = VerifyCharset(aCharset);
|
|
if (NS_SUCCEEDED(res)) {
|
|
oString = aCharset;
|
|
return res;
|
|
}
|
|
}
|
|
|
|
NS_ERROR("unable to use nl_langinfo(CODESET)");
|
|
#endif
|
|
|
|
//
|
|
// try falling back on a deprecated (locale based) name
|
|
//
|
|
char* locale = setlocale(LC_CTYPE, nullptr);
|
|
nsAutoCString localeStr;
|
|
localeStr.Assign(locale);
|
|
return ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oString);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsPlatformCharset::Init()
|
|
{
|
|
//
|
|
// remember default locale so we can use the
|
|
// same charset when asked for the same locale
|
|
//
|
|
char* locale = setlocale(LC_CTYPE, nullptr);
|
|
NS_ASSERTION(locale, "cannot setlocale");
|
|
if (locale) {
|
|
CopyASCIItoUTF16(locale, mLocale);
|
|
} else {
|
|
mLocale.AssignLiteral("en_US");
|
|
}
|
|
|
|
// InitGetCharset only returns NS_OK or NS_SUCESS_USING_FALLBACK_LOCALE
|
|
return InitGetCharset(mCharset);
|
|
}
|
|
|
|
nsresult
|
|
nsPlatformCharset::VerifyCharset(nsCString &aCharset)
|
|
{
|
|
// fast path for UTF-8. Most platform uses UTF-8 as charset now.
|
|
if (aCharset.EqualsLiteral("UTF-8")) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsAutoCString encoding;
|
|
if (!EncodingUtils::FindEncodingForLabelNoReplacement(aCharset, encoding)) {
|
|
return NS_ERROR_UCONV_NOCONV;
|
|
}
|
|
|
|
aCharset.Assign(encoding);
|
|
return NS_OK;
|
|
}
|