13#include <QXmlStreamReader>
17#include <QByteArrayMatcher>
22#if QT_CONFIG(mimetype_database)
23# if defined(Q_CC_MSVC_ONLY)
24# pragma section(".qtmimedatabase", read, shared)
25__declspec(allocate(
".qtmimedatabase")) __declspec(align(4096))
26# elif defined(Q_OS_DARWIN)
28# elif (defined(Q_OF_ELF) || defined(Q_OS_WIN)) && defined(Q_CC_GNU)
32# include "qmimeprovider_database.cpp"
34# ifdef MIME_DATABASE_IS_ZSTD
36# error "MIME database is zstd but no support compiled in!"
40# ifdef MIME_DATABASE_IS_GZIP
42# error "MIME database is zlib but no support compiled in!"
88 return reinterpret_cast<const char *
>(
data +
offset);
115 const int major = getUint16(0);
116 const int minor = getUint16(2);
117 m_valid = (major == 1 && minor >= 1 && minor <= 2);
137 return m_cacheFile !=
nullptr;
158bool QMimeBinaryProvider::checkCacheChanged()
164 m_cacheFile->reload();
174 m_cacheFile = std::make_unique<CacheFile>(cacheFileName);
175 m_mimetypeListLoaded =
false;
176 m_mimetypeExtra.
clear();
178 if (checkCacheChanged()) {
179 m_mimetypeListLoaded =
false;
180 m_mimetypeExtra.
clear();
185 if (!m_cacheFile->isValid())
193 data.fromCache =
true;
203 if (!m_mimetypeListLoaded)
220 if (
result.m_matchingMimeTypes.isEmpty()) {
222 const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset);
223 const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4);
224 matchSuffixTree(
result, m_cacheFile.get(), numRoots, firstRootOffset, lowerFileName,
225 lowerFileName.
size() - 1,
false);
226 if (
result.m_matchingMimeTypes.isEmpty())
227 matchSuffixTree(
result, m_cacheFile.get(), numRoots, firstRootOffset,
fileName,
231 if (
result.m_matchingMimeTypes.isEmpty())
236bool QMimeBinaryProvider::isMimeTypeGlobsExcluded(
const char *mimeTypeName)
243 for (
const auto &mt : toExclude)
249 const int numGlobs = cacheFile->getUint32(off);
251 for (
int i = 0;
i < numGlobs; ++
i) {
252 const int globOffset = cacheFile->getUint32(off + 4 + 12 *
i);
253 const int mimeTypeOffset = cacheFile->getUint32(off + 4 + 12 *
i + 4);
254 const int flagsAndWeight = cacheFile->getUint32(off + 4 + 12 *
i + 8);
255 const int weight = flagsAndWeight & 0xff;
256 const bool caseSensitive = flagsAndWeight & 0x100;
260 const char *
mimeType = cacheFile->getCharStar(mimeTypeOffset);
262 if (isMimeTypeGlobsExcluded(
mimeType))
274 qsizetype charPos,
bool caseSensitiveCheck)
278 int max = numEntries - 1;
280 const int mid = (
min + max) / 2;
281 const int off = firstOffset + 12 * mid;
285 else if (
ch > fileChar)
289 int numChildren = cacheFile->
getUint32(off + 4);
290 int childrenOffset = cacheFile->
getUint32(off + 8);
291 bool success =
false;
293 success = matchSuffixTree(
result, cacheFile, numChildren, childrenOffset,
fileName, charPos, caseSensitiveCheck);
295 for (
int i = 0;
i < numChildren; ++
i) {
296 const int childOff = childrenOffset + 12 *
i;
297 const int mch = cacheFile->
getUint32(childOff);
300 const int mimeTypeOffset = cacheFile->
getUint32(childOff + 4);
302 if (isMimeTypeGlobsExcluded(
mimeType))
304 const int flagsAndWeight = cacheFile->
getUint32(childOff + 8);
305 const int weight = flagsAndWeight & 0xff;
306 const bool caseSensitive = flagsAndWeight & 0x100;
307 if (caseSensitiveCheck || !caseSensitive) {
323 const char *dataPtr =
data.constData();
325 for (
int matchlet = 0; matchlet < numMatchlets; ++matchlet) {
326 const int off = firstOffset + matchlet * 32;
327 const int rangeStart = cacheFile->
getUint32(off);
328 const int rangeLength = cacheFile->
getUint32(off + 4);
330 const int valueLength = cacheFile->
getUint32(off + 12);
331 const int valueOffset = cacheFile->
getUint32(off + 16);
332 const int maskOffset = cacheFile->
getUint32(off + 20);
333 const char *
mask = maskOffset ? cacheFile->
getCharStar(maskOffset) :
nullptr;
338 const int numChildren = cacheFile->
getUint32(off + 24);
339 const int firstChildOffset = cacheFile->
getUint32(off + 28);
340 if (numChildren == 0)
343 if (matchMagicRule(cacheFile, numChildren, firstChildOffset,
data))
352 const int numMatches = m_cacheFile->getUint32(magicListOffset);
354 const int firstMatchOffset = m_cacheFile->getUint32(magicListOffset + 8);
356 for (
int i = 0;
i < numMatches; ++
i) {
357 const int off = firstMatchOffset +
i * 16;
358 const int numMatchlets = m_cacheFile->getUint32(off + 8);
359 const int firstMatchletOffset = m_cacheFile->getUint32(off + 12);
360 if (matchMagicRule(m_cacheFile.get(), numMatchlets, firstMatchletOffset,
data)) {
361 const int mimeTypeOffset = m_cacheFile->getUint32(off + 4);
362 const char *
mimeType = m_cacheFile->getCharStar(mimeTypeOffset);
363 *accuracyPtr = m_cacheFile->getUint32(off);
376 const int numEntries = m_cacheFile->getUint32(parentListOffset);
379 int end = numEntries - 1;
381 const int medium = (
begin +
end) / 2;
382 const int off = parentListOffset + 4 + 8 * medium;
383 const int mimeOffset = m_cacheFile->getUint32(off);
384 const char *aMime = m_cacheFile->getCharStar(mimeOffset);
385 const int cmp =
qstrcmp(aMime, mimeStr);
388 }
else if (cmp > 0) {
391 const int parentsOffset = m_cacheFile->getUint32(off + 4);
392 const int numParents = m_cacheFile->getUint32(parentsOffset);
393 for (
int i = 0;
i < numParents; ++
i) {
394 const int parentOffset = m_cacheFile->getUint32(parentsOffset + 4 + 4 *
i);
395 const char *aParent = m_cacheFile->getCharStar(parentOffset);
408 const int numEntries = m_cacheFile->getUint32(aliasListOffset);
410 int end = numEntries - 1;
412 const int medium = (
begin +
end) / 2;
413 const int off = aliasListOffset + 4 + 8 * medium;
414 const int aliasOffset = m_cacheFile->getUint32(off);
415 const char *alias = m_cacheFile->getCharStar(aliasOffset);
419 }
else if (cmp > 0) {
422 const int mimeOffset = m_cacheFile->getUint32(off + 4);
423 const char *
mimeType = m_cacheFile->getCharStar(mimeOffset);
434 const int numEntries = m_cacheFile->getUint32(aliasListOffset);
435 for (
int pos = 0;
pos < numEntries; ++
pos) {
436 const int off = aliasListOffset + 4 + 8 *
pos;
437 const int mimeOffset = m_cacheFile->getUint32(off + 4);
438 const char *
mimeType = m_cacheFile->getCharStar(mimeOffset);
441 const int aliasOffset = m_cacheFile->getUint32(off);
442 const char *alias = m_cacheFile->getCharStar(aliasOffset);
449void QMimeBinaryProvider::loadMimeTypeList()
451 if (!m_mimetypeListLoaded) {
452 m_mimetypeListLoaded =
true;
453 m_mimetypeNames.
clear();
473 for (
const QString &
name : std::as_const(m_mimetypeNames))
476 for (
const QString &
name : std::as_const(m_mimetypeNames))
485#if QT_CONFIG(xmlstreamreader)
498 QFile qfile(mimeFile);
502 auto insertIt = m_mimetypeExtra.
insert(
data.name, MimeTypeExtra{});
504 MimeTypeExtra &extra = insertIt.value();
507 QXmlStreamReader
xml(&qfile);
508 if (
xml.readNextStartElement()) {
509 if (
xml.name() !=
"mime-type"_L1) {
512 const auto name =
xml.attributes().value(
"type"_L1);
516 qWarning() <<
"Got name" <<
name <<
"in file" << mimeFile <<
"expected" <<
data.name;
518 while (
xml.readNextStartElement()) {
519 const auto tag =
xml.name();
520 if (
tag ==
"comment"_L1) {
521 QString lang =
xml.attributes().value(
"xml:lang"_L1).toString();
528 }
else if (
tag ==
"glob-deleteall"_L1) {
529 extra.globPatterns.
clear();
531 }
else if (
tag ==
"glob"_L1) {
538 xml.skipCurrentElement();
546 (extra.globPatterns.isEmpty() || extra.globPatterns.constFirst() != mainPattern)) {
548 extra.globPatterns.removeAll(mainPattern);
549 extra.globPatterns.prepend(mainPattern);
552 const MimeTypeExtra &
e =
it.value();
553 data.localeComments =
e.localeComments;
554 data.globPatterns =
e.globPatterns;
558 qWarning(
"Cannot load mime type since QXmlStreamReader is not available.");
564QLatin1StringView QMimeBinaryProvider::iconForMime(CacheFile *cacheFile,
int posListOffset,
567 const int iconsListOffset = cacheFile->getUint32(posListOffset);
568 const int numIcons = cacheFile->getUint32(iconsListOffset);
570 int end = numIcons - 1;
572 const int medium = (
begin +
end) / 2;
573 const int off = iconsListOffset + 4 + 8 * medium;
574 const int mimeOffset = cacheFile->getUint32(off);
575 const char *
mime = cacheFile->getCharStar(mimeOffset);
582 const int iconOffset = cacheFile->getUint32(off + 4);
593 if (!
icon.isEmpty()) {
602 if (!
icon.isEmpty()) {
609#if QT_CONFIG(mimetype_database)
610static QString internalMimeFileName()
618 static_assert(
sizeof(mimetype_database),
"Bundled MIME database is empty");
619 static_assert(
sizeof(mimetype_database) <= MimeTypeDatabaseOriginalSize,
620 "Compressed MIME database is larger than the original size");
621 static_assert(MimeTypeDatabaseOriginalSize <= 16*1024*1024,
622 "Bundled MIME database is too big");
623 const char *
data =
reinterpret_cast<const char *
>(mimetype_database);
626#ifdef MIME_DATABASE_IS_ZSTD
628 std::unique_ptr<char []> uncompressed(
new char[
size]);
629 size = ZSTD_decompress(uncompressed.get(),
size, mimetype_database,
sizeof(mimetype_database));
631 data = uncompressed.get();
632#elif defined(MIME_DATABASE_IS_GZIP)
633 std::unique_ptr<char []> uncompressed(
new char[
size]);
635 zs.next_in =
const_cast<Bytef *
>(mimetype_database);
636 zs.avail_in =
sizeof(mimetype_database);
637 zs.next_out =
reinterpret_cast<Bytef *
>(uncompressed.get());
640 int res = inflateInit2(&zs, MAX_WBITS | 32);
644 res = inflateEnd(&zs);
647 data = uncompressed.get();
682#if QT_CONFIG(mimetype_database)
702 bool foundOne =
false;
705 const int priority =
matcher.priority();
706 if (priority > *accuracyPtr) {
707 *accuracyPtr = priority;
708 candidateName =
matcher.mimetype();
723 allFiles.reserve(
files.size());
725 allFiles.append(packageDir + u
'/' + xmlFile);
727 if (m_allFiles == allFiles)
729 m_allFiles = allFiles;
731 m_nameMimeTypeMap.
clear();
734 m_mimeTypeGlobs.
clear();
735 m_magicMatchers.
clear();
740 for (
const QString &
file : std::as_const(allFiles))
767#if QT_CONFIG(mimetype_database)
805 for (
const auto &mt : toExclude) {
806 auto it = m_nameMimeTypeMap.
find(mt);
807 if (
it != m_nameMimeTypeMap.
end())
829 for (
const auto &[alias, mimeName] : std::as_const(m_aliases).asKeyValueRange()) {
830 if (mimeName ==
name)
852 if (std::find_if(
result.constBegin(),
result.constEnd(), [newMime](
const QMimeType &
mime) ->
bool { return mime.name() == newMime; })
\inmodule QtCore \reentrant
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
\inmodule QtCore\reentrant
T * data() const noexcept
Returns a pointer to the shared data object.
uchar * map(qint64 offset, qint64 size, MemoryMapFlags flags=NoOptions)
Maps size bytes of the file into memory starting at offset.
bool atEnd() const override
Returns true if the end of the file has been reached; otherwise returns false.
void close() override
Calls QFileDevice::flush() and closes the file.
\inmodule QtCore \reentrant
QDateTime lastModified() const
Returns the date and time when the file was last modified.
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
qint64 size() const override
\reimp
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
iterator find(const Key &key)
Returns an iterator pointing to the item with the key in the hash.
QList< T > values() const
Returns a list containing all the values in the hash, in an arbitrary order.
const_iterator constBegin() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
T value(const Key &key) const noexcept
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
qint64 readLine(char *data, qint64 maxlen)
This function reads a line of ASCII characters from the device, up to a maximum of maxSize - 1 bytes,...
bool isOpen() const
Returns true if the device is open; otherwise returns false.
QString errorString() const
Returns a human-readable description of the last device error that occurred.
void push_back(parameter_type t)
void append(parameter_type t)
iterator insert(const Key &key, const T &value)
const_iterator constFind(const Key &key) const
const_iterator constEnd() const
void addGlob(const QMimeGlobPattern &glob)
void removeMimeType(const QString &mimeType)
void matchingGlobs(const QString &fileName, QMimeGlobMatchResult &result) const
void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override
QString resolveAlias(const QString &name) override
void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override
void ensureLoaded() override
void loadIcon(QMimeTypePrivate &) override
void addAliases(const QString &name, QStringList &result) override
virtual ~QMimeBinaryProvider()
void addAllMimeTypes(QList< QMimeType > &result) override
void addParents(const QString &mime, QStringList &result) override
void loadGenericIcon(QMimeTypePrivate &) override
QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory)
void excludeMimeTypeGlobs(const QStringList &toExclude) override
QMimeType mimeTypeForName(const QString &name) override
bool isInternalDatabase() const override
bool loadMimeTypePrivate(QMimeTypePrivate &) override
The QMimeGlobPattern class contains the glob pattern for file names for MIME type matching.
The QMimeMagicRuleMatcher class checks a number of rules based on operator "or".
static bool matchSubstring(const char *dataPtr, qsizetype dataSize, int rangeStart, int rangeLength, qsizetype valueLength, const char *valueData, const char *mask)
QStringList m_mimeTypesWithExcludedGlobs
QStringList m_mimeTypesWithDeletedGlobs
QMimeProviderBase(QMimeDatabasePrivate *db, const QString &directory)
bool parse(QIODevice *dev, const QString &fileName, QString *errorMessage)
QExplicitlySharedDataPointer< QMimeTypePrivate > d
QString name
the name of the MIME type
void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override
void addGlobPattern(const QMimeGlobPattern &glob)
void addAliases(const QString &name, QStringList &result) override
void addAlias(const QString &alias, const QString &name)
void excludeMimeTypeGlobs(const QStringList &toExclude) override
bool load(const QString &fileName, QString *errorMessage)
void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override
void ensureLoaded() override
bool isInternalDatabase() const override
QString resolveAlias(const QString &name) override
void addParents(const QString &mime, QStringList &result) override
void addAllMimeTypes(QList< QMimeType > &result) override
QMimeType mimeTypeForName(const QString &name) override
QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum)
void addMagicMatcher(const QMimeMagicRuleMatcher &matcher)
void addMimeType(const QMimeType &mt)
void addParent(const QString &child, const QString &parent)
bool contains(const T &value) const
iterator insert(const T &value)
\macro QT_RESTRICTED_CAST_FROM_ASCII
void chop(qsizetype n)
Removes n characters from the end of the string.
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void clear()
Clears the contents of the string and makes it null.
qsizetype size() const
Returns the number of characters in this string.
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
QString & insert(qsizetype i, QChar c)
QString toLower() const &
QSet< QString >::iterator it
Combined button and popup list for selecting options.
constexpr const T & min(const T &a, const T &b)
Q_CORE_EXPORT int qstrcmp(const char *str1, const char *str2)
AudioChannelLayoutTag tag
constexpr T qFromBigEndian(T source)
static QMimeType mimeTypeForNameUnchecked(const QString &name)
@ PosReverseSuffixTreeOffset
@ PosGenericIconsListOffset
static void appendIfNew(QStringList &list, const QString &str)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint GLfloat weight
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLenum GLenum GLenum input
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
Int aligned(Int v, Int byteAlign)
#define qPrintable(string)
#define qUtf16Printable(string)
#define QStringLiteral(str)
static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
static int inflate(Bytef *dest, ulong *destLen, const Bytef *source, ulong sourceLen)
application x qt windows mime
[2]
static const auto matcher
[0]
bool contains(const AT &t) const noexcept
const char * getCharStar(int offset) const
quint16 getUint16(int offset) const
CacheFile(const QString &fileName)
quint32 getUint32(int offset) const
The QMimeGlobMatchResult class accumulates results from glob matching.
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent