MythTV  master
mythmimedatabase.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QBuffer>
3 #include <QIODevice>
4 #include <QGlobalStatic>
5 #include <QMimeDatabase>
6 #include <QStandardPaths>
7 
8 // MythTV
9 #include "mythlogging.h"
10 #include "http/mythmimedatabase.h"
11 
12 #define LOC QString("MimeDB: ")
13 static constexpr qint64 PEEK_SIZE { 100 };
14 
21 {
22  using MimeDesc = std::tuple<QString,QString,MimeMagic,uint,QStringList>;
23 
24  public:
26  {
27  auto paths =
28  QStandardPaths::locateAll(QStandardPaths::GenericDataLocation,
29  QLatin1String("mime/packages"),
30  QStandardPaths::LocateDirectory);
31  LOG(VB_GENERAL, LOG_DEBUG, LOC +
32  QString("Standard paths: %1").arg(paths.join(", ")));
33 
34  static const std::vector<MimeDesc> s_types =
35  {
36  { "application/cbor", ".cbor", { std::monostate() }, 90, {}},
37  { "application/x-www-form-urlencoded", ".json", { std::monostate() }, 10, { "text/plain" }},
38  { "application/x-plist", ".plist", { QByteArrayLiteral("bplist00") }, 50, {}},
39  { "application/x-apple-binary-plist", ".plist", { QByteArrayLiteral("bplist00") }, 50, {}},
40  { "text/x-apple-plist+xml", ".plist", { QStringLiteral("http://www.apple.com/DTDs/PropertyList-1.0.dtd") },
41  50, { "text/plain", "application/xml"}}
42  };
43 
44  LOG(VB_GENERAL, LOG_DEBUG, LOC +
45  QString("Custom entries: %1").arg(s_types.size()));
46  // cppcheck-suppress unassignedVariable
47  for (const auto & [name, suffix, magic, weight, inherits] : s_types)
48  m_mimes.push_back({name, suffix, magic, weight, inherits});
49  }
50 
51  const MythMimeTypes& AllTypes() const
52  {
53  return m_mimes;
54  }
55 
56  MythMimeType MimeTypeForName(const QString& Name) const
57  {
58  auto found = std::find_if(m_mimes.cbegin(), m_mimes.cend(),
59  [&Name](const auto & Mime) { return Name.compare(Mime.Name(), Qt::CaseInsensitive) == 0; });
60  if (found != m_mimes.cend())
61  return *found;
62  return MythMimeType {};
63  }
64 
65  MythMimeTypes MimeTypesForFileName(const QString &FileName) const
66  {
67  MythMimeTypes result;
68  auto name = FileName.trimmed().toLower();
69  for (const auto & mime : m_mimes)
70  if (name.endsWith(mime.m_suffix))
71  result.push_back(mime);
72  return result;
73  }
74 
75  QString SuffixForFileName(const QString &FileName) const
76  {
77  auto name = FileName.trimmed().toLower();
78  for (const auto & mime : m_mimes)
79  if (name.endsWith(mime.m_suffix))
80  return mime.Suffix();
81  return ".";
82  }
83 
84  static MythMimeType MagicSearch(const MythMimeTypes& Types, const QByteArray& Data)
85  {
86  MythMimeType result;
87  for (const auto & mime : Types)
88  {
89  if (const auto * bytes = std::get_if<QByteArray>(&mime.m_magic); bytes)
90  {
91  if (Data.contains(*bytes) && (mime.m_weight > result.m_weight))
92  result = mime;
93  }
94  else if (const auto * string = std::get_if<QString>(&mime.m_magic); string)
95  {
96  if (QString(Data.constData()).contains(*string, Qt::CaseInsensitive) && (mime.m_weight > result.m_weight))
97  result = mime;
98  }
99  }
100  return result;
101  }
102 
103  MythMimeType MimeTypeForFileNameAndData(const QString& FileName, QIODevice* Device) const
104  {
105  // Try and match by extension
106  auto filtered = MimeTypesForFileName(FileName);
107 
108  // If we have a single extension match, return it
109  if (filtered.size() == 1)
110  return filtered.front();
111 
112  // If device is not opened, open it
113  bool wasopen = Device->isOpen();
114  if (!wasopen)
115  Device->open(QIODevice::ReadOnly);
116 
117  // Peek at the contents
118  auto peek = Device->peek(PEEK_SIZE);
119 
120  // Use matched types or fallback to all for magic search
121  auto result = MagicSearch(filtered.empty() ? AllTypes() : filtered, peek);
122 
123  // Close again if necessary
124  if (!wasopen)
125  Device->close();
126 
127  return result;
128  }
129 
130  static MythMimeTypes ToMythMimeTypes(const QList<QMimeType>& Types)
131  {
132  MythMimeTypes result;
133  std::transform(Types.cbegin(), Types.cend(), std::back_inserter(result),
134  [](auto Type) { return MythMimeType { Type }; });
135  return result;
136  }
137 
138  private:
140 };
141 
142 //NOLINTNEXTLINE(readability-redundant-member-init)
143 Q_GLOBAL_STATIC(MythMimeDatabasePriv, s_mimeDB)
144 
145 
159  : m_priv(s_mimeDB)
160 {
161 }
162 
166 {
167  auto all = MythMimeDatabasePriv::ToMythMimeTypes(QMimeDatabase().allMimeTypes());
168  const auto & mythtv = s_mimeDB->AllTypes();
169  all.insert(all.cend(), mythtv.cbegin(), mythtv.cend());
170  return all;
171 }
172 
176 {
177  auto result = MythMimeDatabasePriv::ToMythMimeTypes(QMimeDatabase().mimeTypesForFileName(FileName));
178  const auto mythtv = s_mimeDB->MimeTypesForFileName(FileName);
179  result.insert(result.cend(), mythtv.cbegin(), mythtv.cend());
180  return result;
181 }
182 
187 QString MythMimeDatabase::SuffixForFileName(const QString &FileName)
188 {
189  if (auto result = QMimeDatabase().suffixForFileName(FileName); !result.isEmpty())
190  return result;
191  return s_mimeDB->SuffixForFileName(FileName);
192 }
193 
202 {
203  if (auto result = s_mimeDB->MimeTypeForName(Name); result.IsValid())
204  return result;
205  return QMimeDatabase().mimeTypeForName(Name);
206 }
207 
217 MythMimeType MythMimeDatabase::MimeTypeForFileNameAndData(const QString& FileName, const QByteArray& Data)
218 {
219  if (auto result = QMimeDatabase().mimeTypeForFileNameAndData(FileName, Data); result.isValid())
220  return result;
221  QBuffer buffer(const_cast<QByteArray*>(&Data));
222  return s_mimeDB->MimeTypeForFileNameAndData(FileName, &buffer);
223 }
224 
226 {
227  if (auto result = QMimeDatabase().mimeTypeForFileNameAndData(FileName, Device); result.isValid())
228  return result;
229  return s_mimeDB->MimeTypeForFileNameAndData(FileName, Device);
230 }
MythMimeDatabasePriv::MythMimeDatabasePriv
MythMimeDatabasePriv()
Definition: mythmimedatabase.cpp:25
MythMimeDatabasePriv::AllTypes
const MythMimeTypes & AllTypes() const
Definition: mythmimedatabase.cpp:51
PEEK_SIZE
static constexpr qint64 PEEK_SIZE
Definition: mythmimedatabase.cpp:13
MythMimeDatabase::MimeTypesForFileName
static MythMimeTypes MimeTypesForFileName(const QString &FileName)
Return a vector of mime types that match the given filename.
Definition: mythmimedatabase.cpp:175
MythMimeDatabasePriv::ToMythMimeTypes
static MythMimeTypes ToMythMimeTypes(const QList< QMimeType > &Types)
Definition: mythmimedatabase.cpp:130
MythMimeDatabase
A wrapper around QMimeDatabase that supports additional mime types.
Definition: mythmimedatabase.h:10
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMimeDatabasePriv::m_mimes
MythMimeTypes m_mimes
Definition: mythmimedatabase.cpp:139
Device
A device containing images (ie. USB stick, CD, storage group etc)
Definition: imagemanager.cpp:35
MythMimeDatabasePriv
A private, internal class that holds custom mime types.
Definition: mythmimedatabase.cpp:20
mythlogging.h
MythMimeTypes
std::vector< MythMimeType > MythMimeTypes
Definition: mythmimetype.h:13
MythMimeDatabase::SuffixForFileName
static QString SuffixForFileName(const QString &FileName)
Return the preferred suffix for the given filename.
Definition: mythmimedatabase.cpp:187
mythmimedatabase.h
MythMimeDatabase::MimeTypeForName
static MythMimeType MimeTypeForName(const QString &Name)
Return a mime type that matches the given name.
Definition: mythmimedatabase.cpp:201
LOC
#define LOC
Definition: mythmimedatabase.cpp:12
hardwareprofile.distros.mythtv_data.main.mythtv
def mythtv
Definition: main.py:90
musicbrainzngs.compat.bytes
bytes
Definition: compat.py:49
Name
Definition: channelsettings.cpp:71
MythMimeDatabase::AllTypes
static MythMimeTypes AllTypes()
Return a vector containing all of the known types (both Qt and MythTV)
Definition: mythmimedatabase.cpp:165
MythMimeType
Definition: mythmimetype.h:16
MythMimeDatabasePriv::SuffixForFileName
QString SuffixForFileName(const QString &FileName) const
Definition: mythmimedatabase.cpp:75
MythMimeDatabasePriv::MimeDesc
std::tuple< QString, QString, MimeMagic, uint, QStringList > MimeDesc
Definition: mythmimedatabase.cpp:22
MythMimeDatabasePriv::MimeTypeForFileNameAndData
MythMimeType MimeTypeForFileNameAndData(const QString &FileName, QIODevice *Device) const
Definition: mythmimedatabase.cpp:103
MythMimeDatabasePriv::MimeTypesForFileName
MythMimeTypes MimeTypesForFileName(const QString &FileName) const
Definition: mythmimedatabase.cpp:65
MythMimeDatabasePriv::MagicSearch
static MythMimeType MagicSearch(const MythMimeTypes &Types, const QByteArray &Data)
Definition: mythmimedatabase.cpp:84
MythMimeType::m_weight
uint m_weight
Definition: mythmimetype.h:42
MythMimeDatabase::MimeTypeForFileNameAndData
static MythMimeType MimeTypeForFileNameAndData(const QString &FileName, const QByteArray &Data)
Return a mime type for the given FileName and data.
Definition: mythmimedatabase.cpp:217
MythMimeDatabasePriv::MimeTypeForName
MythMimeType MimeTypeForName(const QString &Name) const
Definition: mythmimedatabase.cpp:56
build_compdb.paths
paths
Definition: build_compdb.py:13