• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • applications API Reference
  • KDE Home
  • Contact Us
 

libkonq

  • sources
  • kde-4.12
  • applications
  • kde-baseapps
  • lib
  • konq
  • favicons
favicons.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE project
2  Copyright (C) 2001 Malte Starostik <malte@kde.org>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 #include "favicons.h"
21 #include "favicons_adaptor.h"
22 
23 #include <kicontheme.h>
24 #include <kconfig.h>
25 #include <klocale.h>
26 #include <kde_file.h>
27 #include <kstandarddirs.h>
28 #include <kio/job.h>
29 #include <kconfiggroup.h>
30 #include <kdebug.h>
31 #include <kpluginfactory.h>
32 #include <kpluginloader.h>
33 
34 #include <QtCore/QBuffer>
35 #include <QtCore/QFile>
36 #include <QtCore/QCache>
37 #include <QtCore/QTimer>
38 #include <QImage>
39 #include <QImageReader>
40 
41 #include <ctime>
42 
43 
44 K_PLUGIN_FACTORY(FavIconsFactory,
45  registerPlugin<FavIconsModule>();
46  )
47 K_EXPORT_PLUGIN(FavIconsFactory("favicons"))
48 
49 static QString portForUrl(const KUrl& url)
50 {
51  if (url.port() > 0) {
52  return (QString(QLatin1Char('_')) + QString::number(url.port()));
53  }
54  return QString();
55 }
56 
57 static QString simplifyURL(const KUrl &url)
58 {
59  // splat any = in the URL so it can be safely used as a config key
60  QString result = url.host() + portForUrl(url) + url.path();
61  for (int i = 0; i < result.length(); ++i)
62  if (result[i] == '=')
63  result[i] = '_';
64  return result;
65 }
66 
67 static QString iconNameFromURL(const KUrl &iconURL)
68 {
69  if (iconURL.path() == QLatin1String("/favicon.ico"))
70  return iconURL.host() + portForUrl(iconURL);
71 
72  QString result = simplifyURL(iconURL);
73  // splat / so it can be safely used as a file name
74  for (int i = 0; i < result.length(); ++i)
75  if (result[i] == '/')
76  result[i] = '_';
77 
78  QString ext = result.right(4);
79  if (ext == QLatin1String(".ico") || ext == QLatin1String(".png") || ext == QLatin1String(".xpm"))
80  result.remove(result.length() - 4, 4);
81 
82  return result;
83 }
84 
85 struct FavIconsModulePrivate
86 {
87  virtual ~FavIconsModulePrivate() { delete config; }
88 
89  struct DownloadInfo
90  {
91  QString hostOrURL;
92  bool isHost;
93  QByteArray iconData;
94  };
95  QString makeIconName(const DownloadInfo& download, const KUrl& iconURL)
96  {
97  QString iconName (QLatin1String("favicons/"));
98  iconName += (download.isHost ? download.hostOrURL : iconNameFromURL(iconURL));
99  return iconName;
100  }
101 
102  QMap<KJob *, DownloadInfo> downloads;
103  KUrl::List failedDownloads;
104  KConfig *config;
105  QList<KIO::Job*> killJobs;
106  KIO::MetaData metaData;
107  QString faviconsDir;
108  QCache<QString,QString> faviconsCache;
109 };
110 
111 FavIconsModule::FavIconsModule(QObject* parent, const QList<QVariant>&)
112  : KDEDModule(parent)
113 {
114  // create our favicons folder so that KIconLoader knows about it
115  d = new FavIconsModulePrivate;
116  d->faviconsDir = KGlobal::dirs()->saveLocation( "cache", QLatin1String("favicons/"));
117  d->faviconsDir.truncate(d->faviconsDir.length()-9); // Strip off "favicons/"
118  d->metaData.insert(QLatin1String("ssl_no_client_cert"), QLatin1String("true"));
119  d->metaData.insert(QLatin1String("ssl_no_ui"), QLatin1String("true"));
120  d->metaData.insert(QLatin1String("UseCache"), "false");
121  d->metaData.insert(QLatin1String("cookies"), "none");
122  d->metaData.insert(QLatin1String("no-www-auth"), QLatin1String("true"));
123  d->metaData.insert(QLatin1String("errorPage"), QLatin1String("false"));
124  d->config = new KConfig(KStandardDirs::locateLocal("data", QLatin1String("konqueror/faviconrc")));
125 
126  new FavIconsAdaptor( this );
127 }
128 
129 FavIconsModule::~FavIconsModule()
130 {
131  delete d;
132 }
133 
134 static QString removeSlash(QString result)
135 {
136  for (unsigned int i = result.length() - 1; i > 0; --i) {
137  if (result[i] != '/') {
138  result.truncate(i + 1);
139  break;
140  }
141  }
142 
143  return result;
144 }
145 
146 QString FavIconsModule::iconForUrl(const KUrl &url)
147 {
148  if (url.host().isEmpty())
149  return QString();
150 
151  //kDebug() << url;
152 
153  const QString simplifiedURL = removeSlash(simplifyURL(url));
154  QString *iconURL = d->faviconsCache[simplifiedURL];
155  QString icon = (iconURL ? *iconURL : d->config->group(QString()).readEntry(simplifiedURL, QString()));
156 
157  if (!icon.isEmpty())
158  icon = iconNameFromURL(KUrl(icon));
159  else
160  icon = url.host();
161 
162  icon = QLatin1String("favicons/") + icon;
163 
164  kDebug() << "URL:" << url << "ICON:" << icon;
165 
166  if (QFile::exists(d->faviconsDir+icon+QLatin1String(".png")))
167  return icon;
168 
169  return QString();
170 }
171 
172 bool FavIconsModule::isIconOld(const QString &icon)
173 {
174  KDE_struct_stat st;
175  if (KDE::stat(QFile::encodeName(icon), &st) != 0) {
176  //kDebug() << "isIconOld" << icon << "yes, no such file";
177  return true; // Trigger a new download on error
178  }
179 
180  //kDebug() << "isIconOld" << icon << "?";
181  return (time(0) - st.st_mtime) > 604800; // arbitrary value (one week)
182 }
183 
184 void FavIconsModule::setIconForUrl(const KUrl &url, const KUrl &iconURL)
185 {
186  //kDebug() << url << iconURL;
187  const QString simplifiedURL = simplifyURL(url);
188 
189  d->faviconsCache.insert(removeSlash(simplifiedURL), new QString(iconURL.url()) );
190 
191  const QString iconName = QLatin1String("favicons/") + iconNameFromURL(iconURL);
192  const QString iconFile = d->faviconsDir + iconName + QLatin1String(".png");
193 
194  if (!isIconOld(iconFile)) {
195  //kDebug() << "emit iconChanged" << false << url << iconName;
196  emit iconChanged(false, url.url(), iconName);
197  return;
198  }
199 
200  startDownload(url.url(), false, iconURL);
201 }
202 
203 void FavIconsModule::downloadHostIcon(const KUrl &url)
204 {
205  //kDebug() << url;
206  const QString iconFile = d->faviconsDir + QLatin1String("favicons/") + url.host() + QLatin1String(".png");
207  if (!isIconOld(iconFile)) {
208  //kDebug() << "not old -> doing nothing";
209  return;
210  }
211  startDownload(url.host(), true, KUrl(url, QLatin1String("/favicon.ico")));
212 }
213 
214 void FavIconsModule::forceDownloadHostIcon(const KUrl &url)
215 {
216  //kDebug() << url;
217  KUrl iconURL = KUrl(url, QLatin1String("/favicon.ico"));
218  d->failedDownloads.removeAll(iconURL); // force a download to happen
219  startDownload(url.host(), true, iconURL);
220 }
221 
222 void FavIconsModule::startDownload(const QString &hostOrURL, bool isHost, const KUrl &iconURL)
223 {
224  if (d->failedDownloads.contains(iconURL)) {
225  //kDebug() << iconURL << "already in failedDownloads, emitting error";
226  emit error(isHost, hostOrURL, i18n("No favicon found"));
227  return;
228  }
229 
230  //kDebug() << iconURL;
231  KIO::Job *job = KIO::get(iconURL, KIO::NoReload, KIO::HideProgressInfo);
232  job->addMetaData(d->metaData);
233  connect(job, SIGNAL(data(KIO::Job*,QByteArray)), SLOT(slotData(KIO::Job*,QByteArray)));
234  connect(job, SIGNAL(result(KJob*)), SLOT(slotResult(KJob*)));
235  connect(job, SIGNAL(infoMessage(KJob*,QString,QString)), SLOT(slotInfoMessage(KJob*,QString)));
236  FavIconsModulePrivate::DownloadInfo download;
237  download.hostOrURL = hostOrURL;
238  download.isHost = isHost;
239  d->downloads.insert(job, download);
240 }
241 
242 void FavIconsModule::slotData(KIO::Job *job, const QByteArray &data)
243 {
244  KIO::TransferJob* tjob = static_cast<KIO::TransferJob*>(job);
245  FavIconsModulePrivate::DownloadInfo &download = d->downloads[job];
246  unsigned int oldSize = download.iconData.size();
247  // Size limit. Stop downloading if the file is huge.
248  // Testcase (as of june 2008, at least): http://planet-soc.com/favicon.ico, 136K and strange format.
249  if (oldSize > 0x10000) {
250  kDebug() << "Favicon too big, aborting download of" << tjob->url();
251  d->killJobs.append(job);
252  QTimer::singleShot(0, this, SLOT(slotKill()));
253  const KUrl iconURL = tjob->url();
254  d->failedDownloads.append(iconURL);
255  }
256  download.iconData.resize(oldSize + data.size());
257  memcpy(download.iconData.data() + oldSize, data.data(), data.size());
258 }
259 
260 void FavIconsModule::slotResult(KJob *job)
261 {
262  KIO::TransferJob* tjob = static_cast<KIO::TransferJob*>(job);
263  FavIconsModulePrivate::DownloadInfo download = d->downloads[job];
264  d->killJobs.removeAll(tjob);
265  d->downloads.remove(job);
266  const KUrl iconURL = tjob->url();
267  QString iconName;
268  QString errorMessage;
269  if (!job->error())
270  {
271  QBuffer buffer(&download.iconData);
272  buffer.open(QIODevice::ReadOnly);
273  QImageReader ir( &buffer );
274  QSize desired( 16,16 );
275  if( ir.canRead() ) {
276  while( ir.imageCount() > 1
277  && ir.currentImageRect() != QRect(0, 0, desired.width(), desired.height())) {
278  if (!ir.jumpToNextImage()) {
279  break;
280  }
281  }
282  ir.setScaledSize( desired );
283  const QImage img = ir.read();
284  if( !img.isNull() ) {
285  iconName = d->makeIconName(download, iconURL);
286  const QString localPath = d->faviconsDir + iconName + QLatin1String(".png");
287  if( !img.save(localPath, "PNG") ) {
288  iconName.clear();
289  errorMessage = i18n("Error saving image to %1", localPath);
290  } else if (!download.isHost)
291  d->config->group(QString()).writeEntry(removeSlash(download.hostOrURL), iconURL.url());
292  }
293  }
294  } else {
295  errorMessage = job->errorString();
296  }
297  if (iconName.isEmpty()) {
298  //kDebug() << "adding" << iconURL << "to failed downloads";
299  d->failedDownloads.append(iconURL);
300  emit error(download.isHost, download.hostOrURL, errorMessage);
301  } else {
302  //kDebug() << "emit iconChanged" << download.isHost << download.hostOrURL << iconName;
303  emit iconChanged(download.isHost, download.hostOrURL, iconName);
304  }
305 }
306 
307 void FavIconsModule::slotInfoMessage(KJob *job, const QString &msg)
308 {
309  emit infoMessage(static_cast<KIO::TransferJob *>( job )->url().url(), msg);
310 }
311 
312 void FavIconsModule::slotKill()
313 {
314  //kDebug();
315  Q_FOREACH(KIO::Job* job, d->killJobs) {
316  job->kill();
317  }
318  d->killJobs.clear();
319 }
320 
321 #include "favicons.moc"
iconNameFromURL
static QString iconNameFromURL(const KUrl &iconURL)
Definition: favicons.cpp:67
FavIconsModule::infoMessage
void infoMessage(QString iconURL, QString msg)
Progress info while downloading an icon.
KDEDModule
favicons.h
FavIconsModule::downloadHostIcon
void downloadHostIcon(const KUrl &url)
Downloads the icon for a given host if it was not downloaded before or the download was too long ago...
Definition: favicons.cpp:203
QObject
FavIconsModule::~FavIconsModule
virtual ~FavIconsModule()
Definition: favicons.cpp:129
FavIconsModule::iconChanged
void iconChanged(bool isHost, QString hostOrURL, QString iconName)
Emitted once a new icon is available, for a host or url.
removeSlash
static QString removeSlash(QString result)
Definition: favicons.cpp:134
FavIconsModule::error
void error(bool isHost, QString hostOrURL, QString errorString)
Emitted if an error occurred while downloading the icon for the given host or url.
FavIconsModule::iconForUrl
QString iconForUrl(const KUrl &url)
Looks up an icon name for a given URL.
Definition: favicons.cpp:146
FavIconsModule::FavIconsModule
FavIconsModule(QObject *parent, const QList< QVariant > &)
Definition: favicons.cpp:111
K_PLUGIN_FACTORY
K_PLUGIN_FACTORY(FavIconsFactory, registerPlugin< FavIconsModule >();) static QString portForUrl(const KUrl &url)
Definition: favicons.cpp:44
simplifyURL
static QString simplifyURL(const KUrl &url)
Definition: favicons.cpp:57
FavIconsModule::setIconForUrl
void setIconForUrl(const KUrl &url, const KUrl &iconURL)
Associates an icon with the given URL.
Definition: favicons.cpp:184
QList
FavIconsModule::forceDownloadHostIcon
void forceDownloadHostIcon(const KUrl &url)
Downloads the icon for a given host, even if we tried very recently.
Definition: favicons.cpp:214
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:31:18 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libkonq

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

applications API Reference

Skip menu "applications API Reference"
  •   kate
  •       kate
  •   KTextEditor
  •   Kate
  • Applications
  •   Libraries
  •     libkonq
  • Konsole

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal