qmimedatabase.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/corelib/mimetypes/qmimedatabase.cpp
Switch to Source codePreprocessed file
LineSourceCount
1-
2-
3-
4-
5-
6-
7-
8-
9-
10-
11-
12namespace { namespace Q_QGS_staticQMimeDatabase { typedef QMimeDatabasePrivate Type; QBasicAtomicInt guard = { QtGlobalStatic::Uninitialized }; __attribute__((visibility("hidden"))) inline Type *innerFunction() { struct HolderBase { ~HolderBase() noexcept { if (guard.load() == QtGlobalStatic::Initialized) guard.store(QtGlobalStatic::Destroyed); } }; static struct Holder : public HolderBase { Type value; Holder() noexcept(noexcept(Type ())) : value () { guard.store(QtGlobalStatic::Initialized); } } holder; return &holder.value; } } } static QGlobalStatic<QMimeDatabasePrivate, Q_QGS_staticQMimeDatabase::innerFunction, Q_QGS_staticQMimeDatabase::guard> staticQMimeDatabase;-
13-
14QMimeDatabasePrivate *QMimeDatabasePrivate::instance()-
15{-
16 return staticQMimeDatabase();-
17}-
18-
19QMimeDatabasePrivate::QMimeDatabasePrivate()-
20 : m_provider(0), m_defaultMimeType(QLatin1String("application/octet-stream"))-
21{-
22}-
23-
24QMimeDatabasePrivate::~QMimeDatabasePrivate()-
25{-
26 delete m_provider;-
27 m_provider = 0;-
28}-
29-
30QMimeProviderBase *QMimeDatabasePrivate::provider()-
31{-
32 if (!m_provider) {-
33 QMimeProviderBase *binaryProvider = new QMimeBinaryProvider(this);-
34 if (binaryProvider->isValid()) {-
35 m_provider = binaryProvider;-
36 } else {-
37 delete binaryProvider;-
38 m_provider = new QMimeXMLProvider(this);-
39 }-
40 }-
41 return m_provider;-
42}-
43-
44void QMimeDatabasePrivate::setProvider(QMimeProviderBase *theProvider)-
45{-
46 delete m_provider;-
47 m_provider = theProvider;-
48}-
49-
50-
51-
52-
53-
54QMimeType QMimeDatabasePrivate::mimeTypeForName(const QString &nameOrAlias)-
55{-
56 return provider()->mimeTypeForName(provider()->resolveAlias(nameOrAlias));-
57}-
58-
59QStringList QMimeDatabasePrivate::mimeTypeForFileName(const QString &fileName, QString *foundSuffix)-
60{-
61 if (fileName.endsWith(QLatin1Char('/'))
fileName.endsW...tin1Char('/'))Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
FALSEevaluated 2621 times by 22 tests
Evaluated by:
  • tst_QAccessibility
  • tst_QCalendarWidget
  • tst_QComboBox
  • tst_QCompleter
  • tst_QDateTimeEdit
  • tst_QFileDialog2
  • tst_QFileIconProvider
  • tst_QFileSystemModel
  • tst_QFiledialog
  • tst_QFontComboBox
  • tst_QGraphicsProxyWidget
  • tst_QGraphicsWidget
  • tst_QGuiApplication
  • tst_QGuiVariant
  • tst_QIcon
  • tst_QMimeDatabase
  • tst_QPrinter
  • tst_QSidebar
  • tst_QStyle
  • tst_QSystemTrayIcon
  • tst_QToolButton
  • tst_languageChange
)
4-2621
62 return
executed 4 times by 1 test: return QStringList() << QLatin1String("inode/directory");
Executed by:
  • tst_QMimeDatabase
QStringList() << QLatin1String("inode/directory");
executed 4 times by 1 test: return QStringList() << QLatin1String("inode/directory");
Executed by:
  • tst_QMimeDatabase
4
63-
64 constQStringList matchingMimeTypes = provider()->findByFileName(QFileInfo(fileName).fileName(), foundSuffix);-
65 matchingMimeTypes.sort();-
66 return
executed 2621 times by 22 tests: return matchingMimeTypes;
Executed by:
  • tst_QAccessibility
  • tst_QCalendarWidget
  • tst_QComboBox
  • tst_QCompleter
  • tst_QDateTimeEdit
  • tst_QFileDialog2
  • tst_QFileIconProvider
  • tst_QFileSystemModel
  • tst_QFiledialog
  • tst_QFontComboBox
  • tst_QGraphicsProxyWidget
  • tst_QGraphicsWidget
  • tst_QGuiApplication
  • tst_QGuiVariant
  • tst_QIcon
  • tst_QMimeDatabase
  • tst_QPrinter
  • tst_QSidebar
  • tst_QStyle
  • tst_QSystemTrayIcon
  • tst_QToolButton
  • tst_languageChange
matchingMimeTypes;
executed 2621 times by 22 tests: return matchingMimeTypes;
Executed by:
  • tst_QAccessibility
  • tst_QCalendarWidget
  • tst_QComboBox
  • tst_QCompleter
  • tst_QDateTimeEdit
  • tst_QFileDialog2
  • tst_QFileIconProvider
  • tst_QFileSystemModel
  • tst_QFiledialog
  • tst_QFontComboBox
  • tst_QGraphicsProxyWidget
  • tst_QGraphicsWidget
  • tst_QGuiApplication
  • tst_QGuiVariant
  • tst_QIcon
  • tst_QMimeDatabase
  • tst_QPrinter
  • tst_QSidebar
  • tst_QStyle
  • tst_QSystemTrayIcon
  • tst_QToolButton
  • tst_languageChange
2621
67}-
68-
69static inline bool isTextFile(const QByteArray &data)-
70{-
71-
72 static const char bigEndianBOM[] = "\xFE\xFF";-
73 static const char littleEndianBOM[] = "\xFF\xFE";-
74 if (data.startsWith(bigEndianBOM) || data.startsWith(littleEndianBOM))-
75 return true;-
76-
77-
78 const char *p = data.constData();-
79 const char *e = p + qMin(32, data.size());-
80 for ( ; p < e; ++p) {-
81 if ((unsigned char)(*p) < 32 && *p != 9 && *p !=10 && *p != 13)-
82 return false;-
83 }-
84-
85 return true;-
86}-
87-
88QMimeType QMimeDatabasePrivate::findByData(const QByteArray &data, int *accuracyPtr)-
89{-
90 if (data.isEmpty()) {-
91 *accuracyPtr = 100;-
92 return mimeTypeForName(QLatin1String("application/x-zerosize"));-
93 }-
94-
95 *accuracyPtr = 0;-
96 QMimeType candidate = provider()->findByMagic(data, accuracyPtr);-
97-
98 if (candidate.isValid())-
99 return candidate;-
100-
101 if (isTextFile(data)) {-
102 *accuracyPtr = 5;-
103 return mimeTypeForName(QLatin1String("text/plain"));-
104 }-
105-
106 return mimeTypeForName(defaultMimeType());-
107}-
108-
109QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device, int *accuracyPtr)-
110{-
111-
112-
113-
114-
115-
116 *accuracyPtr = 0;-
117-
118-
119 QStringList candidatesByName = mimeTypeForFileName(fileName);-
120 if (candidatesByName.count() == 1
candidatesByName.count() == 1Description
TRUEevaluated 2453 times by 21 tests
Evaluated by:
  • tst_QAccessibility
  • tst_QCalendarWidget
  • tst_QComboBox
  • tst_QCompleter
  • tst_QDateTimeEdit
  • tst_QFileDialog2
  • tst_QFileIconProvider
  • tst_QFileSystemModel
  • tst_QFiledialog
  • tst_QFontComboBox
  • tst_QGraphicsProxyWidget
  • tst_QGuiApplication
  • tst_QGuiVariant
  • tst_QIcon
  • tst_QMimeDatabase
  • tst_QPrinter
  • tst_QSidebar
  • tst_QStyle
  • tst_QSystemTrayIcon
  • tst_QToolButton
  • tst_languageChange
FALSEevaluated 34 times by 3 tests
Evaluated by:
  • tst_QGraphicsWidget
  • tst_QIcon
  • tst_QMimeDatabase
) {
34-2453
121 *accuracyPtr = 100;-
122 const QMimeType mime = mimeTypeForName(candidatesByName.at(0));-
123 if (mime.isValid()
mime.isValid()Description
TRUEevaluated 2453 times by 21 tests
Evaluated by:
  • tst_QAccessibility
  • tst_QCalendarWidget
  • tst_QComboBox
  • tst_QCompleter
  • tst_QDateTimeEdit
  • tst_QFileDialog2
  • tst_QFileIconProvider
  • tst_QFileSystemModel
  • tst_QFiledialog
  • tst_QFontComboBox
  • tst_QGraphicsProxyWidget
  • tst_QGuiApplication
  • tst_QGuiVariant
  • tst_QIcon
  • tst_QMimeDatabase
  • tst_QPrinter
  • tst_QSidebar
  • tst_QStyle
  • tst_QSystemTrayIcon
  • tst_QToolButton
  • tst_languageChange
FALSEnever evaluated
)
0-2453
124 return
executed 2453 times by 21 tests: return mime;
Executed by:
  • tst_QAccessibility
  • tst_QCalendarWidget
  • tst_QComboBox
  • tst_QCompleter
  • tst_QDateTimeEdit
  • tst_QFileDialog2
  • tst_QFileIconProvider
  • tst_QFileSystemModel
  • tst_QFiledialog
  • tst_QFontComboBox
  • tst_QGraphicsProxyWidget
  • tst_QGuiApplication
  • tst_QGuiVariant
  • tst_QIcon
  • tst_QMimeDatabase
  • tst_QPrinter
  • tst_QSidebar
  • tst_QStyle
  • tst_QSystemTrayIcon
  • tst_QToolButton
  • tst_languageChange
mime;
executed 2453 times by 21 tests: return mime;
Executed by:
  • tst_QAccessibility
  • tst_QCalendarWidget
  • tst_QComboBox
  • tst_QCompleter
  • tst_QDateTimeEdit
  • tst_QFileDialog2
  • tst_QFileIconProvider
  • tst_QFileSystemModel
  • tst_QFiledialog
  • tst_QFontComboBox
  • tst_QGraphicsProxyWidget
  • tst_QGuiApplication
  • tst_QGuiVariant
  • tst_QIcon
  • tst_QMimeDatabase
  • tst_QPrinter
  • tst_QSidebar
  • tst_QStyle
  • tst_QSystemTrayIcon
  • tst_QToolButton
  • tst_languageChange
2453
125 candidatesByName.clear();-
126 }
never executed: end of block
0
127-
128-
129-
130 if (device->isOpen()
device->isOpen()Description
TRUEevaluated 26 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
FALSEevaluated 8 times by 3 tests
Evaluated by:
  • tst_QGraphicsWidget
  • tst_QIcon
  • tst_QMimeDatabase
) {
8-26
131-
132-
133-
134 const QByteArray data = device->peek(16384);-
135-
136 int magicAccuracy = 0;-
137 QMimeType candidateByData(findByData(data, &magicAccuracy));-
138-
139-
140 if (candidateByData.isValid()
candidateByData.isValid()Description
TRUEevaluated 26 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
FALSEnever evaluated
&& magicAccuracy > 0
magicAccuracy > 0Description
TRUEevaluated 26 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
FALSEnever evaluated
) {
0-26
141-
142-
143 const QString sniffedMime = candidateByData.name();-
144 for (QForeachContainer<typename QtPrivate::remove_reference<decltype(candidatesByName)>::type> _container_((candidatesByName)); _container_.control && _container_.i != _container_.e; ++_container_.i, _container_.control ^= 1)for (const QString &m = *_container_.i; _container_.control; _container_.control = 0): qAsConst(candidatesByName)) {-
145 if (inherits(m, sniffedMime)
inherits(m, sniffedMime)Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
146-
147 *accuracyPtr = 100;-
148 return
never executed: return mimeTypeForName(m);
mimeTypeForName(m);
never executed: return mimeTypeForName(m);
0
149 }-
150 }
never executed: end of block
0
151 *accuracyPtr = magicAccuracy;-
152 return
executed 26 times by 1 test: return candidateByData;
Executed by:
  • tst_QMimeDatabase
candidateByData;
executed 26 times by 1 test: return candidateByData;
Executed by:
  • tst_QMimeDatabase
26
153 }-
154 }
never executed: end of block
0
155-
156 if (candidatesByName.count() > 1
candidatesByName.count() > 1Description
TRUEnever evaluated
FALSEevaluated 8 times by 3 tests
Evaluated by:
  • tst_QGraphicsWidget
  • tst_QIcon
  • tst_QMimeDatabase
) {
0-8
157 *accuracyPtr = 20;-
158 candidatesByName.sort();const QMimeType mime = mimeTypeForName(candidatesByName.at(0));-
159 if (mime.isValid()
mime.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
160 return
never executed: return mime;
mime;
never executed: return mime;
0
161 }
never executed: end of block
0
162-
163 return
executed 8 times by 3 tests: return mimeTypeForName(defaultMimeType());
Executed by:
  • tst_QGraphicsWidget
  • tst_QIcon
  • tst_QMimeDatabase
mimeTypeForName(defaultMimeType());
executed 8 times by 3 tests: return mimeTypeForName(defaultMimeType());
Executed by:
  • tst_QGraphicsWidget
  • tst_QIcon
  • tst_QMimeDatabase
8
164}-
165-
166QList<QMimeType> QMimeDatabasePrivate::allMimeTypes()-
167{-
168 return provider()->allMimeTypes();-
169}-
170-
171bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent)-
172{-
173 const QString resolvedParent = provider()->resolveAlias(parent);-
174-
175 QStackstd::stack<QString, QStringList> toCheck;-
176 toCheck.push(mime);-
177 while (!toCheck.isEmptyempty()
!toCheck.empty()Description
TRUEevaluated 116 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
FALSEevaluated 4 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
) {
4-116
178 const QString current = toCheck.pop();if (currenttoCheck.top()
toCheck.top() ...resolvedParentDescription
TRUEevaluated 48 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
FALSEevaluated 68 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
== resolvedParent
toCheck.top() ...resolvedParentDescription
TRUEevaluated 48 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
FALSEevaluated 68 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
)
48-68
179 return
executed 48 times by 1 test: return true;
Executed by:
  • tst_QMimeDatabase
true;
executed 48 times by 1 test: return true;
Executed by:
  • tst_QMimeDatabase
48
180 for (QForeachContainer<typename QtPrivate::remove_reference<decltype(provider()->const auto parents (current))>::type> _container_((= provider()->parents(current))); _container_.control && _container_.i != _container_.e; ++_container_toCheck.i, _container_top());-
181 toCheck.control ^= 1)pop();-
182 for (const QString &par = *_container_.i; _container_.control; _container_.control = 0: parents)-
183 toCheck.push(par);
executed 68 times by 1 test: toCheck.push(par);
Executed by:
  • tst_QMimeDatabase
68
184 }
executed 68 times by 1 test: end of block
Executed by:
  • tst_QMimeDatabase
68
185 return
executed 4 times by 1 test: return false;
Executed by:
  • tst_QMimeDatabase
false;
executed 4 times by 1 test: return false;
Executed by:
  • tst_QMimeDatabase
4
186}-
187QMimeDatabase::QMimeDatabase() :-
188 d(staticQMimeDatabase())-
189{-
190}-
191-
192-
193-
194-
195-
196QMimeDatabase::~QMimeDatabase()-
197{-
198 d = 0;-
199}-
200-
201-
202-
203-
204-
205QMimeType QMimeDatabase::mimeTypeForName(const QString &nameOrAlias) const-
206{-
207 QMutexLocker locker(&d->mutex);-
208-
209 return d->mimeTypeForName(nameOrAlias);-
210}-
211QMimeType QMimeDatabase::mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode) const-
212{-
213 QMutexLocker locker(&d->mutex);-
214-
215 if (fileInfo.isDir())-
216 return d->mimeTypeForName(QLatin1String("inode/directory"));-
217-
218 QFile file(fileInfo.absoluteFilePath());-
219-
220-
221-
222-
223 const QByteArray nativeFilePath = QFile::encodeName(file.fileName());-
224 struct stat64 statBuffer;-
225 if (::stat64(nativeFilePath.constData(), &statBuffer) == 0) {-
226 if (((((statBuffer.st_mode)) & 0170000) == (0020000)))-
227 return d->mimeTypeForName(QLatin1String("inode/chardevice"));-
228 if (((((statBuffer.st_mode)) & 0170000) == (0060000)))-
229 return d->mimeTypeForName(QLatin1String("inode/blockdevice"));-
230 if (((((statBuffer.st_mode)) & 0170000) == (0010000)))-
231 return d->mimeTypeForName(QLatin1String("inode/fifo"));-
232 if (((((statBuffer.st_mode)) & 0170000) == (0140000)))-
233 return d->mimeTypeForName(QLatin1String("inode/socket"));-
234 }-
235-
236-
237 int priority = 0;-
238 switch (mode) {-
239 case MatchDefault:-
240 file.open(QIODevice::ReadOnly);-
241 return d->mimeTypeForFileNameAndData(fileInfo.absoluteFilePath(), &file, &priority);-
242 case MatchExtension:-
243 locker.unlock();-
244 return mimeTypeForFile(fileInfo.absoluteFilePath(), mode);-
245 case MatchContent:-
246 if (file.open(QIODevice::ReadOnly)) {-
247 locker.unlock();-
248 return mimeTypeForData(&file);-
249 } else {-
250 return d->mimeTypeForName(d->defaultMimeType());-
251 }-
252 default:-
253 ((!(false)) ? qt_assert("false",__FILE__,388395) : qt_noop());-
254 }-
255 return d->mimeTypeForName(d->defaultMimeType());-
256}-
257-
258-
259-
260-
261-
262-
263QMimeType QMimeDatabase::mimeTypeForFile(const QString &fileName, MatchMode mode) const-
264{-
265 if (mode == MatchExtension
mode == MatchExtensionDescription
TRUEevaluated 68 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
FALSEevaluated 40 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
) {
40-68
266 QMutexLocker locker(&d->mutex);-
267 const QStringList matches = d->mimeTypeForFileName(fileName);-
268 const int matchCount = matches.count();-
269 if (matchCount == 0
matchCount == 0Description
TRUEevaluated 16 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
FALSEevaluated 52 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
) {
16-52
270 return
executed 16 times by 1 test: return d->mimeTypeForName(d->defaultMimeType());
Executed by:
  • tst_QMimeDatabase
d->mimeTypeForName(d->defaultMimeType());
executed 16 times by 1 test: return d->mimeTypeForName(d->defaultMimeType());
Executed by:
  • tst_QMimeDatabase
16
271 } else if (matchCount == 1
matchCount == 1Description
TRUEevaluated 52 times by 1 test
Evaluated by:
  • tst_QMimeDatabase
FALSEnever evaluated
) {
0-52
272 return
executed 52 times by 1 test: return d->mimeTypeForName(matches.first());
Executed by:
  • tst_QMimeDatabase
d->mimeTypeForName(matches.first());
executed 52 times by 1 test: return d->mimeTypeForName(matches.first());
Executed by:
  • tst_QMimeDatabase
52
273 } else {-
274-
275 matches.sort();return
never executed: return d->mimeTypeForName(matches.first());
d->mimeTypeForName(matches.first());
never executed: return d->mimeTypeForName(matches.first());
0
276 }-
277 } else {-
278-
279 QFileInfo fileInfo(fileName);-
280 return
executed 40 times by 1 test: return mimeTypeForFile(fileInfo, mode);
Executed by:
  • tst_QMimeDatabase
mimeTypeForFile(fileInfo, mode);
executed 40 times by 1 test: return mimeTypeForFile(fileInfo, mode);
Executed by:
  • tst_QMimeDatabase
40
281 }-
282}-
283QList<QMimeType> QMimeDatabase::mimeTypesForFileName(const QString &fileName) const-
284{-
285 QMutexLocker locker(&d->mutex);-
286-
287 const QStringList matches = d->mimeTypeForFileName(fileName);-
288 QList<QMimeType> mimes;-
289 matches.sort();mimes.reserve(matches.count());-
290 for (QForeachContainer<typename QtPrivate::remove_reference<decltype(matches)>::type> _container_((matches)); _container_.control && _container_.i != _container_.e; ++_container_.i, _container_.control ^= 1)for (const QString &mime = *_container_.i; _container_.control; _container_.control = 0: matches)-
291 mimes.append(d->mimeTypeForName(mime));
executed 52 times by 1 test: mimes.append(d->mimeTypeForName(mime));
Executed by:
  • tst_QMimeDatabase
52
292 return
executed 54 times by 1 test: return mimes;
Executed by:
  • tst_QMimeDatabase
mimes;
executed 54 times by 1 test: return mimes;
Executed by:
  • tst_QMimeDatabase
54
293}-
294-
295-
296-
297-
298-
299-
300QString QMimeDatabase::suffixForFileName(const QString &fileName) const-
301{-
302 QMutexLocker locker(&d->mutex);-
303 QString foundSuffix;-
304 d->mimeTypeForFileName(fileName, &foundSuffix);-
305 return foundSuffix;-
306}-
307QMimeType QMimeDatabase::mimeTypeForData(const QByteArray &data) const-
308{-
309 QMutexLocker locker(&d->mutex);-
310-
311 int accuracy = 0;-
312 return d->findByData(data, &accuracy);-
313}-
314QMimeType QMimeDatabase::mimeTypeForData(QIODevice *device) const-
315{-
316 QMutexLocker locker(&d->mutex);-
317-
318 int accuracy = 0;-
319 const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);-
320 if (device->isOpen()) {-
321-
322-
323 const QByteArray data = device->peek(16384);-
324 const QMimeType result = d->findByData(data, &accuracy);-
325 if (openedByUs)-
326 device->close();-
327 return result;-
328 }-
329 return d->mimeTypeForName(d->defaultMimeType());-
330}-
331QMimeType QMimeDatabase::mimeTypeForUrl(const QUrl &url) const-
332{-
333 if (url.isLocalFile())-
334 return mimeTypeForFile(url.toLocalFile());-
335-
336 const QString scheme = url.scheme();-
337 if (scheme.startsWith(QLatin1String("http")) || scheme == QLatin1String("mailto"))-
338 return mimeTypeForName(d->defaultMimeType());-
339-
340 return mimeTypeForFile(url.path());-
341}-
342QMimeType QMimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, QIODevice *device) const-
343{-
344 int accuracy = 0;-
345 const bool openedByUs = !device->isOpen() && device->open(QIODevice::ReadOnly);-
346 const QMimeType result = d->mimeTypeForFileNameAndData(fileName, device, &accuracy);-
347 if (openedByUs)-
348 device->close();-
349 return result;-
350}-
351QMimeType QMimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, const QByteArray &data) const-
352{-
353 QBuffer buffer(const_cast<QByteArray *>(&data));-
354 buffer.open(QIODevice::ReadOnly);-
355 int accuracy = 0;-
356 return d->mimeTypeForFileNameAndData(fileName, &buffer, &accuracy);-
357}-
358QList<QMimeType> QMimeDatabase::allMimeTypes() const-
359{-
360 QMutexLocker locker(&d->mutex);-
361-
362 return d->allMimeTypes();-
363}-
364-
Switch to Source codePreprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9