MythTV master
mythhttpmetaservice.cpp
Go to the documentation of this file.
1// Qt
2#include <QMetaClassInfo>
3
4// MythTV
5#include "mythlogging.h"
8
16MythHTTPMetaService::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
129int 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
168bool 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}
#define RegisterCallback(a, b, c)
static HTTPMethodPtr Create(int Index, QMetaMethod &Method, int RequestTypes, const QString &ReturnName={}, bool Slot=true)
MythHTTPMetaService(const QString &Name, const QMetaObject &Meta, const HTTPRegisterTypes &RegisterCallback=nullptr, const QString &MethodsToHide={})
static int ParseRequestTypes(const QMetaObject &Meta, const QString &Method, QString &ReturnName)
HTTPProperties m_properties
static bool isProtected(const QMetaObject &Meta, const QString &Method)
static int RequestsFromString(const QString &Requests)
static const struct wl_interface * types[]
std::map< QString, HTTPMethodPtr > HTTPMethods
std::shared_ptr< MythHTTPMetaMethod > HTTPMethodPtr
std::function< void()> HTTPRegisterTypes
Definition: mythhttptypes.h:50
@ HTTPGet
Definition: mythhttptypes.h:94
@ HTTPUnknown
Definition: mythhttptypes.h:92
@ HTTPHead
Definition: mythhttptypes.h:93
@ HTTPPost
Definition: mythhttptypes.h:95
@ HTTPOptions
Definition: mythhttptypes.h:98
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
dictionary info
Definition: azlyrics.py:7