12#include <QXmlStreamReader>
16#include <QByteArrayMatcher>
21#if QT_CONFIG(mimetype_database)
22# if defined(Q_CC_MSVC_ONLY)
23# pragma section(".qtmimedatabase", read, shared)
24__declspec(allocate(
".qtmimedatabase")) __declspec(align(4096))
25# elif defined(Q_OS_DARWIN)
27# elif (defined(Q_OF_ELF) || defined(Q_OS_WIN)) && defined(Q_CC_GNU)
31# include "qmimeprovider_database.cpp"
33# ifdef MIME_DATABASE_IS_ZSTD
35# error "MIME database is zstd but no support compiled in!"
39# ifdef MIME_DATABASE_IS_GZIP
41# error "MIME database is zlib but no support compiled in!"
69 return reinterpret_cast<const char *
>(
data +
offset);
133 const int major = getUint16(0);
134 const int minor = getUint16(2);
135 m_valid = (major == 1 && minor >= 1 && minor <= 2);
155 return m_cacheFile !=
nullptr;
176bool QMimeBinaryProvider::checkCacheChanged()
182 m_cacheFile->reload();
192 m_cacheFile = std::make_unique<CacheFile>(cacheFileName);
193 m_mimetypeListLoaded =
false;
194 m_mimetypeExtra.clear();
196 if (checkCacheChanged()) {
197 m_mimetypeListLoaded =
false;
198 m_mimetypeExtra.clear();
203 if (!m_cacheFile->isValid())
209 if (!m_mimetypeListLoaded)
221 numMatches = matchGlobList(
result, m_cacheFile.get(),
224 if (numMatches == 0) {
227 const int numRoots = m_cacheFile->getUint32(reverseSuffixTreeOffset);
228 const int firstRootOffset = m_cacheFile->getUint32(reverseSuffixTreeOffset + 4);
229 if (matchSuffixTree(
result, m_cacheFile.get(), numRoots, firstRootOffset, lowerFileName,
230 lowerFileName.size() - 1,
false)) {
232 }
else if (matchSuffixTree(
result, m_cacheFile.get(), numRoots, firstRootOffset,
fileName,
247 const int numGlobs = cacheFile->getUint32(off);
249 for (
int i = 0;
i < numGlobs; ++
i) {
250 const int globOffset = cacheFile->getUint32(off + 4 + 12 *
i);
251 const int mimeTypeOffset = cacheFile->getUint32(off + 4 + 12 *
i + 4);
252 const int flagsAndWeight = cacheFile->getUint32(off + 4 + 12 *
i + 8);
253 const int weight = flagsAndWeight & 0xff;
254 const bool caseSensitive = flagsAndWeight & 0x100;
275 qsizetype charPos,
bool caseSensitiveCheck)
279 int max = numEntries - 1;
281 const int mid = (
min + max) / 2;
282 const int off = firstOffset + 12 * mid;
283 const QChar ch = char16_t(cacheFile->getUint32(off));
286 else if (
ch > fileChar)
290 int numChildren = cacheFile->getUint32(off + 4);
291 int childrenOffset = cacheFile->getUint32(off + 8);
292 bool success =
false;
294 success = matchSuffixTree(
result, cacheFile, numChildren, childrenOffset,
fileName, charPos, caseSensitiveCheck);
296 for (
int i = 0;
i < numChildren; ++
i) {
297 const int childOff = childrenOffset + 12 *
i;
298 const int mch = cacheFile->getUint32(childOff);
301 const int mimeTypeOffset = cacheFile->getUint32(childOff + 4);
305 const int flagsAndWeight = cacheFile->getUint32(childOff + 8);
306 const int weight = flagsAndWeight & 0xff;
307 const bool caseSensitive = flagsAndWeight & 0x100;
308 if (caseSensitiveCheck || !caseSensitive) {
324 const char *dataPtr =
data.constData();
326 for (
int matchlet = 0; matchlet < numMatchlets; ++matchlet) {
327 const int off = firstOffset + matchlet * 32;
328 const int rangeStart = cacheFile->getUint32(off);
329 const int rangeLength = cacheFile->getUint32(off + 4);
331 const int valueLength = cacheFile->getUint32(off + 12);
332 const int valueOffset = cacheFile->getUint32(off + 16);
333 const int maskOffset = cacheFile->getUint32(off + 20);
334 const char *
mask = maskOffset ? cacheFile->getCharStar(maskOffset) :
nullptr;
339 const int numChildren = cacheFile->getUint32(off + 24);
340 const int firstChildOffset = cacheFile->getUint32(off + 28);
341 if (numChildren == 0)
344 if (matchMagicRule(cacheFile, numChildren, firstChildOffset,
data))
353 const int numMatches = m_cacheFile->getUint32(magicListOffset);
355 const int firstMatchOffset = m_cacheFile->getUint32(magicListOffset + 8);
357 for (
int i = 0;
i < numMatches; ++
i) {
358 const int off = firstMatchOffset +
i * 16;
359 const int numMatchlets = m_cacheFile->getUint32(off + 8);
360 const int firstMatchletOffset = m_cacheFile->getUint32(off + 12);
361 if (matchMagicRule(m_cacheFile.get(), numMatchlets, firstMatchletOffset,
data)) {
362 const int mimeTypeOffset = m_cacheFile->getUint32(off + 4);
363 const char *
mimeType = m_cacheFile->getCharStar(mimeTypeOffset);
364 const int accuracy =
static_cast<int>(m_cacheFile->getUint32(off));
365 if (accuracy >
result.accuracy) {
366 result.accuracy = accuracy;
379 const int numEntries = m_cacheFile->getUint32(parentListOffset);
382 int end = numEntries - 1;
384 const int medium = (
begin +
end) / 2;
385 const int off = parentListOffset + 4 + 8 * medium;
386 const int mimeOffset = m_cacheFile->getUint32(off);
387 const char *aMime = m_cacheFile->getCharStar(mimeOffset);
388 const int cmp =
qstrcmp(aMime, mimeStr);
391 }
else if (cmp > 0) {
394 const int parentsOffset = m_cacheFile->getUint32(off + 4);
395 const int numParents = m_cacheFile->getUint32(parentsOffset);
396 for (
int i = 0;
i < numParents; ++
i) {
397 const int parentOffset = m_cacheFile->getUint32(parentsOffset + 4 + 4 *
i);
398 const char *aParent = m_cacheFile->getCharStar(parentOffset);
411 const int numEntries = m_cacheFile->getUint32(aliasListOffset);
413 int end = numEntries - 1;
415 const int medium = (
begin +
end) / 2;
416 const int off = aliasListOffset + 4 + 8 * medium;
417 const int aliasOffset = m_cacheFile->getUint32(off);
418 const char *alias = m_cacheFile->getCharStar(aliasOffset);
422 }
else if (cmp > 0) {
425 const int mimeOffset = m_cacheFile->getUint32(off + 4);
426 const char *
mimeType = m_cacheFile->getCharStar(mimeOffset);
437 const int numEntries = m_cacheFile->getUint32(aliasListOffset);
438 for (
int pos = 0;
pos < numEntries; ++
pos) {
439 const int off = aliasListOffset + 4 + 8 *
pos;
440 const int mimeOffset = m_cacheFile->getUint32(off + 4);
441 const char *
mimeType = m_cacheFile->getCharStar(mimeOffset);
444 const int aliasOffset = m_cacheFile->getUint32(off);
445 const char *alias = m_cacheFile->getCharStar(aliasOffset);
452void QMimeBinaryProvider::loadMimeTypeList()
454 if (!m_mimetypeListLoaded) {
455 m_mimetypeListLoaded =
true;
456 m_mimetypeNames.
clear();
464 if (lineView.endsWith(
'\n'))
477 for (
const QString &
name : std::as_const(m_mimetypeNames))
480 for (
const QString &
name : std::as_const(m_mimetypeNames))
489 MimeTypeExtraMap::const_iterator
it = loadMimeTypeExtra(
name);
490 if (
it != m_mimetypeExtra.cend())
491 return it->second.localeComments;
497 MimeTypeExtraMap::const_iterator
it = loadMimeTypeExtra(
name);
498 if (
it != m_mimetypeExtra.cend())
499 return it->second.hasGlobDeleteAll;
505 MimeTypeExtraMap::const_iterator
it = loadMimeTypeExtra(
name);
506 if (
it != m_mimetypeExtra.cend())
507 return it->second.globPatterns;
511QMimeBinaryProvider::MimeTypeExtraMap::const_iterator
512QMimeBinaryProvider::loadMimeTypeExtra(
const QString &mimeName)
514#if QT_CONFIG(xmlstreamreader)
515 auto it = m_mimetypeExtra.find(mimeName);
516 if (
it == m_mimetypeExtra.cend()) {
522 mimeFile =
m_directory + u
'/' + mimeName +
".xml"_L1;
524 QFile qfile(mimeFile);
526 return m_mimetypeExtra.cend();
528 it = m_mimetypeExtra.try_emplace(mimeName).first;
529 MimeTypeExtra &extra =
it->second;
532 QXmlStreamReader
xml(&qfile);
533 if (
xml.readNextStartElement()) {
534 if (
xml.name() !=
"mime-type"_L1) {
535 return m_mimetypeExtra.cend();
537 const auto name =
xml.attributes().value(
"type"_L1);
539 return m_mimetypeExtra.cend();
541 qWarning() <<
"Got name" <<
name <<
"in file" << mimeFile <<
"expected" << mimeName;
543 while (
xml.readNextStartElement()) {
544 const auto tag =
xml.name();
545 if (
tag ==
"comment"_L1) {
546 QString lang =
xml.attributes().value(
"xml:lang"_L1).toString();
553 }
else if (
tag ==
"glob-deleteall"_L1) {
554 extra.hasGlobDeleteAll =
true;
555 }
else if (
tag ==
"glob"_L1) {
557 if (mainPattern.isEmpty() &&
pattern.startsWith(u
'*')) {
562 xml.skipCurrentElement();
569 if (!mainPattern.isEmpty() &&
570 (extra.globPatterns.isEmpty() || extra.globPatterns.constFirst() != mainPattern)) {
572 extra.globPatterns.removeAll(mainPattern);
573 extra.globPatterns.prepend(mainPattern);
579 qWarning(
"Cannot load mime type since QXmlStreamReader is not available.");
580 return m_mimetypeExtra.cend();
585QLatin1StringView QMimeBinaryProvider::iconForMime(CacheFile *cacheFile,
int posListOffset,
588 const int iconsListOffset = cacheFile->getUint32(posListOffset);
589 const int numIcons = cacheFile->getUint32(iconsListOffset);
591 int end = numIcons - 1;
593 const int medium = (
begin +
end) / 2;
594 const int off = iconsListOffset + 4 + 8 * medium;
595 const int mimeOffset = cacheFile->getUint32(off);
596 const char *
mime = cacheFile->getCharStar(mimeOffset);
603 const int iconOffset = cacheFile->getUint32(off + 4);
624#if QT_CONFIG(mimetype_database)
625static QString internalMimeFileName()
633 static_assert(
sizeof(mimetype_database),
"Bundled MIME database is empty");
634 static_assert(
sizeof(mimetype_database) <= MimeTypeDatabaseOriginalSize,
635 "Compressed MIME database is larger than the original size");
636 static_assert(MimeTypeDatabaseOriginalSize <= 16*1024*1024,
637 "Bundled MIME database is too big");
638 const char *
data =
reinterpret_cast<const char *
>(mimetype_database);
641#ifdef MIME_DATABASE_IS_ZSTD
643 std::unique_ptr<char []> uncompressed(
new char[
size]);
644 size = ZSTD_decompress(uncompressed.get(),
size, mimetype_database,
sizeof(mimetype_database));
646 data = uncompressed.get();
647#elif defined(MIME_DATABASE_IS_GZIP)
648 std::unique_ptr<char []> uncompressed(
new char[
size]);
650 zs.next_in =
const_cast<Bytef *
>(mimetype_database);
651 zs.avail_in =
sizeof(mimetype_database);
652 zs.next_out =
reinterpret_cast<Bytef *
>(uncompressed.get());
655 int res = inflateInit2(&zs, MAX_WBITS | 32);
659 res = inflateEnd(&zs);
662 data = uncompressed.get();
697#if QT_CONFIG(mimetype_database)
719 const int priority =
matcher.priority();
720 if (priority >
result.accuracy) {
721 result.accuracy = priority;
736 allFiles.append(packageDir + u
'/' + xmlFile);
738 if (m_allFiles == allFiles)
740 m_allFiles = allFiles;
742 m_nameMimeTypeMap.
clear();
745 m_mimeTypeGlobs.
clear();
746 m_magicMatchers.
clear();
750 for (
const QString &
file : std::as_const(allFiles))
802#if QT_CONFIG(mimetype_database)
828 if (!
result.contains(parent))
835 m_parents[
child].append(parent);
841 for (
const auto &[alias, mimeName] : std::as_const(m_aliases).asKeyValueRange()) {
842 if (mimeName ==
name)
867 if (std::find_if(
result.constBegin(),
result.constEnd(), [newMime](
const QMimeType &
mime) ->
bool { return mime.name() == newMime; })
struct capHdr __attribute__
\inmodule QtCore \reentrant
void setData(const QByteArray &data)
Sets the contents of the internal buffer to be data.
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
\inmodule QtCore\reentrant
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.
QDateTime lastModified() const
Returns the date and time when the file was last modified.
QFILE_MAYBE_NODISCARD 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 ...
const_iterator constBegin() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
T value(const Key &key) const noexcept
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)
void addGlob(const QMimeGlobPattern &glob)
void matchingGlobs(const QString &fileName, QMimeGlobMatchResult &result, const AddMatchFilterFunc &filterFunc) const
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.
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)
bool isMimeTypeGlobsExcluded(const QString &name) const
QMimeProviderBase * m_overrideProvider
virtual bool hasGlobDeleteAll(const QString &name)=0
QMimeProviderBase * overrideProvider() const
void setOverrideProvider(QMimeProviderBase *provider)
QMimeProviderBase(QMimeDatabasePrivate *db, const QString &directory)
bool parse(QIODevice *dev, const QString &fileName, QString *errorMessage)
QMimeTypePrivate::LocaleHash localeComments
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)
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
bool contains(const T &value) const
iterator insert(const T &value)
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
\macro QT_RESTRICTED_CAST_FROM_ASCII
void reserve(qsizetype size)
Ensures the string has space for at least size characters.
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isEmpty() const noexcept
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)
@ PosReverseSuffixTreeOffset
@ PosGenericIconsListOffset
static void appendIfNew(QStringList &list, const QString &str)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLuint GLfloat weight
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.