• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.8 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 patterns();
440  if ( _name == QLatin1String("Comment") )
441  return comment();
442  if ( _name == QLatin1String("Icon") )
443  return QVariant( iconName(KUrl()) );
444 
445  return KServiceTypePrivate::property( _name );
446 }
447 
448 QStringList KMimeTypePrivate::propertyNames() const
449 {
450  QStringList res = KServiceTypePrivate::propertyNames();
451  res.append( QString::fromLatin1("Patterns") );
452  res.append( QString::fromLatin1("Icon") );
453  return res;
454 }
455 
456 KMimeType::~KMimeType()
457 {
458 }
459 
460 QString KMimeType::iconNameForUrl( const KUrl & _url, mode_t mode )
461 {
462  const KMimeType::Ptr mt = findByUrl( _url, mode, _url.isLocalFile(),
463  false /*HACK*/);
464  if (!mt) {
465  return QString();
466  }
467  static const QString& unknown = KGlobal::staticQString("unknown");
468  const QString mimeTypeIcon = mt->iconName( _url );
469  QString i = mimeTypeIcon;
470 
471  // if we don't find an icon, maybe we can use the one for the protocol
472  if ( i == unknown || i.isEmpty() || mt->name() == defaultMimeType()
473  // and for the root of the protocol (e.g. trash:/) the protocol icon has priority over the mimetype icon
474  || _url.path().length() <= 1 )
475  {
476  i = favIconForUrl( _url ); // maybe there is a favicon?
477 
478  if ( i.isEmpty() )
479  i = KProtocolInfo::icon( _url.protocol() );
480 
481  // root of protocol: if we found nothing, revert to mimeTypeIcon (which is usually "folder")
482  if ( _url.path().length() <= 1 && ( i == unknown || i.isEmpty() ) )
483  i = mimeTypeIcon;
484  }
485  return !i.isEmpty() ? i : unknown;
486 }
487 
488 QString KMimeType::favIconForUrl( const KUrl& url )
489 {
490  /* The kded module also caches favicons, for one week, without any way
491  * to clean up the cache meanwhile.
492  * On the other hand, this QHash will get cleaned up after 5000 request
493  * (a selection in konsole of 80 chars generates around 500 requests)
494  * or by simply restarting the application (or the whole desktop,
495  * more likely, for the case of konqueror or konsole).
496  */
497  static QHash<QUrl, QString> iconNameCache;
498  static int autoClearCache = 0;
499  const QString notFound = QLatin1String("NOTFOUND");
500 
501  if (url.isLocalFile()
502  || !url.protocol().startsWith(QLatin1String("http"))
503  || !KMimeTypeRepository::self()->useFavIcons())
504  return QString();
505 
506  QString iconNameFromCache = iconNameCache.value(url, notFound);
507  if ( iconNameFromCache != notFound ) {
508  if ( (++autoClearCache) < 5000 ) {
509  return iconNameFromCache;
510  }
511  else {
512  iconNameCache.clear();
513  autoClearCache = 0;
514  }
515  }
516 
517  QDBusInterface kded( QString::fromLatin1("org.kde.kded"),
518  QString::fromLatin1("/modules/favicons"),
519  QString::fromLatin1("org.kde.FavIcon") );
520  QDBusReply<QString> result = kded.call( QString::fromLatin1("iconForUrl"), url.url() );
521  iconNameCache.insert(url, result.value());
522  return result; // default is QString()
523 }
524 
525 QString KMimeType::comment( const KUrl &url) const
526 {
527  Q_D(const KMimeType);
528  return d->comment(url);
529 }
530 
531 #ifndef KDE_NO_DEPRECATED
532 QString KMimeType::parentMimeType() const
533 {
534  const QStringList parents = parentMimeTypes();
535  if (!parents.isEmpty())
536  return parents.first();
537  return QString();
538 }
539 #endif
540 
541 bool KMimeTypePrivate::inherits(const QString& mime) const
542 {
543  QStack<QString> toCheck;
544  toCheck.push(m_strName);
545  while (!toCheck.isEmpty()) {
546  const QString current = toCheck.pop();
547  if (current == mime)
548  return true;
549  Q_FOREACH(const QString& parent, KMimeTypeRepository::self()->parents(current)) {
550  toCheck.push(parent);
551  }
552  }
553  return false;
554 }
555 
556 bool KMimeType::is( const QString& mimeTypeName ) const
557 {
558  Q_D(const KMimeType);
559  if (name() == mimeTypeName)
560  return true;
561  const QString mime = KMimeTypeRepository::self()->canonicalName(mimeTypeName);
562  return d->inherits(mime);
563 }
564 
565 QStringList KMimeType::parentMimeTypes() const
566 {
567  Q_D(const KMimeType);
568  return KMimeTypeRepository::self()->parents(d->m_strName);
569 }
570 
571 static void collectParentMimeTypes(const QString& mime, QStringList& allParents)
572 {
573  QStringList parents = KMimeTypeRepository::self()->parents(mime);
574  Q_FOREACH(const QString& parent, parents) {
575  // I would use QSet, but since order matters I better not
576  if (!allParents.contains(parent))
577  allParents.append(parent);
578  }
579  // We want a breadth-first search, so that the least-specific parent (octet-stream) is last
580  // This means iterating twice, unfortunately.
581  Q_FOREACH(const QString& parent, parents) {
582  collectParentMimeTypes(parent, allParents);
583  }
584 }
585 
586 QStringList KMimeType::allParentMimeTypes() const
587 {
588  Q_D(const KMimeType);
589  QStringList allParents;
590  const QString canonical = KMimeTypeRepository::self()->resolveAlias(name());
591  if (!canonical.isEmpty())
592  allParents.append(canonical);
593  collectParentMimeTypes(d->m_strName, allParents);
594  return allParents;
595 }
596 
597 QString KMimeType::defaultMimeType()
598 {
599  static const QString & s_strDefaultMimeType =
600  KGlobal::staticQString( "application/octet-stream" );
601  return s_strDefaultMimeType;
602 }
603 
604 QString KMimeType::iconName( const KUrl& url) const
605 {
606  Q_D(const KMimeType);
607  return d->iconName(url);
608 }
609 
610 QStringList KMimeType::patterns() const
611 {
612  Q_D(const KMimeType);
613  return d->patterns();
614 }
615 
616 // loads comment, icon, mainPattern, m_lstPatterns
617 void KMimeTypePrivate::ensureXmlDataLoaded() const
618 {
619  if (m_xmlDataLoaded)
620  return;
621 
622  m_xmlDataLoaded = true;
623 
624  const QString file = m_strName + QLatin1String(".xml");
625  const QStringList mimeFiles = KGlobal::dirs()->findAllResources("xdgdata-mime", file);
626  if (mimeFiles.isEmpty()) {
627  kWarning() << "No file found for" << file << ", even though the file appeared in a directory listing.";
628  kWarning() << "Either it was just removed, or the directory doesn't have executable permission...";
629  kWarning() << KGlobal::dirs()->resourceDirs("xdgdata-mime");
630  return;
631  }
632 
633  QString comment;
634  QString mainPattern;
635  const QStringList languageList = KGlobal::locale()->languageList();
636  QString preferredLanguage = languageList.first();
637  QMap<QString, QString> commentsByLanguage;
638 
639  QListIterator<QString> mimeFilesIter(mimeFiles);
640  mimeFilesIter.toBack();
641  while (mimeFilesIter.hasPrevious()) { // global first, then local.
642  const QString fullPath = mimeFilesIter.previous();
643  QFile qfile(fullPath);
644  if (!qfile.open(QFile::ReadOnly))
645  continue;
646 
647  QXmlStreamReader xml(&qfile);
648  if (xml.readNextStartElement()) {
649  if (xml.name() != "mime-type") {
650  continue;
651  }
652  const QString name = xml.attributes().value(QLatin1String("type")).toString();
653  if (name.isEmpty())
654  continue;
655  if (name != m_strName) {
656  kWarning() << "Got name" << name << "in file" << file << "expected" << m_strName;
657  }
658 
659  while (xml.readNextStartElement()) {
660  const QStringRef tag = xml.name();
661  if (tag == "comment") {
662  QString lang = xml.attributes().value(QLatin1String("xml:lang")).toString();
663  const QString text = xml.readElementText();
664  if (lang.isEmpty()) {
665  lang = QLatin1String("en_US");
666  }
667  if (lang == preferredLanguage) {
668  comment = text;
669  } else {
670  commentsByLanguage.insert(lang, text);
671  }
672  continue; // we called readElementText, so we're at the EndElement already.
673  } else if (tag == "icon") { // as written out by shared-mime-info >= 0.40
674  m_iconName = xml.attributes().value(QLatin1String("name")).toString();
675  } else if (tag == "glob-deleteall") { // as written out by shared-mime-info >= 0.70
676  mainPattern.clear();
677  m_lstPatterns.clear();
678  } else if (tag == "glob") { // as written out by shared-mime-info >= 0.70
679  const QString pattern = xml.attributes().value(QLatin1String("pattern")).toString();
680  if (mainPattern.isEmpty() && pattern.startsWith(QLatin1Char('*'))) {
681  mainPattern = pattern;
682  }
683  if (!m_lstPatterns.contains(pattern))
684  m_lstPatterns.append(pattern);
685  }
686  xml.skipCurrentElement();
687  }
688  if (xml.name() != "mime-type") {
689  kFatal() << "Programming error in KMimeType XML loading, please create a bug report on http://bugs.kde.org and attach the file" << fullPath;
690  }
691  }
692  }
693 
694  if (comment.isEmpty()) {
695  Q_FOREACH(const QString& lang, languageList) {
696  const QString comm = commentsByLanguage.value(lang);
697  if (!comm.isEmpty()) {
698  comment = comm;
699  break;
700  }
701  const int pos = lang.indexOf(QLatin1Char('_'));
702  if (pos != -1) {
703  // "pt_BR" not found? try just "pt"
704  const QString shortLang = lang.left(pos);
705  const QString comm = commentsByLanguage.value(shortLang);
706  if (!comm.isEmpty()) {
707  comment = comm;
708  break;
709  }
710  }
711  }
712  if (comment.isEmpty()) {
713  kWarning() << "Missing <comment> field in" << file;
714  }
715  }
716  m_strComment = comment;
717 
718  const bool globsInXml = (KMimeType::sharedMimeInfoVersion() >= KDE_MAKE_VERSION(0, 70, 0));
719  if (globsInXml) {
720  if (!mainPattern.isEmpty() && m_lstPatterns.first() != mainPattern) {
721  // ensure it's first in the list of patterns
722  m_lstPatterns.removeAll(mainPattern);
723  m_lstPatterns.prepend(mainPattern);
724  }
725  } else {
726  // Fallback: get the patterns from the globs file
727  m_lstPatterns = KMimeTypeRepository::self()->patternsForMimetype(m_strName);
728  }
729 }
730 
731 QString KMimeType::userSpecifiedIconName() const
732 {
733  Q_D(const KMimeType);
734  d->ensureXmlDataLoaded();
735  return d->m_iconName;
736 }
737 
738 int KMimeType::sharedMimeInfoVersion()
739 {
740  return KMimeTypeRepository::self()->sharedMimeInfoVersion();
741 }
742 
743 QString KMimeType::mainExtension() const
744 {
745  Q_D(const KMimeType);
746 
747 #if 1 // HACK START - can be removed once shared-mime-info >= 0.70 is used/required.
748  // The idea was: first usable pattern from m_lstPatterns.
749  // But update-mime-database makes a mess of the order of the patterns,
750  // because it uses a hash internally.
751  static const struct { const char* mime; const char* extension; } s_hardcodedMimes[] = {
752  { "text/plain", ".txt" } };
753  if (d->m_lstPatterns.count() > 1) {
754  const QByteArray me = name().toLatin1();
755  for (uint i = 0; i < sizeof(s_hardcodedMimes)/sizeof(*s_hardcodedMimes); ++i) {
756  if (me == s_hardcodedMimes[i].mime)
757  return QString::fromLatin1(s_hardcodedMimes[i].extension);
758  }
759  }
760 #endif // HACK END
761 
762  Q_FOREACH(const QString& pattern, patterns()) {
763  // Skip if if looks like: README or *. or *.*
764  // or *.JP*G or *.JP?
765  if (pattern.startsWith(QLatin1String("*.")) &&
766  pattern.length() > 2 &&
767  pattern.indexOf(QLatin1Char('*'), 2) < 0 && pattern.indexOf(QLatin1Char('?'), 2) < 0) {
768  return pattern.mid(1);
769  }
770  }
771  // TODO we should also look into the parent mimetype's patterns, no?
772  return QString();
773 }
774 
775 bool KMimeType::matchFileName( const QString &filename, const QString &pattern )
776 {
777  return KMimeTypeRepository::matchFileName( filename, pattern );
778 }
779 
780 int KMimeTypePrivate::serviceOffersOffset() const
781 {
782  return KMimeTypeFactory::self()->serviceOffersOffset(name());
783 }
784 
785 QString KMimeTypePrivate::iconName(const KUrl &) const
786 {
787  static QHash<QUrl, QString> iconNameCache;
788  QString iconNameFromCache = iconNameCache.value(m_strName);
789  if (!iconNameFromCache.isEmpty())
790  return iconNameFromCache;
791 
792  ensureXmlDataLoaded();
793  QString result;
794  if (!m_iconName.isEmpty()) {
795  result = m_iconName;
796  } else {
797  // Make default icon name from the mimetype name
798  // Don't store this in m_iconName, it would make the filetype editor
799  // write out icon names in every local mimetype definition file.
800  QString icon = m_strName;
801  const int slashindex = icon.indexOf(QLatin1Char('/'));
802  if (slashindex != -1) {
803  icon[slashindex] = QLatin1Char('-');
804  }
805  result = icon;
806  }
807  iconNameCache.insert(m_strName, result);
808  return result;
809 }
KMimeType::Ptr
KSharedPtr< KMimeType > Ptr
Definition: kmimetype.h:50
QVariant
KMimeTypeRepository::defaultMimeTypePtr
KMimeType::Ptr defaultMimeTypePtr()
Definition: kmimetyperepository.cpp:662
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:604
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:460
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:599
KMimeTypeRepository::findMimeTypeByName
KMimeType::Ptr findMimeTypeByName(const QString &_name, KMimeType::FindByNameOption options=KMimeType::DontResolveAlias)
Creates a KMimeType.
Definition: kmimetyperepository.cpp:59
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:488
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:775
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:63
KMimeType::userSpecifiedIconName
QString userSpecifiedIconName() const
Returns the user-specified icon for this mimetype.
Definition: kmimetype.cpp:731
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:785
kmimetyperepository_p.h
KUrl::toLocalFile
QString toLocalFile(AdjustPathOption trailing=LeaveTrailingSlash) const
Definition: kurl.cpp:885
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:35
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:738
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:98
KMimeTypePrivate::serviceOffersOffset
virtual int serviceOffersOffset() const
Definition: kmimetype.cpp:780
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:565
KMimeTypePrivate::m_iconName
QString m_iconName
Definition: kmimetype_p.h:62
KUrl::setPath
void setPath(const QString &path)
Definition: kurl.cpp:1772
kmimetype_p.h
KMimeTypeRepository::parents
QStringList parents(const QString &mime)
Returns the list of parents for a given mimetype.
Definition: kmimetyperepository.cpp:294
KProtocolInfoFactory::self
static KProtocolInfoFactory * self()
The instance of the KProtocolInfoFactory.
Definition: kprotocolinfofactory.cpp:119
KMimeTypePrivate::m_lstPatterns
QStringList m_lstPatterns
Definition: kmimetype_p.h:61
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:681
KUrl::protocol
QString protocol() const
Returns the protocol for the URL (i.e., file, http, etc.), lowercased.
Definition: kurl.cpp:672
QStringList
KMimeTypePrivate::inherits
bool inherits(const QString &mime) const
Definition: kmimetype.cpp:541
KMimeTypePrivate::ensureXmlDataLoaded
void ensureXmlDataLoaded() const
Definition: kmimetype.cpp:617
KMimeType::mainExtension
QString mainExtension() const
Return the primary extension associated with this mimetype, if any.
Definition: kmimetype.cpp:743
KServiceTypePrivate::name
virtual QString name() const
Definition: kservicetype_p.h:49
KUrl::path
QString path(AdjustPathOption trailing=LeaveTrailingSlash) const
Definition: kurl.cpp:873
KProtocolInfoFactory::findProtocol
KProtocolInfo::Ptr findProtocol(const QString &protocol)
Definition: kprotocolinfofactory.cpp:91
KMimeTypeRepository::sharedMimeInfoVersion
int sharedMimeInfoVersion()
Definition: kmimetyperepository.cpp:783
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:85
KMimeTypePrivate::comment
virtual QString comment(const KUrl &=KUrl()) const
Definition: kmimetype_p.h:42
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:1069
KGlobal::locale
KLocale * locale()
Returns the global locale object.
Definition: kglobal.cpp:170
KMimeTypePrivate::patterns
QStringList patterns() const
Definition: kmimetype_p.h:48
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:586
KMimeTypePrivate::propertyNames
virtual QStringList propertyNames() const
Definition: kmimetype.cpp:448
KUrl::fileName
QString fileName(const DirectoryOptions &options=IgnoreTrailingSlash) const
Returns the filename of the path.
Definition: kurl.cpp:1283
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:597
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:616
KUrl::hasSubUrl
bool hasSubUrl() const
Checks whether the URL has any sub URLs.
Definition: kurl.cpp:1030
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:1035
KGlobal::staticQString
const QString & staticQString(const char *str)
Creates a static QString.
Definition: kglobal.cpp:271
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:900
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:924
KMimeType::~KMimeType
virtual ~KMimeType()
Definition: kmimetype.cpp:456
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:90
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:610
KMimeType::parentMimeType
QString parentMimeType() const
If this mimetype is a subclass of another mimetype, return the name of the parent.
Definition: kmimetype.cpp:532
QMap
collectParentMimeTypes
static void collectParentMimeTypes(const QString &mime, QStringList &allParents)
Definition: kmimetype.cpp:571
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:556
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-2020 The KDE developers.
Generated on Sun Oct 4 2020 07:14:36 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.14.8 API Reference

Skip menu "kdelibs-4.14.8 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