KDELibs4Support

kmimetype.cpp
1 /* This file is part of the KDE libraries
2  * Copyright (C) 1999 Waldo Bastian <[email protected]>
3  * 2000-2007 David Faure <[email protected]>
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 "kmimetyperepository_p.h"
23 #include "qmimedatabase.h"
24 
25 #include <kdebug.h>
26 #include <kde_file.h> // KDE::stat
27 #include <kdeversion.h> // KDE_MAKE_VERSION
28 #include <klocalizedstring.h>
29 #include <qstandardpaths.h>
30 #include <kurl.h>
31 #include <kio/global.h>
32 
33 #include <QFile>
34 
35 #ifdef Q_OS_WIN
36 #include <windows.h>
37 #endif
38 
39 #ifndef S_ISSOCK
40 #define S_ISSOCK(x) false
41 #endif
42 
43 extern int servicesDebugArea();
44 
46 
48 {
49  return KMimeTypeRepository::self()->defaultMimeTypePtr();
50 }
51 
53 {
54  return name() == defaultMimeType();
55 }
56 
57 KMimeType::Ptr KMimeType::mimeType(const QString &name, FindByNameOption options)
58 {
59  Q_UNUSED(options);
60  QMimeDatabase db;
61  QMimeType mime = db.mimeTypeForName(name);
62  if (mime.isValid()) {
63  return KMimeType::Ptr(new KMimeType(mime));
64  } else {
65  return KMimeType::Ptr();
66  }
67 }
68 
70 {
71  // This could be done faster...
72  KMimeType::List lst;
73  QMimeDatabase db;
74  Q_FOREACH (const QMimeType &mimeType, db.allMimeTypes()) {
75  Q_ASSERT(!mimeType.name().startsWith(QLatin1String("x-scheme-handler")));
76  lst.append(KMimeType::Ptr(new KMimeType(mimeType)));
77  }
78  return lst;
79 }
80 
81 // TODO used outside of kmimetype?
83 {
84  // Check the first 32 bytes (see shared-mime spec)
85  const char *p = data.data();
86  const int end = qMin(32, data.size());
87  for (int i = 0; i < end; ++i) {
88  if ((unsigned char)(p[i]) < 32 && p[i] != 9 && p[i] != 10 && p[i] != 13) { // ASCII control character
89  return true;
90  }
91  }
92  return false;
93 }
94 
95 // the windows-specific code, and the locked directory, are missing from QMimeDatabase.
96 static KMimeType::Ptr findFromMode(const QString &path /*only used if is_local_file*/,
97  mode_t mode /*0 if unknown*/,
98  bool is_local_file)
99 {
100  if (is_local_file && (mode == 0 || mode == (mode_t) - 1)) {
101  KDE_struct_stat buff;
102  if (KDE::stat(path, &buff) != -1) {
103  mode = buff.st_mode;
104  }
105  }
106 
107  if (S_ISDIR(mode)) {
108  // KDE4 TODO: use an overlay instead
109 #if 0
110  // Special hack for local files. We want to see whether we
111  // are allowed to enter the directory
112  if (is_local_file) {
113  if (KDE::access(path, R_OK) == -1) {
114  return KMimeType::mimeType("inode/directory-locked");
115  }
116  }
117 #endif
118  return KMimeType::mimeType(QLatin1String("inode/directory"));
119  }
120  if (S_ISCHR(mode)) {
121  return KMimeType::mimeType(QLatin1String("inode/chardevice"));
122  }
123  if (S_ISBLK(mode)) {
124  return KMimeType::mimeType(QLatin1String("inode/blockdevice"));
125  }
126  if (S_ISFIFO(mode)) {
127  return KMimeType::mimeType(QLatin1String("inode/fifo"));
128  }
129  if (S_ISSOCK(mode)) {
130  return KMimeType::mimeType(QLatin1String("inode/socket"));
131  }
132 #ifdef Q_OS_WIN
133  // FIXME: distinguish between mounted & unmounted
134  int size = path.size();
135  if (size == 2 || size == 3) {
136  //GetDriveTypeW is not defined in wince
137 #ifndef _WIN32_WCE
138  unsigned int type = GetDriveTypeW((LPCWSTR) path.utf16());
139  switch (type) {
140  case DRIVE_REMOVABLE:
141  return KMimeType::mimeType(QLatin1String("media/floppy_mounted"));
142  case DRIVE_FIXED:
143  return KMimeType::mimeType(QLatin1String("media/hdd_mounted"));
144  case DRIVE_REMOTE:
145  return KMimeType::mimeType(QLatin1String("media/smb_mounted"));
146  case DRIVE_CDROM:
147  return KMimeType::mimeType(QLatin1String("media/cdrom_mounted"));
148  case DRIVE_RAMDISK:
149  return KMimeType::mimeType(QLatin1String("media/hdd_mounted"));
150  default:
151  break;
152  };
153 #else
154  return KMimeType::mimeType(QLatin1String("media/hdd_mounted"));
155 #endif
156  }
157 #endif
158  // remote executable file? stop here (otherwise findFromContent can do that better for local files)
159  if (!is_local_file && S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
160  return KMimeType::mimeType(QLatin1String("application/x-executable"));
161  }
162 
163  return KMimeType::Ptr();
164 }
165 
166 /*
167  Note: in KDE we want the file views to sniff in a delayed manner.
168  So there's also a fast mode which is:
169  if no glob matches, or if more than one glob matches, use default mimetype and mark as "can be refined".
170 */
171 
172 KMimeType::Ptr KMimeType::findByUrl(const QUrl &url, mode_t mode,
173  bool is_local_file, bool fast_mode,
174  int *accuracy)
175 {
176  Q_UNUSED(mode); // special devices only matter locally; caller can use S_ISDIR by itself.
177  Q_UNUSED(is_local_file); // QUrl can tell us...
178  QMimeDatabase db;
179  if (accuracy) {
180  *accuracy = 80; // not supported anymore; was it really used for anything?
181  }
182  if (fast_mode) {
183  return KMimeType::Ptr(new KMimeType(db.mimeTypeForFile(url.path(), QMimeDatabase::MatchExtension)));
184  }
185  return KMimeType::Ptr(new KMimeType(db.mimeTypeForUrl(url)));
186 }
187 
188 KMimeType::Ptr KMimeType::findByPath(const QString &path, mode_t mode,
189  bool fast_mode, int *accuracy)
190 {
191  Q_UNUSED(mode); // special devices only matter locally; caller can use S_ISDIR by itself.
192  QMimeDatabase db;
193  if (accuracy) {
194  *accuracy = 80; // not supported anymore; was it really used for anything?
195  }
196  if (fast_mode) {
197  return KMimeType::Ptr(new KMimeType(db.mimeTypeForFile(path, QMimeDatabase::MatchExtension)));
198  }
199  return KMimeType::Ptr(new KMimeType(db.mimeTypeForFile(path)));
200 }
201 
202 KMimeType::Ptr KMimeType::findByNameAndContent(const QString &name, const QByteArray &data,
203  mode_t mode, int *accuracy)
204 {
205  Q_UNUSED(mode); // If we have data, then this is a regular file anyway...
206  if (accuracy) {
207  *accuracy = 80; // not supported anymore; was it really used for anything?
208  }
209  QMimeDatabase db;
210  return KMimeType::Ptr(new KMimeType(db.mimeTypeForFileNameAndData(name, data)));
211 }
212 
213 KMimeType::Ptr KMimeType::findByNameAndContent(const QString &name, QIODevice *device,
214  mode_t mode, int *accuracy)
215 {
216  Q_UNUSED(mode); // If we have data, then this is a regular file anyway...
217  if (accuracy) {
218  *accuracy = 80; // not supported anymore; was it really used for anything?
219  }
220  QMimeDatabase db;
221  return KMimeType::Ptr(new KMimeType(db.mimeTypeForFileNameAndData(name, device)));
222 }
223 
225 {
226  QMimeDatabase db;
227  return db.suffixForFileName(fileName);
228 }
229 
230 KMimeType::Ptr KMimeType::findByContent(const QByteArray &data, int *accuracy)
231 {
232  QMimeDatabase db;
233  if (accuracy) {
234  *accuracy = 80; // not supported anymore; was it really used for anything?
235  }
236  return KMimeType::Ptr(new KMimeType(db.mimeTypeForData(data)));
237 }
238 
239 KMimeType::Ptr KMimeType::findByContent(QIODevice *device, int *accuracy)
240 {
241  QMimeDatabase db;
242  if (accuracy) {
243  *accuracy = 80; // not supported anymore; was it really used for anything?
244  }
245  return KMimeType::Ptr(new KMimeType(db.mimeTypeForData(device)));
246 }
247 
248 KMimeType::Ptr KMimeType::findByFileContent(const QString &fileName, int *accuracy)
249 {
250  QFile device(fileName);
251 #if 1
252  // Look at mode first
253  KMimeType::Ptr mimeFromMode = findFromMode(fileName, 0, true);
254  if (mimeFromMode) {
255  if (accuracy) {
256  *accuracy = 100;
257  }
258  return mimeFromMode;
259  }
260 #endif
261  QMimeDatabase db;
262  KMimeType::Ptr mime(new KMimeType(db.mimeTypeForData(&device)));
263  if (accuracy) {
264  *accuracy = mime->isDefault() ? 0 : 80; // not supported anymore; was it really used for anything?
265  }
266  return mime;
267 }
268 
269 bool KMimeType::isBinaryData(const QString &fileName)
270 {
271  QFile file(fileName);
272  if (!file.open(QIODevice::ReadOnly)) {
273  return false; // err, whatever
274  }
275  const QByteArray data = file.read(32);
276  return isBufferBinaryData(data);
277 }
278 
280  : d_ptr(new KMimeTypePrivate(mime))
281 {
282 }
283 
284 KMimeType::~KMimeType()
285 {
286  delete d_ptr;
287 }
288 
290 {
291  return KIO::favIconForUrl(url);
292 }
293 
294 QString KMimeType::iconNameForUrl(const QUrl &url, mode_t mode)
295 {
296  Q_UNUSED(mode)
297  return KIO::iconNameForUrl(url);
298 }
299 
301 {
302  return d_ptr->m_qmime.comment();
303 }
304 
305 #ifndef KDELIBS4SUPPORT_NO_DEPRECATED
307 {
308  const QStringList parents = d_ptr->m_qmime.parentMimeTypes();
309  if (!parents.isEmpty()) {
310  return parents.first();
311  }
312  return QString();
313 }
314 #endif
315 
316 bool KMimeType::is(const QString &mimeTypeName) const
317 {
318  return d_ptr->m_qmime.inherits(mimeTypeName);
319 }
320 
322 {
323  return d_ptr->m_qmime.parentMimeTypes();
324 }
325 
327 {
328  return d_ptr->m_qmime.allAncestors();
329 }
330 
332 {
333  return QLatin1String("application/octet-stream");
334 }
335 
337 {
338  return d_ptr->m_qmime.iconName();
339 }
340 
342 {
343  return d_ptr->m_qmime.globPatterns();
344 }
345 
346 // TODO MOVE TO keditfiletype/mimetypedata.cpp
348 {
349  //d->ensureXmlDataLoaded();
350  //return d->m_iconName;
351  return QString();
352 }
353 
355 {
356  return KMimeTypeRepository::self()->sharedMimeInfoVersion();
357 }
358 
360 {
361 #if 1 // HACK START - can be removed once shared-mime-info >= 0.70 is used/required.
362  // The idea was: first usable pattern from m_lstPatterns.
363  // But update-mime-database makes a mess of the order of the patterns,
364  // because it uses a hash internally.
365  static const struct {
366  const char *mime;
367  const char *extension;
368  } s_hardcodedMimes[] = {
369  { "text/plain", ".txt" }
370  };
371  if (patterns().count() > 1) {
372  const QByteArray me = name().toLatin1();
373  for (uint i = 0; i < sizeof(s_hardcodedMimes) / sizeof(*s_hardcodedMimes); ++i) {
374  if (me == s_hardcodedMimes[i].mime) {
375  return QString::fromLatin1(s_hardcodedMimes[i].extension);
376  }
377  }
378  }
379 #endif // HACK END
380 
381  Q_FOREACH (const QString &pattern, patterns()) {
382  // Skip if if looks like: README or *. or *.*
383  // or *.JP*G or *.JP?
384  if (pattern.startsWith(QLatin1String("*.")) &&
385  pattern.length() > 2 &&
386  pattern.indexOf(QLatin1Char('*'), 2) < 0 && pattern.indexOf(QLatin1Char('?'), 2) < 0) {
387  return pattern.mid(1);
388  }
389  }
390  // TODO we should also look into the parent mimetype's patterns, no?
391  return QString();
392 }
393 
394 bool KMimeType::matchFileName(const QString &filename, const QString &pattern)
395 {
396  return KMimeTypeRepository::matchFileName(filename, pattern);
397 }
398 
399 /*
400 int KMimeTypePrivate::serviceOffersOffset() const
401 {
402  return KMimeTypeFactory::self()->serviceOffersOffset(name());
403 }
404 */
405 
407 {
408  return d_ptr->m_qmime.name();
409 }
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QString suffixForFileName(const QString &fileName) const const
static Ptr findByNameAndContent(const QString &name, const QByteArray &data, mode_t mode=0, int *accuracy=nullptr)
Tries to find out the MIME type of filename/url and a data chunk.
Definition: kmimetype.cpp:202
static bool matchFileName(const QString &filename, const QString &pattern)
Returns true if the given filename matches the given pattern.
Definition: kmimetype.cpp:394
This file provides portable defines for file support.
KMimeType(const QMimeType &mime)
Construct a KMimeType from a QMimeType.
Definition: kmimetype.cpp:279
QString userSpecifiedIconName() const
Returns the user-specified icon for this mimetype.
Definition: kmimetype.cpp:347
int size() const const
int stat(const QString &path, KDE_struct_stat *buf)
replacement for stat()/::stat64() to handle filenames in a platform independent way ...
Definition: kde_file.h:207
static int sharedMimeInfoVersion()
Returns the version of the installed update-mime-database program (from freedesktop.org shared-mime-info).
Definition: kmimetype.cpp:354
static QString extractKnownExtension(const QString &fileName)
Determines the extension from a filename (or full path) using the mimetype database.
Definition: kmimetype.cpp:224
QString iconName() const
Return the filename of the icon associated with the mimetype.
Definition: kmimetype.cpp:336
The file contains macros and functions related to the KDE version.
static KMimeType::Ptr defaultMimeTypePtr()
Returns the default mimetype.
Definition: kmimetype.cpp:47
QStringList parentMimeTypes() const
If this mimetype is a subclass of one or more other mimetypes, return the list of those mimetypes...
Definition: kmimetype.cpp:321
QString comment() const
Returns the descriptive comment associated with the MIME type.
Definition: kmimetype.cpp:300
QMimeType mimeTypeForFile(const QString &fileName, QMimeDatabase::MatchMode mode) const const
void append(const T &value)
PartitionTable::TableType type
QMimeType mimeTypeForUrl(const QUrl &url) const const
static QString iconNameForUrl(const QUrl &url, mode_t mode=0)
Return the filename of the icon associated with the mimetype, for a given url.
Definition: kmimetype.cpp:294
bool isEmpty() const const
static Ptr findByUrl(const QUrl &url, mode_t mode=0, bool is_local_file=false, bool fast_mode=false, int *accuracy=nullptr)
Finds a KMimeType with the given url.
Definition: kmimetype.cpp:172
QMimeType mimeTypeForData(const QByteArray &data) const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
QString mainExtension() const
Return the primary extension associated with this mimetype, if any.
Definition: kmimetype.cpp:359
QList< QMimeType > allMimeTypes() const const
QString path(QUrl::ComponentFormattingOptions options) const const
qint64 read(char *data, qint64 maxSize)
T & first()
QMimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device) const const
virtual bool open(QIODevice::OpenMode mode) override
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
bool isDefault() const
Return true if this mimetype is the default mimetype.
Definition: kmimetype.cpp:52
static Ptr findByContent(const QByteArray &data, int *accuracy=nullptr)
Tries to find out the MIME type of a data chunk by looking for certain magic numbers and characterist...
Definition: kmimetype.cpp:230
bool isValid() const const
QString name() const
Definition: kmimetype.cpp:406
QByteArray toLatin1() const const
const ushort * utf16() const const
QString mid(int position, int n) const const
QStringList allParentMimeTypes() const
Return all parent mimetypes of this mimetype, direct or indirect.
Definition: kmimetype.cpp:326
static List allMimeTypes()
Get all the mimetypes.
Definition: kmimetype.cpp:69
int access(const QString &path, int mode)
replacement for access() to handle filenames in a platform independent way
Definition: kde_file.h:179
static QString defaultMimeType()
Returns the name of the default mimetype.
Definition: kmimetype.cpp:331
static QString favIconForUrl(const QUrl &url)
Return the "favicon" (see http://www.favicon.com) for the given url, if available.
Definition: kmimetype.cpp:289
int length() const const
char * data()
QString fromLatin1(const char *str, int size)
static Ptr mimeType(const QString &name, FindByNameOption options=ResolveAliases)
Retrieve a pointer to the mime type name.
Definition: kmimetype.cpp:57
static Ptr findByFileContent(const QString &fileName, int *accuracy=nullptr)
Tries to find out the MIME type of a file by looking for certain magic numbers and characteristic str...
Definition: kmimetype.cpp:248
int size() const const
static bool isBufferBinaryData(const QByteArray &data)
Returns whether a buffer has an internal format that is not human readable.
Definition: kmimetype.cpp:82
QStringList patterns() const
Retrieve the list of patterns associated with the MIME Type.
Definition: kmimetype.cpp:341
QString parentMimeType() const
If this mimetype is a subclass of another mimetype, return the name of the parent.
Definition: kmimetype.cpp:306
static Ptr findByPath(const QString &path, mode_t mode=0, bool fast_mode=false, int *accuracy=nullptr)
Finds a KMimeType with the given url.
Definition: kmimetype.cpp:188
bool is(const QString &mimeTypeName) const
Do not use name()=="somename" anymore, to check for a given mimetype.
Definition: kmimetype.cpp:316
static bool isBinaryData(const QString &fileName)
Returns whether a file has an internal format that is not human readable.
Definition: kmimetype.cpp:269
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Dec 7 2021 22:51:20 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.