From 4f1ebf666e36020c501e6d3b20d70320b45ab2ec Mon Sep 17 00:00:00 2001 From: David Faure Date: Thu, 26 Mar 2020 11:09:24 +0200 Subject: QMimeType::suffixForFileName shouldn't lowercase the file suffix It was returning a lowercased suffix because it was extracting it from the pattern (*.txt) rather than from the filename ("README.TXT"). This broke expectations on the application side, since this method is documented to return a suffix from the given filename. Ref: https://bugs.kde.org/show_bug.cgi?id=402388 Change-Id: I7dae13db31280249d3f592fa9592c4067804e22d Reviewed-by: Thiago Macieira --- src/corelib/mimetypes/qmimedatabase.cpp | 3 ++- src/corelib/mimetypes/qmimeglobpattern.cpp | 26 ++++++++++++++++++++------ src/corelib/mimetypes/qmimeglobpattern_p.h | 12 ++++-------- src/corelib/mimetypes/qmimeprovider.cpp | 2 +- 4 files changed, 27 insertions(+), 16 deletions(-) (limited to 'src/corelib/mimetypes') diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index d65f1bdebd..974ca36a40 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -638,7 +638,8 @@ QList QMimeDatabase::mimeTypesForFileName(const QString &fileName) co QString QMimeDatabase::suffixForFileName(const QString &fileName) const { QMutexLocker locker(&d->mutex); - return d->findByFileName(QFileInfo(fileName).fileName()).m_foundSuffix; + const int suffixLength = d->findByFileName(QFileInfo(fileName).fileName()).m_knownSuffixLength; + return fileName.right(suffixLength); } /*! diff --git a/src/corelib/mimetypes/qmimeglobpattern.cpp b/src/corelib/mimetypes/qmimeglobpattern.cpp index 6d2a1f5425..9971913f9d 100644 --- a/src/corelib/mimetypes/qmimeglobpattern.cpp +++ b/src/corelib/mimetypes/qmimeglobpattern.cpp @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE Handles glob weights, and preferring longer matches over shorter matches. */ -void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const QString &pattern) +void QMimeGlobMatchResult::addMatch(const QString &mimeType, int weight, const QString &pattern, int knownSuffixLength) { if (m_allMatchingMimeTypes.contains(mimeType)) return; @@ -84,8 +84,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); + m_knownSuffixLength = knownSuffixLength; } } @@ -152,6 +151,18 @@ bool QMimeGlobPattern::matchFileName(const QString &inputFilename) const #endif } +static bool isSimplePattern(const QString &pattern) +{ + // starts with "*.", has no other '*' + return pattern.lastIndexOf(QLatin1Char('*')) == 0 + && pattern.length() > 1 + && pattern.at(1) == QLatin1Char('.') // (other dots are OK, like *.tar.bz2) + // and contains no other special character + && !pattern.contains(QLatin1Char('?')) + && !pattern.contains(QLatin1Char('[')) + ; +} + static bool isFastPattern(const QString &pattern) { // starts with "*.", has no other '*' and no other '.' @@ -205,8 +216,11 @@ void QMimeGlobPatternList::match(QMimeGlobMatchResult &result, const QMimeGlobPatternList::const_iterator endIt = this->constEnd(); for (; it != endIt; ++it) { const QMimeGlobPattern &glob = *it; - if (glob.matchFileName(fileName)) - result.addMatch(glob.mimeType(), glob.weight(), glob.pattern()); + if (glob.matchFileName(fileName)) { + const QString pattern = glob.pattern(); + const int suffixLen = isSimplePattern(pattern) ? pattern.length() - 2 : 0; + result.addMatch(glob.mimeType(), glob.weight(), pattern, suffixLen); + } } } @@ -226,7 +240,7 @@ void QMimeAllGlobPatterns::matchingGlobs(const QString &fileName, QMimeGlobMatch const QStringList matchingMimeTypes = m_fastPatterns.value(simpleExtension); const QString simplePattern = QLatin1String("*.") + simpleExtension; for (const QString &mime : matchingMimeTypes) - result.addMatch(mime, 50, simplePattern); + result.addMatch(mime, 50, simplePattern, simpleExtension.size()); // 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. } diff --git a/src/corelib/mimetypes/qmimeglobpattern_p.h b/src/corelib/mimetypes/qmimeglobpattern_p.h index cf27d6ab30..49f145e8db 100644 --- a/src/corelib/mimetypes/qmimeglobpattern_p.h +++ b/src/corelib/mimetypes/qmimeglobpattern_p.h @@ -62,17 +62,13 @@ QT_BEGIN_NAMESPACE struct QMimeGlobMatchResult { - QMimeGlobMatchResult() - : m_weight(0), m_matchingPatternLength(0) - {} - - void addMatch(const QString &mimeType, int weight, const QString &pattern); + void addMatch(const QString &mimeType, int weight, const QString &pattern, int knownSuffixLength = 0); QStringList m_matchingMimeTypes; // only those with highest weight QStringList m_allMatchingMimeTypes; - int m_weight; - int m_matchingPatternLength; - QString m_foundSuffix; + int m_weight = 0; + int m_matchingPatternLength = 0; + int m_knownSuffixLength = 0; }; class QMimeGlobPattern diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index 83574a40f0..e8e81e65ab 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -306,7 +306,7 @@ bool QMimeBinaryProvider::matchSuffixTree(QMimeGlobMatchResult &result, QMimeBin const bool caseSensitive = flagsAndWeight & 0x100; if (caseSensitiveCheck || !caseSensitive) { result.addMatch(QLatin1String(mimeType), weight, - QLatin1Char('*') + fileName.midRef(charPos + 1)); + QLatin1Char('*') + fileName.midRef(charPos + 1), fileName.size() - charPos - 2); success = true; } } -- cgit v1.2.3