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