1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qdbuserror.h"
5
6#include <qdebug.h>
7#include <qvarlengtharray.h>
8#include <private/qoffsetstringarray_p.h>
9
10#ifndef QT_BOOTSTRAPPED
11#include "qdbus_symbols_p.h"
12#include "qdbusmessage.h"
13#include "qdbusmessage_p.h"
14#endif
15
16#ifndef QT_NO_DBUS
17
18QT_BEGIN_NAMESPACE
19
20QT_IMPL_METATYPE_EXTERN(QDBusError)
21
22static constexpr const auto errorMessages = qOffsetStringArray(
23 strings: "NoError",
24 strings: "other",
25 strings: "org.freedesktop.DBus.Error.Failed",
26 strings: "org.freedesktop.DBus.Error.NoMemory",
27 strings: "org.freedesktop.DBus.Error.ServiceUnknown",
28 strings: "org.freedesktop.DBus.Error.NoReply",
29 strings: "org.freedesktop.DBus.Error.BadAddress",
30 strings: "org.freedesktop.DBus.Error.NotSupported",
31 strings: "org.freedesktop.DBus.Error.LimitsExceeded",
32 strings: "org.freedesktop.DBus.Error.AccessDenied",
33 strings: "org.freedesktop.DBus.Error.NoServer",
34 strings: "org.freedesktop.DBus.Error.Timeout",
35 strings: "org.freedesktop.DBus.Error.NoNetwork",
36 strings: "org.freedesktop.DBus.Error.AddressInUse",
37 strings: "org.freedesktop.DBus.Error.Disconnected",
38 strings: "org.freedesktop.DBus.Error.InvalidArgs",
39 strings: "org.freedesktop.DBus.Error.UnknownMethod",
40 strings: "org.freedesktop.DBus.Error.TimedOut",
41 strings: "org.freedesktop.DBus.Error.InvalidSignature",
42 strings: "org.freedesktop.DBus.Error.UnknownInterface",
43 strings: "org.freedesktop.DBus.Error.UnknownObject",
44 strings: "org.freedesktop.DBus.Error.UnknownProperty",
45 strings: "org.freedesktop.DBus.Error.PropertyReadOnly",
46 strings: "org.qtproject.QtDBus.Error.InternalError",
47 strings: "org.qtproject.QtDBus.Error.InvalidService",
48 strings: "org.qtproject.QtDBus.Error.InvalidObjectPath",
49 strings: "org.qtproject.QtDBus.Error.InvalidInterface",
50 strings: "org.qtproject.QtDBus.Error.InvalidMember",
51 strings: ""
52);
53
54#ifndef QT_BOOTSTRAPPED
55static inline QDBusError::ErrorType get(const char *name)
56{
57 if (!name || !*name)
58 return QDBusError::NoError;
59 for (int i = 0; i < errorMessages.count(); ++i)
60 if (strcmp(s1: name, s2: errorMessages.at(index: i)) == 0)
61 return QDBusError::ErrorType(i);
62 return QDBusError::Other;
63}
64#endif
65
66/*!
67 \class QDBusError
68 \inmodule QtDBus
69 \since 4.2
70
71 \brief The QDBusError class represents an error received from the
72 D-Bus bus or from remote applications found in the bus.
73
74 When dealing with the D-Bus bus service or with remote
75 applications over D-Bus, a number of error conditions can
76 happen. This error conditions are sometimes signalled by a
77 returned error value or by a QDBusError.
78
79 C++ and Java exceptions are a valid analogy for D-Bus errors:
80 instead of returning normally with a return value, remote
81 applications and the bus may decide to throw an error
82 condition. However, the Qt D-Bus implementation does not use the C++
83 exception-throwing mechanism, so you will receive QDBusErrors in
84 the return reply (see QDBusReply::error()).
85
86 QDBusError objects are used to inspect the error name and message
87 as received from the bus and remote applications. You should not
88 create such objects yourself to signal error conditions when
89 called from D-Bus: instead, use QDBusMessage::createError() and
90 QDBusConnection::send().
91
92 \sa QDBusConnection::send(), QDBusMessage, QDBusReply
93*/
94
95/*!
96 \enum QDBusError::ErrorType
97
98 In order to facilitate verification of the most common D-Bus errors generated by the D-Bus
99 implementation and by the bus daemon itself, QDBusError can be compared to a set of pre-defined
100 values:
101
102 \value NoError QDBusError is invalid (i.e., the call succeeded)
103 \value Other QDBusError contains an error that is not one of the well-known ones
104 \value Failed The call failed (\c org.freedesktop.DBus.Error.Failed)
105 \value NoMemory Out of memory (\c org.freedesktop.DBus.Error.NoMemory)
106 \value ServiceUnknown The called service is not known
107 (\c org.freedesktop.DBus.Error.ServiceUnknown)
108 \value NoReply The called method did not reply within the specified timeout
109 (\c org.freedesktop.DBus.Error.NoReply)
110 \value BadAddress The address given is not valid
111 (\c org.freedesktop.DBus.Error.BadAddress)
112 \value NotSupported The call/operation is not supported
113 (\c org.freedesktop.DBus.Error.NotSupported)
114 \value LimitsExceeded The limits allocated to this process/call/connection exceeded the
115 pre-defined values (\c org.freedesktop.DBus.Error.LimitsExceeded)
116 \value AccessDenied The call/operation tried to access a resource it isn't allowed to
117 (\c org.freedesktop.DBus.Error.AccessDenied)
118 \value NoServer \e {Documentation doesn't say what this is for}
119 (\c org.freedesktop.DBus.Error.NoServer)
120 \value Timeout \e {Documentation doesn't say what this is for or how it's used}
121 (\c org.freedesktop.DBus.Error.Timeout)
122 \value NoNetwork \e {Documentation doesn't say what this is for}
123 (\c org.freedesktop.DBus.Error.NoNetwork)
124 \value AddressInUse QDBusServer tried to bind to an address that is already in use
125 (\c org.freedesktop.DBus.Error.AddressInUse)
126 \value Disconnected The call/process/message was sent after QDBusConnection disconnected
127 (\c org.freedesktop.DBus.Error.Disconnected)
128 \value InvalidArgs The arguments passed to this call/operation are not valid
129 (\c org.freedesktop.DBus.Error.InvalidArgs)
130 \value UnknownMethod The method called was not found in this object/interface with the
131 given parameters (\c org.freedesktop.DBus.Error.UnknownMethod)
132 \value TimedOut \e {Documentation doesn't say...}
133 (\c org.freedesktop.DBus.Error.TimedOut)
134 \value InvalidSignature The type signature is not valid or compatible
135 (\c org.freedesktop.DBus.Error.InvalidSignature)
136 \value UnknownInterface The interface is not known in this object
137 (\c org.freedesktop.DBus.Error.UnknownInterface)
138 \value UnknownObject The object path points to an object that does not exist
139 (\c org.freedesktop.DBus.Error.UnknownObject)
140 \value UnknownProperty The property does not exist in this interface
141 (\c org.freedesktop.DBus.Error.UnknownProperty)
142 \value PropertyReadOnly The property set failed because the property is read-only
143 (\c org.freedesktop.DBus.Error.PropertyReadOnly)
144
145 \value InternalError An internal error occurred
146
147 \value InvalidObjectPath The object path provided is invalid.
148
149 \value InvalidService The service requested is invalid.
150
151 \value InvalidMember The member is invalid.
152
153 \value InvalidInterface The interface is invalid.
154*/
155
156/*!
157 \internal
158 Constructs a QDBusError that represents no error.
159*/
160QDBusError::QDBusError()
161 : code(NoError)
162{
163 // ### This class has an implicit (therefore inline) destructor
164 // so the following field cannot be used.
165 Q_UNUSED(unused);
166}
167
168#ifndef QT_BOOTSTRAPPED
169/*!
170 \internal
171 Constructs a QDBusError from a DBusError structure.
172*/
173QDBusError::QDBusError(const DBusError *error)
174 : code(NoError)
175{
176 if (!error || !q_dbus_error_is_set(error))
177 return;
178
179 code = get(name: error->name);
180 msg = QString::fromUtf8(utf8: error->message);
181 nm = QString::fromUtf8(utf8: error->name);
182}
183
184/*!
185 \internal
186 Constructs a QDBusError from a QDBusMessage.
187*/
188QDBusError::QDBusError(const QDBusMessage &qdmsg)
189 : code(NoError)
190{
191 if (qdmsg.type() != QDBusMessage::ErrorMessage)
192 return;
193
194 code = get(name: qdmsg.errorName().toUtf8().constData());
195 nm = qdmsg.errorName();
196 msg = qdmsg.errorMessage();
197}
198#endif
199
200/*!
201 \internal
202 Constructs a QDBusError from a well-known error code
203*/
204QDBusError::QDBusError(ErrorType error, const QString &mess)
205 : code(error)
206{
207 nm = QLatin1StringView(errorMessages[error]);
208 msg = mess;
209}
210
211/*!
212 \internal
213 Constructs a QDBusError from another QDBusError object
214*/
215QDBusError::QDBusError(const QDBusError &other)
216 : code(other.code), msg(other.msg), nm(other.nm)
217{
218}
219
220/*!
221 \internal
222 Assignment operator
223*/
224
225QDBusError &QDBusError::operator=(const QDBusError &other)
226{
227 code = other.code;
228 msg = other.msg;
229 nm = other.nm;
230 return *this;
231}
232
233#ifndef QT_BOOTSTRAPPED
234/*!
235 \internal
236 Assignment operator from a QDBusMessage
237*/
238QDBusError &QDBusError::operator=(const QDBusMessage &qdmsg)
239{
240 if (qdmsg.type() == QDBusMessage::ErrorMessage) {
241 code = get(name: qdmsg.errorName().toUtf8().constData());
242 nm = qdmsg.errorName();
243 msg = qdmsg.errorMessage();
244 } else {
245 code =NoError;
246 nm.clear();
247 msg.clear();
248 }
249 return *this;
250}
251#endif
252
253/*!
254 Returns this error's ErrorType.
255
256 \sa ErrorType
257*/
258
259QDBusError::ErrorType QDBusError::type() const
260{
261 return code;
262}
263
264/*!
265 Returns this error's name. Error names are similar to D-Bus Interface names, like
266 \c org.freedesktop.DBus.InvalidArgs.
267
268 \sa type()
269*/
270
271QString QDBusError::name() const
272{
273 return nm;
274}
275
276/*!
277 Returns the message that the callee associated with this error. Error messages are
278 implementation defined and usually contain a human-readable error code, though this does not
279 mean it is suitable for your end-users.
280*/
281
282QString QDBusError::message() const
283{
284 return msg;
285}
286
287/*!
288 Returns \c true if this is a valid error condition (i.e., if there was an error),
289 otherwise false.
290*/
291
292bool QDBusError::isValid() const
293{
294 return (code != NoError);
295}
296
297/*!
298 \since 4.3
299 Returns the error name associated with error condition \a error.
300*/
301QString QDBusError::errorString(ErrorType error)
302{
303 return QLatin1StringView(errorMessages[error]);
304}
305
306#ifndef QT_NO_DEBUG_STREAM
307QDebug operator<<(QDebug dbg, const QDBusError &msg)
308{
309 QDebugStateSaver saver(dbg);
310 dbg.nospace() << "QDBusError(" << msg.name() << ", " << msg.message() << ')';
311 return dbg;
312}
313#endif
314
315/*!
316 \fn void QDBusError::swap(QDBusError &other)
317
318 Swaps this QDBusError instance with \a other.
319*/
320
321QT_END_NAMESPACE
322
323#include "moc_qdbuserror.cpp"
324
325#endif // QT_NO_DBUS
326
327/*
328MSVC2015 has the warning C4503 at the end of the file:
329QtPrivate::StaticStringBuilder<QtPrivate::IndexesList<...> - decorated name length exceeded, name was truncated
330It is used by qOffsetStringArray in a constexpr evaluation and this code does not exist in the object file,
331but we still have the warning or even error with -WX flag
332*/
333QT_WARNING_DISABLE_MSVC(4503)
334

source code of qtbase/src/dbus/qdbuserror.cpp