• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.10.5 API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • kdecore
  • services
kmimetype.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries
2  * Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
3  * 2000-2007 David Faure <faure@kde.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License version 2 as published by the Free Software Foundation;
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 "kmimetype.h"
21 #include "kmimetype_p.h"
22 #include "kmimetypefactory.h"
23 #include "kmimetyperepository_p.h"
24 
25 #include <kdebug.h>
26 #include <kde_file.h> // KDE::stat
27 #include <kdeversion.h> // KDE_MAKE_VERSION
28 #include <klocale.h>
29 #include <kprotocolinfo.h>
30 #include <kprotocolinfofactory.h>
31 #include <kstandarddirs.h>
32 #include <kurl.h>
33 
34 #include <QtCore/QFile>
35 #include <QtDBus/QtDBus>
36 #include <QtCore/QHash>
37 #include <QBuffer>
38 
39 extern int servicesDebugArea();
40 
41 template class KSharedPtr<KMimeType>;
42 
43 KMimeType::Ptr KMimeType::defaultMimeTypePtr()
44 {
45  return KMimeTypeRepository::self()->defaultMimeTypePtr();
46 }
47 
48 bool KMimeType::isDefault() const
49 {
50  return name() == defaultMimeType();
51 }
52 
53 void KMimeType::checkEssentialMimeTypes()
54 {
55  KMimeTypeRepository::self()->checkEssentialMimeTypes();
56 }
57 
58 KMimeType::Ptr KMimeType::mimeType(const QString& name, FindByNameOption options)
59 {
60  return KMimeTypeRepository::self()->findMimeTypeByName(name, options);
61 }
62 
63 KMimeType::List KMimeType::allMimeTypes()
64 {
65  // This could be done faster...
66  KMimeType::List lst;
67  Q_FOREACH(const QString& mimeType, KMimeTypeFactory::self()->allMimeTypes()) {
68  if (!mimeType.startsWith(QLatin1String("x-scheme-handler")))
69  lst.append(KMimeType::mimeType(mimeType));
70  }
71  return lst;
72 }
73 
74 bool KMimeType::isBufferBinaryData(const QByteArray& data)
75 {
76  // Check the first 32 bytes (see shared-mime spec)
77  const char* p = data.data();
78  const int end = qMin(32, data.size());
79  for (int i = 0; i < end; ++i) {
80  if ((unsigned char)(p[i]) < 32 && p[i] != 9 && p[i] != 10 && p[i] != 13) // ASCII control character
81  return true;
82  }
83  return false;
84 }
85 
86 static KMimeType::Ptr findFromMode( const QString& path /*only used if is_local_file*/,
87  mode_t mode /*0 if unknown*/,
88  bool is_local_file )
89 {
90  if ( is_local_file && (mode == 0 || mode == (mode_t)-1) ) {
91  KDE_struct_stat buff;
92  if ( KDE::stat( path, &buff ) != -1 )
93  mode = buff.st_mode;
94  }
95 
96  if ( S_ISDIR( mode ) ) {
97  // KDE4 TODO: use an overlay instead
98 #if 0
99  // Special hack for local files. We want to see whether we
100  // are allowed to enter the directory
101  if ( is_local_file )
102  {
103  if ( KDE::access( path, R_OK ) == -1 )
104  return KMimeType::mimeType( "inode/directory-locked" );
105  }
106 #endif
107  return KMimeType::mimeType( QLatin1String("inode/directory") );
108  }
109  if ( S_ISCHR( mode ) )
110  return KMimeType::mimeType( QLatin1String("inode/chardevice") );
111  if ( S_ISBLK( mode ) )
112  return KMimeType::mimeType( QLatin1String("inode/blockdevice") );
113  if ( S_ISFIFO( mode ) )
114  return KMimeType::mimeType( QLatin1String("inode/fifo") );
115  if ( S_ISSOCK( mode ) )
116  return KMimeType::mimeType( QLatin1String("inode/socket") );
117 #ifdef Q_OS_WIN
118  // FIXME: distinguish between mounted & unmounted
119  int size = path.size();
120  if ( size == 2 || size == 3 ) {
121  //GetDriveTypeW is not defined in wince
122 #ifndef _WIN32_WCE
123  unsigned int type = GetDriveTypeW( (LPCWSTR) path.utf16() );
124  switch( type ) {
125  case DRIVE_REMOVABLE:
126  return KMimeType::mimeType( QLatin1String("media/floppy_mounted") );
127  case DRIVE_FIXED:
128  return KMimeType::mimeType( QLatin1String("media/hdd_mounted") );
129  case DRIVE_REMOTE:
130  return KMimeType::mimeType( QLatin1String("media/smb_mounted") );
131  case DRIVE_CDROM:
132  return KMimeType::mimeType( QLatin1String("media/cdrom_mounted") );
133  case DRIVE_RAMDISK:
134  return KMimeType::mimeType( QLatin1String("media/hdd_mounted") );
135  default:
136  break;
137  };
138 #else
139  return KMimeType::mimeType( QLatin1String("media/hdd_mounted") );
140 #endif
141  }
142 #endif
143  // remote executable file? stop here (otherwise findFromContent can do that better for local files)
144  if ( !is_local_file && S_ISREG( mode ) && ( mode & ( S_IXUSR | S_IXGRP | S_IXOTH ) ) )
145  return KMimeType::mimeType( QLatin1String("application/x-executable") );
146 
147  return KMimeType::Ptr();
148 }
149 
150 /*
151 
152 As agreed on the XDG list (and unlike the current shared-mime spec):
153 
154 Glob-matching should prefer derived mimetype over base mimetype, and longer matches
155 over shorter ones. However if two globs of the same length match the file, and the two
156 matches are not related in the inheritance tree, then we have a "glob conflict", which
157 will be resolved below.
158 
159 If only one glob matches, use that
160 
161 If no glob matches, sniff and use that
162 
163 If several globs matches, and sniffing gives a result we do:
164  if sniffed prio >= 80, use sniffed type
165  for glob_match in glob_matches:
166  if glob_match is subclass or equal to sniffed_type, use glob_match
167 
168 If several globs matches, and sniffing fails, or doesn't help:
169  fall back to the first glob match
170 
171 This algorithm only sniffs when there is some uncertainty with the
172 extension matching (thus, it's usable for a file manager).
173 
174 Note: in KDE we want the file views to sniff in a delayed manner.
175 So there's also a fast mode which is:
176  if no glob matches, or if more than one glob matches, use default mimetype and mark as "can be refined".
177 
178 */
179 
180 KMimeType::Ptr KMimeType::findByUrlHelper( const KUrl& _url, mode_t mode,
181  bool is_local_file,
182  QIODevice* device,
183  int* accuracy )
184 {
185  checkEssentialMimeTypes();
186  const QString path = is_local_file ? _url.toLocalFile() : _url.path();
187 
188  if (accuracy)
189  *accuracy = 100;
190 
191  // Look at mode first
192  KMimeType::Ptr mimeFromMode = findFromMode( path, mode, is_local_file );
193  if (mimeFromMode)
194  return mimeFromMode;
195 
196  // First try to find out by looking at the filename (if there's one)
197  const QString fileName( _url.fileName() );
198  QStringList mimeList;
199  if ( !fileName.isEmpty() && !path.endsWith( QLatin1Char('/') ) ) {
200  // and if we can trust it (e.g. don't trust *.pl over HTTP, could be anything)
201  if ( is_local_file || _url.hasSubUrl() || // Explicitly trust suburls
202  KProtocolInfo::determineMimetypeFromExtension( _url.protocol() ) ) {
203  mimeList = KMimeTypeRepository::self()->findFromFileName( fileName );
204  // Found one glob match exactly: OK, use that.
205  // We disambiguate multiple glob matches by sniffing, below.
206  if ( mimeList.count() == 1 ) {
207  const QString selectedMime = mimeList.at(0);
208  KMimeType::Ptr mime = mimeType(selectedMime);
209  if (!mime) {
210  // #265188 - this can happen when an old globs file is lying around after
211  // the packages xml file was removed.
212  kWarning() << "Glob file refers to" << selectedMime << "but this mimetype does not exist!";
213  mimeList.clear();
214  } else {
215  return mime;
216  }
217  }
218  }
219  }
220 
221  if ( device && !device->isOpen() ) {
222  if ( !device->open(QIODevice::ReadOnly) ) {
223  device = 0;
224  }
225  }
226 
227  // Try the magic matches (if we can read the data)
228  QByteArray beginning;
229  if ( device ) {
230  int magicAccuracy;
231  KMimeType::Ptr mime = KMimeTypeRepository::self()->findFromContent(device, &magicAccuracy, beginning);
232  // mime can't be 0, except in case of install problems.
233  // However we get magicAccuracy==0 for octet-stream, i.e. no magic match found.
234  //kDebug(servicesDebugArea()) << "findFromContent said" << (mime?mime->name():QString()) << "with accuracy" << magicAccuracy;
235  if (mime && magicAccuracy > 0) {
236 
237  // Disambiguate conflicting extensions (if magic found something and the magicrule was <80)
238  if (magicAccuracy < 80 && !mimeList.isEmpty()) {
239  // "for glob_match in glob_matches:"
240  // "if glob_match is subclass or equal to sniffed_type, use glob_match"
241  const QString sniffedMime = mime->name();
242  foreach(const QString &m, mimeList) {
243  KMimeType::Ptr mimeFromPattern = KMimeType::mimeType(m);
244  //kDebug(servicesDebugArea()) << "sniffedMime=" << sniffedMime << "mimeFromPattern=" << mimeFromPattern->name();
245  if (mimeFromPattern && mimeFromPattern->is(sniffedMime)) {
246  // We have magic + pattern pointing to this, so it's a pretty good match
247  if (accuracy)
248  *accuracy = 100;
249  return mimeFromPattern;
250  }
251  }
252  }
253 
254  if (accuracy)
255  *accuracy = magicAccuracy;
256  return mime;
257  }
258  }
259 
260  // Not a local file, or no magic allowed, or magic found nothing
261 
262  // Maybe we had multiple matches from globs?
263  if (!mimeList.isEmpty()) {
264  if (accuracy)
265  *accuracy = 20;
266  // We have to pick one...
267  // At least make this deterministic
268  qSort(mimeList.begin(), mimeList.end());
269  Q_FOREACH(const QString& mimeName, mimeList) {
270  KMimeType::Ptr mime = mimeType(mimeName);
271  if (!mime)
272  kWarning() << "Glob file refers to" << mimeName << "but this mimetype does not exist!";
273  else
274  return mime;
275  }
276  }
277 
278  // Find a fallback from the protocol
279  if (accuracy)
280  *accuracy = 10;
281  // ## this breaks with proxying; find a way to move proxying info to kdecore's kprotocolinfo?
282  // ## or hardcode the only case of proxying that we ever had? (ftp-over-http)
283  KProtocolInfo::Ptr prot = KProtocolInfoFactory::self()->findProtocol( _url.protocol() );
284  QString def;
285  if (prot)
286  def = prot->defaultMimeType();
287  if ( !def.isEmpty() && def != defaultMimeType() ) {
288  // The protocol says it always returns a given mimetype (e.g. text/html for "man:")
289  KMimeType::Ptr mime = mimeType( def );
290  if (mime)
291  return mime;
292  }
293  if ( path.endsWith( QLatin1Char('/') ) || path.isEmpty() ) {
294  // We have no filename at all. Maybe the protocol has a setting for
295  // which mimetype this means (e.g. directory).
296  // For HTTP (def==defaultMimeType()) we don't assume anything,
297  // because of redirections (e.g. freshmeat downloads).
298  if ( def.isEmpty() ) {
299  // Assume inode/directory, if the protocol supports listing.
300  KProtocolInfo::Ptr prot = KProtocolInfoFactory::self()->findProtocol( _url.protocol() );
301  if ( prot && prot->supportsListing() ) {
302  KMimeType::Ptr mime = mimeType( QLatin1String("inode/directory") );
303  if (mime) { // only 0 if no mimetypes installed
304  return mime;
305  }
306  } else
307  return defaultMimeTypePtr(); // == 'no idea', e.g. for "data:,foo/"
308  }
309  }
310 
311  if (accuracy)
312  *accuracy = 0;
313  return defaultMimeTypePtr();
314 }
315 
316 KMimeType::Ptr KMimeType::findByUrl( const KUrl& url, mode_t mode,
317  bool is_local_file, bool fast_mode,
318  int *accuracy )
319 {
320  if ( !is_local_file && url.isLocalFile() )
321  is_local_file = true;
322  if (is_local_file && !fast_mode) {
323  QFile file(url.toLocalFile());
324  return findByUrlHelper(url, mode, is_local_file, &file, accuracy);
325  }
326  return findByUrlHelper(url, mode, is_local_file, 0, accuracy);
327 }
328 
329 KMimeType::Ptr KMimeType::findByPath( const QString& path, mode_t mode,
330  bool fast_mode, int* accuracy )
331 {
332  KUrl url;
333  url.setPath(path);
334  return findByUrl(url, mode, true, fast_mode, accuracy);
335 }
336 
337 KMimeType::Ptr KMimeType::findByNameAndContent( const QString& name, const QByteArray& data,
338  mode_t mode, int* accuracy )
339 {
340  KUrl url;
341  url.setPath(name);
342  QBuffer buffer(const_cast<QByteArray *>(&data));
343  return findByUrlHelper(url, mode, false, &buffer, accuracy);
344 }
345 
346 KMimeType::Ptr KMimeType::findByNameAndContent( const QString& name, QIODevice* device,
347  mode_t mode, int* accuracy )
348 {
349  KUrl url;
350  url.setPath(name);
351  return findByUrlHelper(url, mode, false, device, accuracy);
352 }
353 
354 QString KMimeType::extractKnownExtension(const QString &fileName)
355 {
356  QString pattern;
357  KMimeTypeRepository::self()->findFromFileName( fileName, &pattern );
358  return pattern;
359 }
360 
361 KMimeType::Ptr KMimeType::findByContent( const QByteArray &data, int *accuracy )
362 {
363  QBuffer buffer(const_cast<QByteArray *>(&data));
364  buffer.open(QIODevice::ReadOnly);
365  QByteArray cache;
366  return KMimeTypeRepository::self()->findFromContent(&buffer, accuracy, cache);
367 }
368 
369 KMimeType::Ptr KMimeType::findByContent( QIODevice* device, int* accuracy )
370 {
371  QByteArray cache;
372  return KMimeTypeRepository::self()->findFromContent(device, accuracy, cache);
373 }
374 
375 KMimeType::Ptr KMimeType::findByFileContent( const QString &fileName, int *accuracy )
376 {
377  checkEssentialMimeTypes();
378 
379  QFile device(fileName);
380  // Look at mode first
381  KMimeType::Ptr mimeFromMode = findFromMode( fileName, 0, true );
382  if (mimeFromMode) {
383  if (accuracy)
384  *accuracy = 100;
385  return mimeFromMode;
386  }
387  if (!device.open(QIODevice::ReadOnly)) {
388  if (accuracy)
389  *accuracy = 0;
390  return KMimeType::defaultMimeTypePtr();
391  }
392 
393  QByteArray cache;
394  return KMimeTypeRepository::self()->findFromContent(&device, accuracy, cache);
395 }
396 
397 bool KMimeType::isBinaryData( const QString &fileName )
398 {
399  QFile file(fileName);
400  if (!file.open(QIODevice::ReadOnly))
401  return false; // err, whatever
402  const QByteArray data = file.read(32);
403  return isBufferBinaryData(data);
404 }
405 
406 KMimeType::KMimeType( KMimeTypePrivate &dd, const QString& name,
407  const QString& comment )
408  : KServiceType( dd, name, comment )
409 {
410 }
411 
412 KMimeType::KMimeType( const QString & fullpath, const QString& name,
413  const QString& comment )
414  : KServiceType( *new KMimeTypePrivate(fullpath), name, comment )
415 {
416 }
417 
418 KMimeType::KMimeType( KMimeTypePrivate &dd)
419  : KServiceType(dd)
420 {
421 }
422 
423 KMimeType::KMimeType( QDataStream& _str, int offset )
424  : KServiceType( *new KMimeTypePrivate(_str, offset ))
425 {
426 }
427 
428 void KMimeTypePrivate::save( QDataStream& _str )
429 {
430  KServiceTypePrivate::save( _str );
431  // Warning adding fields here involves a binary incompatible change - update version
432  // number in ksycoca.h. Never remove fields.
433  _str << m_lstPatterns << QString() << QStringList() << m_iconName;
434 }
435 
436 QVariant KMimeTypePrivate::property( const QString& _name ) const
437 {
438  if ( _name == QLatin1String("Patterns") )
439  return QVariant( m_lstPatterns );
440  if ( _name == QLatin1String("Icon") )
441  return QVariant( iconName(KUrl()) );
442 
443  return KServiceTypePrivate::property( _name );
444 }
445 
446 QStringList KMimeTypePrivate::propertyNames() const
447 {
448  QStringList res = KServiceTypePrivate::propertyNames();
449  res.append( QString::fromLatin1("Patterns") );
450  res.append( QString::fromLatin1("Icon") );
451  return res;
452 }
453 
454 KMimeType::~KMimeType()
455 {
456 }
457 
458 QString KMimeType::iconNameForUrl( const KUrl & _url, mode_t mode )
459 {
460  const KMimeType::Ptr mt = findByUrl( _url, mode, _url.isLocalFile(),
461  false /*HACK*/);
462  if (!mt) {
463  return QString();
464  }
465  static const QString& unknown = KGlobal::staticQString("unknown");
466  const QString mimeTypeIcon = mt->iconName( _url );
467  QString i = mimeTypeIcon;
468 
469  // if we don't find an icon, maybe we can use the one for the protocol
470  if ( i == unknown || i.isEmpty() || mt->name() == defaultMimeType()
471  // and for the root of the protocol (e.g. trash:/) the protocol icon has priority over the mimetype icon
472  || _url.path().length() <= 1 )
473  {
474  i = favIconForUrl( _url ); // maybe there is a favicon?
475 
476  if ( i.isEmpty() )
477  i = KProtocolInfo::icon( _url.protocol() );
478 
479  // root of protocol: if we found nothing, revert to mimeTypeIcon (which is usually "folder")
480  if ( _url.path().length() <= 1 && ( i == unknown || i.isEmpty() ) )
481  i = mimeTypeIcon;
482  }
483  return !i.isEmpty() ? i : unknown;
484 }
485 
486 QString KMimeType::favIconForUrl( const KUrl& url )
487 {
488  /* The kded module also caches favicons, for one week, without any way
489  * to clean up the cache meanwhile.
490  * On the other hand, this QHash will get cleaned up after 5000 request
491  * (a selection in konsole of 80 chars generates around 500 requests)
492  * or by simply restarting the application (or the whole desktop,
493  * more likely, for the case of konqueror or konsole).
494  */
495  static QHash<QUrl, QString> iconNameCache;
496  static int autoClearCache = 0;
497  const QString notFound = QLatin1String("NOTFOUND");
498 
499  if (url.isLocalFile()
500  || !url.protocol().startsWith(QLatin1String("http"))
501  || !KMimeTypeRepository::self()->useFavIcons())
502  return QString();
503 
504  QString iconNameFromCache = iconNameCache.value(url, notFound);
505  if ( iconNameFromCache != notFound ) {
506  if ( (++autoClearCache) < 5000 ) {
507  return iconNameFromCache;
508  }
509  else {
510  iconNameCache.clear();
511  autoClearCache = 0;
512  }
513  }
514 
515  QDBusInterface kded( QString::fromLatin1("org.kde.kded"),
516  QString::fromLatin1("/modules/favicons"),
517  QString::fromLatin1("org.kde.FavIcon") );
518  QDBusReply<QString> result = kded.call( QString::fromLatin1("iconForUrl"), url.url() );
519  iconNameCache.insert(url, result.value());
520  return result; // default is QString()
521 }
522 
523 QString KMimeType::comment( const KUrl &url) const
524 {
525  Q_D(const KMimeType);
526  return d->comment(url);
527 }
528 
529 #ifndef KDE_NO_DEPRECATED
530 QString KMimeType::parentMimeType() const
531 {
532  const QStringList parents = parentMimeTypes();
533  if (!parents.isEmpty())
534  return parents.first();
535  return QString();
536 }
537 #endif
538 
539 bool KMimeTypePrivate::inherits(const QString& mime) const
540 {
541  QStack<QString> toCheck;
542  toCheck.push(m_strName);
543  while (!toCheck.isEmpty()) {
544  const QString current = toCheck.pop();
545  if (current == mime)
546  return true;
547  Q_FOREACH(const QString& parent, KMimeTypeRepository::self()->parents(current)) {
548  toCheck.push(parent);
549  }
550  }
551  return false;
552 }
553 
554 bool KMimeType::is( const QString& mimeTypeName ) const
555 {
556  Q_D(const KMimeType);
557  if (name() == mimeTypeName)
558  return true;
559  const QString mime = KMimeTypeRepository::self()->canonicalName(mimeTypeName);
560  return d->inherits(mime);
561 }
562 
563 QStringList KMimeType::parentMimeTypes() const
564 {
565  Q_D(const KMimeType);
566  return KMimeTypeRepository::self()->parents(d->m_strName);
567 }
568 
569 static void collectParentMimeTypes(const QString& mime, QStringList& allParents)
570 {
571  QStringList parents = KMimeTypeRepository::self()->parents(mime);
572  Q_FOREACH(const QString& parent, parents) {
573  // I would use QSet, but since order matters I better not
574  if (!allParents.contains(parent))
575  allParents.append(parent);
576  }
577  // We want a breadth-first search, so that the least-specific parent (octet-stream) is last
578  // This means iterating twice, unfortunately.
579  Q_FOREACH(const QString& parent, parents) {
580  collectParentMimeTypes(parent, allParents);
581  }
582 }
583 
584 QStringList KMimeType::allParentMimeTypes() const
585 {
586  Q_D(const KMimeType);
587  QStringList allParents;
588  const QString canonical = KMimeTypeRepository::self()->resolveAlias(name());
589  if (!canonical.isEmpty())
590  allParents.append(canonical);
591  collectParentMimeTypes(d->m_strName, allParents);
592  return allParents;
593 }
594 
595 QString KMimeType::defaultMimeType()
596 {
597  static const QString & s_strDefaultMimeType =
598  KGlobal::staticQString( "application/octet-stream" );
599  return s_strDefaultMimeType;
600 }
601 
602 QString KMimeType::iconName( const KUrl& url) const
603 {
604  Q_D(const KMimeType);
605  return d->iconName(url);
606 }
607 
608 QStringList KMimeType::patterns() const
609 {
610  Q_D(const KMimeType);
611  d->ensureXmlDataLoaded();
612  return d->m_lstPatterns;
613 }
614 
615 // loads comment, icon, mainPattern, m_lstPatterns
616 void KMimeTypePrivate::ensureXmlDataLoaded() const
617 {
618  if (m_xmlDataLoaded)
619  return;
620 
621  m_xmlDataLoaded = true;
622 
623  const QString file = m_strName + QLatin1String(".xml");
624  const QStringList mimeFiles = KGlobal::dirs()->findAllResources("xdgdata-mime", file);
625  if (mimeFiles.isEmpty()) {
626  kWarning() << "No file found for" << file << ", even though the file appeared in a directory listing.";
627  kWarning() << "Either it was just removed, or the directory doesn't have executable permission...";
628  kWarning() << KGlobal::dirs()->resourceDirs("xdgdata-mime");
629  return;
630  }
631 
632  QString comment;
633  QString mainPattern;
634  const QStringList languageList = KGlobal::locale()->languageList();
635  QString preferredLanguage = languageList.first();
636  QMap<QString, QString> commentsByLanguage;
637 
638  QListIterator<QString> mimeFilesIter(mimeFiles);
639  mimeFilesIter.toBack();
640  while (mimeFilesIter.hasPrevious()) { // global first, then local.
641  const QString fullPath = mimeFilesIter.previous();
642  QFile qfile(fullPath);
643  if (!qfile.open(QFile::ReadOnly))
644  continue;
645 
646  QXmlStreamReader xml(&qfile);
647  if (xml.readNextStartElement()) {
648  if (xml.name() != "mime-type") {
649  continue;
650  }
651  const QString name = xml.attributes().value(QLatin1String("type")).toString();
652  if (name.isEmpty())
653  continue;
654  if (name != m_strName) {
655  kWarning() << "Got name" << name << "in file" << file << "expected" << m_strName;
656  }
657 
658  while (xml.readNextStartElement()) {
659  const QStringRef tag = xml.name();
660  if (tag == "comment") {
661  QString lang = xml.attributes().value(QLatin1String("xml:lang")).toString();
662  const QString text = xml.readElementText();
663  if (lang.isEmpty()) {
664  lang = QLatin1String("en_US");
665  }
666  if (lang == preferredLanguage) {
667  comment = text;
668  } else {
669  commentsByLanguage.insert(lang, text);
670  }
671  continue; // we called readElementText, so we're at the EndElement already.
672  } else if (tag == "icon") { // as written out by shared-mime-info >= 0.40
673  m_iconName = xml.attributes().value(QLatin1String("name")).toString();
674  } else if (tag == "glob-deleteall") { // as written out by shared-mime-info >= 0.70
675  mainPattern.clear();
676  m_lstPatterns.clear();
677  } else if (tag == "glob") { // as written out by shared-mime-info >= 0.70
678  const QString pattern = xml.attributes().value(QLatin1String("pattern")).toString();
679  if (mainPattern.isEmpty() && pattern.startsWith(QLatin1Char('*'))) {
680  mainPattern = pattern;
681  }
682  if (!m_lstPatterns.contains(pattern))
683  m_lstPatterns.append(pattern);
684  }
685  xml.skipCurrentElement();
686  }
687  if (xml.name() != "mime-type") {
688  kFatal() << "Programming error in KMimeType XML loading, please create a bug report on http://bugs.kde.org and attach the file" << fullPath;
689  }
690  }
691  }
692 
693  if (comment.isEmpty()) {
694  Q_FOREACH(const QString& lang, languageList) {
695  const QString comm = commentsByLanguage.value(lang);
696  if (!comm.isEmpty()) {
697  comment = comm;
698  break;
699  }
700  const int pos = lang.indexOf(QLatin1Char('_'));
701  if (pos != -1) {
702  // "pt_BR" not found? try just "pt"
703  const QString shortLang = lang.left(pos);
704  const QString comm = commentsByLanguage.value(shortLang);
705  if (!comm.isEmpty()) {
706  comment = comm;
707  break;
708  }
709  }
710  }
711  if (comment.isEmpty()) {
712  kWarning() << "Missing <comment> field in" << file;
713  }
714  }
715  m_strComment = comment;
716 
717  const bool globsInXml = (KMimeType::sharedMimeInfoVersion() >= KDE_MAKE_VERSION(0, 70, 0));
718  if (globsInXml) {
719  if (!mainPattern.isEmpty() && m_lstPatterns.first() != mainPattern) {
720  // ensure it's first in the list of patterns
721  m_lstPatterns.removeAll(mainPattern);
722  m_lstPatterns.prepend(mainPattern);
723  }
724  } else {
725  // Fallback: get the patterns from the globs file
726  m_lstPatterns = KMimeTypeRepository::self()->patternsForMimetype(m_strName);
727  }
728 }
729 
730 QString KMimeType::userSpecifiedIconName() const
731 {
732  Q_D(const KMimeType);
733  d->ensureXmlDataLoaded();
734  return d->m_iconName;
735 }
736 
737 int KMimeType::sharedMimeInfoVersion()
738 {
739  return KMimeTypeRepository::self()->sharedMimeInfoVersion();
740 }
741 
742 QString KMimeType::mainExtension() const
743 {
744  Q_D(const KMimeType);
745 
746 #if 1 // HACK START - can be removed once shared-mime-info >= 0.70 is used/required.
747  // The idea was: first usable pattern from m_lstPatterns.
748  // But update-mime-database makes a mess of the order of the patterns,
749  // because it uses a hash internally.
750  static const struct { const char* mime; const char* extension; } s_hardcodedMimes[] = {
751  { "text/plain", ".txt" } };
752  if (d->m_lstPatterns.count() > 1) {
753  const QByteArray me = name().toLatin1();
754  for (uint i = 0; i < sizeof(s_hardcodedMimes)/sizeof(*s_hardcodedMimes); ++i) {
755  if (me == s_hardcodedMimes[i].mime)
756  return QString::fromLatin1(s_hardcodedMimes[i].extension);
757  }
758  }
759 #endif // HACK END
760 
761  Q_FOREACH(const QString& pattern, patterns()) {
762  // Skip if if looks like: README or *. or *.*
763  // or *.JP*G or *.JP?
764  if (pattern.startsWith(QLatin1String("*.")) &&
765  pattern.length() > 2 &&
766  pattern.indexOf(QLatin1Char('*'), 2) < 0 && pattern.indexOf(QLatin1Char('?'), 2) < 0) {
767  return pattern.mid(1);
768  }
769  }
770  // TODO we should also look into the parent mimetype's patterns, no?
771  return QString();
772 }
773 
774 bool KMimeType::matchFileName( const QString &filename, const QString &pattern )
775 {
776  return KMimeTypeRepository::matchFileName( filename, pattern );
777 }
778 
779 int KMimeTypePrivate::serviceOffersOffset() const
780 {
781  return KMimeTypeFactory::self()->serviceOffersOffset(name());
782 }
783 
784 QString KMimeTypePrivate::iconName(const KUrl &) const
785 {
786  static QHash<QUrl, QString> iconNameCache;
787  QString iconNameFromCache = iconNameCache.value(m_strName);
788  if (!iconNameFromCache.isEmpty())
789  return iconNameFromCache;
790 
791  ensureXmlDataLoaded();
792  QString result;
793  if (!m_iconName.isEmpty()) {
794  result = m_iconName;
795  } else {
796  // Make default icon name from the mimetype name
797  // Don't store this in m_iconName, it would make the filetype editor
798  // write out icon names in every local mimetype definition file.
799  QString icon = m_strName;
800  const int slashindex = icon.indexOf(QLatin1Char('/'));
801  if (slashindex != -1) {
802  icon[slashindex] = QLatin1Char('-');
803  }
804  result = icon;
805  }
806  iconNameCache.insert(m_strName, result);
807  return result;
808 }
KMimeType::Ptr
KSharedPtr< KMimeType > Ptr
Definition: kmimetype.h:50
QVariant
KMimeTypeRepository::defaultMimeTypePtr
KMimeType::Ptr defaultMimeTypePtr()
Definition: kmimetyperepository.cpp:661
KDE_MAKE_VERSION
#define KDE_MAKE_VERSION(a, b, c)
Make a number from the major, minor and release number of a KDE version.
Definition: kdeversion.h.cmake:75
KMimeType::iconName
QString iconName(const KUrl &url=KUrl()) const
Return the filename of the icon associated with the mimetype.
Definition: kmimetype.cpp:602
KSharedPtr< KMimeType >
KProtocolInfo::determineMimetypeFromExtension
static bool determineMimetypeFromExtension(const QString &protocol)
Returns whether mimetypes can be determined based on extension for this protocol. ...
Definition: kprotocolinfo.cpp:328
KMimeType::iconNameForUrl
static QString iconNameForUrl(const KUrl &url, mode_t mode=0)
Return the filename of the icon associated with the mimetype, for a given url.
Definition: kmimetype.cpp:458
kprotocolinfofactory.h
KMimeTypeRepository::patternsForMimetype
QStringList patternsForMimetype(const QString &mimeType)
Return the patterns (globs) for a given mimetype TEMPORARY method, it will go away once we can requir...
Definition: kmimetyperepository.cpp:598
KMimeTypeRepository::findMimeTypeByName
KMimeType::Ptr findMimeTypeByName(const QString &_name, KMimeType::FindByNameOption options=KMimeType::DontResolveAlias)
Creates a KMimeType.
Definition: kmimetyperepository.cpp:58
KMimeType::favIconForUrl
static QString favIconForUrl(const KUrl &url)
Return the &quot;favicon&quot; (see http://www.favicon.com) for the given url, if available.
Definition: kmimetype.cpp:486
kdebug.h
KMimeType::matchFileName
static bool matchFileName(const QString &filename, const QString &pattern)
Returns true if the given filename matches the given pattern.
Definition: kmimetype.cpp:774
KMimeType::FindByNameOption
FindByNameOption
Definition: kmimetype.h:105
kmimetype.h
KServiceTypePrivate::propertyNames
virtual QStringList propertyNames() const
Definition: kservicetype.cpp:169
kurl.h
KMimeTypePrivate::m_xmlDataLoaded
bool m_xmlDataLoaded
Definition: kmimetype_p.h:57
KMimeType::userSpecifiedIconName
QString userSpecifiedIconName() const
Returns the user-specified icon for this mimetype.
Definition: kmimetype.cpp:730
KMimeType::findByPath
static Ptr findByPath(const QString &path, mode_t mode=0, bool fast_mode=false, int *accuracy=0)
Finds a KMimeType with the given url.
Definition: kmimetype.cpp:329
KMimeType
Represent a mime type, like &quot;text/plain&quot;, and the data that is associated with it.
Definition: kmimetype.h:46
KGlobal::dirs
KStandardDirs * dirs()
Returns the application standard dirs object.
KDE::stat
int stat(const QString &path, KDE_struct_stat *buf)
Definition: kde_file_win.cpp:175
KServiceTypePrivate::property
virtual QVariant property(const QString &name) const
Definition: kservicetype.cpp:154
KMimeTypePrivate::iconName
virtual QString iconName(const KUrl &) const
Definition: kmimetype.cpp:784
kmimetyperepository_p.h
KUrl::toLocalFile
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
Definition: kurl.cpp:884
KServiceTypePrivate::m_strName
QString m_strName
Definition: kservicetype_p.h:69
servicesDebugArea
int servicesDebugArea()
Definition: kservice.cpp:47
KMimeTypeRepository::self
static KMimeTypeRepository * self()
Definition: kmimetyperepository.cpp:34
KServiceType
A service type is, well, a type of service, where a service is an application or plugin.
Definition: kservicetype.h:43
KMimeType::sharedMimeInfoVersion
static int sharedMimeInfoVersion()
Returns the version of the installed update-mime-database program (from freedesktop.org shared-mime-info).
Definition: kmimetype.cpp:737
QString
KMimeType::extractKnownExtension
static QString extractKnownExtension(const QString &fileName)
Determines the extension from a filename (or full path) using the mimetype database.
Definition: kmimetype.cpp:354
KServiceTypePrivate::m_strComment
QString m_strComment
Definition: kservicetype_p.h:70
QHash
Definition: ksycocafactory.h:28
klocale.h
KMimeTypeRepository::matchFileName
static bool matchFileName(const QString &filename, const QString &pattern)
Definition: kmimetyperepository.cpp:97
KMimeTypePrivate::serviceOffersOffset
virtual int serviceOffersOffset() const
Definition: kmimetype.cpp:779
KMimeType::defaultMimeTypePtr
static KMimeType::Ptr defaultMimeTypePtr()
Returns the default mimetype.
Definition: kmimetype.cpp:43
KUrl
Represents and parses a URL.
Definition: kurl.h:111
KMimeType::parentMimeTypes
QStringList parentMimeTypes() const
If this mimetype is a subclass of one or more other mimetypes, return the list of those mimetypes...
Definition: kmimetype.cpp:563
KMimeTypePrivate::m_iconName
QString m_iconName
Definition: kmimetype_p.h:56
KUrl::setPath
void setPath(const QString &path)
Definition: kurl.cpp:1770
kmimetype_p.h
KMimeTypeRepository::parents
QStringList parents(const QString &mime)
Returns the list of parents for a given mimetype.
Definition: kmimetyperepository.cpp:293
KProtocolInfoFactory::self
static KProtocolInfoFactory * self()
The instance of the KProtocolInfoFactory.
Definition: kprotocolinfofactory.cpp:119
KMimeTypePrivate::m_lstPatterns
QStringList m_lstPatterns
Definition: kmimetype_p.h:55
KProtocolInfo::icon
static QString icon(const QString &protocol)
Returns the name of the icon, associated with the specified protocol.
Definition: kprotocolinfo.cpp:287
KMimeTypeFactory::self
static KMimeTypeFactory * self()
Definition: kmimetypefactory.cpp:41
KMimeTypeRepository::useFavIcons
bool useFavIcons()
Returns true if KMimeType::favIconForUrl should talk to kded&#39;s favicons module.
Definition: kmimetyperepository.cpp:680
KUrl::protocol
QString protocol() const
Returns the protocol for the URL (i.e., file, http, etc.), lowercased.
Definition: kurl.cpp:671
QStringList
KMimeTypePrivate::inherits
bool inherits(const QString &mime) const
Definition: kmimetype.cpp:539
KMimeTypePrivate::ensureXmlDataLoaded
void ensureXmlDataLoaded() const
Definition: kmimetype.cpp:616
KMimeType::mainExtension
QString mainExtension() const
Return the primary extension associated with this mimetype, if any.
Definition: kmimetype.cpp:742
KServiceTypePrivate::name
virtual QString name() const
Definition: kservicetype_p.h:49
KUrl::path
QString path(AdjustPathOption trailing=LeaveTrailingSlash) const
Definition: kurl.cpp:872
KProtocolInfoFactory::findProtocol
KProtocolInfo::Ptr findProtocol(const QString &protocol)
Definition: kprotocolinfofactory.cpp:91
KMimeTypeRepository::sharedMimeInfoVersion
int sharedMimeInfoVersion()
Definition: kmimetyperepository.cpp:782
KMimeTypePrivate::comment
virtual QString comment(const KUrl &=KUrl()) const
Definition: kmimetype_p.h:42
KMimeTypeRepository::resolveAlias
QString resolveAlias(const QString &mime)
Check if mime is an alias, and return the canonical name for it if it is, otherwise empty...
Definition: kmimetyperepository.cpp:84
KMimeType::isDefault
bool isDefault() const
Return true if this mimetype is the default mimetype.
Definition: kmimetype.cpp:48
kprotocolinfo.h
kWarning
#define kWarning
Definition: kdebug.h:322
KStandardDirs::resourceDirs
QStringList resourceDirs(const char *type) const
This function is used internally by almost all other function as it serves and fills the directories ...
Definition: kstandarddirs.cpp:1063
KGlobal::locale
KLocale * locale()
Returns the global locale object.
Definition: kglobal.cpp:169
KMimeType::findByNameAndContent
static Ptr findByNameAndContent(const QString &name, const QByteArray &data, mode_t mode=0, int *accuracy=0)
Tries to find out the MIME type of filename/url and a data chunk.
Definition: kmimetype.cpp:337
KLocale::languageList
QStringList languageList() const
Returns the language codes selected by user, ordered by decreasing priority.
Definition: klocale.cpp:439
KMimeType::findByContent
static Ptr findByContent(const QByteArray &data, int *accuracy=0)
Tries to find out the MIME type of a data chunk by looking for certain magic numbers and characterist...
Definition: kmimetype.cpp:361
KMimeType::allParentMimeTypes
QStringList allParentMimeTypes() const
Return all parent mimetypes of this mimetype, direct or indirect.
Definition: kmimetype.cpp:584
KMimeTypePrivate::propertyNames
virtual QStringList propertyNames() const
Definition: kmimetype.cpp:446
KUrl::fileName
QString fileName(const DirectoryOptions &options=IgnoreTrailingSlash) const
Returns the filename of the path.
Definition: kurl.cpp:1281
KMimeType::allMimeTypes
static List allMimeTypes()
Get all the mimetypes.
Definition: kmimetype.cpp:63
KDE::access
int access(const QString &path, int mode)
Definition: kde_file_win.cpp:123
KMimeType::defaultMimeType
static QString defaultMimeType()
Returns the name of the default mimetype.
Definition: kmimetype.cpp:595
KMimeType::findByUrl
static Ptr findByUrl(const KUrl &url, mode_t mode=0, bool is_local_file=false, bool fast_mode=false, int *accuracy=0)
Finds a KMimeType with the given url.
Definition: kmimetype.cpp:316
kstandarddirs.h
KMimeTypePrivate::property
virtual QVariant property(const QString &name) const
Definition: kmimetype.cpp:436
KMimeTypeRepository::checkEssentialMimeTypes
void checkEssentialMimeTypes()
This function makes sure that vital mime types are installed.
Definition: kmimetyperepository.cpp:615
KUrl::hasSubUrl
bool hasSubUrl() const
Checks whether the URL has any sub URLs.
Definition: kurl.cpp:1029
KServiceTypePrivate::save
virtual void save(QDataStream &)
Definition: kservicetype.cpp:117
KMimeType::mimeType
static Ptr mimeType(const QString &name, FindByNameOption options=ResolveAliases)
Retrieve a pointer to the mime type name.
Definition: kmimetype.cpp:58
findFromMode
static KMimeType::Ptr findFromMode(const QString &path, mode_t mode, bool is_local_file)
Definition: kmimetype.cpp:86
KUrl::url
QString url(AdjustPathOption trailing=LeaveTrailingSlash) const
Returns the URL as string, with all escape sequences intact, encoded in a given charset.
Definition: kurl.cpp:1034
KGlobal::staticQString
const QString & staticQString(const char *str)
Creates a static QString.
Definition: kglobal.cpp:270
KStandardDirs::findAllResources
QStringList findAllResources(const char *type, const QString &filter=QString(), SearchOptions options=NoSearchOptions) const
Tries to find all resources with the specified type.
Definition: kstandarddirs.cpp:894
KMimeTypeFactory::serviceOffersOffset
int serviceOffersOffset(const QString &mimeTypeName)
Returns the offset into the service offers for a given mimetype.
Definition: kmimetypefactory.cpp:55
KMimeType::findByFileContent
static Ptr findByFileContent(const QString &fileName, int *accuracy=0)
Tries to find out the MIME type of a file by looking for certain magic numbers and characteristic str...
Definition: kmimetype.cpp:375
KServiceType::comment
QString comment() const
Returns the descriptive comment associated, if any.
Definition: kservicetype.cpp:232
KUrl::isLocalFile
bool isLocalFile() const
Checks whether the file is local.
Definition: kurl.cpp:923
KMimeType::~KMimeType
virtual ~KMimeType()
Definition: kmimetype.cpp:454
QIODevice
KMimeTypePrivate
Definition: kmimetype_p.h:24
KMimeType::isBufferBinaryData
static bool isBufferBinaryData(const QByteArray &data)
Returns whether a buffer has an internal format that is not human readable.
Definition: kmimetype.cpp:74
KMimeTypeRepository::canonicalName
QString canonicalName(const QString &mime)
Resolve mime if it&#39;s an alias, and return it otherwise.
Definition: kmimetyperepository.cpp:89
KMimeType::KMimeType
KMimeType(QDataStream &str, int offset)
Definition: kmimetype.cpp:423
KSycocaEntry::name
QString name() const
Definition: ksycocaentry.cpp:157
kFatal
static QDebug kFatal(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
Definition: kdebug.h:198
KMimeType::patterns
QStringList patterns() const
Retrieve the list of patterns associated with the MIME Type.
Definition: kmimetype.cpp:608
KMimeType::parentMimeType
QString parentMimeType() const
If this mimetype is a subclass of another mimetype, return the name of the parent.
Definition: kmimetype.cpp:530
QMap
collectParentMimeTypes
static void collectParentMimeTypes(const QString &mime, QStringList &allParents)
Definition: kmimetype.cpp:569
kmimetypefactory.h
QList< Ptr >
KMimeType::is
bool is(const QString &mimeTypeName) const
Do not use name()==&quot;somename&quot; anymore, to check for a given mimetype.
Definition: kmimetype.cpp:554
KMimeTypePrivate::save
virtual void save(QDataStream &s)
Definition: kmimetype.cpp:428
KMimeType::isBinaryData
static bool isBinaryData(const QString &fileName)
Returns whether a file has an internal format that is not human readable.
Definition: kmimetype.cpp:397
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Jun 17 2014 17:06:50 by doxygen 1.8.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

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

kdelibs-4.10.5 API Reference

Skip menu "kdelibs-4.10.5 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
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