intl/locale/src/unix/nsUNIXCharset.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/intl/locale/src/unix/nsUNIXCharset.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,229 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include <locale.h>
    1.10 +
    1.11 +#include "mozilla/ArrayUtils.h"
    1.12 +
    1.13 +#include "nsIPlatformCharset.h"
    1.14 +#include "nsUConvPropertySearch.h"
    1.15 +#include "nsCOMPtr.h"
    1.16 +#include "nsReadableUtils.h"
    1.17 +#include "nsIComponentManager.h"
    1.18 +#include "nsIServiceManager.h"
    1.19 +#include "nsIUnicodeDecoder.h"
    1.20 +#include "nsIUnicodeEncoder.h"
    1.21 +#include "nsICharsetConverterManager.h"
    1.22 +#include "nsEncoderDecoderUtils.h"
    1.23 +#if HAVE_GNU_LIBC_VERSION_H
    1.24 +#include <gnu/libc-version.h>
    1.25 +#endif
    1.26 +#ifdef HAVE_NL_TYPES_H
    1.27 +#include <nl_types.h>
    1.28 +#endif
    1.29 +#if HAVE_LANGINFO_CODESET
    1.30 +#include <langinfo.h>
    1.31 +#endif
    1.32 +#include "nsPlatformCharset.h"
    1.33 +#include "prinit.h"
    1.34 +#include "nsUnicharUtils.h"
    1.35 +
    1.36 +using namespace mozilla;
    1.37 +
    1.38 +static const char* kUnixCharsets[][3] = {
    1.39 +#include "unixcharset.properties.h"
    1.40 +};
    1.41 +
    1.42 +NS_IMPL_ISUPPORTS(nsPlatformCharset, nsIPlatformCharset)
    1.43 +
    1.44 +nsPlatformCharset::nsPlatformCharset()
    1.45 +{
    1.46 +}
    1.47 +
    1.48 +static nsresult
    1.49 +ConvertLocaleToCharsetUsingDeprecatedConfig(const nsACString& locale,
    1.50 +                                            nsACString& oResult)
    1.51 +{
    1.52 +  if (!(locale.IsEmpty())) {
    1.53 +    nsAutoCString localeKey;
    1.54 +    localeKey.AssignLiteral("locale.all.");
    1.55 +    localeKey.Append(locale);
    1.56 +    if (NS_SUCCEEDED(nsUConvPropertySearch::SearchPropertyValue(kUnixCharsets,
    1.57 +        ArrayLength(kUnixCharsets), localeKey, oResult))) {
    1.58 +      return NS_OK;
    1.59 +    }
    1.60 +  }
    1.61 +  NS_ERROR("unable to convert locale to charset using deprecated config");
    1.62 +  oResult.AssignLiteral("ISO-8859-1");
    1.63 +  return NS_SUCCESS_USING_FALLBACK_LOCALE;
    1.64 +}
    1.65 +
    1.66 +nsPlatformCharset::~nsPlatformCharset()
    1.67 +{
    1.68 +}
    1.69 +
    1.70 +NS_IMETHODIMP 
    1.71 +nsPlatformCharset::GetCharset(nsPlatformCharsetSel selector, nsACString& oResult)
    1.72 +{
    1.73 +  oResult = mCharset; 
    1.74 +  return NS_OK;
    1.75 +}
    1.76 +
    1.77 +NS_IMETHODIMP 
    1.78 +nsPlatformCharset::GetDefaultCharsetForLocale(const nsAString& localeName, nsACString &oResult)
    1.79 +{
    1.80 +  // 
    1.81 +  // if this locale is the user's locale then use the charset 
    1.82 +  // we already determined at initialization
    1.83 +  // 
    1.84 +  if (mLocale.Equals(localeName) ||
    1.85 +    // support the 4.x behavior
    1.86 +    (mLocale.LowerCaseEqualsLiteral("en_us") && 
    1.87 +     localeName.LowerCaseEqualsLiteral("c"))) {
    1.88 +    oResult = mCharset;
    1.89 +    return NS_OK;
    1.90 +  }
    1.91 +
    1.92 +#if HAVE_LANGINFO_CODESET
    1.93 +  //
    1.94 +  // This locale appears to be a different locale from the user's locale. 
    1.95 +  // To do this we would need to lock the global resource we are currently 
    1.96 +  // using or use a library that provides multi locale support. 
    1.97 +  // ICU is a possible example of a multi locale library.
    1.98 +  //     http://oss.software.ibm.com/icu/
    1.99 +  //
   1.100 +  // A more common cause of hitting this warning than the above is that 
   1.101 +  // Mozilla is launched under an ll_CC.UTF-8 locale. In xpLocale, 
   1.102 +  // we only store the language and the region (ll-CC) losing 'UTF-8', which
   1.103 +  // leads |mLocale| to be different from |localeName|. Although we lose
   1.104 +  // 'UTF-8', we init'd |mCharset| with the value obtained via 
   1.105 +  // |nl_langinfo(CODESET)| so that we're all right here.
   1.106 +  // 
   1.107 +  NS_WARNING("GetDefaultCharsetForLocale: need to add multi locale support");
   1.108 +#ifdef DEBUG_jungshik
   1.109 +  printf("localeName=%s mCharset=%s\n", NS_ConvertUTF16toUTF8(localeName).get(),
   1.110 +         mCharset.get());
   1.111 +#endif
   1.112 +  // until we add multi locale support: use the the charset of the user's locale
   1.113 +  oResult = mCharset;
   1.114 +  return NS_SUCCESS_USING_FALLBACK_LOCALE;
   1.115 +#else
   1.116 +  //
   1.117 +  // convert from locale to charset
   1.118 +  // using the deprecated locale to charset mapping 
   1.119 +  //
   1.120 +  NS_LossyConvertUTF16toASCII localeStr(localeName);
   1.121 +  return ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oResult);
   1.122 +#endif
   1.123 +}
   1.124 +
   1.125 +nsresult
   1.126 +nsPlatformCharset::InitGetCharset(nsACString &oString)
   1.127 +{
   1.128 +  char* nl_langinfo_codeset = nullptr;
   1.129 +  nsCString aCharset;
   1.130 +  nsresult res;
   1.131 +
   1.132 +#if HAVE_LANGINFO_CODESET
   1.133 +  nl_langinfo_codeset = nl_langinfo(CODESET);
   1.134 +  NS_ASSERTION(nl_langinfo_codeset, "cannot get nl_langinfo(CODESET)");
   1.135 +
   1.136 +  //
   1.137 +  // see if we can use nl_langinfo(CODESET) directly
   1.138 +  //
   1.139 +  if (nl_langinfo_codeset) {
   1.140 +    aCharset.Assign(nl_langinfo_codeset);
   1.141 +    res = VerifyCharset(aCharset);
   1.142 +    if (NS_SUCCEEDED(res)) {
   1.143 +      oString = aCharset;
   1.144 +      return res;
   1.145 +    }
   1.146 +  }
   1.147 +
   1.148 +  NS_ERROR("unable to use nl_langinfo(CODESET)");
   1.149 +#endif
   1.150 +
   1.151 +  //
   1.152 +  // try falling back on a deprecated (locale based) name
   1.153 +  //
   1.154 +  char* locale = setlocale(LC_CTYPE, nullptr);
   1.155 +  nsAutoCString localeStr;
   1.156 +  localeStr.Assign(locale);
   1.157 +  return ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oString);
   1.158 +}
   1.159 +
   1.160 +NS_IMETHODIMP 
   1.161 +nsPlatformCharset::Init()
   1.162 +{
   1.163 +  //
   1.164 +  // remember default locale so we can use the
   1.165 +  // same charset when asked for the same locale
   1.166 +  //
   1.167 +  char* locale = setlocale(LC_CTYPE, nullptr);
   1.168 +  NS_ASSERTION(locale, "cannot setlocale");
   1.169 +  if (locale) {
   1.170 +    CopyASCIItoUTF16(locale, mLocale); 
   1.171 +  } else {
   1.172 +    mLocale.AssignLiteral("en_US");
   1.173 +  }
   1.174 +
   1.175 +  // InitGetCharset only returns NS_OK or NS_SUCESS_USING_FALLBACK_LOCALE
   1.176 +  return InitGetCharset(mCharset);
   1.177 +}
   1.178 +
   1.179 +nsresult
   1.180 +nsPlatformCharset::VerifyCharset(nsCString &aCharset)
   1.181 +{
   1.182 +  // fast path for UTF-8.  Most platform uses UTF-8 as charset now.
   1.183 +  if (aCharset.EqualsLiteral("UTF-8")) {
   1.184 +    return NS_OK;
   1.185 +  }
   1.186 +
   1.187 +  nsresult res;
   1.188 +  //
   1.189 +  // get the convert manager
   1.190 +  //
   1.191 +  nsCOMPtr <nsICharsetConverterManager>  charsetConverterManager;
   1.192 +  charsetConverterManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &res);
   1.193 +  if (NS_FAILED(res))
   1.194 +    return res;
   1.195 +
   1.196 +  //
   1.197 +  // check if we can get an input converter
   1.198 +  //
   1.199 +  nsCOMPtr <nsIUnicodeEncoder> enc;
   1.200 +  res = charsetConverterManager->GetUnicodeEncoder(aCharset.get(), getter_AddRefs(enc));
   1.201 +  if (NS_FAILED(res)) {
   1.202 +    NS_ERROR("failed to create encoder");
   1.203 +    return res;
   1.204 +  }
   1.205 +
   1.206 +  //
   1.207 +  // check if we can get an output converter
   1.208 +  //
   1.209 +  nsCOMPtr <nsIUnicodeDecoder> dec;
   1.210 +  res = charsetConverterManager->GetUnicodeDecoder(aCharset.get(), getter_AddRefs(dec));
   1.211 +  if (NS_FAILED(res)) {
   1.212 +    NS_ERROR("failed to create decoder");
   1.213 +    return res;
   1.214 +  }
   1.215 +
   1.216 +  //
   1.217 +  // check if we recognize the charset string
   1.218 +  //
   1.219 +
   1.220 +  nsAutoCString result;
   1.221 +  res = charsetConverterManager->GetCharsetAlias(aCharset.get(), result);
   1.222 +  if (NS_FAILED(res)) {
   1.223 +    return res;
   1.224 +  }
   1.225 +
   1.226 +  //
   1.227 +  // return the preferred string
   1.228 +  //
   1.229 +
   1.230 +  aCharset.Assign(result);
   1.231 +  return NS_OK;
   1.232 +}

mercurial