source: filezilla/trunk/fuentes/src/interface/locale_initializer.cpp @ 130

Last change on this file since 130 was 130, checked in by jrpelegrina, 3 years ago

First release to xenial

File size: 7.3 KB
Line 
1#include <filezilla.h>
2#include "locale_initializer.h"
3#ifdef HAVE_LIBPUGIXML
4#include <pugixml.hpp>
5#else
6#include "../pugixml/pugixml.hpp"
7#endif
8#include <string>
9#include <locale.h>
10#include <sys/stat.h>
11
12#ifdef ENABLE_BINRELOC
13        #define BR_PTHREADS 0
14        #include "prefix.h"
15#endif
16
17struct t_fallbacks
18{
19        const char* locale;
20        const char* fallback;
21};
22
23struct t_fallbacks fallbacks[] = {
24
25        // The following entries are needed due to missing language codes wxWidgets
26        { "ka", "ka_GE" },
27        { "ku", "ku_TR" },
28        { "ne", "ne_NP" },
29
30        // Fallback chain for English
31        { "en", "en_US" },
32        { "en_US", "en_GB" },
33        { "en_GB", "C" },
34
35        // Base names
36        { "ar", "ar_EG" },
37        { "ca", "ca_ES" },
38        { "cy", "cy_GB" },
39        { "de", "de_DE" },
40        { "el", "el_GR" },
41        { "es", "es_ES" },
42        { "et", "et_EE" },
43        { "fr", "fr_FR" },
44        { "it", "it_IT" },
45        { "nl", "nl_NL" },
46        { "ru", "ru_RU" },
47        { "sv", "sv_SE" },
48        { "tr", "tr_TR" },
49
50        { 0, 0 }
51};
52
53wxString GetFallbackLocale( wxString const& locale )
54{
55        int i = 0;
56        while (fallbacks[i].locale) {
57                if (fallbacks[i].locale == locale)
58                        return fallbacks[i].fallback;
59                i++;
60        }
61
62        return wxString();
63}
64
65// Custom main method to initialize proper locale
66#ifdef __WXGTK__
67
68bool CInitializer::error = false;
69
70static std::string mkstr(const char* str)
71{
72        if (!str)
73                return "";
74        else
75                return str;
76}
77
78int main(int argc, char** argv)
79{
80        std::string locale = CInitializer::GetLocaleOption();
81        if (locale != "")
82        {
83                if (!CInitializer::SetLocale(locale))
84                {
85#ifdef __WXDEBUG__
86                        printf("failed to set locale\n");
87#endif
88                        CInitializer::error = true;
89                }
90                else
91                {
92#ifdef __WXDEBUG__
93                        printf("locale set to %s\n", setlocale(LC_ALL, 0));
94#endif
95                }
96        }
97
98        return wxEntry(argc, argv);
99}
100
101bool CInitializer::SetLocaleReal(const std::string& locale)
102{
103        if (!setlocale(LC_ALL, locale.c_str()))
104                return false;
105
106#ifdef __WXDEBUG__
107        printf("setlocale %s successful\n", locale.c_str());
108#endif
109#ifdef HAVE_SETENV
110        setenv("LC_ALL", locale.c_str(), 1);
111#else
112        std::string str("LC_ALL=");
113        str += locale;
114        putenv(str.c_str());
115#endif
116        return true;
117}
118
119bool CInitializer::SetLocale(const std::string& arg)
120{
121        const char *encodings[] = {
122                "UTF-8",
123                "UTF8",
124                "utf-8",
125                "utf8",
126                0
127        };
128
129        for (int i = 0; encodings[i]; i++)
130        {
131                std::string locale = CInitializer::LocaleAddEncoding(arg, encodings[i]);
132                if (SetLocaleReal(locale))
133                        return true;
134        }
135
136        if (CInitializer::SetLocaleReal(arg))
137                return true;
138
139        int i = 0;
140        while (fallbacks[i].locale)
141        {
142                if (fallbacks[i].locale == arg)
143                        return SetLocale(fallbacks[i].fallback);
144                i++;
145        }
146
147        return false;
148}
149
150std::string CInitializer::CheckPathForDefaults(std::string path, int strip, std::string suffix)
151{
152        if (path.empty())
153                return "";
154
155        if (path[path.size() - 1] == '/')
156                path = path.substr(0, path.size() - 1);
157        while (strip--)
158        {
159                int p = path.rfind('/');
160                if (p == -1)
161                        return "";
162                path = path.substr(0, p);
163        }
164
165        path += '/' + suffix;
166        struct stat buf;
167        if (!stat(path.c_str(), &buf))
168                return path;
169
170        return "";
171}
172
173std::string CInitializer::GetDefaultsXmlFile()
174{
175        std::string fzdatadir = mkstr(getenv("FZ_DATADIR"));
176        std::string file = CheckPathForDefaults(fzdatadir, 0, "fzdefaults.xml");
177        if (!file.empty())
178                return file;
179        file = CheckPathForDefaults(fzdatadir, 1, "fzdefaults.xml");
180        if (!file.empty())
181                return file;
182
183        file = GetUnadjustedSettingsDir() + "fzdefaults.xml";
184
185        {
186                struct stat buf{};
187                if (!stat(file.c_str(), &buf)) {
188                        return file;
189                }
190        }
191
192        file = "/etc/filezilla/fzdefaults.xml";
193
194        {
195                struct stat buf{};
196                if (!stat(file.c_str(), &buf))
197                        return file;
198        }
199
200
201        file = CheckPathForDefaults(mkstr(SELFPATH), 2, "share/filezilla/fzdefaults.xml");
202        if (!file.empty())
203                return file;
204        file = CheckPathForDefaults(mkstr(DATADIR), 0, "filezilla/fzdefaults.xml");
205        if (!file.empty())
206                return file;
207
208        std::string path = mkstr(getenv("PATH"));
209        while (!path.empty())
210        {
211                std::string segment;
212                int pos = path.find(':');
213                if (pos == -1)
214                        segment.swap(path);
215                else
216                {
217                        segment = path.substr(0, pos);
218                        path = path.substr(pos + 1);
219                }
220
221                file = CheckPathForDefaults(segment, 1, "share/filezilla/fzdefaults.xml");
222                if (!file.empty())
223                        return file;
224        }
225
226        return "";
227}
228
229std::string CInitializer::ReadSettingsFromDefaults(std::string file)
230{
231        std::string dir = CInitializer::GetSettingFromFile(file, "Config Location");
232
233        if (dir.empty())
234                return "";
235
236        std::string result;
237        while (!dir.empty())
238        {
239                std::string token;
240                int pos = dir.find('/');
241                if (pos == -1)
242                        token.swap(dir);
243                else
244                {
245                        token = dir.substr(0, pos);
246                        dir = dir.substr(pos + 1);
247                }
248
249                if (!token.empty() && token[0] == '$')
250                {
251                        if (token[1] == '$')
252                                result += token.substr(1);
253                        else if (token.size() > 1)
254                        {
255                                std::string value = mkstr(getenv(token.substr(1).c_str()));
256                                result += value;
257                        }
258                }
259                else
260                        result += token;
261
262                result += '/';
263        }
264
265        struct stat buf;
266        if (stat(result.c_str(), &buf))
267                return "";
268
269        if (result[result.size() - 1] != '/')
270                result += '/';
271
272        return result;
273}
274
275std::string CInitializer::GetSettingFromFile(std::string file, const std::string& name)
276{
277        pugi::xml_document xmldoc;
278        if (!xmldoc.load_file(file.c_str()))
279                return "";
280
281        auto main = xmldoc.child("FileZilla3");
282        if (!main)
283                return "";
284
285        auto settings = main.child("Settings");
286        if (!settings)
287                return "";
288
289        for (auto setting = settings.child("Setting"); setting; setting = setting.next_sibling("Setting")) {
290                const char* nodeVal = setting.attribute("name").value();
291                if (!nodeVal || strcmp(nodeVal, name.c_str()))
292                        continue;
293
294                const char* text = setting.child_value();
295                return mkstr(text);
296        }
297
298        return "";
299}
300
301namespace {
302std::string TryDirectory( std::string const& env, std::string const& suffix, bool check_exists )
303{
304        std::string path = mkstr(getenv(env.c_str()));
305        if( !path.empty() && path[0] == '/' ) {
306                if( path[path.size()-1] != '/' ) {
307                        path += '/';
308                }
309
310                path += suffix;
311
312                if( check_exists ) {
313                        struct stat buf{};
314                        int res = stat(path.c_str(), &buf);
315                        if( res || !S_ISDIR(buf.st_mode) ) {
316                                path.clear();
317                        }
318                }
319        }
320        else {
321                path.clear();
322        }
323        return path;
324}
325}
326
327std::string CInitializer::GetUnadjustedSettingsDir()
328{
329        std::string cfg = TryDirectory("XDG_CONFIG_HOME", "filezilla/", true);
330        if( cfg.empty() ) {
331                cfg = TryDirectory("HOME", ".config/filezilla/", true);
332        }
333        if( cfg.empty() ) {
334                cfg = TryDirectory("HOME", ".filezilla/", true);
335        }
336        if( cfg.empty() ) {
337                cfg = TryDirectory("XDG_CONFIG_HOME", "filezilla/", false);
338        }
339        if( cfg.empty() ) {
340                cfg = TryDirectory("HOME", ".config/filezilla/", false);
341        }
342        if( cfg.empty() ) {
343                cfg = TryDirectory("HOME", ".filezilla/", false);
344        }
345
346        return cfg;
347}
348
349std::string CInitializer::GetAdjustedSettingsDir()
350{
351        std::string defaults = GetDefaultsXmlFile();
352        if (!defaults.empty())
353        {
354                std::string dir = CInitializer::ReadSettingsFromDefaults(defaults);
355                if (!dir.empty())
356                        return dir;
357        }
358
359        return GetUnadjustedSettingsDir();
360}
361
362std::string CInitializer::GetLocaleOption()
363{
364        const std::string dir = GetAdjustedSettingsDir();
365        if (dir.empty())
366                return "";
367
368#ifdef __WXDEBUG__
369        printf("Reading locale option from %sfilezilla.xml\n", dir.c_str());
370#endif
371        std::string locale = GetSettingFromFile(dir + "filezilla.xml", "Language Code");
372
373        return locale;
374}
375
376std::string CInitializer::LocaleAddEncoding(const std::string& locale, const std::string& encoding)
377{
378        int pos = locale.find('@');
379        if (pos == -1)
380                return locale + '.' + encoding;
381
382        return locale.substr(0, pos) + '.' + encoding + locale.substr(pos);
383}
384
385#endif //__WXGTK__
Note: See TracBrowser for help on using the repository browser.