Line data Source code
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 :
6 : #include <locale.h>
7 :
8 : #include "mozilla/ArrayUtils.h"
9 :
10 : #include "nsIPlatformCharset.h"
11 : #include "nsUConvPropertySearch.h"
12 : #include "nsCOMPtr.h"
13 : #include "nsReadableUtils.h"
14 : #if HAVE_GNU_LIBC_VERSION_H
15 : #include <gnu/libc-version.h>
16 : #endif
17 : #ifdef HAVE_NL_TYPES_H
18 : #include <nl_types.h>
19 : #endif
20 : #if HAVE_LANGINFO_CODESET
21 : #include <langinfo.h>
22 : #endif
23 : #include "nsPlatformCharset.h"
24 : #include "prinit.h"
25 : #include "nsUnicharUtils.h"
26 : #include "mozilla/Encoding.h"
27 :
28 : using namespace mozilla;
29 :
30 : static constexpr nsUConvProp kUnixCharsets[] = {
31 : #include "unixcharset.properties.h"
32 : };
33 :
34 0 : NS_IMPL_ISUPPORTS(nsPlatformCharset, nsIPlatformCharset)
35 :
36 0 : nsPlatformCharset::nsPlatformCharset()
37 : {
38 0 : }
39 :
40 : static nsresult
41 0 : ConvertLocaleToCharsetUsingDeprecatedConfig(const nsACString& locale,
42 : nsACString& oResult)
43 : {
44 0 : if (!(locale.IsEmpty())) {
45 0 : if (NS_SUCCEEDED(nsUConvPropertySearch::SearchPropertyValue(kUnixCharsets,
46 : ArrayLength(kUnixCharsets), locale, oResult))) {
47 0 : return NS_OK;
48 : }
49 : }
50 0 : NS_ERROR("unable to convert locale to charset using deprecated config");
51 0 : oResult.AssignLiteral("ISO-8859-1");
52 0 : return NS_SUCCESS_USING_FALLBACK_LOCALE;
53 : }
54 :
55 0 : nsPlatformCharset::~nsPlatformCharset()
56 : {
57 0 : }
58 :
59 : NS_IMETHODIMP
60 0 : nsPlatformCharset::GetCharset(nsPlatformCharsetSel selector, nsACString& oResult)
61 : {
62 0 : oResult = mCharset;
63 0 : return NS_OK;
64 : }
65 :
66 : nsresult
67 0 : nsPlatformCharset::InitGetCharset(nsACString &oString)
68 : {
69 : #if HAVE_LANGINFO_CODESET
70 0 : char* nl_langinfo_codeset = nullptr;
71 0 : nsCString aCharset;
72 : nsresult res;
73 :
74 0 : nl_langinfo_codeset = nl_langinfo(CODESET);
75 0 : NS_ASSERTION(nl_langinfo_codeset, "cannot get nl_langinfo(CODESET)");
76 :
77 : //
78 : // see if we can use nl_langinfo(CODESET) directly
79 : //
80 0 : if (nl_langinfo_codeset) {
81 0 : aCharset.Assign(nl_langinfo_codeset);
82 0 : res = VerifyCharset(aCharset);
83 0 : if (NS_SUCCEEDED(res)) {
84 0 : oString = aCharset;
85 0 : return res;
86 : }
87 : }
88 :
89 0 : NS_ERROR("unable to use nl_langinfo(CODESET)");
90 : #endif
91 :
92 : //
93 : // try falling back on a deprecated (locale based) name
94 : //
95 0 : char* locale = setlocale(LC_CTYPE, nullptr);
96 0 : nsAutoCString localeStr;
97 0 : localeStr.Assign(locale);
98 0 : return ConvertLocaleToCharsetUsingDeprecatedConfig(localeStr, oString);
99 : }
100 :
101 : NS_IMETHODIMP
102 0 : nsPlatformCharset::Init()
103 : {
104 : //
105 : // remember default locale so we can use the
106 : // same charset when asked for the same locale
107 : //
108 0 : char* locale = setlocale(LC_CTYPE, nullptr);
109 0 : NS_ASSERTION(locale, "cannot setlocale");
110 0 : if (locale) {
111 0 : CopyASCIItoUTF16(locale, mLocale);
112 : } else {
113 0 : mLocale.AssignLiteral("en_US");
114 : }
115 :
116 : // InitGetCharset only returns NS_OK or NS_SUCESS_USING_FALLBACK_LOCALE
117 0 : return InitGetCharset(mCharset);
118 : }
119 :
120 : nsresult
121 0 : nsPlatformCharset::VerifyCharset(nsCString &aCharset)
122 : {
123 : // fast path for UTF-8. Most platform uses UTF-8 as charset now.
124 0 : if (aCharset.EqualsLiteral("UTF-8")) {
125 0 : return NS_OK;
126 : }
127 :
128 0 : const Encoding* encoding = Encoding::ForLabelNoReplacement(aCharset);
129 0 : if (!encoding) {
130 0 : return NS_ERROR_UCONV_NOCONV;
131 : }
132 :
133 0 : encoding->Name(aCharset);
134 0 : return NS_OK;
135 : }
|