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