1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // Copyright (C) 2015 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #ifndef QMIMEPROVIDER_P_H |
6 | #define QMIMEPROVIDER_P_H |
7 | |
8 | // |
9 | // W A R N I N G |
10 | // ------------- |
11 | // |
12 | // This file is not part of the Qt API. It exists purely as an |
13 | // implementation detail. This header file may change from version to |
14 | // version without notice, or even be removed. |
15 | // |
16 | // We mean it. |
17 | // |
18 | |
19 | #include "qmimedatabase_p.h" |
20 | |
21 | QT_REQUIRE_CONFIG(mimetype); |
22 | |
23 | #include "qmimeglobpattern_p.h" |
24 | #include <QtCore/qdatetime.h> |
25 | #include <QtCore/qset.h> |
26 | #include <QtCore/qmap.h> |
27 | |
28 | QT_BEGIN_NAMESPACE |
29 | |
30 | class QMimeMagicRuleMatcher; |
31 | |
32 | class QMimeProviderBase |
33 | { |
34 | Q_DISABLE_COPY(QMimeProviderBase) |
35 | |
36 | public: |
37 | QMimeProviderBase(QMimeDatabasePrivate *db, const QString &directory); |
38 | virtual ~QMimeProviderBase() {} |
39 | |
40 | virtual bool isValid() = 0; |
41 | virtual bool isInternalDatabase() const = 0; |
42 | virtual QMimeType mimeTypeForName(const QString &name) = 0; |
43 | virtual void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) = 0; |
44 | virtual void addParents(const QString &mime, QStringList &result) = 0; |
45 | virtual QString resolveAlias(const QString &name) = 0; |
46 | virtual void addAliases(const QString &name, QStringList &result) = 0; |
47 | virtual void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) = 0; |
48 | virtual void addAllMimeTypes(QList<QMimeType> &result) = 0; |
49 | virtual bool loadMimeTypePrivate(QMimeTypePrivate &) { return false; } |
50 | virtual void loadIcon(QMimeTypePrivate &) {} |
51 | virtual void loadGenericIcon(QMimeTypePrivate &) {} |
52 | virtual void ensureLoaded() {} |
53 | virtual void excludeMimeTypeGlobs(const QStringList &) {} |
54 | |
55 | QString directory() const { return m_directory; } |
56 | |
57 | QMimeDatabasePrivate *m_db; |
58 | QString m_directory; |
59 | |
60 | /* |
61 | MimeTypes with "glob-deleteall" tags are handled differently by each provider |
62 | sub-class: |
63 | - QMimeBinaryProvider parses glob-deleteall tags lazily, i.e. only when loadMimeTypePrivate() |
64 | is called, and clears the glob patterns associated with mimetypes that have this tag |
65 | - QMimeXMLProvider parses glob-deleteall from the the start, i.e. when a XML file is |
66 | parsed with QMimeTypeParser |
67 | |
68 | The two lists below are used to let both provider types (XML and Binary) communicate |
69 | about mimetypes with glob-deleteall. |
70 | */ |
71 | /* |
72 | List of mimetypes in _this_ Provider that have a "glob-deleteall" tag, |
73 | glob patterns for those mimetypes should be ignored in all _other_ lower |
74 | precedence Providers. |
75 | */ |
76 | QStringList m_mimeTypesWithDeletedGlobs; |
77 | |
78 | /* |
79 | List of mimetypes with glob patterns that are "overwritten" in _this_ Provider, |
80 | by a "glob-deleteall" tag in a mimetype definition in a _higher precedence_ |
81 | Provider. With QMimeBinaryProvider, we can't change the data in the binary mmap'ed |
82 | file, hence the need for this list. |
83 | */ |
84 | QStringList m_mimeTypesWithExcludedGlobs; |
85 | }; |
86 | |
87 | /* |
88 | Parses the files 'mime.cache' and 'types' on demand |
89 | */ |
90 | class QMimeBinaryProvider final : public QMimeProviderBase |
91 | { |
92 | public: |
93 | QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory); |
94 | virtual ~QMimeBinaryProvider(); |
95 | |
96 | bool isValid() override; |
97 | bool isInternalDatabase() const override; |
98 | QMimeType mimeTypeForName(const QString &name) override; |
99 | void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override; |
100 | void addParents(const QString &mime, QStringList &result) override; |
101 | QString resolveAlias(const QString &name) override; |
102 | void addAliases(const QString &name, QStringList &result) override; |
103 | void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override; |
104 | void addAllMimeTypes(QList<QMimeType> &result) override; |
105 | bool loadMimeTypePrivate(QMimeTypePrivate &) override; |
106 | void loadIcon(QMimeTypePrivate &) override; |
107 | void loadGenericIcon(QMimeTypePrivate &) override; |
108 | void ensureLoaded() override; |
109 | void excludeMimeTypeGlobs(const QStringList &toExclude) override; |
110 | |
111 | private: |
112 | struct CacheFile; |
113 | |
114 | int matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int offset, |
115 | const QString &fileName); |
116 | bool matchSuffixTree(QMimeGlobMatchResult &result, CacheFile *cacheFile, int numEntries, |
117 | int firstOffset, const QString &fileName, qsizetype charPos, |
118 | bool caseSensitiveCheck); |
119 | bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data); |
120 | bool isMimeTypeGlobsExcluded(const char *name); |
121 | QLatin1StringView iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime); |
122 | void loadMimeTypeList(); |
123 | bool checkCacheChanged(); |
124 | |
125 | std::unique_ptr<CacheFile> m_cacheFile; |
126 | QStringList m_cacheFileNames; |
127 | QSet<QString> m_mimetypeNames; |
128 | bool m_mimetypeListLoaded; |
129 | struct |
130 | { |
131 | // Both retrieved on demand in loadMimeTypePrivate |
132 | QHash<QString, QString> ; |
133 | QStringList ; |
134 | }; |
135 | QMap<QString, MimeTypeExtra> ; |
136 | }; |
137 | |
138 | /* |
139 | Parses the raw XML files (slower) |
140 | */ |
141 | class QMimeXMLProvider final : public QMimeProviderBase |
142 | { |
143 | public: |
144 | enum InternalDatabaseEnum { InternalDatabase }; |
145 | #if QT_CONFIG(mimetype_database) |
146 | enum : bool { InternalDatabaseAvailable = true }; |
147 | #else |
148 | enum : bool { InternalDatabaseAvailable = false }; |
149 | #endif |
150 | QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum); |
151 | QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory); |
152 | ~QMimeXMLProvider(); |
153 | |
154 | bool isValid() override; |
155 | bool isInternalDatabase() const override; |
156 | QMimeType mimeTypeForName(const QString &name) override; |
157 | void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override; |
158 | void addParents(const QString &mime, QStringList &result) override; |
159 | QString resolveAlias(const QString &name) override; |
160 | void addAliases(const QString &name, QStringList &result) override; |
161 | void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override; |
162 | void addAllMimeTypes(QList<QMimeType> &result) override; |
163 | void ensureLoaded() override; |
164 | |
165 | bool load(const QString &fileName, QString *errorMessage); |
166 | |
167 | // Called by the mimetype xml parser |
168 | void addMimeType(const QMimeType &mt); |
169 | void excludeMimeTypeGlobs(const QStringList &toExclude) override; |
170 | void addGlobPattern(const QMimeGlobPattern &glob); |
171 | void addParent(const QString &child, const QString &parent); |
172 | void addAlias(const QString &alias, const QString &name); |
173 | void addMagicMatcher(const QMimeMagicRuleMatcher &matcher); |
174 | |
175 | private: |
176 | void load(const QString &fileName); |
177 | void load(const char *data, qsizetype len); |
178 | |
179 | typedef QHash<QString, QMimeType> NameMimeTypeMap; |
180 | NameMimeTypeMap m_nameMimeTypeMap; |
181 | |
182 | typedef QHash<QString, QString> AliasHash; |
183 | AliasHash m_aliases; |
184 | |
185 | typedef QHash<QString, QStringList> ParentsHash; |
186 | ParentsHash m_parents; |
187 | QMimeAllGlobPatterns m_mimeTypeGlobs; |
188 | |
189 | QList<QMimeMagicRuleMatcher> m_magicMatchers; |
190 | QStringList m_allFiles; |
191 | }; |
192 | |
193 | QT_END_NAMESPACE |
194 | |
195 | #endif // QMIMEPROVIDER_P_H |
196 | |