From d877f0983db8b8f86167f626b1cf64cb4189c795 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 18 Feb 2015 15:16:57 +0100 Subject: [PATCH] MimeDatabase: Prevent funny mixing of different mime type definitions If multiple definitions for the same mime type are found, the mime XML parser/provider would on the one hand replace the first MimeType instance by the later one, but on the other hand keep all previously parsed glob and magic matchers from the first definition. The patch - makes the XML parser ignore definitions of mime types that are already defined - parses custom types first, so custom types can override types from freedesktop.org.xml This fixes opening Cmake projects (CMakeLists.txt) in Qt Creator, because freedesktop.org.xml defines these files to be x-cmake, but we need them to be x-cmake-project. Change-Id: Ia5598c2d0201f608aed6ae8c3268f0512d822f51 Reviewed-by: Daniel Teske --- src/libs/utils/mimetypes/mimeprovider.cpp | 7 ++-- src/libs/utils/mimetypes/mimetypeparser.cpp | 39 +++++++++++++-------- src/libs/utils/mimetypes/mimetypeparser_p.h | 4 +++ 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/libs/utils/mimetypes/mimeprovider.cpp b/src/libs/utils/mimetypes/mimeprovider.cpp index 79fc0c07489..8aad4fae07a 100644 --- a/src/libs/utils/mimetypes/mimeprovider.cpp +++ b/src/libs/utils/mimetypes/mimeprovider.cpp @@ -833,7 +833,8 @@ void MimeXMLProvider::ensureLoaded() { if (!m_loaded /*|| shouldCheck()*/) { // bool fdoXmlFound = false; - QStringList allFiles; + // add custom mime types first, which overrides any default from freedesktop.org.xml + QStringList allFiles = m_additionalFiles; // const QStringList packageDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/packages"), QStandardPaths::LocateDirectory); // //qDebug() << "packageDirs=" << packageDirs; @@ -851,11 +852,9 @@ void MimeXMLProvider::ensureLoaded() // if (!fdoXmlFound) { // // We could instead install the file as part of installing Qt? - allFiles.prepend(QLatin1String(":/qt-project.org/qmime/freedesktop.org.xml")); + allFiles.append(QLatin1String(":/qt-project.org/qmime/freedesktop.org.xml")); // } - allFiles.append(m_additionalFiles); - if (m_allFiles == allFiles) return; m_allFiles = allFiles; diff --git a/src/libs/utils/mimetypes/mimetypeparser.cpp b/src/libs/utils/mimetypes/mimetypeparser.cpp index b7fc1e51953..2b953a9168f 100644 --- a/src/libs/utils/mimetypes/mimetypeparser.cpp +++ b/src/libs/utils/mimetypes/mimetypeparser.cpp @@ -210,9 +210,12 @@ bool MimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString QXmlStreamReader reader(dev); ParseState ps = ParseBeginning; QXmlStreamAttributes atts; + bool ignoreCurrentMimeType = false; while (!reader.atEnd()) { switch (reader.readNext()) { case QXmlStreamReader::StartElement: + if (ignoreCurrentMimeType) + continue; ps = nextState(ps, reader.name()); atts = reader.attributes(); switch (ps) { @@ -221,7 +224,10 @@ bool MimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString if (name.isEmpty()) { reader.raiseError(QString::fromLatin1("Missing '%1'-attribute").arg(QString::fromLatin1(mimeTypeAttributeC))); } else { - data.name = name; + if (mimeTypeExists(name)) + ignoreCurrentMimeType = true; + else + data.name = name; } } break; @@ -307,20 +313,25 @@ bool MimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString { const QStringRef elementName = reader.name(); if (elementName == QLatin1String(mimeTypeTagC)) { - if (!process(MimeType(data), errorMessage)) - return false; + if (!ignoreCurrentMimeType) { + if (!process(MimeType(data), errorMessage)) + return false; + } + ignoreCurrentMimeType = false; data.clear(); - } else if (elementName == QLatin1String(matchTagC)) { - // Closing a tag, pop stack - currentRules.pop(); - //qDebug() << " MATCH closed. Stack size is now" << currentRules.size(); - } else if (elementName == QLatin1String(magicTagC)) { - //qDebug() << "MAGIC ended, we got" << rules.count() << "rules, with prio" << priority; - // Finished a sequence - MimeMagicRuleMatcher ruleMatcher(data.name, priority); - ruleMatcher.addRules(rules); - processMagicMatcher(ruleMatcher); - rules.clear(); + } else if (!ignoreCurrentMimeType) { + if (elementName == QLatin1String(matchTagC)) { + // Closing a tag, pop stack + currentRules.pop(); + //qDebug() << " MATCH closed. Stack size is now" << currentRules.size(); + } else if (elementName == QLatin1String(magicTagC)) { + //qDebug() << "MAGIC ended, we got" << rules.count() << "rules, with prio" << priority; + // Finished a sequence + MimeMagicRuleMatcher ruleMatcher(data.name, priority); + ruleMatcher.addRules(rules); + processMagicMatcher(ruleMatcher); + rules.clear(); + } } break; } diff --git a/src/libs/utils/mimetypes/mimetypeparser_p.h b/src/libs/utils/mimetypes/mimetypeparser_p.h index 65af372a3db..02d5198b4d4 100644 --- a/src/libs/utils/mimetypes/mimetypeparser_p.h +++ b/src/libs/utils/mimetypes/mimetypeparser_p.h @@ -67,6 +67,7 @@ public: bool parse(QIODevice *dev, const QString &fileName, QString *errorMessage); protected: + virtual bool mimeTypeExists(const QString &mimeTypeName) = 0; virtual bool process(const MimeType &t, QString *errorMessage) = 0; virtual bool process(const MimeGlobPattern &t, QString *errorMessage) = 0; virtual void processParent(const QString &child, const QString &parent) = 0; @@ -100,6 +101,9 @@ public: explicit MimeTypeParser(MimeXMLProvider &provider) : m_provider(provider) {} protected: + inline bool mimeTypeExists(const QString &mimeTypeName) + { return m_provider.mimeTypeForName(mimeTypeName).isValid(); } + inline bool process(const MimeType &t, QString *) { m_provider.addMimeType(t); return true; }