MythTV  master
mythhttpmetaservice.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QMetaClassInfo>
3 
4 // MythTV
5 #include "mythlogging.h"
7 #include "http/mythhttptypes.h"
8 
16 MythHTTPMetaService::MythHTTPMetaService(const QString& Name, const QMetaObject& Meta,
18  const QString& MethodsToHide)
19  : m_meta(Meta),
20  m_name(Name)
21 {
22  // Register any types
23  if (RegisterCallback != nullptr)
24  std::invoke(RegisterCallback);
25 
26  // Static list of signals and slots to avoid
27  static QString s_defaultHide = { "destroyed,deleteLater,objectNameChanged,RegisterCustomTypes" };
28 
29  // Retrieve version
30  auto index = Meta.indexOfClassInfo("Version");
31  if (index > -1)
32  m_version = Meta.classInfo(index).value();
33  else
34  LOG(VB_GENERAL, LOG_WARNING, QStringLiteral("Service '%1' is missing version information").arg(Name));
35 
36  // Build complete list of meta objects for class hierarchy
37  QList<const QMetaObject*> metas;
38  metas.append(&Meta);
39  const QMetaObject* super = Meta.superClass();
40  while (super)
41  {
42  metas.append(super);
43  super = super->superClass();
44  }
45 
46  QString hide = s_defaultHide + MethodsToHide;
47 
48  // Pull out public signals and slots, ignoring 'MethodsToHide'
49  for (const auto * meta : metas)
50  {
51  for (int i = 0; i < meta->methodCount(); ++i)
52  {
53  QMetaMethod method = meta->method(i);
54 
55  // We want only public methods
56  if (QMetaMethod::Public != method.access())
57  continue;
58 
59  // Filtered unwanted
60  QString name(method.methodSignature());
61  name = name.section('(', 0, 0);
62  if (hide.contains(name))
63  continue;
64 
65  auto RemoveExisting = [](HTTPMethods& Methods, const HTTPMethodPtr& Method, const QString& Search)
66  {
67  for (const auto & [_name, _method] : Methods)
68  {
69  if ((_name == Search) && (_method->m_method.methodSignature() == Method->m_method.methodSignature()) &&
70  (_method->m_method.returnType() == Method->m_method.returnType()))
71  {
72  Methods.erase(_name);
73  break;
74  }
75  }
76  };
77 
78  // Signals
79  if (QMetaMethod::Signal == method.methodType())
80  {
81  auto newmethod = MythHTTPMetaMethod::Create(i, method, HTTPUnknown, {}, false);
82  if (newmethod)
83  {
84  RemoveExisting(m_signals, newmethod, name);
85  m_signals.emplace(name, newmethod);
86  }
87  }
88  // Slots
89  else if (QMetaMethod::Slot == method.methodType())
90  {
91  QString returnname;
92  int types = ParseRequestTypes(Meta, name, returnname);
93  if (types != HTTPUnknown)
94  {
95  auto newmethod = MythHTTPMetaMethod::Create(i, method, types, returnname);
96  if (newmethod)
97  {
98  newmethod->m_protected = isProtected(Meta, name);
99  RemoveExisting(m_slots, newmethod, name);
100  m_slots.emplace(name, newmethod);
101  }
102  }
103  }
104  }
105  }
106 
107  int constpropertyindex = -1;
108  for (const auto * meta : metas)
109  {
110  for (int i = meta->propertyOffset(); i < meta->propertyCount(); ++i)
111  {
112  QMetaProperty property = meta->property(i);
113  QString propertyname(property.name());
114 
115  if (propertyname != QString("objectName") && property.isReadable() &&
116  ((property.hasNotifySignal() && property.notifySignalIndex() > -1) || property.isConstant()))
117  {
118  // constant properties are given a signal index < 0
119  if (property.notifySignalIndex() > -1)
120  m_properties.emplace(property.notifySignalIndex(), property.propertyIndex());
121  else
122  m_properties.emplace(constpropertyindex--, property.propertyIndex());
123  }
124  }
125  }
126  LOG(VB_GENERAL, LOG_INFO, QString("Service '%1' introspection complete").arg(Name));
127 }
128 
129 int MythHTTPMetaService::ParseRequestTypes(const QMetaObject& Meta, const QString& Method, QString& ReturnName)
130 {
131  int custom = HTTPUnknown;
132  int index = Meta.indexOfClassInfo(Method.toLatin1());
133  if (index > -1)
134  {
135  QStringList infos = QString(Meta.classInfo(index).value()).split(';', Qt::SkipEmptyParts);
136  foreach (const QString &info, infos)
137  {
138  if (info.startsWith(QStringLiteral("methods=")))
139  custom |= MythHTTP::RequestsFromString(info.mid(8));
140  if (info.startsWith(QStringLiteral("name=")))
141  ReturnName = info.mid(5).trimmed();
142  }
143  }
144 
145  // determine allowed request types
146  int allowed = HTTPOptions;
147  if (custom != HTTPUnknown)
148  {
149  allowed |= custom;
150  }
151  else if (Method.startsWith(QStringLiteral("Get"), Qt::CaseInsensitive))
152  {
153  allowed |= HTTPGet | HTTPHead | HTTPPost;
154  }
155  else if (Method.startsWith(QStringLiteral("Set"), Qt::CaseInsensitive))
156  {
157  // Put or Post?
158  allowed |= HTTPPost;
159  }
160  else
161  {
162  LOG(VB_GENERAL, LOG_ERR, QString("Failed to get request types for method '%1'- ignoring").arg(Method));
163  return HTTPUnknown;
164  }
165  return allowed;
166 }
167 
168 bool MythHTTPMetaService::isProtected(const QMetaObject& Meta, const QString& Method)
169 {
170  int index = Meta.indexOfClassInfo(Method.toLatin1());
171  if (index > -1)
172  {
173  QStringList infos = QString(Meta.classInfo(index).value()).split(';', Qt::SkipEmptyParts);
174  auto isAuth = [](const QString& info)
175  { return info.startsWith(QStringLiteral("AuthRequired=")); };
176  return std::any_of(infos.cbegin(), infos.cend(), isAuth);
177  }
178  return false;
179 }
MythHTTPMetaService::m_signals
HTTPMethods m_signals
Definition: mythhttpmetaservice.h:23
HTTPPost
@ HTTPPost
Definition: mythhttptypes.h:95
MythHTTPMetaService::ParseRequestTypes
static int ParseRequestTypes(const QMetaObject &Meta, const QString &Method, QString &ReturnName)
Definition: mythhttpmetaservice.cpp:129
HTTPOptions
@ HTTPOptions
Definition: mythhttptypes.h:98
HTTPGet
@ HTTPGet
Definition: mythhttptypes.h:94
HTTPMethods
std::map< QString, HTTPMethodPtr > HTTPMethods
Definition: mythhttpmetamethod.h:15
mythhttpmetaservice.h
types
static const struct wl_interface * types[]
Definition: idle_inhibit_unstable_v1.c:39
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythHTTP::RequestsFromString
static int RequestsFromString(const QString &Requests)
Definition: mythhttptypes.h:245
MythHTTPMetaMethod::Create
static HTTPMethodPtr Create(int Index, QMetaMethod &Method, int RequestTypes, const QString &ReturnName={}, bool Slot=true)
Definition: mythhttpmetamethod.cpp:117
RegisterCallback
#define RegisterCallback(a, b, c)
Definition: audiooutputopensles.cpp:47
mythlogging.h
MythHTTPMetaService::MythHTTPMetaService
MythHTTPMetaService(const QString &Name, const QMetaObject &Meta, const HTTPRegisterTypes &RegisterCallback=nullptr, const QString &MethodsToHide={})
Definition: mythhttpmetaservice.cpp:16
MythHTTPMetaService::m_properties
HTTPProperties m_properties
Definition: mythhttpmetaservice.h:25
MythHTTPMetaService::m_version
QString m_version
Definition: mythhttpmetaservice.h:22
mythhttptypes.h
Search
Definition: netgrabbermanager.h:143
MythHTTPMetaService::isProtected
static bool isProtected(const QMetaObject &Meta, const QString &Method)
Definition: mythhttpmetaservice.cpp:168
HTTPHead
@ HTTPHead
Definition: mythhttptypes.h:93
MythHTTPMetaService::m_slots
HTTPMethods m_slots
Definition: mythhttpmetaservice.h:24
HTTPUnknown
@ HTTPUnknown
Definition: mythhttptypes.h:92
Name
Definition: channelsettings.cpp:71
azlyrics.info
dictionary info
Definition: azlyrics.py:7
HTTPMethodPtr
std::shared_ptr< MythHTTPMetaMethod > HTTPMethodPtr
Definition: mythhttpmetamethod.h:14
HTTPRegisterTypes
std::function< void()> HTTPRegisterTypes
Definition: mythhttptypes.h:50