File indexing completed on 2024-05-26 05:00:26

0001 /* ============================================================
0002 * Falkon - Qt web browser
0003 * Copyright (C) 2010-2014  David Rosca <nowrep@gmail.com>
0004 *
0005 * This program is free software: you can redistribute it and/or modify
0006 * it under the terms of the GNU General Public License as published by
0007 * the Free Software Foundation, either version 3 of the License, or
0008 * (at your option) any later version.
0009 *
0010 * This program is distributed in the hope that it will be useful,
0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013 * GNU General Public License for more details.
0014 *
0015 * You should have received a copy of the GNU General Public License
0016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0017 * ============================================================ */
0018 #include "operaimporter.h"
0019 #include "bookmarkitem.h"
0020 
0021 #include <QUrl>
0022 #include <QDir>
0023 #include <QFileDialog>
0024 
0025 OperaImporter::OperaImporter(QObject* parent)
0026     : BookmarksImporter(parent)
0027 {
0028     m_stream.setEncoding(QStringConverter::Utf8);
0029 }
0030 
0031 QString OperaImporter::description() const
0032 {
0033     return BookmarksImporter::tr("Opera stores its bookmarks in <b>bookmarks.adr</b> text file. "
0034                                  "This file is usually located in");
0035 }
0036 
0037 QString OperaImporter::standardPath() const
0038 {
0039 #ifdef Q_OS_WIN
0040     return QString("%APPDATA%/Opera/");
0041 #else
0042     return QDir::homePath() + QLatin1String("/.opera/");
0043 #endif
0044 }
0045 
0046 QString OperaImporter::getPath(QWidget* parent)
0047 {
0048     m_path = QFileDialog::getOpenFileName(parent, BookmarksImporter::tr("Choose file..."), standardPath(), QStringLiteral("Bookmarks (*.adr)"));
0049     return m_path;
0050 }
0051 
0052 bool OperaImporter::prepareImport()
0053 {
0054     m_file.setFileName(m_path);
0055 
0056     if (!m_file.open(QFile::ReadOnly)) {
0057         setError(BookmarksImporter::tr("Unable to open file."));
0058         return false;
0059     }
0060 
0061     m_stream.setDevice(&m_file);
0062 
0063     if (m_stream.readLine() != QLatin1String("Opera Hotlist version 2.0")) {
0064         setError(BookmarksImporter::tr("File is not valid Opera bookmarks file!"));
0065         return false;
0066     }
0067 
0068     if (!m_stream.readLine().startsWith(QLatin1String("Options: encoding = utf8"))) {
0069         setError(BookmarksImporter::tr("Only UTF-8 encoded Opera bookmarks file is supported!"));
0070         return false;
0071     }
0072 
0073     return true;
0074 }
0075 
0076 BookmarkItem* OperaImporter::importBookmarks()
0077 {
0078     auto* root = new BookmarkItem(BookmarkItem::Folder);
0079     root->setTitle(QSL("Opera Import"));
0080 
0081     QList<BookmarkItem*> folders;
0082     folders.append(root);
0083 
0084     BookmarkItem* item = nullptr;
0085 
0086 #define PARENT folders.isEmpty() ? root : folders.last()
0087 
0088     while (!m_stream.atEnd()) {
0089         switch (parseLine(m_stream.readLine())) {
0090         case StartFolder:
0091             item = new BookmarkItem(BookmarkItem::Folder, PARENT);
0092             while (!m_stream.atEnd()) {
0093                 Token tok = parseLine(m_stream.readLine());
0094                 if (tok == EmptyLine)
0095                     break;
0096                 else if (tok == KeyValuePair && m_key == QLatin1String("NAME"))
0097                     item->setTitle(m_value);
0098             }
0099             folders.append(item);
0100             break;
0101 
0102         case EndFolder:
0103             if (folders.count() > 0) {
0104                 folders.removeLast();
0105             }
0106             break;
0107 
0108         case StartUrl:
0109             item = new BookmarkItem(BookmarkItem::Url, PARENT);
0110             while (!m_stream.atEnd()) {
0111                 Token tok = parseLine(m_stream.readLine());
0112                 if (tok == EmptyLine) {
0113                     break;
0114                 }
0115                 else if (tok == KeyValuePair) {
0116                     if (m_key == QL1S("NAME"))
0117                         item->setTitle(m_value);
0118                     else if (m_key == QL1S("URL"))
0119                         item->setUrl(QUrl(m_value));
0120                     else if (m_key == QL1S("DESCRIPTION"))
0121                         item->setDescription(m_value);
0122                     else if (m_key == QL1S("SHORT NAME"))
0123                         item->setKeyword(m_value);
0124                 }
0125             }
0126             break;
0127 
0128         case StartSeparator:
0129             item = new BookmarkItem(BookmarkItem::Separator, PARENT);
0130             while (!m_stream.atEnd()) {
0131                 if (parseLine(m_stream.readLine()) == EmptyLine) {
0132                     break;
0133                 }
0134             }
0135             break;
0136 
0137         case StartDeleted:
0138             while (!m_stream.atEnd()) {
0139                 if (parseLine(m_stream.readLine()) == EmptyLine) {
0140                     break;
0141                 }
0142             }
0143             break;
0144 
0145         default: // EmptyLine
0146             break;
0147         }
0148     }
0149 
0150 #undef PARENT
0151 
0152     return root;
0153 }
0154 
0155 OperaImporter::Token OperaImporter::parseLine(const QString &line)
0156 {
0157     const QString str = line.trimmed();
0158 
0159     if (str.isEmpty()) {
0160         return EmptyLine;
0161     }
0162 
0163     if (str == QLatin1String("#FOLDER")) {
0164         return StartFolder;
0165     }
0166 
0167     if (str == QLatin1String("-")) {
0168         return EndFolder;
0169     }
0170 
0171     if (str == QLatin1String("#URL")) {
0172         return StartUrl;
0173     }
0174 
0175     if (str == QLatin1String("#SEPERATOR")) {
0176         return StartSeparator;
0177     }
0178 
0179     if (str == QLatin1String("#DELETED")) {
0180         return StartDeleted;
0181     }
0182 
0183     int index = str.indexOf(QLatin1Char('='));
0184 
0185     // Let's assume "key=" is valid line with empty value (but not "=value")
0186     if (index > 0) {
0187         m_key = str.mid(0, index);
0188         m_value = str.mid(index + 1);
0189         return KeyValuePair;
0190     }
0191 
0192     return Invalid;
0193 }