File indexing completed on 2024-05-05 17:45:00

0001 /*
0002     SPDX-FileCopyrightText: 2007 Glenn Ergeerts <glenn.ergeerts@telenet.be>
0003     SPDX-FileCopyrightText: 2012 Marco Gulino <marco.gulino@xpeppers.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "faviconfromblob.h"
0009 
0010 #include "bookmarksrunner_defs.h"
0011 #include <QDebug>
0012 #include <QDir>
0013 #include <QFile>
0014 #include <QFileInfo>
0015 #include <QPainter>
0016 #include <QPixmap>
0017 #include <QStandardPaths>
0018 
0019 #include <QSqlDatabase>
0020 #include <QSqlError>
0021 #include <QSqlQuery>
0022 #include <QSqlRecord>
0023 
0024 FaviconFromBlob *FaviconFromBlob::chrome(const QString &profileDirectory, QObject *parent)
0025 {
0026     QString profileName = QFileInfo(profileDirectory).fileName();
0027     QString faviconCache = QStringLiteral("%1/bookmarksrunner/KRunner-Chrome-Favicons-%2.sqlite")
0028                                .arg(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation), profileName);
0029     FetchSqlite *fetchSqlite = new FetchSqlite(faviconCache, parent);
0030 
0031     QString faviconQuery;
0032     if (fetchSqlite->tables().contains(QLatin1String("favicon_bitmaps"))) {
0033         faviconQuery = QLatin1String(
0034             "SELECT * FROM favicons "
0035             "inner join icon_mapping on icon_mapping.icon_id = favicons.id "
0036             "inner join favicon_bitmaps on icon_mapping.icon_id = favicon_bitmaps.icon_id "
0037             "WHERE page_url = :url ORDER BY height desc LIMIT 1;");
0038     } else {
0039         faviconQuery = QLatin1String(
0040             "SELECT * FROM favicons "
0041             "inner join icon_mapping on icon_mapping.icon_id = favicons.id "
0042             "WHERE page_url = :url LIMIT 1;");
0043     }
0044 
0045     return new FaviconFromBlob(profileName, faviconQuery, QStringLiteral("image_data"), fetchSqlite, parent);
0046 }
0047 
0048 FaviconFromBlob *FaviconFromBlob::firefox(FetchSqlite *fetchSqlite, QObject *parent)
0049 {
0050     QString faviconQuery = QStringLiteral(
0051         "SELECT moz_icons.data FROM moz_icons"
0052         " INNER JOIN moz_icons_to_pages ON moz_icons.id = moz_icons_to_pages.icon_id"
0053         " INNER JOIN moz_pages_w_icons ON moz_icons_to_pages.page_id = moz_pages_w_icons.id"
0054         " WHERE moz_pages_w_icons.page_url = :url LIMIT 1;");
0055     return new FaviconFromBlob(QStringLiteral("firefox-default"), faviconQuery, QStringLiteral("data"), fetchSqlite, parent);
0056 }
0057 
0058 FaviconFromBlob *FaviconFromBlob::falkon(const QString &profileDirectory, QObject *parent)
0059 {
0060     const QString dbPath = profileDirectory + QStringLiteral("/browsedata.db");
0061     FetchSqlite *fetchSqlite = new FetchSqlite(dbPath, parent);
0062     const QString faviconQuery = QStringLiteral("SELECT icon FROM icons WHERE url = :url LIMIT 1;");
0063     return new FaviconFromBlob(QStringLiteral("falkon-default"), faviconQuery, QStringLiteral("icon"), fetchSqlite, parent);
0064 }
0065 
0066 FaviconFromBlob::FaviconFromBlob(const QString &profileName, const QString &query, const QString &blobColumn, FetchSqlite *fetchSqlite, QObject *parent)
0067     : Favicon(parent)
0068     , m_query(query)
0069     , m_blobcolumn(blobColumn)
0070     , m_fetchsqlite(fetchSqlite)
0071 {
0072     m_profileCacheDirectory =
0073         QStringLiteral("%1/bookmarksrunner/KRunner-Favicons-%2").arg(QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation), profileName);
0074     // qDebug() << "got cache directory: " << m_profileCacheDirectory;
0075     cleanCacheDirectory();
0076     QDir().mkpath(m_profileCacheDirectory);
0077 }
0078 
0079 FaviconFromBlob::~FaviconFromBlob()
0080 {
0081     cleanCacheDirectory();
0082 }
0083 
0084 void FaviconFromBlob::prepare()
0085 {
0086     m_fetchsqlite->prepare();
0087 }
0088 
0089 void FaviconFromBlob::teardown()
0090 {
0091     m_fetchsqlite->teardown();
0092 }
0093 
0094 void FaviconFromBlob::cleanCacheDirectory()
0095 {
0096     QDir(m_profileCacheDirectory).removeRecursively();
0097 }
0098 
0099 QIcon FaviconFromBlob::iconFor(const QString &url)
0100 {
0101     // qDebug() << "got url: " << url;
0102     QString fileChecksum = QString::number(qChecksum(url.toLatin1(), url.toLatin1().size()));
0103     QFile iconFile(m_profileCacheDirectory + QDir::separator() + fileChecksum + QStringLiteral("_favicon"));
0104     if (iconFile.size() == 0)
0105         iconFile.remove();
0106     if (!iconFile.exists()) {
0107         QMap<QString, QVariant> bindVariables;
0108         bindVariables.insert(QStringLiteral(":url"), url);
0109         QList<QVariantMap> faviconFound = m_fetchsqlite->query(m_query, bindVariables);
0110         if (faviconFound.isEmpty())
0111             return defaultIcon();
0112 
0113         QByteArray iconData = faviconFound.first().value(m_blobcolumn).toByteArray();
0114         // qDebug() << "Favicon found: " << iconData.size() << " bytes";
0115         if (iconData.size() <= 0)
0116             return defaultIcon();
0117 
0118         iconFile.open(QFile::WriteOnly);
0119         iconFile.write(iconData);
0120         iconFile.close();
0121     }
0122     return QIcon(iconFile.fileName());
0123 }