1 /**************************************************************************
2 * Otter Browser: Web browser controlled by the user, not vice-versa.
3 * Copyright (C) 2015 - 2018 Michal Dutkiewicz aka Emdek <michal@emdek.pl>
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 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 **************************************************************************/
19 
20 #include "HandlersManager.h"
21 #include "AdblockContentFiltersProfile.h"
22 #include "ContentFiltersManager.h"
23 #include "IniSettings.h"
24 #include "SessionsManager.h"
25 #include "SettingsManager.h"
26 #include "Utils.h"
27 
28 #include <QtCore/QFile>
29 #include <QtCore/QFileInfo>
30 #include <QtCore/QMimeDatabase>
31 #include <QtCore/QUrlQuery>
32 #include <QtGui/QDesktopServices>
33 #include <QtWidgets/QMessageBox>
34 
35 namespace Otter
36 {
37 
38 HandlersManager* HandlersManager::m_instance(nullptr);
39 
HandlersManager(QObject * parent)40 HandlersManager::HandlersManager(QObject *parent) : QObject(parent)
41 {
42 }
43 
createInstance()44 void HandlersManager::createInstance()
45 {
46 	if (!m_instance)
47 	{
48 		m_instance = new HandlersManager(QCoreApplication::instance());
49 	}
50 }
51 
setHandler(const QMimeType & mimeType,const HandlerDefinition & definition)52 void HandlersManager::setHandler(const QMimeType &mimeType, const HandlerDefinition &definition)
53 {
54 	if (SessionsManager::isReadOnly())
55 	{
56 		return;
57 	}
58 
59 	const QString path(SessionsManager::getWritableDataPath(QLatin1String("handlers.ini")));
60 	IniSettings settings(QFile::exists(path) ? path : SessionsManager::getReadableDataPath(QLatin1String("handlers.ini")));
61 	QString transferMode;
62 
63 	switch (definition.transferMode)
64 	{
65 		case HandlerDefinition::IgnoreTransfer:
66 			transferMode = QLatin1String("ignore");
67 
68 			break;
69 		case HandlerDefinition::OpenTransfer:
70 			transferMode = QLatin1String("open");
71 
72 			break;
73 		case HandlerDefinition::SaveTransfer:
74 			transferMode = QLatin1String("save");
75 
76 			break;
77 		case HandlerDefinition::SaveAsTransfer:
78 			transferMode = QLatin1String("saveAs");
79 
80 			break;
81 		default:
82 			transferMode = QLatin1String("ask");
83 
84 			break;
85 	}
86 
87 	settings.beginGroup(mimeType.isValid() ? mimeType.name() : QLatin1String("*"));
88 	settings.setValue(QLatin1String("openCommand"), definition.openCommand);
89 	settings.setValue(QLatin1String("downloadsPath"), definition.downloadsPath);
90 	settings.setValue(QLatin1String("transferMode"), transferMode);
91 	settings.save(path);
92 }
93 
getInstance()94 HandlersManager* HandlersManager::getInstance()
95 {
96 	return m_instance;
97 }
98 
getHandler(const QMimeType & mimeType)99 HandlersManager::HandlerDefinition HandlersManager::getHandler(const QMimeType &mimeType)
100 {
101 	IniSettings settings(SessionsManager::getReadableDataPath(QLatin1String("handlers.ini")));
102 	const QString name(mimeType.isValid() ? mimeType.name() : QLatin1String("*"));
103 	HandlerDefinition definition;
104 	definition.mimeType = mimeType;
105 	definition.isExplicit = settings.getGroups().contains(name);
106 
107 	if (definition.isExplicit)
108 	{
109 		settings.beginGroup(name);
110 	}
111 	else
112 	{
113 		settings.beginGroup(QLatin1String("*"));
114 	}
115 
116 	const QString downloadsPath(settings.getValue(QLatin1String("downloadsPath"), {}).toString());
117 	const QString transferMode(settings.getValue(QLatin1String("transferMode"), {}).toString());
118 
119 	definition.openCommand = settings.getValue(QLatin1String("openCommand"), {}).toString();
120 	definition.downloadsPath = (downloadsPath.isEmpty() ? SettingsManager::getOption(SettingsManager::Paths_DownloadsOption).toString() : downloadsPath);
121 
122 	if (transferMode == QLatin1String("ignore"))
123 	{
124 		definition.transferMode = HandlerDefinition::IgnoreTransfer;
125 	}
126 	else if (transferMode == QLatin1String("open"))
127 	{
128 		definition.transferMode = HandlerDefinition::OpenTransfer;
129 	}
130 	else if (transferMode == QLatin1String("save"))
131 	{
132 		definition.transferMode = HandlerDefinition::SaveTransfer;
133 	}
134 	else if (transferMode == QLatin1String("saveAs"))
135 	{
136 		definition.transferMode = HandlerDefinition::SaveAsTransfer;
137 	}
138 	else
139 	{
140 		definition.transferMode = HandlerDefinition::AskTransfer;
141 	}
142 
143 	return definition;
144 }
145 
getHandlers()146 QVector<HandlersManager::HandlerDefinition> HandlersManager::getHandlers()
147 {
148 	const QMimeDatabase mimeDatabase;
149 	const QStringList mimeTypes(IniSettings(SessionsManager::getReadableDataPath(QLatin1String("handlers.ini"))).getGroups());
150 	QVector<HandlersManager::HandlerDefinition> handlers;
151 	handlers.reserve(mimeTypes.count());
152 
153 	for (int i = 0; i < mimeTypes.count(); ++i)
154 	{
155 		handlers.append(getHandler(mimeDatabase.mimeTypeForName(mimeTypes.at(i))));
156 	}
157 
158 	return handlers;
159 }
160 
handleUrl(const QUrl & url)161 bool HandlersManager::handleUrl(const QUrl &url)
162 {
163 	if (url.scheme() == QLatin1String("abp"))
164 	{
165 		const QUrlQuery query(url.query());
166 		const QUrl location(QUrl::fromPercentEncoding(query.queryItemValue(QLatin1String("location")).toUtf8()));
167 
168 		if (location.isValid())
169 		{
170 			if (ContentFiltersManager::getProfile(location))
171 			{
172 				QMessageBox::critical(nullptr, tr("Error"), tr("Profile with this address already exists."), QMessageBox::Close);
173 			}
174 			else if (QMessageBox::question(nullptr, tr("Question"), tr("Do you want to add this content blocking profile?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
175 			{
176 				ContentFiltersProfile *profile(new AdblockContentFiltersProfile(Utils::createIdentifier(QFileInfo(location.path()).baseName(), ContentFiltersManager::getProfileNames()), QByteArray::fromPercentEncoding(query.queryItemValue(QLatin1String("title")).toUtf8()), location, {}, {}, 0, ContentFiltersProfile::OtherCategory, ContentFiltersProfile::NoFlags));
177 
178 				ContentFiltersManager::addProfile(profile);
179 
180 				profile->update();
181 ///TODO Some sort of passive confirmation that profile was added
182 			}
183 		}
184 
185 		return true;
186 	}
187 
188 	if (url.scheme() == QLatin1String("mailto"))
189 	{
190 		QDesktopServices::openUrl(url);
191 
192 		return true;
193 	}
194 
195 	return false;
196 }
197 
canHandleUrl(const QUrl & url)198 bool HandlersManager::canHandleUrl(const QUrl &url)
199 {
200 	return (url.scheme() == QLatin1String("abp") || url.scheme() == QLatin1String("mailto"));
201 }
202 
203 }
204