summaryrefslogtreecommitdiffstats
path: root/intl/locale/unix/nsUNIXCharset.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'intl/locale/unix/nsUNIXCharset.cpp')
-rw-r--r--intl/locale/unix/nsUNIXCharset.cpp185
1 files changed, 185 insertions, 0 deletions
diff --git a/intl/locale/unix/nsUNIXCharset.cpp b/intl/locale/unix/nsUNIXCharset.cpp
new file mode 100644
index 000000000..d72305e55
--- /dev/null
+++ b/intl/locale/unix/nsUNIXCharset.cpp
@@ -0,0 +1,185 @@
+/* -*- 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;
+}