1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Digia gives you certain additional
26** rights. These rights are described in the Digia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdbuserror.h"
43
44#include <qdebug.h>
45#include <qvarlengtharray.h>
46
47#include "qdbus_symbols_p.h"
48#include "qdbusmessage.h"
49#include "qdbusmessage_p.h"
50
51#ifndef QT_NO_DBUS
52
53QT_BEGIN_NAMESPACE
54
55/*
56 * Use the following Perl script to generate the error string index list:
57===== PERL SCRIPT ====
58print "static const char errorMessages_string[] =\n";
59$counter = 0;
60$i = 0;
61while (<STDIN>) {
62 chomp;
63 print " \"$_\\0\"\n";
64 $sizes[$i++] = $counter;
65 $counter += 1 + length $_;
66}
67print " \"\\0\";\n\nstatic const int errorMessages_indices[] = {\n ";
68for ($j = 0; $j < $i; ++$j) {
69 printf "$sizes[$j], ";
70}
71print "0\n};\n";
72===== PERL SCRIPT ====
73
74 * The input data is as follows:
75other
76org.freedesktop.DBus.Error.Failed
77org.freedesktop.DBus.Error.NoMemory
78org.freedesktop.DBus.Error.ServiceUnknown
79org.freedesktop.DBus.Error.NoReply
80org.freedesktop.DBus.Error.BadAddress
81org.freedesktop.DBus.Error.NotSupported
82org.freedesktop.DBus.Error.LimitsExceeded
83org.freedesktop.DBus.Error.AccessDenied
84org.freedesktop.DBus.Error.NoServer
85org.freedesktop.DBus.Error.Timeout
86org.freedesktop.DBus.Error.NoNetwork
87org.freedesktop.DBus.Error.AddressInUse
88org.freedesktop.DBus.Error.Disconnected
89org.freedesktop.DBus.Error.InvalidArgs
90org.freedesktop.DBus.Error.UnknownMethod
91org.freedesktop.DBus.Error.TimedOut
92org.freedesktop.DBus.Error.InvalidSignature
93org.freedesktop.DBus.Error.UnknownInterface
94com.trolltech.QtDBus.Error.InternalError
95org.freedesktop.DBus.Error.UnknownObject
96com.trolltech.QtDBus.Error.InvalidService
97com.trolltech.QtDBus.Error.InvalidObjectPath
98com.trolltech.QtDBus.Error.InvalidInterface
99com.trolltech.QtDBus.Error.InvalidMember
100*/
101
102// in the same order as KnownErrors!
103static const char errorMessages_string[] =
104 "other\0"
105 "org.freedesktop.DBus.Error.Failed\0"
106 "org.freedesktop.DBus.Error.NoMemory\0"
107 "org.freedesktop.DBus.Error.ServiceUnknown\0"
108 "org.freedesktop.DBus.Error.NoReply\0"
109 "org.freedesktop.DBus.Error.BadAddress\0"
110 "org.freedesktop.DBus.Error.NotSupported\0"
111 "org.freedesktop.DBus.Error.LimitsExceeded\0"
112 "org.freedesktop.DBus.Error.AccessDenied\0"
113 "org.freedesktop.DBus.Error.NoServer\0"
114 "org.freedesktop.DBus.Error.Timeout\0"
115 "org.freedesktop.DBus.Error.NoNetwork\0"
116 "org.freedesktop.DBus.Error.AddressInUse\0"
117 "org.freedesktop.DBus.Error.Disconnected\0"
118 "org.freedesktop.DBus.Error.InvalidArgs\0"
119 "org.freedesktop.DBus.Error.UnknownMethod\0"
120 "org.freedesktop.DBus.Error.TimedOut\0"
121 "org.freedesktop.DBus.Error.InvalidSignature\0"
122 "org.freedesktop.DBus.Error.UnknownInterface\0"
123 "com.trolltech.QtDBus.Error.InternalError\0"
124 "org.freedesktop.DBus.Error.UnknownObject\0"
125 "com.trolltech.QtDBus.Error.InvalidService\0"
126 "com.trolltech.QtDBus.Error.InvalidObjectPath\0"
127 "com.trolltech.QtDBus.Error.InvalidInterface\0"
128 "com.trolltech.QtDBus.Error.InvalidMember\0"
129 "\0";
130
131static const int errorMessages_indices[] = {
132 0, 6, 40, 76, 118, 153, 191, 231,
133 273, 313, 349, 384, 421, 461, 501, 540,
134 581, 617, 661, 705, 746, 787, 829, 874,
135 918, 0
136};
137
138static const int errorMessages_count = sizeof errorMessages_indices /
139 sizeof errorMessages_indices[0];
140
141static inline const char *get(QDBusError::ErrorType code)
142{
143 int intcode = qBound(0, int(code) - int(QDBusError::Other), errorMessages_count);
144 return errorMessages_string + errorMessages_indices[intcode];
145}
146
147static inline QDBusError::ErrorType get(const char *name)
148{
149 if (!name || !*name)
150 return QDBusError::NoError;
151 for (int i = 0; i < errorMessages_count; ++i)
152 if (strcmp(name, errorMessages_string + errorMessages_indices[i]) == 0)
153 return QDBusError::ErrorType(i + int(QDBusError::Other));
154 return QDBusError::Other;
155}
156
157/*!
158 \class QDBusError
159 \inmodule QtDBus
160 \since 4.2
161
162 \brief The QDBusError class represents an error received from the
163 D-Bus bus or from remote applications found in the bus.
164
165 When dealing with the D-Bus bus service or with remote
166 applications over D-Bus, a number of error conditions can
167 happen. This error conditions are sometimes signalled by a
168 returned error value or by a QDBusError.
169
170 C++ and Java exceptions are a valid analogy for D-Bus errors:
171 instead of returning normally with a return value, remote
172 applications and the bus may decide to throw an error
173 condition. However, the QtDBus implementation does not use the C++
174 exception-throwing mechanism, so you will receive QDBusErrors in
175 the return reply (see QDBusReply::error()).
176
177 QDBusError objects are used to inspect the error name and message
178 as received from the bus and remote applications. You should not
179 create such objects yourself to signal error conditions when
180 called from D-Bus: instead, use QDBusMessage::createError() and
181 QDBusConnection::send().
182
183 \sa QDBusConnection::send(), QDBusMessage, QDBusReply
184*/
185
186/*!
187 \enum QDBusError::ErrorType
188
189 In order to facilitate verification of the most common D-Bus errors generated by the D-Bus
190 implementation and by the bus daemon itself, QDBusError can be compared to a set of pre-defined
191 values:
192
193 \value NoError QDBusError is invalid (i.e., the call succeeded)
194 \value Other QDBusError contains an error that is one of the well-known ones
195 \value Failed The call failed (\c org.freedesktop.DBus.Error.Failed)
196 \value NoMemory Out of memory (\c org.freedesktop.DBus.Error.NoMemory)
197 \value ServiceUnknown The called service is not known
198 (\c org.freedesktop.DBus.Error.ServiceUnknown)
199 \value NoReply The called method did not reply within the specified timeout
200 (\c org.freedesktop.DBus.Error.NoReply)
201 \value BadAddress The address given is not valid
202 (\c org.freedesktop.DBus.Error.BadAddress)
203 \value NotSupported The call/operation is not supported
204 (\c org.freedesktop.DBus.Error.NotSupported)
205 \value LimitsExceeded The limits allocated to this process/call/connection exceeded the
206 pre-defined values (\c org.freedesktop.DBus.Error.LimitsExceeded)
207 \value AccessDenied The call/operation tried to access a resource it isn't allowed to
208 (\c org.freedesktop.DBus.Error.AccessDenied)
209 \value NoServer \e {Documentation doesn't say what this is for}
210 (\c org.freedesktop.DBus.Error.NoServer)
211 \value Timeout \e {Documentation doesn't say what this is for or how it's used}
212 (\c org.freedesktop.DBus.Error.Timeout)
213 \value NoNetwork \e {Documentation doesn't say what this is for}
214 (\c org.freedesktop.DBus.Error.NoNetwork)
215 \value AddressInUse QDBusServer tried to bind to an address that is already in use
216 (\c org.freedesktop.DBus.Error.AddressInUse)
217 \value Disconnected The call/process/message was sent after QDBusConnection disconnected
218 (\c org.freedesktop.DBus.Error.Disconnected)
219 \value InvalidArgs The arguments passed to this call/operation are not valid
220 (\c org.freedesktop.DBus.Error.InvalidArgs)
221 \value UnknownMethod The method called was not found in this object/interface with the
222 given parameters (\c org.freedesktop.DBus.Error.UnknownMethod)
223 \value TimedOut \e {Documentation doesn't say...}
224 (\c org.freedesktop.DBus.Error.TimedOut)
225 \value InvalidSignature The type signature is not valid or compatible
226 (\c org.freedesktop.DBus.Error.InvalidSignature)
227 \value UnknownInterface The interface is not known
228 \value InternalError An internal error occurred
229 (\c com.trolltech.QtDBus.Error.InternalError)
230
231 \value InvalidObjectPath The object path provided is invalid.
232
233 \value InvalidService The service requested is invalid.
234
235 \value InvalidMember The member is invalid.
236
237 \value InvalidInterface The interface is invalid.
238
239 \value UnknownObject The remote object could not be found.
240*/
241
242/*!
243 \internal
244 Constructs a QDBusError from a DBusError structure.
245*/
246QDBusError::QDBusError(const DBusError *error)
247 : code(NoError)
248{
249 if (!error || !q_dbus_error_is_set(error))
250 return;
251
252 code = ::get(error->name);
253 msg = QString::fromUtf8(error->message);
254 nm = QString::fromUtf8(error->name);
255}
256
257/*!
258 \internal
259 Constructs a QDBusError from a QDBusMessage.
260*/
261QDBusError::QDBusError(const QDBusMessage &qdmsg)
262 : code(NoError)
263{
264 if (qdmsg.type() != QDBusMessage::ErrorMessage)
265 return;
266
267 code = ::get(qdmsg.errorName().toUtf8().constData());
268 nm = qdmsg.errorName();
269 msg = qdmsg.errorMessage();
270}
271
272/*!
273 \internal
274 Constructs a QDBusError from a well-known error code
275*/
276QDBusError::QDBusError(ErrorType error, const QString &mess)
277 : code(error)
278{
279 nm = QLatin1String(::get(error));
280 msg = mess;
281}
282
283/*!
284 \internal
285 Constructs a QDBusError from another QDBusError object
286*/
287QDBusError::QDBusError(const QDBusError &other)
288 : code(other.code), msg(other.msg), nm(other.nm)
289{
290}
291
292/*!
293 \internal
294 Assignment operator
295*/
296
297QDBusError &QDBusError::operator=(const QDBusError &other)
298{
299 code = other.code;
300 msg = other.msg;
301 nm = other.nm;
302 return *this;
303}
304
305/*!
306 Returns this error's ErrorType.
307
308 \sa ErrorType
309*/
310
311QDBusError::ErrorType QDBusError::type() const
312{
313 return code;
314}
315
316/*!
317 Returns this error's name. Error names are similar to D-Bus Interface names, like
318 \c org.freedesktop.DBus.InvalidArgs.
319
320 \sa type()
321*/
322
323QString QDBusError::name() const
324{
325 return nm;
326}
327
328/*!
329 Returns the message that the callee associated with this error. Error messages are
330 implementation defined and usually contain a human-readable error code, though this does not
331 mean it is suitable for your end-users.
332*/
333
334QString QDBusError::message() const
335{
336 return msg;
337}
338
339/*!
340 Returns true if this is a valid error condition (i.e., if there was an error),
341 otherwise false.
342*/
343
344bool QDBusError::isValid() const
345{
346 return (code != NoError);
347}
348
349/*!
350 \since 4.3
351 Returns the error name associated with error condition \a error.
352*/
353QString QDBusError::errorString(ErrorType error)
354{
355 return QLatin1String(::get(error));
356}
357
358#ifndef QT_NO_DEBUG_STREAM
359QDebug operator<<(QDebug dbg, const QDBusError &msg)
360{
361 dbg.nospace() << "QDBusError(" << msg.name() << ", " << msg.message() << ')';
362 return dbg.space();
363}
364#endif
365
366QT_END_NAMESPACE
367
368#endif // QT_NO_DBUS
369