nsUNIXCharset.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include <locale.h>
  6. #include "mozilla/ArrayUtils.h"
  7. #include "nsIPlatformCharset.h"
  8. #include "nsUConvPropertySearch.h"
  9. #include "nsCOMPtr.h"
  10. #include "nsReadableUtils.h"
  11. #include "nsEncoderDecoderUtils.h"
  12. #if HAVE_GNU_LIBC_VERSION_H
  13. #include <gnu/libc-version.h>
  14. #endif
  15. #ifdef HAVE_NL_TYPES_H
  16. #include <nl_types.h>
  17. #endif
  18. #if HAVE_LANGINFO_CODESET
  19. #include <langinfo.h>
  20. #endif
  21. #include "nsPlatformCharset.h"
  22. #include "prinit.h"
  23. #include "nsUnicharUtils.h"
  24. #include "mozilla/dom/EncodingUtils.h"
  25. using mozilla::dom::EncodingUtils;
  26. using namespace mozilla;
  27. static const nsUConvProp kUnixCharsets[] = {
  28. #include "unixcharset.properties.h"
  29. };
  30. NS_IMPL_ISUPPORTS(nsPlatformCharset, nsIPlatformCharset)
  31. nsPlatformCharset::nsPlatformCharset()
  32. {
  33. }
  34. static nsresult
  35. ConvertLocaleToCharsetUsingDeprecatedConfig(const nsACString& locale,
  36. nsACString& oResult)
  37. {
  38. if (!(locale.IsEmpty())) {
  39. if (NS_SUCCEEDED(nsUConvPropertySearch::SearchPropertyValue(kUnixCharsets,
  40. ArrayLength(kUnixCharsets), locale, oResult))) {
  41. return NS_OK;
  42. }
  43. }
  44. NS_ERROR("unable to convert locale to charset using deprecated config");
  45. oResult.AssignLiteral("ISO-8859-1");
  46. return NS_SUCCESS_USING_FALLBACK_LOCALE;
  47. }
  48. nsPlatformCharset::~nsPlatformCharset()
  49. {
  50. }
  51. NS_IMETHODIMP
  52. nsPlatformCharset::GetCharset(nsPlatformCharsetSel selector, nsACString& oResult)
  53. {
  54. oResult = mCharset;
  55. return NS_OK;
  56. }
  57. NS_IMETHODIMP
  58. nsPlatformCharset::GetDefaultCharsetForLocale(const nsAString& localeName, nsACString &oResult)
  59. {
  60. //
  61. // if this locale is the user's locale then use the charset
  62. // we already determined at initialization
  63. //
  64. if (mLocale.Equals(localeName) ||
  65. // support the 4.x behavior
  66. (mLocale.LowerCaseEqualsLiteral("en_us") &&
  67. localeName.LowerCaseEqualsLiteral("c"))) {
  68. oResult = mCharset;
  69. return NS_OK;
  70. }
  71. #if HAVE_LANGINFO_CODESET
  72. //
  73. // This locale appears to be a different locale from the user's locale.
  74. // To do this we would need to lock the global resource we are currently
  75. // using or use a library that provides multi locale support.
  76. // ICU is a possible example of a multi locale library.
  77. // http://oss.software.ibm.com/icu/
  78. //
  79. // A more common cause of hitting this warning than the above is that
  80. // Mozilla is launched under an ll_CC.UTF-8 locale. In xpLocale,
  81. // we only store the language and the region (ll-CC) losing 'UTF-8', which
  82. // leads |mLocale| to be different from |localeName|. Although we lose
  83. // 'UTF-8', we init'd |mCharset| with the value obtained via
  84. // |nl_langinfo(CODESET)| so that we're all right here.
  85. //
  86. NS_WARNING("GetDefaultCharsetForLocale: need to add multi locale support");
  87. #ifdef DEBUG_jungshik
  88. printf("localeName=%s mCharset=%s\n", NS_ConvertUTF16toUTF8(localeName).get(),
  89. mCharset.get());
  90. #endif
  91. // until we add multi locale support: use the the charset of the user's locale
  92. oResult = mCharset;
  93. return NS_SUCCESS_USING_FALLBACK_LOCALE;
  94. #else
  95. //
  96. // convert from locale to charset
  97. // using the deprecated locale to charset mapping
  98. //
  99. NS_LossyConvertUTF16toASCII localeStr(localeName);
  100. return ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oResult);
  101. #endif
  102. }
  103. nsresult
  104. nsPlatformCharset::InitGetCharset(nsACString &oString)
  105. {
  106. #if HAVE_LANGINFO_CODESET
  107. char* nl_langinfo_codeset = nullptr;
  108. nsCString aCharset;
  109. nsresult res;
  110. nl_langinfo_codeset = nl_langinfo(CODESET);
  111. NS_ASSERTION(nl_langinfo_codeset, "cannot get nl_langinfo(CODESET)");
  112. //
  113. // see if we can use nl_langinfo(CODESET) directly
  114. //
  115. if (nl_langinfo_codeset) {
  116. aCharset.Assign(nl_langinfo_codeset);
  117. res = VerifyCharset(aCharset);
  118. if (NS_SUCCEEDED(res)) {
  119. oString = aCharset;
  120. return res;
  121. }
  122. }
  123. NS_ERROR("unable to use nl_langinfo(CODESET)");
  124. #endif
  125. //
  126. // try falling back on a deprecated (locale based) name
  127. //
  128. char* locale = setlocale(LC_CTYPE, nullptr);
  129. nsAutoCString localeStr;
  130. localeStr.Assign(locale);
  131. return ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oString);
  132. }
  133. NS_IMETHODIMP
  134. nsPlatformCharset::Init()
  135. {
  136. //
  137. // remember default locale so we can use the
  138. // same charset when asked for the same locale
  139. //
  140. char* locale = setlocale(LC_CTYPE, nullptr);
  141. NS_ASSERTION(locale, "cannot setlocale");
  142. if (locale) {
  143. CopyASCIItoUTF16(locale, mLocale);
  144. } else {
  145. mLocale.AssignLiteral("en_US");
  146. }
  147. // InitGetCharset only returns NS_OK or NS_SUCESS_USING_FALLBACK_LOCALE
  148. return InitGetCharset(mCharset);
  149. }
  150. nsresult
  151. nsPlatformCharset::VerifyCharset(nsCString &aCharset)
  152. {
  153. // fast path for UTF-8. Most platform uses UTF-8 as charset now.
  154. if (aCharset.EqualsLiteral("UTF-8")) {
  155. return NS_OK;
  156. }
  157. nsAutoCString encoding;
  158. if (!EncodingUtils::FindEncodingForLabelNoReplacement(aCharset, encoding)) {
  159. return NS_ERROR_UCONV_NOCONV;
  160. }
  161. aCharset.Assign(encoding);
  162. return NS_OK;
  163. }