• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

libkonq

favicons.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 Malte Starostik <malte@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "favicons.h"
00021 #include "favicons_adaptor.h"
00022 
00023 #include <time.h>
00024 
00025 #include <QBuffer>
00026 #include <QFile>
00027 #include <QtCore/QCache>
00028 #include <QImage>
00029 #include <QTimer>
00030 #include <QImageReader>
00031 
00032 #include <kicontheme.h>
00033 #include <kconfig.h>
00034 #include <kstandarddirs.h>
00035 #include <kio/job.h>
00036 #include <kconfiggroup.h>
00037 #include <kdebug.h>
00038 #include <kpluginfactory.h>
00039 #include <kpluginloader.h>
00040 
00041 K_PLUGIN_FACTORY(FavIconsFactory,
00042                  registerPlugin<FavIconsModule>();
00043     )
00044 K_EXPORT_PLUGIN(FavIconsFactory("favicons"))
00045 
00046 static QString simplifyURL(const KUrl &url)
00047 {
00048     // splat any = in the URL so it can be safely used as a config key
00049     QString result = url.host() + url.path();
00050     for (int i = 0; i < result.length(); ++i)
00051         if (result[i] == '=')
00052             result[i] = '_';
00053     return result;
00054 }
00055 
00056 static QString iconNameFromURL(const KUrl &iconURL)
00057 {
00058     if (iconURL.path() == "/favicon.ico")
00059        return iconURL.host();
00060 
00061     QString result = simplifyURL(iconURL);
00062     // splat / so it can be safely used as a file name
00063     for (int i = 0; i < result.length(); ++i)
00064         if (result[i] == '/')
00065             result[i] = '_';
00066 
00067     QString ext = result.right(4);
00068     if (ext == ".ico" || ext == ".png" || ext == ".xpm")
00069         result.remove(result.length() - 4, 4);
00070 
00071     return result;
00072 }
00073 
00074 struct FavIconsModulePrivate
00075 {
00076     virtual ~FavIconsModulePrivate() { delete config; }
00077 
00078     struct DownloadInfo
00079     {
00080         QString hostOrURL;
00081         bool isHost;
00082         QByteArray iconData;
00083     };
00084     QString makeIconName(const DownloadInfo& download, const KUrl& iconURL)
00085     {
00086         QString iconName;
00087         if (download.isHost)
00088             iconName = download.hostOrURL;
00089         else
00090             iconName = iconNameFromURL(iconURL);
00091 
00092         return "favicons/" + iconName;
00093     }
00094 
00095     QMap<KJob *, DownloadInfo> downloads;
00096     QStringList failedDownloads;
00097     KConfig *config;
00098     QList<KIO::Job*> killJobs;
00099     KIO::MetaData metaData;
00100     QString faviconsDir;
00101     QCache<QString,QString> faviconsCache;
00102 };
00103 
00104 FavIconsModule::FavIconsModule(QObject* parent, const QList<QVariant>&)
00105     : KDEDModule(parent)
00106 {
00107     // create our favicons folder so that KIconLoader knows about it
00108     d = new FavIconsModulePrivate;
00109     d->faviconsDir = KGlobal::dirs()->saveLocation( "cache", "favicons/" );
00110     d->faviconsDir.truncate(d->faviconsDir.length()-9); // Strip off "favicons/"
00111     d->metaData.insert("ssl_no_client_cert", "TRUE");
00112     d->metaData.insert("ssl_no_ui", "TRUE");
00113     d->metaData.insert("UseCache", "false");
00114     d->metaData.insert("cookies", "none");
00115     d->metaData.insert("no-auth", "true");
00116     d->config = new KConfig(KStandardDirs::locateLocal("data", "konqueror/faviconrc"));
00117 
00118     new FavIconsAdaptor( this );
00119 }
00120 
00121 FavIconsModule::~FavIconsModule()
00122 {
00123     delete d;
00124 }
00125 
00126 static QString removeSlash(QString result)
00127 {
00128     for (unsigned int i = result.length() - 1; i > 0; --i)
00129         if (result[i] != '/')
00130         {
00131             result.truncate(i + 1);
00132             break;
00133         }
00134 
00135     return result;
00136 }
00137 
00138 
00139 QString FavIconsModule::iconForUrl(const KUrl &url)
00140 {
00141     if (url.host().isEmpty())
00142         return QString();
00143 
00144     QString icon;
00145     QString simplifiedURL = simplifyURL(url);
00146 
00147     QString *iconURL = d->faviconsCache[ removeSlash(simplifiedURL) ];
00148     if (iconURL)
00149         icon = *iconURL;
00150     else
00151         icon = d->config->group(QString()).readEntry( removeSlash(simplifiedURL), QString() );
00152 
00153     if (!icon.isEmpty())
00154         icon = iconNameFromURL(KUrl( icon ));
00155     else
00156         icon = url.host();
00157 
00158     icon = "favicons/" + icon;
00159 
00160     if (QFile::exists(d->faviconsDir+icon+".png"))
00161         return icon;
00162 
00163     return QString();
00164 }
00165 
00166 bool FavIconsModule::isIconOld(const QString &icon)
00167 {
00168     struct stat st;
00169     if (stat(QFile::encodeName(icon), &st) != 0)
00170         return true; // Trigger a new download on error
00171 
00172     return (time(0) - st.st_mtime) > 604800; // arbitrary value (one week)
00173 }
00174 
00175 void FavIconsModule::setIconForUrl(const KUrl &url, const KUrl &iconURL)
00176 {
00177     const QString simplifiedURL = simplifyURL(url);
00178 
00179     d->faviconsCache.insert(removeSlash(simplifiedURL), new QString(iconURL.url()) );
00180 
00181     const QString iconName = "favicons/" + iconNameFromURL(iconURL);
00182     const QString iconFile = d->faviconsDir + iconName + ".png";
00183 
00184     if (!isIconOld(iconFile)) {
00185         emit iconChanged(false, url.url(), iconName);
00186         return;
00187     }
00188 
00189     startDownload(url.url(), false, iconURL);
00190 }
00191 
00192 void FavIconsModule::downloadHostIcon(const KUrl &url)
00193 {
00194     const QString iconFile = d->faviconsDir + "favicons/" + url.host() + ".png";
00195     if (!isIconOld(iconFile))
00196         return;
00197 
00198     startDownload(url.host(), true, KUrl(url, "/favicon.ico"));
00199 }
00200 
00201 void FavIconsModule::startDownload(const QString &hostOrURL, bool isHost, const KUrl &iconURL)
00202 {
00203     if (d->failedDownloads.contains(iconURL.url())) {
00204         return;
00205     }
00206 
00207     KIO::Job *job = KIO::get(iconURL, KIO::NoReload, KIO::HideProgressInfo);
00208     job->addMetaData(d->metaData);
00209     job->addMetaData("errorPage", "false");
00210     connect(job, SIGNAL(data(KIO::Job *, const QByteArray &)), SLOT(slotData(KIO::Job *, const QByteArray &)));
00211     connect(job, SIGNAL(result(KJob *)), SLOT(slotResult(KJob *)));
00212     connect(job, SIGNAL(infoMessage(KJob *, const QString &, const QString &)), SLOT(slotInfoMessage(KJob *, const QString &)));
00213     FavIconsModulePrivate::DownloadInfo download;
00214     download.hostOrURL = hostOrURL;
00215     download.isHost = isHost;
00216     d->downloads.insert(job, download);
00217 }
00218 
00219 void FavIconsModule::slotData(KIO::Job *job, const QByteArray &data)
00220 {
00221     KIO::TransferJob* tjob = static_cast<KIO::TransferJob*>(job);
00222     FavIconsModulePrivate::DownloadInfo &download = d->downloads[job];
00223     unsigned int oldSize = download.iconData.size();
00224     // Size limit. Stop downloading if the file is huge.
00225     // Testcase (as of june 2008, at least): http://planet-soc.com/favicon.ico, 136K and strange format.
00226     if (oldSize > 0x10000) {
00227         kDebug() << "Favicon too big, aborting download of" << tjob->url();
00228         d->killJobs.append(job);
00229         QTimer::singleShot(0, this, SLOT(slotKill()));
00230         const KUrl iconURL = tjob->url();
00231         d->failedDownloads.append(iconURL.url());
00232     }
00233     download.iconData.resize(oldSize + data.size());
00234     memcpy(download.iconData.data() + oldSize, data.data(), data.size());
00235 }
00236 
00237 void FavIconsModule::slotResult(KJob *job)
00238 {
00239     KIO::TransferJob* tjob = static_cast<KIO::TransferJob*>(job);
00240     FavIconsModulePrivate::DownloadInfo download = d->downloads[job];
00241     d->killJobs.removeAll(tjob);
00242     d->downloads.remove(job);
00243     const KUrl iconURL = tjob->url();
00244     QString iconName;
00245     if (!job->error())
00246     {
00247         QBuffer buffer(&download.iconData);
00248         buffer.open(QIODevice::ReadOnly);
00249         QImageReader ir( &buffer );
00250         QSize desired( 16,16 );
00251         if( ir.canRead() ) {
00252 
00253             while( ir.imageCount() > 1
00254               && ir.currentImageRect() != QRect(0, 0, desired.width(), desired.height())) {
00255                 if (!ir.jumpToNextImage()) {
00256                     break;
00257                 }
00258             }
00259             ir.setScaledSize( desired );
00260             QImage img = ir.read();
00261             if( !img.isNull() ) {
00262                 iconName = d->makeIconName(download, iconURL);
00263                 if( !img.save( d->faviconsDir + iconName + ".png", "PNG" ) )
00264                     iconName.clear();
00265                 else if (!download.isHost)
00266                     d->config->group(QString()).writeEntry( removeSlash(download.hostOrURL), iconURL.url());
00267             }
00268         }
00269     }
00270     if (iconName.isEmpty())
00271         d->failedDownloads.append(iconURL.url());
00272 
00273     emit iconChanged(download.isHost, download.hostOrURL, iconName);
00274 }
00275 
00276 void FavIconsModule::slotInfoMessage(KJob *job, const QString &msg)
00277 {
00278     emit infoMessage(static_cast<KIO::TransferJob *>( job )->url().url(), msg);
00279 }
00280 
00281 void FavIconsModule::slotKill()
00282 {
00283     Q_FOREACH(KIO::Job* job, d->killJobs)
00284         job->kill();
00285     d->killJobs.clear();
00286 }
00287 
00288 #include "favicons.moc"
00289 
00290 // vim: ts=4 sw=4 et

libkonq

Skip menu "libkonq"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • Konsole
  • Libraries
  •   libkonq
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal