123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- /* -*- 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;
- }
|