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 +}