Change the mimetype database embedded into QtCore

Instead of freedesktop.org.xml (which is GPL), use the tika mimetypes
definition (Apache licensed), as fallback on platforms where
shared-mime-info isn't installed.

[ChangeLog][QtCore][QMimeDatabase] For licensing reasons, QtCore
no longer ships a copy of the MIME database from freedesktop.org's
shared-mime-info project, but the one from the Apache Tika project.
The tika definitions don't have icons or translated descriptions, but
are sufficient for matching file types.

[ChangeLog][Third-Party Code] Added TIKA mimetypes and the corresponding
attribution file.

Change-Id: I360ed973f6d89a470dc2f17a21abdf5630c6d15d
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 74ad4cbeef40b1f51a59b3168f8c0b62eb0b29c8)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
David Faure 2024-07-08 13:48:08 +02:00 committed by Qt Cherry-pick Bot
parent b0dd8d748e
commit 2d2975bd9f
17 changed files with 8962 additions and 111 deletions

View File

@ -0,0 +1,173 @@
#!/usr/bin/env python3
# Copyright (C) 2024 Klaralvdalens Datakonsult AB (KDAB)
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-3.0-only WITH Qt-GPL-exception-1.0
# The tika database at https://raw.githubusercontent.com/apache/tika/main/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml
# uses a format that is *close* to the freedesktop.org shared-mime-info format, but not quite. They extended it with
# - match types such as stringignorecase, regex, unicodeLE
# - 0x syntax for strings
# - making the type and offset attributes optional
# - <match minShouldMatch="2"> to specify that at least two of the submatches should match
# It's also missing some crucial mimetypes that we need.
# This script fixes all that.
# Usage: download tika-mimetypes.xml as tika-mimetypes.xml.orig and run this script to produce Qt's version of tika-mimetypes.xml
import sys, re
inputfile = "tika-mimetypes.xml.orig"
file = "tika-mimetypes.xml"
def wrap_with_comment(line):
if not '<!--' in line:
return "<!-- DISABLED FOR QT: " + line.rstrip('\n') + "-->\n"
return line
def transform_hex_value(line):
match = re.search(r'value="0x([0-9a-fA-F]+)"', line)
if match:
hex_value = match.group(1)
# Insert \\x before every pair of hex characters
transformed_value = ''.join(f'\\x{hex_value[i:i+2]}' for i in range(0, len(hex_value), 2))
line = re.sub(r'value="0x[0-9a-fA-F]+"', lambda m: f'value="{transformed_value}"', line)
return line
def open_input_file(inputfile):
try:
return open(inputfile, "r")
except FileNotFoundError:
sys.exit(f"{inputfile} not found")
except OSError as e:
sys.exit(f"OS error when opening {inputfile}: {e}")
with open_input_file(inputfile) as f:
with open(file, "w") as out:
current_mime_type = ''
skip_until = ''
for line in f:
line = line.replace('\t', ' ') # Untabify
line = re.sub(r' +\n$', '\n', line) # Remove trailing whitespace
match = re.search(r'<mime-type type="([^"]+)">', line)
if match:
current_mime_type = match.group(1)
# remove mimetypes with regex matches having submatches, just commenting out the line would break the xml structure
if current_mime_type == "application/marc" or current_mime_type == "application/x-touhou" or ';format' in current_mime_type:
# line = wrap_with_comment(line) # leads to issues with -- inside comments
continue
if 'be a bit more flexible, but require one from each of these' in line:
skip_until = '</magic>'
if skip_until == "" and 'minShouldMatch="' in line:
skip_until = '</magic>'
if 'value="OggS\\000' in line: # off by one in mask length, it seems (audio/x-oggflac and following)
skip_until = '</magic>'
if skip_until != "":
if skip_until in line:
skip_until = ""
else:
line = wrap_with_comment(line)
# uncomment "conflicting" globs
pattern = re.compile(r'( *)<!-- (<glob pattern="[^"]*"/>)(.*?)conflicts with(.*?)-->')
match = pattern.search(line)
if match:
line = match.group(1) + match.group(2) + ' <!-- Re-enabled by Qt -->\n'
if not '<!--' in line:
line = line.replace("_comment>", "comment>")
line = line.replace('type="stringignorecase"', 'type="string"') # tika extension, not supported
line = line.replace('value="P4" type="regex"', 'value="P4" type="string"') # no need to be a regex (image/x-portable-bitmap)
line = line.replace('value="P5" type="regex"', 'value="P5" type="string"') # no need to be a regex (image/x-portable-graymap)
line = line.replace('value="P6" type="regex"', 'value="P6" type="string"') # no need to be a regex (image/x-portable-pixmap)
line = line.replace('value="(X|DKIM|ARC)-" type="regex"', 'value="X-" type="string"') # simplify message/rfc822 to avoid regex
# No type specified, assumed string
if '<match value=' in line and '>' in line and not 'type=' in line:
line = line.replace('<match ', '<match type="string" ')
line = line.replace('>', '> <!-- type added by Qt -->')
# No offset specified, spell out 0
if '<match value=' in line and '>' in line and not 'offset=' in line:
line = line.replace('<match ', '<match offset="0" ')
line = line.replace('>', '> <!-- offset added by Qt -->')
# tika extensions, not supported
if 'type="unicodeLE"' in line or 'type="regex"' in line or '<match value="(?:\\\\x' in line:
line = wrap_with_comment(line)
if '<glob pattern="*.c"/>' in line.lower():
line = line.replace('/', ' case-sensitive="true"/')
line = line.replace('>', '> <!-- case-sensitive added by Qt -->')
# Add aliases needed by the unittest
if '<mime-type type="audio/mpeg"' in line:
line += ' <alias type="audio/mp3"/> <!-- added by Qt -->\n';
if '<mime-type type="text/x-diff"' in line:
line += ' <alias type="text/x-patch"/> <!-- added by Qt -->\n';
if '<mime-type type="application/x-sh"' in line:
line += ' <alias type="application/x-shellscript"/> <!-- added by Qt -->\n';
line += ' <sub-class-of type="application/x-executable"/> <!-- added by Qt -->\n';
# Tika supports 0x syntax for strings, shared-mime-info requires escaping each char with \x
if 'value="0x' in line and 'type="string"' in line:
line = transform_hex_value(line)
if '<mime-info xmlns' in line:
line += """
<!-- Qt additions START -->
<mime-type type="application/x-zerosize">
<comment>Empty document</comment>
</mime-type>
<mime-type type="application/x-desktop">
<comment>Desktop file</comment>
<glob pattern="*.desktop"/>
</mime-type>
<mime-type type="text/x-qml">
<comment>Qt Markup Language file</comment>
<sub-class-of type="text/plain"/>
<magic>
<match type="string" value="/bin/env qml" offset="2:16"/>
<match type="string" value="import Qt" offset="0:3000">
<match type="string" value="{" offset="9:3009"/>
</match>
<match type="string" value="import Qml" offset="0:3000">
<match type="string" value="{" offset="9:3009"/>
</match>
</magic>
<glob pattern="*.qml"/>
<glob pattern="*.qmltypes"/>
<glob pattern="*.qmlproject"/>
</mime-type>
<mime-type type="application/x-gzpostscript">
<comment>Compressed postscript</comment>
<glob pattern="*.ps.gz"/>
</mime-type>
<mime-type type="application/x-core">
<comment>Core dump</comment>
<glob pattern="core" case-sensitive="true"/>
</mime-type>
<mime-type type="application/x-bzip2-compressed-tar">
<comment>BZip2 compressed tar file</comment>
<glob pattern="*.tar.bz2"/>
</mime-type>
<mime-type type="inode/directory">
<comment>Directory</comment>
<generic-icon name="folder"/>
</mime-type>
<!-- Qt additions END -->
"""
out.write(line)

View File

@ -0,0 +1,26 @@
[
{
"Id": "tika-mimetypes",
"Name": "Apache Tika MimeType Definitions",
"QDocModule": "qtcore",
"QtUsage":
"Qt Core uses a copy of the Apache Tika MimeType Definitions if shared-mime-info isn't installed on the system.",
"Comment": {
"Files":
"For update, see qtbase/src/corelib/mimetypes/3rdparty/process_tika_mimetypes.py"
},
"Files": [
"tika-mimetypes.xml"
],
"Description":
"The Apache Tika MimeTypes list many known MIME types and how to match files (using globs and/or 'magic' rules for the file contents)",
"Homepage":
"https://github.com/apache/tika/tree/main/tika-core/src/main/resources/org/apache/tika/mime",
"Version": "019041117149667bc4d18fabf222a0670d407959",
"DownloadLocation":
"https://github.com/apache/tika/blob/019041117149667bc4d18fabf222a0670d407959/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml",
"License": "Apache License 2.0",
"LicenseId": "Apache-2.0",
"Copyright": "Copyright 2011 The Apache Software Foundation"
}
]

File diff suppressed because it is too large Load Diff

View File

@ -7,17 +7,17 @@
# file with the same information
set(corelib_mimetypes_resource_file
"${CMAKE_CURRENT_LIST_DIR}/mime/packages/freedesktop.org.xml"
"${CMAKE_CURRENT_LIST_DIR}/3rdparty/tika-mimetypes.xml"
)
function(corelib_add_mimetypes_resources target)
set(source_file "${corelib_mimetypes_resource_file}")
set_source_files_properties("${source_file}"
PROPERTIES QT_RESOURCE_ALIAS "freedesktop.org.xml"
PROPERTIES QT_RESOURCE_ALIAS "tika-mimetypes.xml"
)
qt_internal_add_resource(${target} "mimetypes"
PREFIX
"/qt-project.org/qmime/packages"
"/qt-project.org/qmime/tika/packages"
FILES
"${source_file}"
)

View File

@ -286,6 +286,7 @@ bool QMimeTypeParserBase::parse(QIODevice *dev, const QString &fileName, QString
ruleMatcher.addRules(rules);
processMagicMatcher(ruleMatcher);
rules.clear();
ps = ParseOtherMimeTypeSubTag; // in case of an empty glob tag
}
break;
}

View File

@ -2,8 +2,10 @@
# SPDX-License-Identifier: BSD-3-Clause
if(TARGET Qt::Concurrent)
add_subdirectory(qmimedatabase-xml)
add_subdirectory(qmimedatabase-xml-builtin)
add_subdirectory(qmimedatabase-xml-fdoxml)
endif()
if(TARGET Qt::Concurrent AND UNIX AND NOT APPLE AND NOT QNX)
add_subdirectory(qmimedatabase-cache)
add_subdirectory(qmimedatabase-cache-builtin)
add_subdirectory(qmimedatabase-cache-fdoxml)
endif()

View File

@ -12,23 +12,21 @@ if(NOT QT_FEATURE_private_tests)
endif()
#####################################################################
## tst_qmimedatabase-cache Test:
## tst_qmimedatabase-cache-builtin Test:
#####################################################################
qt_internal_add_test(tst_qmimedatabase-cache
qt_internal_add_test(tst_qmimedatabase-cache-builtin
RUN_SERIAL
SOURCES
../tst_qmimedatabase.h
tst_qmimedatabase-cache.cpp
tst_qmimedatabase-cache-builtin.cpp
LIBRARIES
Qt::CorePrivate
Qt::Concurrent
)
# Resources:
# the freedesktop resources are handled manually below via mimetypes_resources.cmake
#set(mimetypes_resource_files
#"mime/packages/freedesktop.org.xml"
#)
# the builtin mimetype xml is handled manually below via mimetypes_resources.cmake
set(testdata_resource_files
"../add-extension.xml"
"../circular-inheritance.xml"
@ -46,16 +44,16 @@ set(testdata_resource_files
"../yast2-metapackage-handler-mimetypes.xml"
)
qt_internal_add_resource(tst_qmimedatabase-cache "testdata"
qt_internal_add_resource(tst_qmimedatabase-cache-builtin "testdata"
PREFIX
"/qt-project.org/qmime"
"/tst_qmimedatabase/qmime"
BASE
".."
FILES
${testdata_resource_files}
)
qt_internal_add_resource(tst_qmimedatabase-cache "testfiles"
qt_internal_add_resource(tst_qmimedatabase-cache-builtin "testfiles"
PREFIX
"/files"
FILES
@ -65,12 +63,12 @@ qt_internal_add_resource(tst_qmimedatabase-cache "testfiles"
set(corelib_source_dir ../../../../../../src/corelib)
include(${corelib_source_dir}/mimetypes/mimetypes_resources.cmake)
corelib_add_mimetypes_resources(tst_qmimedatabase-cache)
corelib_add_mimetypes_resources(tst_qmimedatabase-cache-builtin)
## Scopes:
#####################################################################
qt_internal_extend_target(tst_qmimedatabase-cache CONDITION GCC
qt_internal_extend_target(tst_qmimedatabase-cache-builtin CONDITION GCC
COMPILE_OPTIONS
-W
-Wall
@ -80,7 +78,7 @@ qt_internal_extend_target(tst_qmimedatabase-cache CONDITION GCC
-Wshadow
)
qt_internal_extend_target(tst_qmimedatabase-cache CONDITION UNIX AND NOT APPLE AND NOT QNX
qt_internal_extend_target(tst_qmimedatabase-cache-builtin CONDITION UNIX AND NOT APPLE AND NOT QNX
DEFINES
USE_XDG_DATA_DIRS
)

View File

@ -0,0 +1,25 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "../tst_qmimedatabase.cpp"
void tst_QMimeDatabase::initTestCaseInternal()
{
#if !QT_CONFIG(process)
QSKIP("No qprocess support", SkipAll);
#else
const QString mimeDirName = m_globalXdgDir + QStringLiteral("/mime");
runUpdateMimeDatabase(mimeDirName);
QVERIFY(QFile::exists(mimeDirName + QStringLiteral("/mime.cache")));
#endif
}
bool tst_QMimeDatabase::useCacheProvider() const
{
return true;
}
bool tst_QMimeDatabase::useFreeDesktopOrgXml() const
{
return false;
}

View File

@ -0,0 +1,95 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qmimedatabase LANGUAGES CXX)
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
if(NOT QT_FEATURE_private_tests)
return()
endif()
#####################################################################
## tst_qmimedatabase-cache-fdoxml Test:
#####################################################################
qt_internal_add_test(tst_qmimedatabase-cache-fdoxml
RUN_SERIAL
SOURCES
../tst_qmimedatabase.h
tst_qmimedatabase-cache-fdoxml.cpp
LIBRARIES
Qt::CorePrivate
Qt::Concurrent
)
# Resources:
set(mimetypes_resource_files
"../3rdparty/freedesktop.org.xml"
)
set(testdata_resource_files
"../add-extension.xml"
"../circular-inheritance.xml"
"../invalid-magic1.xml"
"../invalid-magic2.xml"
"../invalid-magic3.xml"
"../magic-and-hierarchy.foo"
"../magic-and-hierarchy.xml"
"../magic-and-hierarchy2.foo"
"../qml-again.xml"
"../test.qml"
"../text-x-objcsrc.xml"
"../text-plain-subclass.xml"
"../webm-glob-deleteall.xml"
"../yast2-metapackage-handler-mimetypes.xml"
)
qt_internal_add_resource(tst_qmimedatabase-cache-fdoxml "testdata"
PREFIX
"/tst_qmimedatabase/qmime"
BASE
".."
FILES
${testdata_resource_files}
)
qt_internal_add_resource(tst_qmimedatabase-cache-fdoxml "testdata-fdoxml"
PREFIX
"/tst_qmimedatabase/qmime"
BASE
"../3rdparty"
FILES
${mimetypes_resource_files}
)
qt_internal_add_resource(tst_qmimedatabase-cache-fdoxml "testfiles"
PREFIX
"/files"
FILES
"../test.txt"
"../test.qml"
)
set(corelib_source_dir ../../../../../../src/corelib)
include(${corelib_source_dir}/mimetypes/mimetypes_resources.cmake)
corelib_add_mimetypes_resources(tst_qmimedatabase-cache-fdoxml)
## Scopes:
#####################################################################
qt_internal_extend_target(tst_qmimedatabase-cache-fdoxml CONDITION GCC
COMPILE_OPTIONS
-W
-Wall
-Wextra
-Wno-long-long
-Wnon-virtual-dtor
-Wshadow
)
qt_internal_extend_target(tst_qmimedatabase-cache-fdoxml CONDITION UNIX AND NOT APPLE AND NOT QNX
DEFINES
USE_XDG_DATA_DIRS
)

View File

@ -13,3 +13,13 @@ void tst_QMimeDatabase::initTestCaseInternal()
QVERIFY(QFile::exists(mimeDirName + QStringLiteral("/mime.cache")));
#endif
}
bool tst_QMimeDatabase::useCacheProvider() const
{
return true;
}
bool tst_QMimeDatabase::useFreeDesktopOrgXml() const
{
return true;
}

View File

@ -12,23 +12,21 @@ if(NOT QT_FEATURE_private_tests)
endif()
#####################################################################
## tst_qmimedatabase-xml Test:
## tst_qmimedatabase-xml-builtin Test:
#####################################################################
qt_internal_add_test(tst_qmimedatabase-xml
qt_internal_add_test(tst_qmimedatabase-xml-builtin
RUN_SERIAL
SOURCES
../tst_qmimedatabase.h
tst_qmimedatabase-xml.cpp
tst_qmimedatabase-xml-builtin.cpp
LIBRARIES
Qt::Concurrent
Qt::CorePrivate
)
# Resources:
# the freedesktop resources are handled manually below via mimetypes_resources.cmake
#set(mimetypes_resource_files
#"mime/packages/freedesktop.org.xml"
#)
# the builtin mimetype xml is handled manually below via mimetypes_resources.cmake
set(testdata_resource_files
"../add-extension.xml"
"../circular-inheritance.xml"
@ -46,16 +44,16 @@ set(testdata_resource_files
"../yast2-metapackage-handler-mimetypes.xml"
)
qt_internal_add_resource(tst_qmimedatabase-xml "testdata"
qt_internal_add_resource(tst_qmimedatabase-xml-builtin "testdata"
PREFIX
"/qt-project.org/qmime"
"/tst_qmimedatabase/qmime"
BASE
".."
FILES
${testdata_resource_files}
)
qt_internal_add_resource(tst_qmimedatabase-xml "testfiles"
qt_internal_add_resource(tst_qmimedatabase-xml-builtin "testfiles"
PREFIX
"/files"
FILES
@ -65,12 +63,12 @@ qt_internal_add_resource(tst_qmimedatabase-xml "testfiles"
set(corelib_source_dir ../../../../../../src/corelib)
include(${corelib_source_dir}/mimetypes/mimetypes_resources.cmake)
corelib_add_mimetypes_resources(tst_qmimedatabase-xml)
corelib_add_mimetypes_resources(tst_qmimedatabase-xml-builtin)
## Scopes:
#####################################################################
qt_internal_extend_target(tst_qmimedatabase-xml CONDITION GCC
qt_internal_extend_target(tst_qmimedatabase-xml-builtin CONDITION GCC
COMPILE_OPTIONS
-W
-Wall
@ -80,7 +78,7 @@ qt_internal_extend_target(tst_qmimedatabase-xml CONDITION GCC
-Wshadow
)
qt_internal_extend_target(tst_qmimedatabase-xml CONDITION UNIX AND NOT APPLE AND NOT QNX
qt_internal_extend_target(tst_qmimedatabase-xml-builtin CONDITION UNIX AND NOT APPLE AND NOT QNX
DEFINES
USE_XDG_DATA_DIRS
)

View File

@ -0,0 +1,19 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "../tst_qmimedatabase.cpp"
void tst_QMimeDatabase::initTestCaseInternal()
{
qputenv("QT_NO_MIME_CACHE", "1");
}
bool tst_QMimeDatabase::useCacheProvider() const
{
return false;
}
bool tst_QMimeDatabase::useFreeDesktopOrgXml() const
{
return false;
}

View File

@ -0,0 +1,95 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qmimedatabase LANGUAGES CXX)
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
if(NOT QT_FEATURE_private_tests)
return()
endif()
#####################################################################
## tst_qmimedatabase-xml-fdoxml Test:
#####################################################################
qt_internal_add_test(tst_qmimedatabase-xml-fdoxml
RUN_SERIAL
SOURCES
../tst_qmimedatabase.h
tst_qmimedatabase-xml-fdoxml.cpp
LIBRARIES
Qt::CorePrivate
Qt::Concurrent
)
# Resources:
set(mimetypes_resource_files
"../3rdparty/freedesktop.org.xml"
)
set(testdata_resource_files
"../add-extension.xml"
"../circular-inheritance.xml"
"../invalid-magic1.xml"
"../invalid-magic2.xml"
"../invalid-magic3.xml"
"../magic-and-hierarchy.foo"
"../magic-and-hierarchy.xml"
"../magic-and-hierarchy2.foo"
"../qml-again.xml"
"../test.qml"
"../text-x-objcsrc.xml"
"../text-plain-subclass.xml"
"../webm-glob-deleteall.xml"
"../yast2-metapackage-handler-mimetypes.xml"
)
qt_internal_add_resource(tst_qmimedatabase-xml-fdoxml "testdata"
PREFIX
"/tst_qmimedatabase/qmime"
BASE
".."
FILES
${testdata_resource_files}
)
qt_internal_add_resource(tst_qmimedatabase-xml-fdoxml "testdata-fdoxml"
PREFIX
"/tst_qmimedatabase/qmime"
BASE
"../3rdparty"
FILES
${mimetypes_resource_files}
)
qt_internal_add_resource(tst_qmimedatabase-xml-fdoxml "testfiles"
PREFIX
"/files"
FILES
"../test.txt"
"../test.qml"
)
set(corelib_source_dir ../../../../../../src/corelib)
include(${corelib_source_dir}/mimetypes/mimetypes_resources.cmake)
corelib_add_mimetypes_resources(tst_qmimedatabase-xml-fdoxml)
## Scopes:
#####################################################################
qt_internal_extend_target(tst_qmimedatabase-xml-fdoxml CONDITION GCC
COMPILE_OPTIONS
-W
-Wall
-Wextra
-Wno-long-long
-Wnon-virtual-dtor
-Wshadow
)
qt_internal_extend_target(tst_qmimedatabase-xml-fdoxml CONDITION UNIX AND NOT APPLE AND NOT QNX
DEFINES
USE_XDG_DATA_DIRS
)

View File

@ -8,3 +8,12 @@ void tst_QMimeDatabase::initTestCaseInternal()
qputenv("QT_NO_MIME_CACHE", "1");
}
bool tst_QMimeDatabase::useCacheProvider() const
{
return false;
}
bool tst_QMimeDatabase::useFreeDesktopOrgXml() const
{
return true;
}

View File

@ -52,6 +52,7 @@ static const std::array additionalLocalMimeFiles = {
"webm-glob-deleteall.xml",
};
static const auto s_additionalFilesResourcePrefix = ":/tst_qmimedatabase/qmime/"_L1;
static const auto s_resourcePrefix = ":/qt-project.org/qmime/"_L1;
static const auto s_inodeMimetype = "inode/directory"_L1;
@ -131,9 +132,14 @@ void tst_QMimeDatabase::initTestCase()
QVERIFY2(QDir(m_localMimeDir).removeRecursively(), qPrintable(m_localMimeDir + ": " + qt_error_string()));
}
m_isUsingCacheProvider = useCacheProvider();
m_hasFreedesktopOrg = useFreeDesktopOrgXml();
#ifdef USE_XDG_DATA_DIRS
// Create a temporary "global" XDG data dir for later use
// It will initially contain a copy of freedesktop.org.xml
// Create a temporary "global" XDG data dir. It's used
// 1) to install new global mimetypes later on
// 2) to run update-mime-database right away when testing the cache provider
// 3) to host a copy of freedesktop.org.xml in tst_qmimedatabase-xml-fdoxml
QVERIFY2(m_temporaryDir.isValid(),
("Could not create temporary subdir: " + m_temporaryDir.errorString()).toUtf8());
const QDir here = QDir(m_temporaryDir.path());
@ -144,19 +150,27 @@ void tst_QMimeDatabase::initTestCase()
qputenv("XDG_DATA_DIRS", QFile::encodeName(m_globalXdgDir));
qDebug() << "\nGlobal XDG_DATA_DIRS: " << m_globalXdgDir;
const QString freeDesktopXml = QStringLiteral("freedesktop.org.xml");
const QString xmlFileName = s_resourcePrefix + "packages/"_L1 + freeDesktopXml;
const QString xmlTargetFileName = globalPackageDir + QLatin1Char('/') + freeDesktopXml;
QString errorMessage;
QVERIFY2(copyResourceFile(xmlFileName, xmlTargetFileName, &errorMessage), qPrintable(errorMessage));
if (m_isUsingCacheProvider || m_hasFreedesktopOrg) {
const QString xmlFileName = m_hasFreedesktopOrg
? (s_additionalFilesResourcePrefix + "/freedesktop.org.xml"_L1)
: (s_resourcePrefix + "/tika/packages/tika-mimetypes.xml"_L1);
QVERIFY2(QFileInfo::exists(xmlFileName), qPrintable(xmlFileName));
const QString xmlTargetFileName =
globalPackageDir + '/' + QFileInfo(xmlFileName).fileName();
QString errorMessage;
QVERIFY2(copyResourceFile(xmlFileName, xmlTargetFileName, &errorMessage),
qPrintable(errorMessage));
}
#endif
m_testSuite = QFINDTESTDATA("../s-m-i/tests/mime-detection");
if (m_testSuite.isEmpty())
qWarning("%s", qPrintable(testSuiteWarning()));
if (m_hasFreedesktopOrg) {
m_testSuite = QFINDTESTDATA("../s-m-i/tests/mime-detection");
if (m_testSuite.isEmpty()) {
qWarning().noquote() << testSuiteWarning();
}
}
initTestCaseInternal();
m_isUsingCacheProvider = !qEnvironmentVariableIsSet("QT_NO_MIME_CACHE");
}
void tst_QMimeDatabase::init()
@ -185,17 +199,19 @@ void tst_QMimeDatabase::mimeTypeForName()
QVERIFY(s1.isValid());
QCOMPARE(s1.name(), QString::fromLatin1("text/plain"));
QMimeType krita = db.mimeTypeForName(QString::fromLatin1("application/x-krita"));
QVERIFY(krita.isValid());
QMimeType cbor = db.mimeTypeForName(QString::fromLatin1("application/cbor"));
QVERIFY(cbor.isValid());
// Test <comment> parsing with application/rdf+xml which has the english comment after the other ones
QMimeType rdf = db.mimeTypeForName(QString::fromLatin1("application/rdf+xml"));
QVERIFY(rdf.isValid());
QCOMPARE(rdf.comment(), QString::fromLatin1("RDF file"));
QVERIFY(rdf.comment() == QLatin1String("RDF file")
|| rdf.comment() == QLatin1String("XML syntax for RDF graphs") /*tika*/);
QMimeType bzip2 = db.mimeTypeForName(QString::fromLatin1("application/x-bzip2"));
QVERIFY(bzip2.isValid());
QCOMPARE(bzip2.comment(), QString::fromLatin1("Bzip2 archive"));
QVERIFY(bzip2.comment() == QLatin1String("Bzip2 archive")
|| bzip2.comment() == QLatin1String("Bzip 2 UNIX Compressed File") /*tika*/);
QMimeType defaultMime = db.mimeTypeForName(QString::fromLatin1("application/octet-stream"));
QVERIFY(defaultMime.isValid());
@ -206,17 +222,17 @@ void tst_QMimeDatabase::mimeTypeForName()
QCOMPARE(doesNotExist.comment(), QString());
QCOMPARE(doesNotExist.aliases(), QStringList());
// TODO move to findByFile
#ifdef Q_OS_LINUX
QString exePath = QStandardPaths::findExecutable(QLatin1String("ls"));
if (exePath.isEmpty())
qWarning() << "ls not found";
else {
const QString executableType = QString::fromLatin1("application/x-executable");
const QString sharedLibType = QString::fromLatin1("application/x-sharedlib");
//QTest::newRow("executable") << exePath << executableType;
QVERIFY(db.mimeTypeForFile(exePath).name() == executableType ||
db.mimeTypeForFile(exePath).name() == sharedLibType);
if (m_hasFreedesktopOrg) {
QString exePath = QStandardPaths::findExecutable(QLatin1String("ls"));
if (exePath.isEmpty())
qWarning() << "ls not found";
else {
const QString executableType = QString::fromLatin1("application/x-executable");
const QString sharedLibType = QString::fromLatin1("application/x-sharedlib");
QVERIFY(db.mimeTypeForFile(exePath).name() == executableType
|| db.mimeTypeForFile(exePath).name() == sharedLibType);
}
}
#endif
@ -239,8 +255,8 @@ void tst_QMimeDatabase::mimeTypeForFileName_data()
QTest::newRow("case-sensitive-only-match-core") << "core" << "application/x-core";
QTest::newRow("case-sensitive-only-match-Core") << "Core" << "application/octet-stream"; // #198477
QTest::newRow("desktop file") << "foo.desktop" << "application/x-desktop";
QTest::newRow("old kdelnk file is x-desktop too") << "foo.kdelnk" << "application/x-desktop";
QTest::newRow("desktop file") << "foo.desktop"
<< "application/x-desktop";
QTest::newRow("double-extension file") << "foo.tar.bz2"
<< "application/x-bzip2-compressed-tar";
QTest::newRow("single-extension file") << "foo.bz2"
@ -248,12 +264,22 @@ void tst_QMimeDatabase::mimeTypeForFileName_data()
QTest::newRow(".doc should assume msword") << "somefile.doc" << "application/msword"; // #204139
QTest::newRow("glob that uses [] syntax, 1") << "Makefile" << "text/x-makefile";
QTest::newRow("glob that uses [] syntax, 2") << "makefile" << "text/x-makefile";
QTest::newRow("glob that ends with *, no extension") << "README" << "text/x-readme";
QTest::newRow("glob that ends with *, extension") << "README.foo" << "text/x-readme";
QTest::newRow("glob that ends with *, also matches *.txt. Higher weight wins.") << "README.txt" << "text/plain";
QTest::newRow("glob that ends with *, also matches *.nfo. Higher weight wins.") << "README.nfo" << "text/x-nfo";
// fdo bug 15436, needs shared-mime-info >= 0.40 (and this tests the globs2-parsing code).
QTest::newRow("glob that ends with *, also matches *.pdf. *.pdf has higher weight") << "README.pdf" << "application/pdf";
if (m_hasFreedesktopOrg) {
QTest::newRow("glob that ends with *, no extension") << "README"
<< "text/x-readme";
QTest::newRow("glob that ends with *, extension") << "README.foo"
<< "text/x-readme";
QTest::newRow("glob that ends with *, also matches *.txt. Higher weight wins.")
<< "README.txt"
<< "text/plain";
QTest::newRow("glob that ends with *, also matches *.nfo. Higher weight wins.")
<< "README.nfo"
<< "text/x-nfo";
// fdo bug 15436, needs shared-mime-info >= 0.40 (and this tests the globs2-parsing code).
QTest::newRow("glob that ends with *, also matches *.pdf. *.pdf has higher weight")
<< "README.pdf"
<< "application/pdf";
}
QTest::newRow("directory") << "/" << "inode/directory";
QTest::newRow("resource-directory") << ":/files/" << "inode/directory";
QTest::newRow("doesn't exist, no extension") << "IDontExist" << "application/octet-stream";
@ -301,7 +327,11 @@ void tst_QMimeDatabase::mimeTypesForFileName_data()
QTest::newRow("txt, 1 hit") << "foo.txt" << (QStringList() << "text/plain");
QTest::newRow("txtfoobar, 0 hit") << "foo.foobar" << QStringList();
QTest::newRow("m, 2 hits") << "foo.m" << (QStringList() << "text/x-matlab" << "text/x-objcsrc");
QTest::newRow("sub, 3 hits") << "foo.sub" << (QStringList() << "text/x-microdvd" << "text/x-mpsub" << "text/x-subviewer");
if (m_hasFreedesktopOrg)
QTest::newRow("sub, 3 hits") << "foo.sub"
<< (QStringList() << "text/x-microdvd"
<< "text/x-mpsub"
<< "text/x-subviewer");
QTest::newRow("non_ascii") << QString::fromUtf8("AİİA.pdf") << (QStringList() << "application/pdf");
}
@ -334,15 +364,19 @@ void tst_QMimeDatabase::inheritance()
QCOMPARE(wordperfect.parentMimeTypes().join(QString::fromLatin1(",")), QString::fromLatin1("application/octet-stream"));
QVERIFY(wordperfect.inherits(QLatin1String("application/octet-stream")));
QVERIFY(db.mimeTypeForName(QString::fromLatin1("image/svg+xml-compressed")).inherits(QLatin1String("application/x-gzip")));
if (m_hasFreedesktopOrg) {
QVERIFY(db.mimeTypeForName(QString::fromLatin1("image/svg+xml-compressed"))
.inherits(QLatin1String("application/x-gzip")));
// Check that msword derives from ole-storage
const QMimeType msword = db.mimeTypeForName(QString::fromLatin1("application/msword"));
QVERIFY(msword.isValid());
const QMimeType olestorage = db.mimeTypeForName(QString::fromLatin1("application/x-ole-storage"));
QVERIFY(olestorage.isValid());
QVERIFY(msword.inherits(olestorage.name()));
QVERIFY(msword.inherits(QLatin1String("application/octet-stream")));
// Check that msword derives from ole-storage
const QMimeType msword = db.mimeTypeForName(QString::fromLatin1("application/msword"));
QVERIFY(msword.isValid());
const QMimeType olestorage =
db.mimeTypeForName(QString::fromLatin1("application/x-ole-storage"));
QVERIFY(olestorage.isValid());
QVERIFY(msword.inherits(olestorage.name()));
QVERIFY(msword.inherits(QLatin1String("application/octet-stream")));
}
const QMimeType directory = db.mimeTypeForName(s_inodeMimetype);
QVERIFY(directory.isValid());
@ -379,22 +413,27 @@ void tst_QMimeDatabase::inheritance()
QCOMPARE(allSvgAncestors, QStringList() << QLatin1String("application/xml") << QLatin1String("text/plain") << QLatin1String("application/octet-stream"));
// Check that text/x-mrml knows that it inherits from text/plain (implicitly)
const QMimeType mrml = db.mimeTypeForName(QString::fromLatin1("text/x-mrml"));
const QMimeType mrml = db.mimeTypeForName(QString::fromLatin1(
m_hasFreedesktopOrg ? "text/x-mrml" : "text/vnd.trolltech.linguist"));
QVERIFY(mrml.isValid());
QVERIFY(mrml.inherits(QLatin1String("text/plain")));
QVERIFY(mrml.inherits(QLatin1String("application/octet-stream")));
// Check that msword-template inherits msword
const QMimeType mswordTemplate = db.mimeTypeForName(QString::fromLatin1("application/msword-template"));
QVERIFY(mswordTemplate.isValid());
QVERIFY(mswordTemplate.inherits(QLatin1String("application/msword")));
if (m_hasFreedesktopOrg) {
// Check that msword-template inherits msword
const QMimeType mswordTemplate =
db.mimeTypeForName(QString::fromLatin1("application/msword-template"));
QVERIFY(mswordTemplate.isValid());
QVERIFY(mswordTemplate.inherits(QLatin1String("application/msword")));
// Check that buggy type definitions that have circular inheritance don't cause an infinite
// loop, especially when resolving a conflict between the file's name and its contents
const QMimeType ecmascript = db.mimeTypeForName(QString::fromLatin1("application/ecmascript"));
QVERIFY(ecmascript.allAncestors().contains("text/plain"));
const QMimeType javascript = db.mimeTypeForFileNameAndData("xml.js", "<?xml?>");
QVERIFY(javascript.inherits(QString::fromLatin1("text/javascript")));
// Check that buggy type definitions that have circular inheritance don't cause an infinite
// loop, especially when resolving a conflict between the file's name and its contents
const QMimeType ecmascript =
db.mimeTypeForName(QString::fromLatin1("application/ecmascript"));
QVERIFY(ecmascript.allAncestors().contains("text/plain"));
const QMimeType javascript = db.mimeTypeForFileNameAndData("xml.js", "<?xml?>");
QVERIFY(javascript.inherits(QString::fromLatin1("text/javascript")));
}
}
void tst_QMimeDatabase::aliases()
@ -421,9 +460,20 @@ void tst_QMimeDatabase::listAliases_data()
QTest::addColumn<QString>("inputMime");
QTest::addColumn<QString>("expectedAliases");
QTest::newRow("csv") << "text/csv" << "text/x-csv,text/x-comma-separated-values";
QTest::newRow("xml") << "application/xml" << "text/xml";
QTest::newRow("xml2") << "text/xml" /* gets resolved to application/xml */ << "text/xml";
if (m_hasFreedesktopOrg) {
QTest::newRow("csv") << "text/csv"
<< "text/x-csv,text/x-comma-separated-values";
QTest::newRow("xml") << "application/xml"
<< "text/xml";
QTest::newRow("xml2") << "text/xml" /* gets resolved to application/xml */ << "text/xml";
} else {
QTest::newRow("csv") << "text/csv"
<< "";
QTest::newRow("xml") << "application/xml"
<< "text/xml,application/x-xml";
QTest::newRow("xml2") << "text/xml" /* gets resolved to application/xml */
<< "text/xml,application/x-xml";
}
QTest::newRow("no_mime") << "message/news" << "";
}
@ -452,11 +502,15 @@ void tst_QMimeDatabase::icons()
QMimeType pub = db.mimeTypeForFile(QString::fromLatin1("foo.epub"), QMimeDatabase::MatchExtension);
QCOMPARE(pub.name(), QString::fromLatin1("application/epub+zip"));
QCOMPARE(pub.iconName(), QString::fromLatin1("application-epub+zip"));
QCOMPARE(pub.genericIconName(), QString::fromLatin1("x-office-document"));
if (m_hasFreedesktopOrg)
QCOMPARE(pub.genericIconName(), QString::fromLatin1("x-office-document"));
}
void tst_QMimeDatabase::comment()
{
if (!m_hasFreedesktopOrg)
QSKIP("Translations not yet available for tika mimetypes");
struct RestoreLocale
{
~RestoreLocale() { QLocale::setDefault(QLocale::c()); }
@ -513,7 +567,7 @@ void tst_QMimeDatabase::mimeTypeForFileWithContent()
// Now the case where extension differs from contents, but contents has >80 magic rule
// XDG spec says: contents wins. But we can't sniff all files...
{
if (m_hasFreedesktopOrg) {
QTemporaryFile txtTempFile(QDir::tempPath() + QLatin1String("/tst_QMimeDatabase_XXXXXX.txt"));
QVERIFY(txtTempFile.open());
txtTempFile.write("<smil");
@ -588,8 +642,12 @@ void tst_QMimeDatabase::mimeTypeForData_data()
QTest::newRow("tnef data, needs smi >= 0.20") << QByteArray("\x78\x9f\x3e\x22") << "application/vnd.ms-tnef";
QTest::newRow("PDF magic") << QByteArray("%PDF-") << "application/pdf";
QTest::newRow("PHP, High-priority rule") << QByteArray("<?php") << "application/x-php";
QTest::newRow("diff\\t") << QByteArray("diff\t") << "text/x-patch";
QTest::newRow("PHP, High-priority rule")
<< QByteArray("<?php") << (m_hasFreedesktopOrg ? "application/x-php" : "text/x-php");
if (m_hasFreedesktopOrg)
QTest::newRow("diff\\t") << QByteArray("diff\t") << "text/x-patch";
else
QTest::newRow("diff_space") << QByteArray("diff ") << "text/x-diff";
QTest::newRow("unknown") << QByteArray("\001abc?}") << "application/octet-stream";
}
@ -624,7 +682,9 @@ void tst_QMimeDatabase::mimeTypeForFileNameAndData_data()
// If you get powerpoint instead, then you're hit by https://bugs.freedesktop.org/show_bug.cgi?id=435,
// upgrade to shared-mime-info >= 0.22
const QByteArray oleData("\320\317\021\340\241\261\032\341"); // same as \xD0\xCF\x11\xE0 \xA1\xB1\x1A\xE1
QTest::newRow("msword file, unknown extension") << QString::fromLatin1("mswordfile") << oleData << "application/x-ole-storage";
if (m_hasFreedesktopOrg)
QTest::newRow("msword file, unknown extension")
<< QString::fromLatin1("mswordfile") << oleData << "application/x-ole-storage";
QTest::newRow("excel file, found by extension") << QString::fromLatin1("excelfile.xls") << oleData << "application/vnd.ms-excel";
QTest::newRow("text.xls, found by extension, user is in control") << QString::fromLatin1("text.xls") << oleData << "application/vnd.ms-excel";
}
@ -654,6 +714,9 @@ void tst_QMimeDatabase::mimeTypeForUnixSpecials_data()
#ifndef AT_FDCWD
QSKIP("fdopendir and fstatat are not available");
#else
if (!m_hasFreedesktopOrg)
QSKIP("Special devices are not available in tika");
QTest::addColumn<QString>("name");
QTest::addColumn<QString>("expected");
@ -735,7 +798,10 @@ void tst_QMimeDatabase::allMimeTypes()
QVERIFY(!lst.isEmpty());
// Hardcoding this is the only way to check both providers find the same number of mimetypes.
QCOMPARE(lst.size(), 908);
if (m_hasFreedesktopOrg)
QCOMPARE(lst.size(), 908);
else
QCOMPARE(lst.size(), 1640); // interestingly, tika has more mimetypes (but many are empty)
for (const QMimeType &mime : lst) {
const QString name = mime.name();
@ -757,15 +823,27 @@ void tst_QMimeDatabase::suffixes_data()
QTest::newRow("mimetype-with-multiple-patterns-kpr") << "application/x-kpresenter" << "*.kpr;*.kpt" << "kpr";
// The preferred suffix for image/jpeg is *.jpg, as per https://bugs.kde.org/show_bug.cgi?id=176737
QTest::newRow("jpeg") << "image/jpeg"
<< "*.jfif;*.jpe;*.jpg;*.jpeg"
<< (m_hasFreedesktopOrg ? "*.jfif;*.jpe;*.jpg;*.jpeg"
: "*.jfi;*.jfif;*.jif;*.jpe;*.jpeg;*.jpg")
<< "jpg";
QTest::newRow("mimetype with many patterns") << "application/vnd.wordperfect" << "*.wp;*.wp4;*.wp5;*.wp6;*.wpd;*.wpp" << "wp";
QTest::newRow("mimetype with many patterns")
<< "application/vnd.wordperfect"
<< (m_hasFreedesktopOrg ? "*.wp;*.wp4;*.wp5;*.wp6;*.wpd;*.wpp"
: "*.w60;*.wp;*.wp5;*.wp6;*.wp61;*.wpd;*.wpt")
<< (m_hasFreedesktopOrg ? "wp" : "wpd");
QTest::newRow("oasis text mimetype") << "application/vnd.oasis.opendocument.text" << "*.odt" << "odt";
QTest::newRow("oasis presentation mimetype") << "application/vnd.oasis.opendocument.presentation" << "*.odp" << "odp";
QTest::newRow("mimetype-multiple-patterns-text-plain") << "text/plain" << "*.asc;*.txt;*,v" << "txt";
QTest::newRow("mimetype with uncommon pattern") << "text/x-readme" << "README*" << QString();
QTest::newRow("mimetype with no patterns") << "application/x-ole-storage" << QString() << QString();
QTest::newRow("default_mimetype") << "application/octet-stream" << QString() << QString();
if (m_hasFreedesktopOrg) { // tika has a very very long list of patterns for text/plain
QTest::newRow("mimetype-multiple-patterns-text-plain") << "text/plain"
<< "*.asc;*.txt;*,v"
<< "txt";
QTest::newRow("mimetype with uncommon pattern") << "text/x-readme"
<< "README*" << QString();
}
QTest::newRow("mimetype with no patterns")
<< "application/x-zerosize" << QString() << QString();
if (m_hasFreedesktopOrg) // tika has a long list of patterns for application/octet-stream
QTest::newRow("default_mimetype") << "application/octet-stream" << QString() << QString();
}
void tst_QMimeDatabase::suffixes()
@ -793,8 +871,13 @@ void tst_QMimeDatabase::knownSuffix()
QCOMPARE(db.suffixForFileName(QString::fromLatin1("foo.bar.bz2")), QString::fromLatin1("bz2"));
QCOMPARE(db.suffixForFileName(QString::fromLatin1("foo.tar.bz2")), QString::fromLatin1("tar.bz2"));
QCOMPARE(db.suffixForFileName(QString::fromLatin1("foo.TAR")), QString::fromLatin1("TAR")); // preserve case
QCOMPARE(db.suffixForFileName(QString::fromLatin1("foo.flatpakrepo")), QString::fromLatin1("flatpakrepo"));
QCOMPARE(db.suffixForFileName(QString::fromLatin1("foo.anim2")), QString()); // the glob is anim[0-9], no way to extract the extension without expensive regexp capturing
if (m_hasFreedesktopOrg) {
QCOMPARE(db.suffixForFileName(QString::fromLatin1("foo.flatpakrepo")),
QString::fromLatin1("flatpakrepo"));
QCOMPARE(db.suffixForFileName(QString::fromLatin1("foo.anim2")),
QString()); // the glob is anim[0-9], no way to extract the extension without
// expensive regexp capturing
}
}
void tst_QMimeDatabase::filterString_data()
@ -802,10 +885,15 @@ void tst_QMimeDatabase::filterString_data()
QTest::addColumn<QString>("mimeType");
QTest::addColumn<QString>("expectedFilterString");
QTest::newRow("single-pattern") << "application/pdf"
<< "PDF document (*.pdf)";
QTest::newRow("multiple-patterns-text-plain") << "text/plain"
<< "Plain text document (*.txt *.asc *,v)";
QTest::newRow("single-pattern")
<< "application/pdf"
<< (m_hasFreedesktopOrg ? "PDF document (*.pdf)" : "Portable Document Format (*.pdf)");
if (m_hasFreedesktopOrg)
QTest::newRow("multiple-patterns-text-plain") << "text/plain"
<< "Plain text document (*.txt *.asc *,v)";
else
QTest::newRow("multiple-patterns-kword") << "application/vnd.kde.kword"
<< "KWord File (*.kwd *.kwt)";
}
void tst_QMimeDatabase::filterString()
@ -820,6 +908,9 @@ void tst_QMimeDatabase::filterString()
void tst_QMimeDatabase::symlinkToFifo() // QTBUG-48529
{
#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)
if (!m_hasFreedesktopOrg)
QSKIP("Special devices are not available in tika");
QTemporaryDir tempDir;
QVERIFY(tempDir.isValid());
const QString dir = tempDir.path();
@ -1081,7 +1172,7 @@ void copyFiles(const QSpan<const char *const> &additionalMimeFiles, const QStrin
{
const QString notFoundErrorMessage = QString::fromLatin1("Cannot find '%1'");
for (const char *mimeFile : additionalMimeFiles) {
const QString resourceFilePath = s_resourcePrefix + QLatin1String(mimeFile);
const QString resourceFilePath = s_additionalFilesResourcePrefix + QLatin1String(mimeFile);
QVERIFY2(QFile::exists(resourceFilePath),
qPrintable(notFoundErrorMessage.arg(resourceFilePath)));
@ -1131,17 +1222,17 @@ void tst_QMimeDatabase::installNewGlobalMimeType()
checkHasMimeType("text/x-suse-ymp");
// Test that a double-definition of a mimetype doesn't lead to sniffing ("conflicting globs").
const QString qmlTestFile = s_resourcePrefix + "test.qml"_L1;
const QString qmlTestFile = s_additionalFilesResourcePrefix + "test.qml"_L1;
QVERIFY2(!qmlTestFile.isEmpty(),
qPrintable(QString::fromLatin1("Cannot find '%1' starting from '%2'").
arg("test.qml", QDir::currentPath())));
QCOMPARE(db.mimeTypeForFile(qmlTestFile).name(),
QString::fromLatin1("text/x-qml"));
const QString fooTestFile = s_resourcePrefix + "magic-and-hierarchy.foo"_L1;
const QString fooTestFile = s_additionalFilesResourcePrefix + "magic-and-hierarchy.foo"_L1;
QCOMPARE(db.mimeTypeForFile(fooTestFile).name(), QString::fromLatin1("application/foo"));
const QString fooTestFile2 = s_resourcePrefix + "magic-and-hierarchy2.foo"_L1;
const QString fooTestFile2 = s_additionalFilesResourcePrefix + "magic-and-hierarchy2.foo"_L1;
QCOMPARE(db.mimeTypeForFile(fooTestFile2).name(), QString::fromLatin1("application/vnd.qnx.bar-descriptor"));
// Test if we can use the default comment
@ -1235,7 +1326,7 @@ void tst_QMimeDatabase::installNewLocalMimeType()
QString::fromLatin1("text/plain"));
// Test that a double-definition of a mimetype doesn't lead to sniffing ("conflicting globs").
const QString qmlTestFile = s_resourcePrefix + "test.qml"_L1;
const QString qmlTestFile = s_additionalFilesResourcePrefix + "test.qml"_L1;
QVERIFY2(!qmlTestFile.isEmpty(),
qPrintable(QString::fromLatin1("Cannot find '%1' starting from '%2'").
arg("test.qml", QDir::currentPath())));
@ -1255,7 +1346,9 @@ void tst_QMimeDatabase::installNewLocalMimeType()
// QTBUG-116905: globPatterns() should merge all locations
// add-extension.xml adds *.jnewext
const QStringList expectedJpegPatterns{ "*.jpg", "*.jpeg", "*.jpe", "*.jfif", "*.jnewext" };
const auto expectedJpegPatterns = m_hasFreedesktopOrg
? QStringList{ "*.jpg", "*.jpeg", "*.jpe", "*.jfif", "*.jnewext" }
: QStringList{ "*.jpg", "*.jpeg", "*.jpe", "*.jif", "*.jfif", "*.jfi", "*.jnewext" };
QCOMPARE(db.mimeTypeForName(QStringLiteral("image/jpeg")).globPatterns(), expectedJpegPatterns);
// Now that we have two directories with mime definitions, check that everything still works

View File

@ -69,6 +69,8 @@ private slots:
private:
void initTestCaseInternal(); // test-specific
bool useCacheProvider() const; // test-specific
bool useFreeDesktopOrgXml() const; // test-specific
QString m_globalXdgDir;
QString m_localMimeDir;
@ -77,6 +79,7 @@ private:
QTemporaryDir m_temporaryDir;
QString m_testSuite;
bool m_isUsingCacheProvider;
bool m_hasFreedesktopOrg = false;
};
#endif // TST_QMIMEDATABASE_H