10#include <qstandardpaths.h>
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)
27__attribute__((section(
"__TEXT,.qtmimedatabase"), aligned(4096)))
28# elif (defined(Q_OF_ELF) || defined(Q_OS_WIN)) && defined(Q_CC_GNU)
29__attribute__((section(
".qtmimedatabase"), aligned(4096)))
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!"
52using namespace Qt::StringLiterals;
83
84
85
86
87
88
89
90
91
97 bool load(
const CacheFile *cacheFile, quint64 posListOffset, quint32 stride);
99 quint64 firstRecordPos, quint32 stride);
106 Q_ASSERT(index < m_count);
107 return m_firstRecord + quint64(index) * m_stride;
113 bool setRecords(
const CacheFile *cacheFile, quint64 firstRecord,
114 quint32 count, quint32 stride);
116 quint64 m_firstRecord = 0;
117 quint32 m_stride = 0;
129 if (offset > m_fileSize || m_fileSize - offset <
sizeof(quint16))
131 return qFromBigEndian<quint16>(m_data + offset);
135 if (offset > m_fileSize || extra > m_fileSize - offset)
137 const quint64 pos = offset + extra;
138 if (m_fileSize - pos <
sizeof(quint32))
140 return qFromBigEndian<quint32>(m_data + pos);
144 if (offset >= m_fileSize)
145 return QLatin1StringView();
146 const char *str =
reinterpret_cast<
const char *>(m_data + offset);
147 const void *end = std::memchr(str,
'\0', m_fileSize - offset);
149 return QLatin1StringView();
150 return QLatin1StringView(str,
static_cast<
const char *>(end));
152 inline const char *
getData(quint64 offset, quint64 length)
const
154 if (offset > m_fileSize || length > m_fileSize - offset)
156 return reinterpret_cast<
const char *>(m_data + offset);
160 quint32 index, quint32 stride)
const
162 if (base > m_fileSize || headerSize > m_fileSize - base)
164 const quint64 avail = m_fileSize - base - headerSize;
166 if (!stride || index >= avail / stride)
168 return base + headerSize + quint64(index) * stride;
175 const quint64 pos = list.recordOffset(index) + fieldOffset;
176 return qFromBigEndian<quint32>(m_data + pos);
200bool QMimeBinaryProvider::
RecordList::setRecords(
const CacheFile *cacheFile, quint64 firstRecord,
201 quint32 count, quint32 stride)
203 if (!stride || (firstRecord > cacheFile->m_fileSize))
205 if (count > (cacheFile->m_fileSize - firstRecord) / stride)
207 m_firstRecord = firstRecord;
218 const std::optional<quint32> listOffset = cacheFile->getUint32(posListOffset);
221 const std::optional<quint32> n = cacheFile->getUint32(*listOffset);
224 return setRecords(cacheFile, quint64(*listOffset) + 4, *n, stride);
228 quint64 posListOffset, quint64 firstRecordPos,
231 const std::optional<quint32> listOffset = cacheFile->getUint32(posListOffset);
234 const std::optional<quint32> n = cacheFile->getUint32(*listOffset);
235 const std::optional<quint32> first = cacheFile->getUint32(*listOffset + firstRecordPos);
238 return setRecords(cacheFile, *first, *n, stride);
241static inline void appendIfNew(QStringList &list,
const QString &str)
243 if (!list.contains(str))
248 :
m_db(db), m_directory(directory)
290 if (!m_file.open(QIODevice::ReadOnly))
292 const qint64 fileSize = m_file.size();
293 m_fileSize = fileSize > 0 ? fileSize : 0;
294 m_data = m_file.map(0, m_fileSize);
295 if (m_data && m_fileSize >= 4) {
296 const quint16 major = *getUint16(0);
297 const quint16 minor = *getUint16(2);
298 m_valid = (major == 1 && minor >= 1 && minor <= 2)
299 && m_aliases.load(
this, PosAliasListOffset, AliasRecordSize)
300 && m_parents.load(
this, PosParentListOffset, ParentRecordSize)
301 && m_literals.load(
this, PosLiteralListOffset, GlobRecordSize)
302 && m_globs.load(
this, PosGlobListOffset, GlobRecordSize)
303 && m_icons.load(
this, PosIconsListOffset, IconRecordSize)
304 && m_genericIcons.load(
this, PosGenericIconsListOffset, IconRecordSize)
305 && m_suffixTreeRoots.loadIndirect(
this, PosReverseSuffixTreeOffset,
306 PosFirstRootOffset, SuffixNodeSize)
307 && m_magicMatches.loadIndirect(
this, PosMagicListOffset, PosFirstMatchOffset,
310 m_mtime = QFileInfo(m_file).lastModified(QTimeZone::UTC);
317 if (m_file.isOpen()) {
322 m_aliases = RecordList();
323 m_parents = RecordList();
324 m_literals = RecordList();
325 m_globs = RecordList();
326 m_suffixTreeRoots = RecordList();
327 m_magicMatches = RecordList();
328 m_icons = RecordList();
329 m_genericIcons = RecordList();
337 return m_cacheFile !=
nullptr;
345bool QMimeBinaryProvider::checkCacheChanged()
347 QFileInfo fileInfo(m_cacheFile->m_file);
348 if (fileInfo.lastModified(QTimeZone::UTC) > m_cacheFile->m_mtime) {
351 m_cacheFile->reload();
360 const QString cacheFileName = m_directory +
"/mime.cache"_L1;
361 m_cacheFile = std::make_unique<CacheFile>(cacheFileName);
362 m_mimetypeListLoaded =
false;
363 m_mimetypeExtra.clear();
365 if (checkCacheChanged()) {
366 m_mimetypeListLoaded =
false;
367 m_mimetypeExtra.clear();
372 if (!m_cacheFile->isValid())
378 if (!m_mimetypeListLoaded)
380 return m_mimetypeNames.contains(name);
385 if (fileName.isEmpty())
387 Q_ASSERT(m_cacheFile);
389 quint32 numMatches = matchGlobList(result, m_cacheFile.get(), m_cacheFile->m_literals, fileName);
391 if (numMatches == 0) {
392 const QString lowerFileName = fileName.toLower();
393 const RecordList &roots = m_cacheFile->m_suffixTreeRoots;
394 if (matchSuffixTree(result, m_cacheFile.get(), roots.count(), roots.firstRecord(),
395 lowerFileName, lowerFileName.size() - 1,
false)) {
397 }
else if (matchSuffixTree(result, m_cacheFile.get(), roots.count(), roots.firstRecord(),
398 fileName, fileName.size() - 1,
true)) {
404 matchGlobList(result, m_cacheFile.get(), m_cacheFile->m_globs, fileName);
407quint32 QMimeBinaryProvider::matchGlobList(QMimeGlobMatchResult &result,
CacheFile *cacheFile,
408 const RecordList &globs,
const QString &fileName)
410 quint32 numMatches = 0;
412 for (quint32 i = 0; i < globs.count(); ++i) {
413 const quint32 globOffset = cacheFile->recordUint32(globs, i, 0);
414 const quint32 mimeTypeOffset = cacheFile->recordUint32(globs, i, 4);
415 const quint32 flagsAndWeight = cacheFile->recordUint32(globs, i, 8);
416 const quint32 weight = flagsAndWeight & 0xff;
417 const bool caseSensitive = flagsAndWeight & 0x100;
418 const Qt::CaseSensitivity qtCaseSensitive = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
419 const QLatin1StringView patternL1 = cacheFile->getLatin1String(globOffset);
420 const QLatin1StringView mimeType = cacheFile->getLatin1String(mimeTypeOffset);
421 if (patternL1.isNull() || mimeType.isNull())
425 if (isMimeTypeGlobsExcluded(mimeType))
428 const QString pattern = patternL1;
430 if (glob.matchFileName(fileName)) {
431 result.addMatch(mimeType, weight, pattern);
438bool QMimeBinaryProvider::matchSuffixTree(QMimeGlobMatchResult &result,
439 QMimeBinaryProvider::
CacheFile *cacheFile, quint32 numEntries,
440 quint64 firstOffset,
const QString &fileName,
441 qsizetype charPos,
bool caseSensitiveCheck)
443 QChar fileChar = fileName[charPos];
444 if (fileChar.isNull())
449 quint32 max = numEntries - 1;
451 const quint32 mid = (min + max) / 2;
452 const std::optional<quint64> off = cacheFile->safeRecordOffset(firstOffset, 0, mid,
SuffixNodeSize);
455 const std::optional<quint32> chValue = cacheFile->getUint32(*off);
458 const QChar ch =
char16_t(*chValue);
461 }
else if (ch > fileChar) {
467 const std::optional<quint32> numChildrenOpt = cacheFile->getUint32(*off, 4);
468 const std::optional<quint32> childrenOffsetOpt = cacheFile->getUint32(*off, 8);
469 if (!numChildrenOpt || !childrenOffsetOpt)
471 const quint32 numChildren = *numChildrenOpt;
472 const quint32 childrenOffset = *childrenOffsetOpt;
473 bool success =
false;
475 success = matchSuffixTree(result, cacheFile, numChildren, childrenOffset, fileName, charPos, caseSensitiveCheck);
477 for (quint32 i = 0; i < numChildren; ++i) {
478 const std::optional<quint64> childOff =
479 cacheFile->safeRecordOffset(childrenOffset, 0, i,
SuffixNodeSize);
482 const std::optional<quint32> mchOpt = cacheFile->getUint32(*childOff);
487 const std::optional<quint32> mimeTypeOffset = cacheFile->getUint32(*childOff, 4);
488 const std::optional<quint32> flagsAndWeight = cacheFile->getUint32(*childOff, 8);
489 if (!mimeTypeOffset || !flagsAndWeight)
491 const QLatin1StringView mimeType = cacheFile->getLatin1String(*mimeTypeOffset);
492 if (mimeType.isNull())
494 if (isMimeTypeGlobsExcluded(mimeType))
496 const quint32 weight = *flagsAndWeight & 0xff;
497 const bool caseSensitive = *flagsAndWeight & 0x100;
498 if (caseSensitiveCheck || !caseSensitive) {
499 result.addMatch(mimeType, weight,
500 u'*' + QStringView{ fileName }.mid(charPos + 1),
501 fileName.size() - charPos - 2);
512bool QMimeBinaryProvider::matchMagicRule(QMimeBinaryProvider::
CacheFile *cacheFile, quint32 numMatchlets, quint64 firstOffset,
const QByteArray &data)
514 const char *dataPtr = data.constData();
515 const qsizetype dataSize = data.size();
516 for (quint32 matchlet = 0; matchlet < numMatchlets; ++matchlet) {
517 const std::optional<quint64> off = cacheFile->safeRecordOffset(firstOffset, 0, matchlet,
MagicMatchletSize);
520 const std::optional<quint32> rangeStartOpt = cacheFile->getUint32(*off);
521 const std::optional<quint32> rangeLengthOpt = cacheFile->getUint32(*off, 4);
523 const std::optional<quint32> valueLengthOpt = cacheFile->getUint32(*off, 12);
524 const std::optional<quint32> valueOffsetOpt = cacheFile->getUint32(*off, 16);
525 const std::optional<quint32> maskOffsetOpt = cacheFile->getUint32(*off, 20);
526 if (!rangeStartOpt || !rangeLengthOpt || !valueLengthOpt || !valueOffsetOpt
529 const quint32 rangeStart = *rangeStartOpt;
530 const quint32 rangeLength = *rangeLengthOpt;
531 const quint32 valueLength = *valueLengthOpt;
532 const quint32 valueOffset = *valueOffsetOpt;
533 const quint32 maskOffset = *maskOffsetOpt;
534 const char *value = cacheFile->getData(valueOffset, valueLength);
535 const char *mask = maskOffset ? cacheFile->getData(maskOffset, valueLength) :
nullptr;
536 if (!value || (maskOffset && !mask))
539 if (!QMimeMagicRule::matchSubstring(dataPtr, dataSize, rangeStart, rangeLength, valueLength, value, mask))
542 const std::optional<quint32> numChildrenOpt = cacheFile->getUint32(*off, 24);
543 const std::optional<quint32> firstChildOffsetOpt = cacheFile->getUint32(*off, 28);
544 if (!numChildrenOpt || !firstChildOffsetOpt)
546 const quint32 numChildren = *numChildrenOpt;
547 const quint32 firstChildOffset = *firstChildOffsetOpt;
548 if (numChildren == 0)
551 if (matchMagicRule(cacheFile, numChildren, firstChildOffset, data))
559 const RecordList &matches = m_cacheFile->m_magicMatches;
560 for (quint32 i = 0; i < matches.count(); ++i) {
561 const quint32 numMatchlets = m_cacheFile->recordUint32(matches, i, 8);
562 const quint32 firstMatchletOffset = m_cacheFile->recordUint32(matches, i, 12);
563 if (matchMagicRule(m_cacheFile.get(), numMatchlets, firstMatchletOffset, data)) {
564 const int accuracy =
static_cast<
int>(m_cacheFile->recordUint32(matches, i, 0));
566 const quint32 mimeTypeOffset = m_cacheFile->recordUint32(matches, i, 4);
567 const QLatin1StringView candidate = m_cacheFile->getLatin1String(mimeTypeOffset);
568 if (candidate.isNull())
571 result.candidate = candidate;
579void QMimeBinaryProvider::
addParents(
const QString &mime, QStringList &result)
581 const RecordList &parentList = m_cacheFile->m_parents;
582 const quint32 count = parentList.count();
586 quint32 end = count - 1;
587 while (begin <= end) {
588 const quint32 medium = (begin + end) / 2;
589 const quint32 mimeOffset = m_cacheFile->recordUint32(parentList, medium, 0);
590 const QLatin1StringView aMime = m_cacheFile->getLatin1String(mimeOffset);
593 const int cmp = aMime.compare(mime);
596 }
else if (cmp > 0) {
603 const quint32 parentsOffset = m_cacheFile->recordUint32(parentList, medium, 4);
604 const std::optional<quint32> numParentsOpt = m_cacheFile->getUint32(parentsOffset);
607 const quint32 numParents = *numParentsOpt;
608 for (quint32 i = 0; i < numParents; ++i) {
609 const std::optional<quint64> parentOff =
610 m_cacheFile->safeRecordOffset(parentsOffset, 4, i, 4);
613 const std::optional<quint32> parentOffsetOpt = m_cacheFile->getUint32(*parentOff);
614 if (!parentOffsetOpt)
616 const QLatin1StringView parentL1 = m_cacheFile->getLatin1String(*parentOffsetOpt);
617 if (parentL1.isNull())
619 appendIfNew(result, QString(parentL1));
628 const RecordList &aliases = m_cacheFile->m_aliases;
630 const quint32 count = aliases.count();
633 quint32 end = count - 1;
634 while (begin <= end) {
635 const quint32 medium = (begin + end) / 2;
636 const quint32 aliasOffset = m_cacheFile->recordUint32(aliases, medium, 0);
637 const QLatin1StringView alias = m_cacheFile->getLatin1String(aliasOffset);
640 const int cmp = alias.compare(name);
643 }
else if (cmp > 0) {
648 const quint32 mimeOffset = m_cacheFile->recordUint32(aliases, medium, 4);
650 return m_cacheFile->getLatin1String(mimeOffset);
656void QMimeBinaryProvider::
addAliases(
const QString &name, QStringList &result)
658 const RecordList &aliases = m_cacheFile->m_aliases;
659 for (quint32 pos = 0; pos < aliases.count(); ++pos) {
660 const quint32 mimeOffset = m_cacheFile->recordUint32(aliases, pos, 4);
661 const QLatin1StringView mimeType = m_cacheFile->getLatin1String(mimeOffset);
662 if (mimeType.isNull())
665 if (name == QLatin1StringView(mimeType)) {
666 const quint32 aliasOffset = m_cacheFile->recordUint32(aliases, pos, 0);
667 const QLatin1StringView aliasL1 = m_cacheFile->getLatin1String(aliasOffset);
668 if (aliasL1.isNull())
670 appendIfNew(result, QString(aliasL1));
675void QMimeBinaryProvider::loadMimeTypeList()
677 if (!m_mimetypeListLoaded) {
678 m_mimetypeListLoaded =
true;
679 m_mimetypeNames.clear();
682 QFile file(m_directory + QStringView(u"/types"));
683 if (file.open(QIODevice::ReadOnly)) {
685 while (file.readLineInto(&line)) {
686 auto lineView = QByteArrayView(line);
687 if (lineView.endsWith(
'\n'))
689 m_mimetypeNames.insert(QString::fromLatin1(lineView));
698 if (result.isEmpty()) {
699 result.reserve(m_mimetypeNames.size());
700 for (
const QString &name : std::as_const(m_mimetypeNames))
701 result.append(QMimeType(QMimeTypePrivate(name)));
703 for (
const QString &name : std::as_const(m_mimetypeNames))
704 if (std::find_if(result.constBegin(), result.constEnd(), [name](
const QMimeType &mime) ->
bool {
return mime.name() == name; })
705 == result.constEnd())
706 result.append(QMimeType(QMimeTypePrivate(name)));
712 MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name);
713 if (it != m_mimetypeExtra.cend())
714 return it->second.localeComments;
720 MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name);
721 if (it != m_mimetypeExtra.cend())
722 return it->second.hasGlobDeleteAll;
728 MimeTypeExtraMap::const_iterator it = loadMimeTypeExtra(name);
729 if (it != m_mimetypeExtra.cend())
730 return it->second.globPatterns;
734QMimeBinaryProvider::MimeTypeExtraMap::const_iterator
735QMimeBinaryProvider::loadMimeTypeExtra(
const QString &mimeName)
737#if QT_CONFIG(xmlstreamreader)
738 auto [it, insertionOccurred] = m_mimetypeExtra.try_emplace(mimeName);
739 if (insertionOccurred) {
744 const QString mimeFile = m_directory + u'/' + mimeName.toLower() +
".xml"_L1;
745 qfile.setFileName(mimeFile);
746 if (!qfile.open(QFile::ReadOnly)) {
747 const QString fallbackMimeFile = m_directory + u'/' + mimeName +
".xml"_L1;
748 qfile.setFileName(fallbackMimeFile);
749 if (!qfile.open(QFile::ReadOnly))
753 MimeTypeExtra &extra = it->second;
756 QXmlStreamReader xml(&qfile);
757 if (xml.readNextStartElement()) {
758 if (xml.name() !=
"mime-type"_L1) {
759 return m_mimetypeExtra.cend();
761 const auto name = xml.attributes().value(
"type"_L1);
763 return m_mimetypeExtra.cend();
764 if (name.compare(mimeName, Qt::CaseInsensitive))
765 qWarning() <<
"Got name" << name <<
"in file" << mimeFile <<
"expected" << mimeName;
767 while (xml.readNextStartElement()) {
768 const auto tag = xml.name();
769 if (tag ==
"comment"_L1) {
770 QString lang = xml.attributes().value(
"xml:lang"_L1).toString();
771 const QString text = xml.readElementText();
772 if (lang.isEmpty()) {
775 extra.localeComments.insert(lang, text);
777 }
else if (tag ==
"glob-deleteall"_L1) {
778 extra.hasGlobDeleteAll =
true;
779 }
else if (tag ==
"glob"_L1) {
780 const QString pattern = xml.attributes().value(
"pattern"_L1).toString();
781 if (mainPattern.isEmpty() && pattern.startsWith(u'*')) {
782 mainPattern = pattern;
784 appendIfNew(extra.globPatterns, pattern);
786 xml.skipCurrentElement();
788 Q_ASSERT(xml.name() ==
"mime-type"_L1);
793 if (!mainPattern.isEmpty() &&
794 (extra.globPatterns.isEmpty() || extra.globPatterns.constFirst() != mainPattern)) {
796 extra.globPatterns.removeAll(mainPattern);
797 extra.globPatterns.prepend(mainPattern);
803 qWarning(
"Cannot load mime type since QXmlStreamReader is not available.");
804 return m_mimetypeExtra.cend();
809QLatin1StringView QMimeBinaryProvider::iconForMime(
CacheFile *cacheFile,
const RecordList &icons,
810 QStringView inputMime)
813 const quint32 count = icons.count();
815 return QLatin1StringView();
816 quint32 end = count - 1;
817 while (begin <= end) {
818 const quint32 medium = (begin + end) / 2;
819 const quint32 mimeOffset = cacheFile->recordUint32(icons, medium, 0);
820 const QLatin1StringView mime = cacheFile->getLatin1String(mimeOffset);
823 const int cmp = mime.compare(inputMime);
826 }
else if (cmp > 0) {
831 const quint32 iconOffset = cacheFile->recordUint32(icons, medium, 4);
833 return cacheFile->getLatin1String(iconOffset);
836 return QLatin1StringView();
841 return iconForMime(m_cacheFile.get(), m_cacheFile->m_icons, name);
846 return iconForMime(m_cacheFile.get(), m_cacheFile->m_genericIcons, name);
851#if QT_CONFIG(mimetype_database)
852static QString internalMimeFileName()
854 return QStringLiteral(
"<internal MIME data>");
857QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum)
858 : QMimeProviderBase(db, internalMimeFileName())
860 static_assert(
sizeof(mimetype_database),
"Bundled MIME database is empty");
861 static_assert(
sizeof(mimetype_database) <= MimeTypeDatabaseOriginalSize,
862 "Compressed MIME database is larger than the original size");
863 static_assert(MimeTypeDatabaseOriginalSize <= 16*1024*1024,
864 "Bundled MIME database is too big");
865 const char *data =
reinterpret_cast<
const char *>(mimetype_database);
866 qsizetype size = MimeTypeDatabaseOriginalSize;
868#ifdef MIME_DATABASE_IS_ZSTD
870 std::unique_ptr<
char []> uncompressed(
new char[size]);
871 size = ZSTD_decompress(uncompressed.get(), size, mimetype_database,
sizeof(mimetype_database));
872 Q_ASSERT(!ZSTD_isError(size));
873 data = uncompressed.get();
874#elif defined(MIME_DATABASE_IS_GZIP)
875 std::unique_ptr<
char []> uncompressed(
new char[size]);
877 zs.next_in =
const_cast<Bytef *>(mimetype_database);
878 zs.avail_in =
sizeof(mimetype_database);
879 zs.next_out =
reinterpret_cast<Bytef *>(uncompressed.get());
882 int res = inflateInit2(&zs, MAX_WBITS | 32);
883 Q_ASSERT(res == Z_OK);
884 res = inflate(&zs, Z_FINISH);
885 Q_ASSERT(res == Z_STREAM_END);
886 res = inflateEnd(&zs);
887 Q_ASSERT(res == Z_OK);
889 data = uncompressed.get();
924#if QT_CONFIG(mimetype_database)
925 return m_directory == internalMimeFileName();
933 return m_nameMimeTypeMap.contains(name);
938 auto filterFunc = [
this](
const QString &name) {
return !isMimeTypeGlobsExcluded(name); };
939 m_mimeTypeGlobs.matchingGlobs(fileName, result, filterFunc);
944 for (
const QMimeMagicRuleMatcher &matcher : std::as_const(m_magicMatchers)) {
945 if (matcher.matches(data)) {
946 const int priority = matcher.priority();
947 if (priority < result.accuracy)
949 if (priority == result.accuracy) {
950 if (m_db->inherits(result.candidate, matcher.mimetype()))
953 if (!m_db->inherits(matcher.mimetype(), result.candidate)) {
956 qWarning(
"QMimeXMLProvider: MimeType is ambiguous between %ls and %ls",
957 qUtf16Printable(result.candidate),
958 qUtf16Printable(matcher.mimetype()));
963 result.accuracy = priority;
964 result.candidate = matcher.mimetype();
971 QStringList allFiles;
972 const QString packageDir = m_directory + QStringView(u"/packages");
973 for (
const auto &entry : QDirListing(packageDir, QDirListing::IteratorFlag::FilesOnly
974 | QDirListing::IteratorFlag::ResolveSymlinks))
975 allFiles.emplace_back(packageDir + u'/' + entry.fileName());
977 if (m_allFiles == allFiles)
979 m_allFiles = allFiles;
981 m_nameMimeTypeMap.clear();
985 m_magicMatchers.clear();
989 for (
const QString &file : std::as_const(allFiles))
995 return m_nameMimeTypeMap.value(name).localeComments;
1000 return m_nameMimeTypeMap.value(name).hasGlobDeleteAll;
1005 return m_nameMimeTypeMap.value(name).globPatterns;
1010 return m_nameMimeTypeMap.value(name).iconName;
1015 return m_nameMimeTypeMap.value(name).genericIconName;
1018void QMimeXMLProvider::load(
const QString &fileName)
1020 QString errorMessage;
1021 if (!load(fileName, &errorMessage))
1022 qWarning(
"QMimeDatabase: Error loading %ls\n%ls", qUtf16Printable(fileName), qUtf16Printable(errorMessage));
1025bool QMimeXMLProvider::
load(
const QString &fileName, QString *errorMessage)
1027 QFile file(fileName);
1028 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
1030 *errorMessage =
"Cannot open "_L1 + fileName +
": "_L1 + file.errorString();
1035 errorMessage->clear();
1038 return parser.parse(&file, fileName, errorMessage);
1041#if QT_CONFIG(mimetype_database)
1042void QMimeXMLProvider::load(
const char *data, qsizetype len)
1045 buffer.setData(QByteArray::fromRawData(data, len));
1046 buffer.open(QIODevice::ReadOnly);
1047 QString errorMessage;
1048 QMimeTypeParser parser(*
this);
1049 if (!parser.parse(&buffer, internalMimeFileName(), &errorMessage))
1050 qWarning(
"QMimeDatabase: Error loading internal MIME data\n%s", qPrintable(errorMessage));
1061 m_nameMimeTypeMap.insert(mt.name, mt);
1064void QMimeXMLProvider::
addParents(
const QString &mime, QStringList &result)
1066 const QStringList parents = m_parents.value(mime);
1067 for (
const QString &parent : parents) {
1068 if (!result.contains(parent))
1069 result.append(parent);
1073void QMimeXMLProvider::
addParent(
const QString &child,
const QString &parent)
1075 m_parents[child].append(parent);
1078void QMimeXMLProvider::
addAliases(
const QString &name, QStringList &result)
1081 for (
const auto &[alias, mimeName] : std::as_const(m_aliases).asKeyValueRange()) {
1082 if (mimeName == name)
1083 appendIfNew(result, alias);
1089 return m_aliases.value(name);
1092void QMimeXMLProvider::
addAlias(
const QString &alias,
const QString &name)
1094 m_aliases.insert(alias, name);
1099 if (result.isEmpty()) {
1100 for (
auto it = m_nameMimeTypeMap.constBegin(), end = m_nameMimeTypeMap.constEnd();
1102 result.append(QMimeType(QMimeTypePrivate(it.value().name)));
1105 for (
auto it = m_nameMimeTypeMap.constBegin(), end = m_nameMimeTypeMap.constEnd() ; it != end ; ++it) {
1106 const QString newMime = it.key();
1107 if (
std::find_if(result.constBegin(), result.constEnd(), [newMime](
const QMimeType &mime) ->
bool {
return mime.name() == newMime; })
1108 == result.constEnd())
1109 result.append(QMimeType(QMimeTypePrivate(it.value().name)));
1116 m_magicMatchers.append(matcher);
void addGlob(const QMimeGlobPattern &glob)
quint64 recordOffset(quint32 index) const
quint64 firstRecord() const
bool loadIndirect(const CacheFile *cacheFile, quint64 posListOffset, quint64 firstRecordPos, quint32 stride)
bool load(const CacheFile *cacheFile, quint64 posListOffset, quint32 stride)
void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override
QString resolveAlias(const QString &name) override
void findByMagic(const QByteArray &data, QMimeMagicResult &result) override
bool knowsMimeType(const QString &name) override
QString icon(const QString &name) override
bool hasGlobDeleteAll(const QString &name) override
void ensureLoaded() 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
QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory)
QStringList globPatterns(const QString &name) override
QString genericIcon(const QString &name) override
bool isInternalDatabase() const override
QMimeTypePrivate::LocaleHash localeComments(const QString &name) override
The QMimeGlobPattern class contains the glob pattern for file names for MIME type matching.
bool isMimeTypeGlobsExcluded(const QString &name) const
QMimeProviderBase * m_overrideProvider
QMimeProviderBase * overrideProvider() const
void setOverrideProvider(QMimeProviderBase *provider)
QMimeDatabasePrivate * m_db
QMimeTypeParser(QMimeXMLProvider &provider)
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)
QMimeTypePrivate::LocaleHash localeComments(const QString &name) override
QStringList globPatterns(const QString &name) override
bool load(const QString &fileName, QString *errorMessage)
QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory)
void ensureLoaded() override
bool knowsMimeType(const QString &name) override
bool isInternalDatabase() const override
QString resolveAlias(const QString &name) override
void addMimeType(const QMimeTypeXMLData &mt)
void findByMagic(const QByteArray &data, QMimeMagicResult &result) override
QString icon(const QString &name) override
void addParents(const QString &mime, QStringList &result) override
void addAllMimeTypes(QList< QMimeType > &result) override
QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum)
void addMagicMatcher(const QMimeMagicRuleMatcher &matcher)
bool hasGlobDeleteAll(const QString &name) override
void addParent(const QString &child, const QString &parent)
QString genericIcon(const QString &name) override
@ PosGenericIconsListOffset
@ PosReverseSuffixTreeOffset
static void appendIfNew(QStringList &list, const QString &str)
std::optional< quint32 > getUint32(quint64 offset, quint64 extra=0) const
std::optional< quint16 > getUint16(quint64 offset) const
RecordList m_genericIcons
quint32 recordUint32(const RecordList &list, quint32 index, quint32 fieldOffset) const
RecordList m_suffixTreeRoots
QLatin1StringView getLatin1String(quint64 offset) const
CacheFile(const QString &fileName)
RecordList m_magicMatches
std::optional< quint64 > safeRecordOffset(quint64 base, quint64 headerSize, quint32 index, quint32 stride) const
const char * getData(quint64 offset, quint64 length) const