Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/corelib/mimetypes/qmimemagicrule.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /**************************************************************************** | - | ||||||||||||||||||||||||
2 | ** | - | ||||||||||||||||||||||||
3 | ** Copyright (C) 2015 The Qt Company Ltd. | - | ||||||||||||||||||||||||
4 | ** Contact: http://www.qt.io/licensing/ | - | ||||||||||||||||||||||||
5 | ** | - | ||||||||||||||||||||||||
6 | ** This file is part of the QtCore module of the Qt Toolkit. | - | ||||||||||||||||||||||||
7 | ** | - | ||||||||||||||||||||||||
8 | ** $QT_BEGIN_LICENSE:LGPL21$ | - | ||||||||||||||||||||||||
9 | ** Commercial License Usage | - | ||||||||||||||||||||||||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||||||||||||||||||||
11 | ** accordance with the commercial license agreement provided with the | - | ||||||||||||||||||||||||
12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||||||||||||||||||||
13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||||||||||||||||||||
14 | ** and conditions see http://www.qt.io/terms-conditions. For further | - | ||||||||||||||||||||||||
15 | ** information use the contact form at http://www.qt.io/contact-us. | - | ||||||||||||||||||||||||
16 | ** | - | ||||||||||||||||||||||||
17 | ** GNU Lesser General Public License Usage | - | ||||||||||||||||||||||||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||||||||||||||
19 | ** General Public License version 2.1 or version 3 as published by the Free | - | ||||||||||||||||||||||||
20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and | - | ||||||||||||||||||||||||
21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the | - | ||||||||||||||||||||||||
22 | ** following information to ensure the GNU Lesser General Public License | - | ||||||||||||||||||||||||
23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and | - | ||||||||||||||||||||||||
24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | - | ||||||||||||||||||||||||
25 | ** | - | ||||||||||||||||||||||||
26 | ** As a special exception, The Qt Company gives you certain additional | - | ||||||||||||||||||||||||
27 | ** rights. These rights are described in The Qt Company LGPL Exception | - | ||||||||||||||||||||||||
28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | - | ||||||||||||||||||||||||
29 | ** | - | ||||||||||||||||||||||||
30 | ** $QT_END_LICENSE$ | - | ||||||||||||||||||||||||
31 | ** | - | ||||||||||||||||||||||||
32 | ****************************************************************************/ | - | ||||||||||||||||||||||||
33 | - | |||||||||||||||||||||||||
34 | - | |||||||||||||||||||||||||
35 | #define QT_NO_CAST_FROM_ASCII | - | ||||||||||||||||||||||||
36 | - | |||||||||||||||||||||||||
37 | #include "qmimemagicrule_p.h" | - | ||||||||||||||||||||||||
38 | - | |||||||||||||||||||||||||
39 | #ifndef QT_NO_MIMETYPE | - | ||||||||||||||||||||||||
40 | - | |||||||||||||||||||||||||
41 | #include "qmimetypeparser_p.h" | - | ||||||||||||||||||||||||
42 | #include <QtCore/QList> | - | ||||||||||||||||||||||||
43 | #include <QtCore/QDebug> | - | ||||||||||||||||||||||||
44 | #include <qendian.h> | - | ||||||||||||||||||||||||
45 | - | |||||||||||||||||||||||||
46 | QT_BEGIN_NAMESPACE | - | ||||||||||||||||||||||||
47 | - | |||||||||||||||||||||||||
48 | // in the same order as Type! | - | ||||||||||||||||||||||||
49 | static const char magicRuleTypes_string[] = | - | ||||||||||||||||||||||||
50 | "invalid\0" | - | ||||||||||||||||||||||||
51 | "string\0" | - | ||||||||||||||||||||||||
52 | "host16\0" | - | ||||||||||||||||||||||||
53 | "host32\0" | - | ||||||||||||||||||||||||
54 | "big16\0" | - | ||||||||||||||||||||||||
55 | "big32\0" | - | ||||||||||||||||||||||||
56 | "little16\0" | - | ||||||||||||||||||||||||
57 | "little32\0" | - | ||||||||||||||||||||||||
58 | "byte\0" | - | ||||||||||||||||||||||||
59 | "\0"; | - | ||||||||||||||||||||||||
60 | - | |||||||||||||||||||||||||
61 | static const int magicRuleTypes_indices[] = { | - | ||||||||||||||||||||||||
62 | 0, 8, 15, 22, 29, 35, 41, 50, 59, 65, 0 | - | ||||||||||||||||||||||||
63 | }; | - | ||||||||||||||||||||||||
64 | - | |||||||||||||||||||||||||
65 | QMimeMagicRule::Type QMimeMagicRule::type(const QByteArray &theTypeName) | - | ||||||||||||||||||||||||
66 | { | - | ||||||||||||||||||||||||
67 | for (int i = String; i <= Byte; ++i) {
| 0-7377 | ||||||||||||||||||||||||
68 | if (theTypeName == magicRuleTypes_string + magicRuleTypes_indices[i])
| 3319-4058 | ||||||||||||||||||||||||
69 | return Type(i); executed 4058 times by 1 test: return Type(i); Executed by:
| 4058 | ||||||||||||||||||||||||
70 | } executed 3319 times by 1 test: end of block Executed by:
| 3319 | ||||||||||||||||||||||||
71 | return Invalid; never executed: return Invalid; | 0 | ||||||||||||||||||||||||
72 | } | - | ||||||||||||||||||||||||
73 | - | |||||||||||||||||||||||||
74 | QByteArray QMimeMagicRule::typeName(QMimeMagicRule::Type theType) | - | ||||||||||||||||||||||||
75 | { | - | ||||||||||||||||||||||||
76 | return magicRuleTypes_string + magicRuleTypes_indices[theType]; never executed: return magicRuleTypes_string + magicRuleTypes_indices[theType]; | 0 | ||||||||||||||||||||||||
77 | } | - | ||||||||||||||||||||||||
78 | - | |||||||||||||||||||||||||
79 | class QMimeMagicRulePrivate | - | ||||||||||||||||||||||||
80 | { | - | ||||||||||||||||||||||||
81 | public: | - | ||||||||||||||||||||||||
82 | bool operator==(const QMimeMagicRulePrivate &other) const; | - | ||||||||||||||||||||||||
83 | - | |||||||||||||||||||||||||
84 | QMimeMagicRule::Type type; | - | ||||||||||||||||||||||||
85 | QByteArray value; | - | ||||||||||||||||||||||||
86 | int startPos; | - | ||||||||||||||||||||||||
87 | int endPos; | - | ||||||||||||||||||||||||
88 | QByteArray mask; | - | ||||||||||||||||||||||||
89 | - | |||||||||||||||||||||||||
90 | QByteArray pattern; | - | ||||||||||||||||||||||||
91 | quint32 number; | - | ||||||||||||||||||||||||
92 | quint32 numberMask; | - | ||||||||||||||||||||||||
93 | - | |||||||||||||||||||||||||
94 | typedef bool (*MatchFunction)(const QMimeMagicRulePrivate *d, const QByteArray &data); | - | ||||||||||||||||||||||||
95 | MatchFunction matchFunction; | - | ||||||||||||||||||||||||
96 | }; | - | ||||||||||||||||||||||||
97 | - | |||||||||||||||||||||||||
98 | bool QMimeMagicRulePrivate::operator==(const QMimeMagicRulePrivate &other) const | - | ||||||||||||||||||||||||
99 | { | - | ||||||||||||||||||||||||
100 | return type == other.type && never executed: return type == other.type && value == other.value && startPos == other.startPos && endPos == other.endPos && mask == other.mask && pattern == other.pattern && number == other.number && numberMask == other.numberMask && matchFunction == other.matchFunction;
| 0 | ||||||||||||||||||||||||
101 | value == other.value && never executed: return type == other.type && value == other.value && startPos == other.startPos && endPos == other.endPos && mask == other.mask && pattern == other.pattern && number == other.number && numberMask == other.numberMask && matchFunction == other.matchFunction;
| 0 | ||||||||||||||||||||||||
102 | startPos == other.startPos && never executed: return type == other.type && value == other.value && startPos == other.startPos && endPos == other.endPos && mask == other.mask && pattern == other.pattern && number == other.number && numberMask == other.numberMask && matchFunction == other.matchFunction;
| 0 | ||||||||||||||||||||||||
103 | endPos == other.endPos && never executed: return type == other.type && value == other.value && startPos == other.startPos && endPos == other.endPos && mask == other.mask && pattern == other.pattern && number == other.number && numberMask == other.numberMask && matchFunction == other.matchFunction;
| 0 | ||||||||||||||||||||||||
104 | mask == other.mask && never executed: return type == other.type && value == other.value && startPos == other.startPos && endPos == other.endPos && mask == other.mask && pattern == other.pattern && number == other.number && numberMask == other.numberMask && matchFunction == other.matchFunction;
| 0 | ||||||||||||||||||||||||
105 | pattern == other.pattern && never executed: return type == other.type && value == other.value && startPos == other.startPos && endPos == other.endPos && mask == other.mask && pattern == other.pattern && number == other.number && numberMask == other.numberMask && matchFunction == other.matchFunction;
| 0 | ||||||||||||||||||||||||
106 | number == other.number && never executed: return type == other.type && value == other.value && startPos == other.startPos && endPos == other.endPos && mask == other.mask && pattern == other.pattern && number == other.number && numberMask == other.numberMask && matchFunction == other.matchFunction;
| 0 | ||||||||||||||||||||||||
107 | numberMask == other.numberMask && never executed: return type == other.type && value == other.value && startPos == other.startPos && endPos == other.endPos && mask == other.mask && pattern == other.pattern && number == other.number && numberMask == other.numberMask && matchFunction == other.matchFunction;
| 0 | ||||||||||||||||||||||||
108 | matchFunction == other.matchFunction; never executed: return type == other.type && value == other.value && startPos == other.startPos && endPos == other.endPos && mask == other.mask && pattern == other.pattern && number == other.number && numberMask == other.numberMask && matchFunction == other.matchFunction;
| 0 | ||||||||||||||||||||||||
109 | } | - | ||||||||||||||||||||||||
110 | - | |||||||||||||||||||||||||
111 | // Used by both providers | - | ||||||||||||||||||||||||
112 | bool QMimeMagicRule::matchSubstring(const char *dataPtr, int dataSize, int rangeStart, int rangeLength, | - | ||||||||||||||||||||||||
113 | int valueLength, const char *valueData, const char *mask) | - | ||||||||||||||||||||||||
114 | { | - | ||||||||||||||||||||||||
115 | // Size of searched data. | - | ||||||||||||||||||||||||
116 | // Example: value="ABC", rangeLength=3 -> we need 3+3-1=5 bytes (ABCxx,xABCx,xxABC would match) | - | ||||||||||||||||||||||||
117 | const int dataNeeded = qMin(rangeLength + valueLength - 1, dataSize - rangeStart); | - | ||||||||||||||||||||||||
118 | - | |||||||||||||||||||||||||
119 | if (!mask) {
| 9901-17592 | ||||||||||||||||||||||||
120 | // callgrind says QByteArray::indexOf is much slower, since our strings are typically too | - | ||||||||||||||||||||||||
121 | // short for be worth Boyer-Moore matching (1 to 71 bytes, 11 bytes on average). | - | ||||||||||||||||||||||||
122 | bool found = false; | - | ||||||||||||||||||||||||
123 | for (int i = rangeStart; i < rangeStart + rangeLength; ++i) {
| 5928-39384 | ||||||||||||||||||||||||
124 | if (i + valueLength > dataSize)
| 3928-35456 | ||||||||||||||||||||||||
125 | break; executed 3928 times by 1 test: break; Executed by:
| 3928 | ||||||||||||||||||||||||
126 | - | |||||||||||||||||||||||||
127 | if (memcmp(valueData, dataPtr + i, valueLength) == 0) {
| 45-35411 | ||||||||||||||||||||||||
128 | found = true; | - | ||||||||||||||||||||||||
129 | break; executed 45 times by 1 test: break; Executed by:
| 45 | ||||||||||||||||||||||||
130 | } | - | ||||||||||||||||||||||||
131 | } executed 35411 times by 1 test: end of block Executed by:
| 35411 | ||||||||||||||||||||||||
132 | if (!found)
| 45-9856 | ||||||||||||||||||||||||
133 | return false; executed 9856 times by 1 test: return false; Executed by:
| 9856 | ||||||||||||||||||||||||
134 | } else { executed 45 times by 1 test: end of block Executed by:
| 45 | ||||||||||||||||||||||||
135 | bool found = false; | - | ||||||||||||||||||||||||
136 | const char *readDataBase = dataPtr + rangeStart; | - | ||||||||||||||||||||||||
137 | // Example (continued from above): | - | ||||||||||||||||||||||||
138 | // deviceSize is 4, so dataNeeded was max'ed to 4. | - | ||||||||||||||||||||||||
139 | // maxStartPos = 4 - 3 + 1 = 2, and indeed | - | ||||||||||||||||||||||||
140 | // we need to check for a match a positions 0 and 1 (ABCx and xABC). | - | ||||||||||||||||||||||||
141 | const int maxStartPos = dataNeeded - valueLength + 1; | - | ||||||||||||||||||||||||
142 | for (int i = 0; i < maxStartPos; ++i) {
| 17592-38620 | ||||||||||||||||||||||||
143 | const char *d = readDataBase + i; | - | ||||||||||||||||||||||||
144 | bool valid = true; | - | ||||||||||||||||||||||||
145 | for (int idx = 0; idx < valueLength; ++idx) {
| 46-39071 | ||||||||||||||||||||||||
146 | if (((*d++) & mask[idx]) != (valueData[idx] & mask[idx])) {
| 497-38574 | ||||||||||||||||||||||||
147 | valid = false; | - | ||||||||||||||||||||||||
148 | break; executed 38574 times by 1 test: break; Executed by:
| 38574 | ||||||||||||||||||||||||
149 | } | - | ||||||||||||||||||||||||
150 | } executed 497 times by 1 test: end of block Executed by:
| 497 | ||||||||||||||||||||||||
151 | if (valid)
| 46-38574 | ||||||||||||||||||||||||
152 | found = true; executed 46 times by 1 test: found = true; Executed by:
| 46 | ||||||||||||||||||||||||
153 | } executed 38620 times by 1 test: end of block Executed by:
| 38620 | ||||||||||||||||||||||||
154 | if (!found)
| 46-17546 | ||||||||||||||||||||||||
155 | return false; executed 17546 times by 1 test: return false; Executed by:
| 17546 | ||||||||||||||||||||||||
156 | } executed 46 times by 1 test: end of block Executed by:
| 46 | ||||||||||||||||||||||||
157 | //qDebug() << "Found" << value << "in" << searchedData; | - | ||||||||||||||||||||||||
158 | return true; executed 91 times by 1 test: return true; Executed by:
| 91 | ||||||||||||||||||||||||
159 | } | - | ||||||||||||||||||||||||
160 | - | |||||||||||||||||||||||||
161 | static bool matchString(const QMimeMagicRulePrivate *d, const QByteArray &data) | - | ||||||||||||||||||||||||
162 | { | - | ||||||||||||||||||||||||
163 | const int rangeLength = d->endPos - d->startPos + 1; | - | ||||||||||||||||||||||||
164 | return QMimeMagicRule::matchSubstring(data.constData(), data.size(), d->startPos, rangeLength, d->pattern.size(), d->pattern.constData(), d->mask.constData()); executed 17377 times by 1 test: return QMimeMagicRule::matchSubstring(data.constData(), data.size(), d->startPos, rangeLength, d->pattern.size(), d->pattern.constData(), d->mask.constData()); Executed by:
| 17377 | ||||||||||||||||||||||||
165 | } | - | ||||||||||||||||||||||||
166 | - | |||||||||||||||||||||||||
167 | template <typename T> | - | ||||||||||||||||||||||||
168 | static bool matchNumber(const QMimeMagicRulePrivate *d, const QByteArray &data) | - | ||||||||||||||||||||||||
169 | { | - | ||||||||||||||||||||||||
170 | const T value(d->number); | - | ||||||||||||||||||||||||
171 | const T mask(d->numberMask); | - | ||||||||||||||||||||||||
172 | - | |||||||||||||||||||||||||
173 | //qDebug() << "matchNumber" << "0x" << QString::number(d->number, 16) << "size" << sizeof(T); | - | ||||||||||||||||||||||||
174 | //qDebug() << "mask" << QString::number(d->numberMask, 16); | - | ||||||||||||||||||||||||
175 | - | |||||||||||||||||||||||||
176 | const char *p = data.constData() + d->startPos; | - | ||||||||||||||||||||||||
177 | const char *e = data.constData() + qMin(data.size() - int(sizeof(T)), d->endPos + 1); | - | ||||||||||||||||||||||||
178 | for ( ; p <= e; ++p) {
| 1854-3457 | ||||||||||||||||||||||||
179 | if ((qFromUnaligned<T>(reinterpret_cast<const uchar *>(p)) & mask) == (value & mask))
| 13-3444 | ||||||||||||||||||||||||
180 | return true; executed 13 times by 1 test: return true; Executed by:
| 13 | ||||||||||||||||||||||||
181 | } executed 3444 times by 1 test: end of block Executed by:
| 3444 | ||||||||||||||||||||||||
182 | - | |||||||||||||||||||||||||
183 | return false; executed 1854 times by 1 test: return false; Executed by:
| 1854 | ||||||||||||||||||||||||
184 | } | - | ||||||||||||||||||||||||
185 | - | |||||||||||||||||||||||||
186 | static inline QByteArray makePattern(const QByteArray &value) | - | ||||||||||||||||||||||||
187 | { | - | ||||||||||||||||||||||||
188 | QByteArray pattern(value.size(), Qt::Uninitialized); | - | ||||||||||||||||||||||||
189 | char *data = pattern.data(); | - | ||||||||||||||||||||||||
190 | - | |||||||||||||||||||||||||
191 | const char *p = value.constData(); | - | ||||||||||||||||||||||||
192 | const char *e = p + value.size(); | - | ||||||||||||||||||||||||
193 | for ( ; p < e; ++p) {
| 3431-33647 | ||||||||||||||||||||||||
194 | if (*p == '\\' && ++p < e) {
| 0-31392 | ||||||||||||||||||||||||
195 | if (*p == 'x') { // hex (\\xff)
| 775-1480 | ||||||||||||||||||||||||
196 | char c = 0; | - | ||||||||||||||||||||||||
197 | for (int i = 0; i < 2 && p + 1 < e; ++i) {
| 10-1550 | ||||||||||||||||||||||||
198 | ++p; | - | ||||||||||||||||||||||||
199 | if (*p >= '0' && *p <= '9')
| 0-1540 | ||||||||||||||||||||||||
200 | c = (c << 4) + *p - '0'; executed 1260 times by 1 test: c = (c << 4) + *p - '0'; Executed by:
| 1260 | ||||||||||||||||||||||||
201 | else if (*p >= 'a' && *p <= 'f')
| 0-220 | ||||||||||||||||||||||||
202 | c = (c << 4) + *p - 'a' + 10; executed 220 times by 1 test: c = (c << 4) + *p - 'a' + 10; Executed by:
| 220 | ||||||||||||||||||||||||
203 | else if (*p >= 'A' && *p <= 'F')
| 0-60 | ||||||||||||||||||||||||
204 | c = (c << 4) + *p - 'A' + 10; executed 60 times by 1 test: c = (c << 4) + *p - 'A' + 10; Executed by:
| 60 | ||||||||||||||||||||||||
205 | else | - | ||||||||||||||||||||||||
206 | continue; never executed: continue; | 0 | ||||||||||||||||||||||||
207 | } | - | ||||||||||||||||||||||||
208 | *data++ = c; | - | ||||||||||||||||||||||||
209 | } else if (*p >= '0' && *p <= '7') { // oct (\\7, or \\77, or \\377) executed 775 times by 1 test: end of block Executed by:
| 45-1435 | ||||||||||||||||||||||||
210 | char c = *p - '0'; | - | ||||||||||||||||||||||||
211 | if (p + 1 < e && p[1] >= '0' && p[1] <= '7') {
| 0-1195 | ||||||||||||||||||||||||
212 | c = (c << 3) + *(++p) - '0'; | - | ||||||||||||||||||||||||
213 | if (p + 1 < e && p[1] >= '0' && p[1] <= '7' && p[-1] <= '3')
| 0-1055 | ||||||||||||||||||||||||
214 | c = (c << 3) + *(++p) - '0'; executed 1045 times by 1 test: c = (c << 3) + *(++p) - '0'; Executed by:
| 1045 | ||||||||||||||||||||||||
215 | } executed 1060 times by 1 test: end of block Executed by:
| 1060 | ||||||||||||||||||||||||
216 | *data++ = c; | - | ||||||||||||||||||||||||
217 | } else if (*p == 'n') { executed 1280 times by 1 test: end of block Executed by:
| 75-1280 | ||||||||||||||||||||||||
218 | *data++ = '\n'; | - | ||||||||||||||||||||||||
219 | } else if (*p == 'r') { executed 75 times by 1 test: end of block Executed by:
| 10-115 | ||||||||||||||||||||||||
220 | *data++ = '\r'; | - | ||||||||||||||||||||||||
221 | } else if (*p == 't') { executed 10 times by 1 test: end of block Executed by:
| 10-100 | ||||||||||||||||||||||||
222 | *data++ = '\t'; | - | ||||||||||||||||||||||||
223 | } else { // escaped executed 15 times by 1 test: end of block Executed by:
| 15 | ||||||||||||||||||||||||
224 | *data++ = *p; | - | ||||||||||||||||||||||||
225 | } executed 100 times by 1 test: end of block Executed by:
| 100 | ||||||||||||||||||||||||
226 | } else { | - | ||||||||||||||||||||||||
227 | *data++ = *p; | - | ||||||||||||||||||||||||
228 | } executed 31392 times by 1 test: end of block Executed by:
| 31392 | ||||||||||||||||||||||||
229 | } | - | ||||||||||||||||||||||||
230 | pattern.truncate(data - pattern.data()); | - | ||||||||||||||||||||||||
231 | - | |||||||||||||||||||||||||
232 | return pattern; executed 3431 times by 1 test: return pattern; Executed by:
| 3431 | ||||||||||||||||||||||||
233 | } | - | ||||||||||||||||||||||||
234 | - | |||||||||||||||||||||||||
235 | // Evaluate a magic match rule like | - | ||||||||||||||||||||||||
236 | // <match value="must be converted with BinHex" type="string" offset="11"/> | - | ||||||||||||||||||||||||
237 | // <match value="0x9501" type="big16" offset="0:64"/> | - | ||||||||||||||||||||||||
238 | - | |||||||||||||||||||||||||
239 | QMimeMagicRule::QMimeMagicRule(const QString &typeStr, | - | ||||||||||||||||||||||||
240 | const QByteArray &theValue, | - | ||||||||||||||||||||||||
241 | const QString &offsets, | - | ||||||||||||||||||||||||
242 | const QByteArray &theMask, | - | ||||||||||||||||||||||||
243 | QString *errorString) : | - | ||||||||||||||||||||||||
244 | d(new QMimeMagicRulePrivate) | - | ||||||||||||||||||||||||
245 | { | - | ||||||||||||||||||||||||
246 | d->value = theValue; | - | ||||||||||||||||||||||||
247 | d->mask = theMask; | - | ||||||||||||||||||||||||
248 | d->matchFunction = 0; | - | ||||||||||||||||||||||||
249 | - | |||||||||||||||||||||||||
250 | d->type = QMimeMagicRule::type(typeStr.toLatin1()); | - | ||||||||||||||||||||||||
251 | if (d->type == Invalid) {
| 0-4058 | ||||||||||||||||||||||||
252 | *errorString = QStringLiteral("Type %s is not supported").arg(typeStr); never executed: return qstring_literal_temp; | 0 | ||||||||||||||||||||||||
253 | } never executed: end of block | 0 | ||||||||||||||||||||||||
254 | - | |||||||||||||||||||||||||
255 | // Parse for offset as "1" or "1:10" | - | ||||||||||||||||||||||||
256 | const int colonIndex = offsets.indexOf(QLatin1Char(':')); | - | ||||||||||||||||||||||||
257 | const QString startPosStr = colonIndex == -1 ? offsets : offsets.mid(0, colonIndex);
| 492-3566 | ||||||||||||||||||||||||
258 | const QString endPosStr = colonIndex == -1 ? offsets : offsets.mid(colonIndex + 1);
| 492-3566 | ||||||||||||||||||||||||
259 | if (!QMimeTypeParserBase::parseNumber(startPosStr, &d->startPos, errorString) ||
| 0-4058 | ||||||||||||||||||||||||
260 | !QMimeTypeParserBase::parseNumber(endPosStr, &d->endPos, errorString)) {
| 0-4058 | ||||||||||||||||||||||||
261 | d->type = Invalid; | - | ||||||||||||||||||||||||
262 | return; never executed: return; | 0 | ||||||||||||||||||||||||
263 | } | - | ||||||||||||||||||||||||
264 | - | |||||||||||||||||||||||||
265 | if (d->value.isEmpty()) {
| 0-4058 | ||||||||||||||||||||||||
266 | d->type = Invalid; | - | ||||||||||||||||||||||||
267 | if (errorString)
| 0 | ||||||||||||||||||||||||
268 | *errorString = QLatin1String("Invalid empty magic rule value"); never executed: *errorString = QLatin1String("Invalid empty magic rule value"); | 0 | ||||||||||||||||||||||||
269 | return; never executed: return; | 0 | ||||||||||||||||||||||||
270 | } | - | ||||||||||||||||||||||||
271 | - | |||||||||||||||||||||||||
272 | if (d->type >= Host16 && d->type <= Byte) {
| 0-3431 | ||||||||||||||||||||||||
273 | bool ok; | - | ||||||||||||||||||||||||
274 | d->number = d->value.toUInt(&ok, 0); // autodetect | - | ||||||||||||||||||||||||
275 | if (!ok) {
| 2-625 | ||||||||||||||||||||||||
276 | d->type = Invalid; | - | ||||||||||||||||||||||||
277 | if (errorString)
| 0-2 | ||||||||||||||||||||||||
278 | *errorString = QString::fromLatin1("Invalid magic rule value \"%1\"").arg( executed 2 times by 1 test: *errorString = QString::fromLatin1("Invalid magic rule value \"%1\"").arg( QString::fromLatin1(d->value)); Executed by:
| 2 | ||||||||||||||||||||||||
279 | QString::fromLatin1(d->value)); executed 2 times by 1 test: *errorString = QString::fromLatin1("Invalid magic rule value \"%1\"").arg( QString::fromLatin1(d->value)); Executed by:
| 2 | ||||||||||||||||||||||||
280 | return; executed 2 times by 1 test: return; Executed by:
| 2 | ||||||||||||||||||||||||
281 | } | - | ||||||||||||||||||||||||
282 | d->numberMask = !d->mask.isEmpty() ? d->mask.toUInt(&ok, 0) : 0; // autodetect
| 50-575 | ||||||||||||||||||||||||
283 | } executed 625 times by 1 test: end of block Executed by:
| 625 | ||||||||||||||||||||||||
284 | - | |||||||||||||||||||||||||
285 | switch (d->type) { | - | ||||||||||||||||||||||||
286 | case String: executed 3431 times by 1 test: case String: Executed by:
| 3431 | ||||||||||||||||||||||||
287 | d->pattern = makePattern(d->value); | - | ||||||||||||||||||||||||
288 | d->pattern.squeeze(); | - | ||||||||||||||||||||||||
289 | if (!d->mask.isEmpty()) {
| 29-3402 | ||||||||||||||||||||||||
290 | if (d->mask.size() < 4 || !d->mask.startsWith("0x")) {
| 0-29 | ||||||||||||||||||||||||
291 | d->type = Invalid; | - | ||||||||||||||||||||||||
292 | if (errorString)
| 0-2 | ||||||||||||||||||||||||
293 | *errorString = QString::fromLatin1("Invalid magic rule mask \"%1\"").arg( executed 2 times by 1 test: *errorString = QString::fromLatin1("Invalid magic rule mask \"%1\"").arg( QString::fromLatin1(d->mask)); Executed by:
| 2 | ||||||||||||||||||||||||
294 | QString::fromLatin1(d->mask)); executed 2 times by 1 test: *errorString = QString::fromLatin1("Invalid magic rule mask \"%1\"").arg( QString::fromLatin1(d->mask)); Executed by:
| 2 | ||||||||||||||||||||||||
295 | return; executed 2 times by 1 test: return; Executed by:
| 2 | ||||||||||||||||||||||||
296 | } | - | ||||||||||||||||||||||||
297 | const QByteArray &tempMask = QByteArray::fromHex(QByteArray::fromRawData( | - | ||||||||||||||||||||||||
298 | d->mask.constData() + 2, d->mask.size() - 2)); | - | ||||||||||||||||||||||||
299 | if (tempMask.size() != d->pattern.size()) {
| 2-25 | ||||||||||||||||||||||||
300 | d->type = Invalid; | - | ||||||||||||||||||||||||
301 | if (errorString)
| 0-2 | ||||||||||||||||||||||||
302 | *errorString = QString::fromLatin1("Invalid magic rule mask size \"%1\"").arg( executed 2 times by 1 test: *errorString = QString::fromLatin1("Invalid magic rule mask size \"%1\"").arg( QString::fromLatin1(d->mask)); Executed by:
| 2 | ||||||||||||||||||||||||
303 | QString::fromLatin1(d->mask)); executed 2 times by 1 test: *errorString = QString::fromLatin1("Invalid magic rule mask size \"%1\"").arg( QString::fromLatin1(d->mask)); Executed by:
| 2 | ||||||||||||||||||||||||
304 | return; executed 2 times by 1 test: return; Executed by:
| 2 | ||||||||||||||||||||||||
305 | } | - | ||||||||||||||||||||||||
306 | d->mask = tempMask; | - | ||||||||||||||||||||||||
307 | } else { executed 25 times by 1 test: end of block Executed by:
| 25 | ||||||||||||||||||||||||
308 | d->mask.fill(char(-1), d->pattern.size()); | - | ||||||||||||||||||||||||
309 | } executed 3402 times by 1 test: end of block Executed by:
| 3402 | ||||||||||||||||||||||||
310 | d->mask.squeeze(); | - | ||||||||||||||||||||||||
311 | d->matchFunction = matchString; | - | ||||||||||||||||||||||||
312 | break; executed 3427 times by 1 test: break; Executed by:
| 3427 | ||||||||||||||||||||||||
313 | case Byte: executed 205 times by 1 test: case Byte: Executed by:
| 205 | ||||||||||||||||||||||||
314 | if (d->number <= quint8(-1)) {
| 0-205 | ||||||||||||||||||||||||
315 | if (d->numberMask == 0)
| 0-205 | ||||||||||||||||||||||||
316 | d->numberMask = quint8(-1); executed 205 times by 1 test: d->numberMask = quint8(-1); Executed by:
| 205 | ||||||||||||||||||||||||
317 | d->matchFunction = matchNumber<quint8>; | - | ||||||||||||||||||||||||
318 | } executed 205 times by 1 test: end of block Executed by:
| 205 | ||||||||||||||||||||||||
319 | break; executed 205 times by 1 test: break; Executed by:
| 205 | ||||||||||||||||||||||||
320 | case Big16: executed 65 times by 1 test: case Big16: Executed by:
| 65 | ||||||||||||||||||||||||
321 | case Host16: executed 20 times by 1 test: case Host16: Executed by:
| 20 | ||||||||||||||||||||||||
322 | case Little16: executed 85 times by 1 test: case Little16: Executed by:
| 85 | ||||||||||||||||||||||||
323 | if (d->number <= quint16(-1)) {
| 0-170 | ||||||||||||||||||||||||
324 | d->number = d->type == Little16 ? qFromLittleEndian<quint16>(d->number) : qFromBigEndian<quint16>(d->number);
| 85 | ||||||||||||||||||||||||
325 | if (d->numberMask == 0)
| 5-165 | ||||||||||||||||||||||||
326 | d->numberMask = quint16(-1); executed 165 times by 1 test: d->numberMask = quint16(-1); Executed by:
| 165 | ||||||||||||||||||||||||
327 | d->matchFunction = matchNumber<quint16>; | - | ||||||||||||||||||||||||
328 | } executed 170 times by 1 test: end of block Executed by:
| 170 | ||||||||||||||||||||||||
329 | break; executed 170 times by 1 test: break; Executed by:
| 170 | ||||||||||||||||||||||||
330 | case Big32: executed 95 times by 1 test: case Big32: Executed by:
| 95 | ||||||||||||||||||||||||
331 | case Host32: executed 20 times by 1 test: case Host32: Executed by:
| 20 | ||||||||||||||||||||||||
332 | case Little32: executed 135 times by 1 test: case Little32: Executed by:
| 135 | ||||||||||||||||||||||||
333 | if (d->number <= quint32(-1)) {
| 0-250 | ||||||||||||||||||||||||
334 | d->number = d->type == Little32 ? qFromLittleEndian<quint32>(d->number) : qFromBigEndian<quint32>(d->number);
| 115-135 | ||||||||||||||||||||||||
335 | if (d->numberMask == 0)
| 45-205 | ||||||||||||||||||||||||
336 | d->numberMask = quint32(-1); executed 205 times by 1 test: d->numberMask = quint32(-1); Executed by:
| 205 | ||||||||||||||||||||||||
337 | d->matchFunction = matchNumber<quint32>; | - | ||||||||||||||||||||||||
338 | } executed 250 times by 1 test: end of block Executed by:
| 250 | ||||||||||||||||||||||||
339 | break; executed 250 times by 1 test: break; Executed by:
| 250 | ||||||||||||||||||||||||
340 | default: never executed: default: | 0 | ||||||||||||||||||||||||
341 | break; never executed: break; | 0 | ||||||||||||||||||||||||
342 | } | - | ||||||||||||||||||||||||
343 | } | - | ||||||||||||||||||||||||
344 | - | |||||||||||||||||||||||||
345 | QMimeMagicRule::QMimeMagicRule(const QMimeMagicRule &other) : | - | ||||||||||||||||||||||||
346 | d(new QMimeMagicRulePrivate(*other.d)) | - | ||||||||||||||||||||||||
347 | { | - | ||||||||||||||||||||||||
348 | } executed 4058 times by 1 test: end of block Executed by:
| 4058 | ||||||||||||||||||||||||
349 | - | |||||||||||||||||||||||||
350 | QMimeMagicRule::~QMimeMagicRule() | - | ||||||||||||||||||||||||
351 | { | - | ||||||||||||||||||||||||
352 | } | - | ||||||||||||||||||||||||
353 | - | |||||||||||||||||||||||||
354 | QMimeMagicRule &QMimeMagicRule::operator=(const QMimeMagicRule &other) | - | ||||||||||||||||||||||||
355 | { | - | ||||||||||||||||||||||||
356 | *d = *other.d; | - | ||||||||||||||||||||||||
357 | return *this; never executed: return *this; | 0 | ||||||||||||||||||||||||
358 | } | - | ||||||||||||||||||||||||
359 | - | |||||||||||||||||||||||||
360 | bool QMimeMagicRule::operator==(const QMimeMagicRule &other) const | - | ||||||||||||||||||||||||
361 | { | - | ||||||||||||||||||||||||
362 | return d == other.d || never executed: return d == other.d || *d == *other.d;
| 0 | ||||||||||||||||||||||||
363 | *d == *other.d; never executed: return d == other.d || *d == *other.d;
| 0 | ||||||||||||||||||||||||
364 | } | - | ||||||||||||||||||||||||
365 | - | |||||||||||||||||||||||||
366 | QMimeMagicRule::Type QMimeMagicRule::type() const | - | ||||||||||||||||||||||||
367 | { | - | ||||||||||||||||||||||||
368 | return d->type; never executed: return d->type; | 0 | ||||||||||||||||||||||||
369 | } | - | ||||||||||||||||||||||||
370 | - | |||||||||||||||||||||||||
371 | QByteArray QMimeMagicRule::value() const | - | ||||||||||||||||||||||||
372 | { | - | ||||||||||||||||||||||||
373 | return d->value; never executed: return d->value; | 0 | ||||||||||||||||||||||||
374 | } | - | ||||||||||||||||||||||||
375 | - | |||||||||||||||||||||||||
376 | int QMimeMagicRule::startPos() const | - | ||||||||||||||||||||||||
377 | { | - | ||||||||||||||||||||||||
378 | return d->startPos; never executed: return d->startPos; | 0 | ||||||||||||||||||||||||
379 | } | - | ||||||||||||||||||||||||
380 | - | |||||||||||||||||||||||||
381 | int QMimeMagicRule::endPos() const | - | ||||||||||||||||||||||||
382 | { | - | ||||||||||||||||||||||||
383 | return d->endPos; never executed: return d->endPos; | 0 | ||||||||||||||||||||||||
384 | } | - | ||||||||||||||||||||||||
385 | - | |||||||||||||||||||||||||
386 | QByteArray QMimeMagicRule::mask() const | - | ||||||||||||||||||||||||
387 | { | - | ||||||||||||||||||||||||
388 | QByteArray result = d->mask; | - | ||||||||||||||||||||||||
389 | if (d->type == String) {
| 0 | ||||||||||||||||||||||||
390 | // restore '0x' | - | ||||||||||||||||||||||||
391 | result = "0x" + result.toHex(); | - | ||||||||||||||||||||||||
392 | } never executed: end of block | 0 | ||||||||||||||||||||||||
393 | return result; never executed: return result; | 0 | ||||||||||||||||||||||||
394 | } | - | ||||||||||||||||||||||||
395 | - | |||||||||||||||||||||||||
396 | bool QMimeMagicRule::isValid() const | - | ||||||||||||||||||||||||
397 | { | - | ||||||||||||||||||||||||
398 | return d->matchFunction; executed 4058 times by 1 test: return d->matchFunction; Executed by:
| 4058 | ||||||||||||||||||||||||
399 | } | - | ||||||||||||||||||||||||
400 | - | |||||||||||||||||||||||||
401 | bool QMimeMagicRule::matches(const QByteArray &data) const | - | ||||||||||||||||||||||||
402 | { | - | ||||||||||||||||||||||||
403 | const bool ok = d->matchFunction && d->matchFunction(d.data(), data);
| 0-19244 | ||||||||||||||||||||||||
404 | if (!ok)
| 59-19185 | ||||||||||||||||||||||||
405 | return false; executed 19185 times by 1 test: return false; Executed by:
| 19185 | ||||||||||||||||||||||||
406 | - | |||||||||||||||||||||||||
407 | // No submatch? Then we are done. | - | ||||||||||||||||||||||||
408 | if (m_subMatches.isEmpty())
| 22-37 | ||||||||||||||||||||||||
409 | return true; executed 37 times by 1 test: return true; Executed by:
| 37 | ||||||||||||||||||||||||
410 | - | |||||||||||||||||||||||||
411 | //qDebug() << "Checking" << m_subMatches.count() << "sub-rules"; | - | ||||||||||||||||||||||||
412 | // Check that one of the submatches matches too | - | ||||||||||||||||||||||||
413 | for ( QList<QMimeMagicRule>::const_iterator it = m_subMatches.begin(), end = m_subMatches.end() ; | - | ||||||||||||||||||||||||
414 | it != end ; ++it ) {
| 18-22 | ||||||||||||||||||||||||
415 | if ((*it).matches(data)) {
| 4-18 | ||||||||||||||||||||||||
416 | // One of the hierarchies matched -> mimetype recognized. | - | ||||||||||||||||||||||||
417 | return true; executed 4 times by 1 test: return true; Executed by:
| 4 | ||||||||||||||||||||||||
418 | } | - | ||||||||||||||||||||||||
419 | } executed 18 times by 1 test: end of block Executed by:
| 18 | ||||||||||||||||||||||||
420 | return false; executed 18 times by 1 test: return false; Executed by:
| 18 | ||||||||||||||||||||||||
421 | - | |||||||||||||||||||||||||
422 | - | |||||||||||||||||||||||||
423 | } | - | ||||||||||||||||||||||||
424 | - | |||||||||||||||||||||||||
425 | QT_END_NAMESPACE | - | ||||||||||||||||||||||||
426 | - | |||||||||||||||||||||||||
427 | #endif // QT_NO_MIMETYPE | - | ||||||||||||||||||||||||
Source code | Switch to Preprocessed file |