1 /**************************************************************************
2 * Otter Browser: Web browser controlled by the user, not vice-versa.
3 * Copyright (C) 2014 Piotr Wójcik <chocimier@tlen.pl>
4 * Copyright (C) 2014 - 2018 Michal Dutkiewicz aka Emdek <michal@emdek.pl>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 **************************************************************************/
20 
21 #include "OperaBookmarksImporter.h"
22 #include "../../../core/BookmarksManager.h"
23 #include "../../../ui/BookmarksImporterWidget.h"
24 
25 #include <QtCore/QDateTime>
26 #include <QtCore/QDir>
27 #include <QtCore/QFile>
28 #include <QtCore/QStandardPaths>
29 #include <QtCore/QTextStream>
30 
31 namespace Otter
32 {
33 
OperaBookmarksImporter(QObject * parent)34 OperaBookmarksImporter::OperaBookmarksImporter(QObject *parent) : BookmarksImporter(parent),
35 	m_optionsWidget(nullptr)
36 {
37 }
38 
createOptionsWidget(QWidget * parent)39 QWidget* OperaBookmarksImporter::createOptionsWidget(QWidget *parent)
40 {
41 	if (!m_optionsWidget)
42 	{
43 		m_optionsWidget = new BookmarksImporterWidget(parent);
44 	}
45 
46 	return m_optionsWidget;
47 }
48 
getTitle() const49 QString OperaBookmarksImporter::getTitle() const
50 {
51 	return tr("Opera Bookmarks");
52 }
53 
getDescription() const54 QString OperaBookmarksImporter::getDescription() const
55 {
56 	return tr("Imports bookmarks from Opera Browser version 12 or earlier");
57 }
58 
getVersion() const59 QString OperaBookmarksImporter::getVersion() const
60 {
61 	return QLatin1String("0.8");
62 }
63 
getSuggestedPath(const QString & path) const64 QString OperaBookmarksImporter::getSuggestedPath(const QString &path) const
65 {
66 	if (!path.isEmpty())
67 	{
68 		if (QFileInfo(path).isDir())
69 		{
70 			return QDir(path).filePath(QLatin1String("bookmarks.adr"));
71 		}
72 
73 		return path;
74 	}
75 #if !defined(Q_OS_MAC) && defined(Q_OS_UNIX)
76 	const QString homePath(QStandardPaths::standardLocations(QStandardPaths::HomeLocation).value(0));
77 
78 	if (!homePath.isEmpty())
79 	{
80 		return QDir(homePath).filePath(QLatin1String(".opera/bookmarks.adr"));
81 	}
82 #endif
83 
84 	return path;
85 }
86 
getBrowser() const87 QString OperaBookmarksImporter::getBrowser() const
88 {
89 	return QLatin1String("opera");
90 }
91 
getHomePage() const92 QUrl OperaBookmarksImporter::getHomePage() const
93 {
94 	return QUrl(QLatin1String("https://otter-browser.org/"));
95 }
96 
getFileFilters() const97 QStringList OperaBookmarksImporter::getFileFilters() const
98 {
99 	return {tr("Opera bookmarks files (bookmarks.adr)")};
100 }
101 
import(const QString & path)102 bool OperaBookmarksImporter::import(const QString &path)
103 {
104 	QFile file(getSuggestedPath(path));
105 
106 	if (!file.open(QIODevice::ReadOnly))
107 	{
108 		emit importFinished(BookmarksImport, FailedImport, 0);
109 
110 		return false;
111 	}
112 
113 	QTextStream stream(&file);
114 	stream.setCodec("UTF-8");
115 
116 	QString line(stream.readLine());
117 
118 	if (line != QLatin1String("Opera Hotlist version 2.0"))
119 	{
120 		emit importFinished(BookmarksImport, FailedImport, 0);
121 
122 		return false;
123 	}
124 
125 	emit importStarted(BookmarksImport, -1);
126 
127 	if (m_optionsWidget)
128 	{
129 		if (m_optionsWidget->hasToRemoveExisting())
130 		{
131 			removeAllBookmarks();
132 
133 			if (m_optionsWidget->isImportingIntoSubfolder())
134 			{
135 				setImportFolder(BookmarksManager::addBookmark(BookmarksModel::FolderBookmark, {{BookmarksModel::TitleRole, m_optionsWidget->getSubfolderName()}}, BookmarksManager::getModel()->getRootItem()));
136 			}
137 			else
138 			{
139 				setImportFolder(BookmarksManager::getModel()->getRootItem());
140 			}
141 		}
142 		else
143 		{
144 			setAllowDuplicates(m_optionsWidget->areDuplicatesAllowed());
145 			setImportFolder(m_optionsWidget->getTargetFolder());
146 		}
147 	}
148 
149 	const int estimatedAmount((file.size() > 0) ? static_cast<int>(file.size() / 250) : 0);
150 	int totalAmount(0);
151 
152 	BookmarksManager::getModel()->beginImport(getImportFolder(), estimatedAmount, qMin(estimatedAmount, 100));
153 
154 	BookmarksModel::Bookmark *bookmark(nullptr);
155 	OperaBookmarkEntry type(NoEntry);
156 	bool isHeader(true);
157 
158 	while (!stream.atEnd())
159 	{
160 		line = stream.readLine();
161 
162 		if (isHeader && (line.isEmpty() || line.at(0) != QLatin1Char('#')))
163 		{
164 			continue;
165 		}
166 
167 		isHeader = false;
168 
169 		if (line.isEmpty())
170 		{
171 			if (bookmark)
172 			{
173 				if (type == FolderStartEntry)
174 				{
175 					setCurrentFolder(bookmark);
176 				}
177 
178 				bookmark = nullptr;
179 			}
180 			else if (type == FolderEndEntry)
181 			{
182 				goToParent();
183 			}
184 
185 			type = NoEntry;
186 		}
187 		else if (line.startsWith(QLatin1String("#URL")))
188 		{
189 			bookmark = BookmarksManager::addBookmark(BookmarksModel::UrlBookmark, {}, getCurrentFolder());
190 			type = UrlEntry;
191 
192 			++totalAmount;
193 		}
194 		else if (line.startsWith(QLatin1String("#FOLDER")))
195 		{
196 			bookmark = BookmarksManager::addBookmark(BookmarksModel::FolderBookmark, {}, getCurrentFolder());
197 			type = FolderStartEntry;
198 
199 			++totalAmount;
200 		}
201 		else if (line.startsWith(QLatin1String("#SEPERATOR")))
202 		{
203 			bookmark = BookmarksManager::addBookmark(BookmarksModel::SeparatorBookmark, {}, getCurrentFolder());
204 			type = SeparatorEntry;
205 
206 			++totalAmount;
207 		}
208 		else if (line == QLatin1String("-"))
209 		{
210 			type = FolderEndEntry;
211 		}
212 		else if (bookmark)
213 		{
214 			if (line.startsWith(QLatin1String("\tURL=")))
215 			{
216 				const QUrl url(line.section(QLatin1Char('='), 1, -1));
217 
218 				if (!areDuplicatesAllowed() && BookmarksManager::hasBookmark(url))
219 				{
220 					bookmark->remove();
221 					bookmark = nullptr;
222 				}
223 				else
224 				{
225 					bookmark->setData(url, BookmarksModel::UrlRole);
226 				}
227 			}
228 			else if (line.startsWith(QLatin1String("\tNAME=")))
229 			{
230 				bookmark->setData(line.section(QLatin1Char('='), 1, -1), BookmarksModel::TitleRole);
231 			}
232 			else if (line.startsWith(QLatin1String("\tDESCRIPTION=")))
233 			{
234 				bookmark->setData(line.section(QLatin1Char('='), 1, -1).replace(QLatin1String("\x02\x02"), QLatin1String("\n")), BookmarksModel::DescriptionRole);
235 			}
236 			else if (line.startsWith(QLatin1String("\tSHORT NAME=")))
237 			{
238 				const QString keyword(line.section(QLatin1Char('='), 1, -1));
239 
240 				if (!BookmarksManager::hasKeyword(keyword))
241 				{
242 					bookmark->setData(keyword, BookmarksModel::KeywordRole);
243 				}
244 			}
245 			else if (line.startsWith(QLatin1String("\tCREATED=")))
246 			{
247 				bookmark->setData(QDateTime::fromTime_t(line.section(QLatin1Char('='), 1, -1).toUInt()), BookmarksModel::TimeAddedRole);
248 			}
249 			else if (line.startsWith(QLatin1String("\tVISITED=")))
250 			{
251 				bookmark->setData(QDateTime::fromTime_t(line.section(QLatin1Char('='), 1, -1).toUInt()), BookmarksModel::TimeVisitedRole);
252 			}
253 		}
254 	}
255 
256 	BookmarksManager::getModel()->endImport();
257 
258 	emit importFinished(BookmarksImport, SuccessfullImport, totalAmount);
259 
260 	file.close();
261 
262 	return true;
263 }
264 
265 }
266