summaryrefslogtreecommitdiffstats
path: root/src/corelib/mimetypes
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/mimetypes')
-rw-r--r--src/corelib/mimetypes/qmimedatabase.cpp27
-rw-r--r--src/corelib/mimetypes/qmimedatabase_p.h2
-rw-r--r--src/corelib/mimetypes/qmimeglobpattern.cpp50
-rw-r--r--src/corelib/mimetypes/qmimeglobpattern_p.h5
-rw-r--r--src/corelib/mimetypes/qmimemagicrule.cpp16
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp15
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h7
7 files changed, 68 insertions, 54 deletions
diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp
index 448e6117b1..fda9f01643 100644
--- a/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/src/corelib/mimetypes/qmimedatabase.cpp
@@ -108,12 +108,12 @@ QMimeType QMimeDatabasePrivate::mimeTypeForName(const QString &nameOrAlias)
return provider()->mimeTypeForName(provider()->resolveAlias(nameOrAlias));
}
-QStringList QMimeDatabasePrivate::mimeTypeForFileName(const QString &fileName, QString *foundSuffix)
+QStringList QMimeDatabasePrivate::mimeTypeForFileName(const QString &fileName)
{
if (fileName.endsWith(QLatin1Char('/')))
return QStringList() << QLatin1String("inode/directory");
- QStringList matchingMimeTypes = provider()->findByFileName(QFileInfo(fileName).fileName(), foundSuffix);
+ QStringList matchingMimeTypes = provider()->findByFileName(QFileInfo(fileName).fileName()).m_matchingMimeTypes;
matchingMimeTypes.sort(); // make it deterministic
return matchingMimeTypes;
}
@@ -168,13 +168,17 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa
*accuracyPtr = 0;
// Pass 1) Try to match on the file name
- QStringList candidatesByName = mimeTypeForFileName(fileName);
- if (candidatesByName.count() == 1) {
+ QMimeGlobMatchResult candidatesByName;
+ if (fileName.endsWith(QLatin1Char('/')))
+ candidatesByName.addMatch(QLatin1String("inode/directory"), 100, QString());
+ else
+ candidatesByName = provider()->findByFileName(QFileInfo(fileName).fileName());
+ if (candidatesByName.m_allMatchingMimeTypes.count() == 1) {
*accuracyPtr = 100;
- const QMimeType mime = mimeTypeForName(candidatesByName.at(0));
+ const QMimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0));
if (mime.isValid())
return mime;
- candidatesByName.clear();
+ candidatesByName = {};
}
// Extension is unknown, or matches multiple mimetypes.
@@ -193,7 +197,7 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa
// "for glob_match in glob_matches:"
// "if glob_match is subclass or equal to sniffed_type, use glob_match"
const QString sniffedMime = candidateByData.name();
- for (const QString &m : qAsConst(candidatesByName)) {
+ for (const QString &m : qAsConst(candidatesByName.m_matchingMimeTypes)) {
if (inherits(m, sniffedMime)) {
// We have magic + pattern pointing to this, so it's a pretty good match
*accuracyPtr = 100;
@@ -205,9 +209,10 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa
}
}
- if (candidatesByName.count() > 1) {
+ if (candidatesByName.m_allMatchingMimeTypes.count() > 1) {
+ candidatesByName.m_matchingMimeTypes.sort(); // make it deterministic
*accuracyPtr = 20;
- const QMimeType mime = mimeTypeForName(candidatesByName.at(0));
+ const QMimeType mime = mimeTypeForName(candidatesByName.m_matchingMimeTypes.at(0));
if (mime.isValid())
return mime;
}
@@ -455,9 +460,7 @@ QList<QMimeType> QMimeDatabase::mimeTypesForFileName(const QString &fileName) co
QString QMimeDatabase::suffixForFileName(const QString &fileName) const
{
QMutexLocker locker(&d->mutex);
- QString foundSuffix;
- d->mimeTypeForFileName(fileName, &foundSuffix);
- return foundSuffix;
+ return d->provider()->findByFileName(QFileInfo(fileName).fileName()).m_foundSuffix;
}
/*!
diff --git a/src/corelib/mimetypes/qmimedatabase_p.h b/src/corelib/mimetypes/qmimedatabase_p.h
index 4ff5110a5b..3f63f5f103 100644
--- a/src/corelib/mimetypes/qmimedatabase_p.h
+++ b/src/corelib/mimetypes/qmimedatabase_p.h
@@ -90,7 +90,7 @@ public:
QMimeType mimeTypeForName(const QString &nameOrAlias);
QMimeType mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device, int *priorityPtr);
QMimeType findByData(const QByteArray &data, int *priorityPtr);
- QStringList mimeTypeForFileName(const QString &fileName, QString *foundSuffix = 0);
+ QStringList mimeTypeForFileName(const QString &fileName);
mutable QMimeProviderBase *m_provider;
const QString m_defaultMimeType;
diff --git a/src/corelib/mimetypes/qmimeglobpattern.cpp b/src/corelib/mimetypes/qmimeglobpattern.cpp
index 568f9bf4de..a4d2b046fa 100644
--- a/src/corelib/mimetypes/qmimeglobpattern.cpp
+++ b/src/corelib/mimetypes/qmimeglobpattern.cpp
@@ -58,9 +58,13 @@ QT_BEGIN_NAMESPACE
void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const QString &pattern)
{
+ if (m_allMatchingMimeTypes.contains(mimeType))
+ return;
// Is this a lower-weight pattern than the last match? Skip this match then.
- if (weight < m_weight)
+ if (weight < m_weight) {
+ m_allMatchingMimeTypes.append(mimeType);
return;
+ }
bool replace = weight > m_weight;
if (!replace) {
// Compare the length of the match
@@ -79,6 +83,7 @@ void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const Q
}
if (!m_matchingMimeTypes.contains(mimeType)) {
m_matchingMimeTypes.append(mimeType);
+ m_allMatchingMimeTypes.append(mimeType);
if (pattern.startsWith(QLatin1String("*.")))
m_foundSuffix = pattern.mid(2);
}
@@ -201,35 +206,32 @@ void QMimeGlobPatternList::match(QMimeGlobMatchResult &result,
}
}
-QStringList QMimeAllGlobPatterns::matchingGlobs(const QString &fileName, QString *foundSuffix) const
+QMimeGlobMatchResult QMimeAllGlobPatterns::matchingGlobs(const QString &fileName) const
{
// First try the high weight matches (>50), if any.
QMimeGlobMatchResult result;
m_highWeightGlobs.match(result, fileName);
- if (result.m_matchingMimeTypes.isEmpty()) {
-
- // Now use the "fast patterns" dict, for simple *.foo patterns with weight 50
- // (which is most of them, so this optimization is definitely worth it)
- const int lastDot = fileName.lastIndexOf(QLatin1Char('.'));
- if (lastDot != -1) { // if no '.', skip the extension lookup
- const int ext_len = fileName.length() - lastDot - 1;
- const QString simpleExtension = fileName.right(ext_len).toLower();
- // (toLower because fast patterns are always case-insensitive and saved as lowercase)
-
- const QStringList matchingMimeTypes = m_fastPatterns.value(simpleExtension);
- const QString simplePattern = QLatin1String("*.") + simpleExtension;
- for (const QString &mime : matchingMimeTypes)
- result.addMatch(mime, 50, simplePattern);
- // Can't return yet; *.tar.bz2 has to win over *.bz2, so we need the low-weight mimetypes anyway,
- // at least those with weight 50.
- }
- // Finally, try the low weight matches (<=50)
- m_lowWeightGlobs.match(result, fileName);
+ // Now use the "fast patterns" dict, for simple *.foo patterns with weight 50
+ // (which is most of them, so this optimization is definitely worth it)
+ const int lastDot = fileName.lastIndexOf(QLatin1Char('.'));
+ if (lastDot != -1) { // if no '.', skip the extension lookup
+ const int ext_len = fileName.length() - lastDot - 1;
+ const QString simpleExtension = fileName.right(ext_len).toLower();
+ // (toLower because fast patterns are always case-insensitive and saved as lowercase)
+
+ const QStringList matchingMimeTypes = m_fastPatterns.value(simpleExtension);
+ const QString simplePattern = QLatin1String("*.") + simpleExtension;
+ for (const QString &mime : matchingMimeTypes)
+ result.addMatch(mime, 50, simplePattern);
+ // Can't return yet; *.tar.bz2 has to win over *.bz2, so we need the low-weight mimetypes anyway,
+ // at least those with weight 50.
}
- if (foundSuffix)
- *foundSuffix = result.m_foundSuffix;
- return result.m_matchingMimeTypes;
+
+ // Finally, try the low weight matches (<=50)
+ m_lowWeightGlobs.match(result, fileName);
+
+ return result;
}
void QMimeAllGlobPatterns::clear()
diff --git a/src/corelib/mimetypes/qmimeglobpattern_p.h b/src/corelib/mimetypes/qmimeglobpattern_p.h
index 3e4fdb50f6..c8b70464fd 100644
--- a/src/corelib/mimetypes/qmimeglobpattern_p.h
+++ b/src/corelib/mimetypes/qmimeglobpattern_p.h
@@ -68,7 +68,8 @@ struct QMimeGlobMatchResult
void addMatch(const QString &mimeType, int weight, const QString &pattern);
- QStringList m_matchingMimeTypes;
+ QStringList m_matchingMimeTypes; // only those with highest weight
+ QStringList m_allMatchingMimeTypes;
int m_weight;
int m_matchingPatternLength;
QString m_foundSuffix;
@@ -153,7 +154,7 @@ public:
void addGlob(const QMimeGlobPattern &glob);
void removeMimeType(const QString &mimeType);
- QStringList matchingGlobs(const QString &fileName, QString *foundSuffix) const;
+ QMimeGlobMatchResult matchingGlobs(const QString &fileName) const;
void clear();
PatternsMap m_fastPatterns; // example: "doc" -> "application/msword", "text/plain"
diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp
index 7e07f8acb9..5bbf1bba9d 100644
--- a/src/corelib/mimetypes/qmimemagicrule.cpp
+++ b/src/corelib/mimetypes/qmimemagicrule.cpp
@@ -161,7 +161,7 @@ bool QMimeMagicRule::matchNumber(const QByteArray &data) const
//qDebug() << "mask" << QString::number(m_numberMask, 16);
const char *p = data.constData() + m_startPos;
- const char *e = data.constData() + qMin(data.size() - int(sizeof(T)), m_endPos + 1);
+ const char *e = data.constData() + qMin(data.size() - int(sizeof(T)), m_endPos);
for ( ; p <= e; ++p) {
if ((qFromUnaligned<T>(p) & mask) == (value & mask))
return true;
@@ -299,20 +299,30 @@ QMimeMagicRule::QMimeMagicRule(const QString &type,
}
break;
case Big16:
- case Host16:
case Little16:
if (m_number <= quint16(-1)) {
m_number = m_type == Little16 ? qFromLittleEndian<quint16>(m_number) : qFromBigEndian<quint16>(m_number);
+ if (m_numberMask != 0)
+ m_numberMask = m_type == Little16 ? qFromLittleEndian<quint16>(m_numberMask) : qFromBigEndian<quint16>(m_numberMask);
+ }
+ Q_FALLTHROUGH();
+ case Host16:
+ if (m_number <= quint16(-1)) {
if (m_numberMask == 0)
m_numberMask = quint16(-1);
m_matchFunction = &QMimeMagicRule::matchNumber<quint16>;
}
break;
case Big32:
- case Host32:
case Little32:
if (m_number <= quint32(-1)) {
m_number = m_type == Little32 ? qFromLittleEndian<quint32>(m_number) : qFromBigEndian<quint32>(m_number);
+ if (m_numberMask != 0)
+ m_numberMask = m_type == Little32 ? qFromLittleEndian<quint32>(m_numberMask) : qFromBigEndian<quint32>(m_numberMask);
+ }
+ Q_FALLTHROUGH();
+ case Host32:
+ if (m_number <= quint32(-1)) {
if (m_numberMask == 0)
m_numberMask = quint32(-1);
m_matchFunction = &QMimeMagicRule::matchNumber<quint32>;
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index 65b011b439..959421bf52 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -287,13 +287,13 @@ QMimeType QMimeBinaryProvider::mimeTypeForName(const QString &name)
return mimeTypeForNameUnchecked(name);
}
-QStringList QMimeBinaryProvider::findByFileName(const QString &fileName, QString *foundSuffix)
+QMimeGlobMatchResult QMimeBinaryProvider::findByFileName(const QString &fileName)
{
checkCache();
+ QMimeGlobMatchResult result;
if (fileName.isEmpty())
- return QStringList();
+ return result;
const QString lowerFileName = fileName.toLower();
- QMimeGlobMatchResult result;
// TODO this parses in the order (local, global). Check that it handles "NOGLOBS" correctly.
for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) {
matchGlobList(result, cacheFile, cacheFile->getUint32(PosLiteralListOffset), fileName);
@@ -305,9 +305,7 @@ QStringList QMimeBinaryProvider::findByFileName(const QString &fileName, QString
if (result.m_matchingMimeTypes.isEmpty())
matchSuffixTree(result, cacheFile, numRoots, firstRootOffset, fileName, fileName.length() - 1, true);
}
- if (foundSuffix)
- *foundSuffix = result.m_foundSuffix;
- return result.m_matchingMimeTypes;
+ return result;
}
void QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int off, const QString &fileName)
@@ -728,12 +726,11 @@ QMimeType QMimeXMLProvider::mimeTypeForName(const QString &name)
return m_nameMimeTypeMap.value(name);
}
-QStringList QMimeXMLProvider::findByFileName(const QString &fileName, QString *foundSuffix)
+QMimeGlobMatchResult QMimeXMLProvider::findByFileName(const QString &fileName)
{
ensureLoaded();
- const QStringList matchingMimeTypes = m_mimeTypeGlobs.matchingGlobs(fileName, foundSuffix);
- return matchingMimeTypes;
+ return m_mimeTypeGlobs.matchingGlobs(fileName);
}
QMimeType QMimeXMLProvider::findByMagic(const QByteArray &data, int *accuracyPtr)
diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h
index e6fc47bf80..f410e62267 100644
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -56,6 +56,7 @@
#ifndef QT_NO_MIMETYPE
+#include "qmimeglobpattern_p.h"
#include <QtCore/qdatetime.h>
#include <QtCore/qset.h>
#include <QtCore/qelapsedtimer.h>
@@ -72,7 +73,7 @@ public:
virtual bool isValid() = 0;
virtual QMimeType mimeTypeForName(const QString &name) = 0;
- virtual QStringList findByFileName(const QString &fileName, QString *foundSuffix) = 0;
+ virtual QMimeGlobMatchResult findByFileName(const QString &fileName) = 0;
virtual QStringList parents(const QString &mime) = 0;
virtual QString resolveAlias(const QString &name) = 0;
virtual QStringList listAliases(const QString &name) = 0;
@@ -99,7 +100,7 @@ public:
virtual bool isValid() Q_DECL_OVERRIDE;
virtual QMimeType mimeTypeForName(const QString &name) Q_DECL_OVERRIDE;
- virtual QStringList findByFileName(const QString &fileName, QString *foundSuffix) Q_DECL_OVERRIDE;
+ virtual QMimeGlobMatchResult findByFileName(const QString &fileName) Q_DECL_OVERRIDE;
virtual QStringList parents(const QString &mime) Q_DECL_OVERRIDE;
virtual QString resolveAlias(const QString &name) Q_DECL_OVERRIDE;
virtual QStringList listAliases(const QString &name) Q_DECL_OVERRIDE;
@@ -142,7 +143,7 @@ public:
virtual bool isValid() Q_DECL_OVERRIDE;
virtual QMimeType mimeTypeForName(const QString &name) Q_DECL_OVERRIDE;
- virtual QStringList findByFileName(const QString &fileName, QString *foundSuffix) Q_DECL_OVERRIDE;
+ virtual QMimeGlobMatchResult findByFileName(const QString &fileName) Q_DECL_OVERRIDE;
virtual QStringList parents(const QString &mime) Q_DECL_OVERRIDE;
virtual QString resolveAlias(const QString &name) Q_DECL_OVERRIDE;
virtual QStringList listAliases(const QString &name) Q_DECL_OVERRIDE;