1 /*****************************************************************************
2 ** QNapi
3 ** Copyright (C) 2008-2017 Piotr Krzemiński <pio.krzeminski@gmail.com>
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12 **
13 *****************************************************************************/
14 
15 #include "configreader.h"
16 #include <QCoreApplication>
17 #include <QDir>
18 #include <QFileInfo>
19 #include <QLocale>
20 #include <QProcess>
21 #include "subtitlelanguage.h"
22 
ConfigReader(const QString & appExecutableDir,const QSharedPointer<const StaticConfig> & staticConfig,const QSharedPointer<const SubtitleDownloadEnginesRegistry> enginesRegistry)23 ConfigReader::ConfigReader(
24     const QString& appExecutableDir,
25     const QSharedPointer<const StaticConfig>& staticConfig,
26     const QSharedPointer<const SubtitleDownloadEnginesRegistry> enginesRegistry)
27     : appExecutableDir(appExecutableDir),
28       staticConfig(staticConfig),
29       enginesRegistry(enginesRegistry) {}
30 
readUserConfig() const31 const QNapiConfig ConfigReader::readUserConfig() const {
32   return readConfig(
33       QSettings(QSettings::IniFormat, QSettings::UserScope, "qnapi"));
34 }
35 
readPortableConfig(const QString & configFilePath) const36 const QNapiConfig ConfigReader::readPortableConfig(
37     const QString& configFilePath) const {
38   return readConfig(QSettings(configFilePath, QSettings::IniFormat));
39 }
40 
readConfig(const QSettings & settings) const41 const QNapiConfig ConfigReader::readConfig(const QSettings& settings) const {
42   return QNapiConfig(settings.value("qnapi/firstrun", true).toBool(),
43                      settings.value("qnapi/version", "").toString(),
44                      readGeneralConfig(settings), readEnabledEngines(settings),
45                      readEnginesConfig(settings),
46                      readPostProcessingConfig(settings),
47                      readScanConfig(settings),
48                      settings.value("qnapi/last_opened_dir", "").toString());
49 }
50 
readGeneralConfig(const QSettings & settings) const51 const GeneralConfig ConfigReader::readGeneralConfig(
52     const QSettings& settings) const {
53   QString sysLangCode = QLocale::system().name().left(2);
54   QString preferredLangCode =
55       SubtitleLanguage().listLanguageTwoLetterCodes().contains(sysLangCode)
56           ? sysLangCode
57           : "en";
58   QString backupLangCode = (preferredLangCode != "en") ? "en" : "";
59 
60   auto cfg = GeneralConfig(
61       settings.value("qnapi/ui_language", "").toString(),
62       settings.value("qnapi/7z_path", "").toString(),
63       settings.value("qnapi/tmp_path", "").toString(),
64       settings.value("qnapi/language", preferredLangCode).toString(),
65       settings.value("qnapi/language_backup", backupLangCode).toString(),
66       settings.value("qnapi/no_backup", false).toBool(),
67       settings.value("qnapi/quiet_batch", false).toBool(),
68       static_cast<SearchPolicy>(
69           settings.value("qnapi/search_policy", SP_BREAK_IF_FOUND).toInt()),
70       static_cast<DownloadPolicy>(
71           settings.value("qnapi/download_policy", DP_SHOW_LIST_IF_NEEDED)
72               .toInt()),
73       settings.value("qnapi/change_permissions", false).toBool(),
74       settings.value("qnapi/permissions", "644").toString());
75 
76   auto cfg1 = resolveP7zipPath(cfg);
77   auto cfg2 = resolveTmpPath(cfg1);
78   return cfg2;
79 }
80 
readEnabledEngines(const QSettings & settings) const81 const QList<QPair<QString, bool>> ConfigReader::readEnabledEngines(
82     const QSettings& settings) const {
83   QList<QPair<QString, bool>> defaultEnabledEngines;
84   foreach (QString engineName, enginesRegistry->listEngineNames()) {
85     defaultEnabledEngines << qMakePair(engineName, true);
86   }
87 
88   QStringList enabledEnginesStr =
89       settings.value("qnapi/engines", QStringList()).toStringList();
90 
91   if (enabledEnginesStr.size() != enginesRegistry->listEngineNames().size()) {
92     return defaultEnabledEngines;
93   } else {
94     QList<QPair<QString, bool>> enabledEngines;
95     foreach (QString engineEnableStr, enabledEnginesStr) {
96       QStringList engineParts =
97           engineEnableStr.split(":", QString::SkipEmptyParts);
98       if (engineParts.size() != 2) {
99         return defaultEnabledEngines;
100       }
101       enabledEngines << qMakePair(engineParts[0], engineParts[1] == "on");
102     }
103     return enabledEngines;
104   }
105 }
106 
readEnginesConfig(const QSettings & settings) const107 const QMap<QString, EngineConfig> ConfigReader::readEnginesConfig(
108     const QSettings& settings) const {
109   QMap<QString, EngineConfig> engineConfigurations;
110   foreach (QString engineName, enginesRegistry->listEngineNames()) {
111     engineConfigurations.insert(engineName,
112                                 readEngineConfig(engineName, settings));
113   }
114   return engineConfigurations;
115 }
116 
readEngineConfig(QString engineName,const QSettings & settings) const117 const EngineConfig ConfigReader::readEngineConfig(
118     QString engineName, const QSettings& settings) const {
119   return EngineConfig(settings.value(engineName + "/nick", "").toString(),
120                       settings.value(engineName + "/password", "").toString());
121 }
122 
readPostProcessingConfig(const QSettings & settings) const123 const PostProcessingConfig ConfigReader::readPostProcessingConfig(
124     const QSettings& settings) const {
125   return PostProcessingConfig(
126       settings.value("qnapi/post_processing", true).toBool(),
127       static_cast<EncodingChangeMethod>(
128           settings.value("qnapi/encoding_method", ECM_CHANGE).toInt()),
129       settings.value("qnapi/enc_from", "windows-1250").toString(),
130       settings.value("qnapi/auto_detect_encoding", true).toBool(),
131       settings.value("qnapi/enc_to", "UTF-8").toString(),
132       settings.value("qnapi/show_all_encodings", false).toBool(),
133       settings.value("qnapi/sub_format", "srt").toString(),
134       settings.value("qnapi/sub_ext", "").toString(),
135       settings.value("qnapi/skip_convert_ads", false).toBool(),
136       settings.value("qnapi/remove_lines", false).toBool(),
137       settings
138           .value("qnapi/remove_words", QStringList() << "movie info"
139                                                      << "synchro")
140           .toStringList());
141 }
142 
readScanConfig(const QSettings & settings) const143 const ScanConfig ConfigReader::readScanConfig(const QSettings& settings) const {
144   return ScanConfig(
145       settings.value("scan/last_scan_dir", "").toString(),
146       settings.value("scan/skip_if_subtitles_exist", false).toBool(),
147       settings.value("scan/filters", QStringList()).toStringList(),
148       settings.value("scan/skip_filters", "PL dubbing").toString());
149 }
150 
resolveP7zipPath(const GeneralConfig & config) const151 const GeneralConfig ConfigReader::resolveP7zipPath(
152     const GeneralConfig& config) const {
153   if (QFileInfo(config.p7zipPath()).isExecutable()) {
154     return config;
155   } else {
156     QString p7zipPath = "";
157 
158 #if defined(Q_OS_MAC)
159     p7zipPath =
160         QFileInfo(appExecutableDir + "/../Resources/7za").absoluteFilePath();
161 #elif defined(Q_OS_WIN)
162     p7zipPath = QFileInfo(appExecutableDir + "/7za.exe").absoluteFilePath();
163 #else
164     QString pathEnv =
165         QProcess::systemEnvironment().filter(QRegExp("^PATH=(.*)$")).value(0);
166     QStringList sysPaths = pathEnv.mid(5).split(":");
167     sysPaths.removeAll("");
168     sysPaths.append(".");
169 
170     if (sysPaths.isEmpty()) {
171       sysPaths << "/bin"
172                << "/usr/bin"
173                << "/usr/local/bin";
174     }
175 
176     sysPaths << appExecutableDir;
177 
178     QStringList p7zipBinaries = {"7z", "7za"};
179 
180     foreach (const QString sysPath, sysPaths) {
181       foreach (const QString p7zipBinary, p7zipBinaries) {
182         QFileInfo fi(sysPath + QDir::separator() + p7zipBinary);
183         if (fi.isExecutable()) {
184           p7zipPath = fi.absoluteFilePath();
185           break;
186         }
187       }
188 
189       if (!p7zipPath.isEmpty()) {
190         break;
191       }
192     }
193 
194     if (p7zipPath.isEmpty()) {
195       p7zipPath = "7z";
196     }
197 #endif
198 
199     return config.setP7zipPath(p7zipPath);
200   }
201 }
202 
resolveTmpPath(const GeneralConfig & config) const203 const GeneralConfig ConfigReader::resolveTmpPath(
204     const GeneralConfig& config) const {
205   QFileInfo fi(config.tmpPath());
206 
207   if (fi.isDir() && fi.isWritable()) {
208     return config;
209   } else {
210     return config.setTmpPath(QDir::tempPath());
211   }
212 }
213