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 | |
53 | QT_BEGIN_NAMESPACE |
54 | |
55 | /* |
56 | * Use the following Perl script to generate the error string index list: |
57 | ===== PERL SCRIPT ==== |
58 | print "static const char errorMessages_string[] =\n"; |
59 | $counter = 0; |
60 | $i = 0; |
61 | while (<STDIN>) { |
62 | chomp; |
63 | print " \"$_\\0\"\n"; |
64 | $sizes[$i++] = $counter; |
65 | $counter += 1 + length $_; |
66 | } |
67 | print " \"\\0\";\n\nstatic const int errorMessages_indices[] = {\n "; |
68 | for ($j = 0; $j < $i; ++$j) { |
69 | printf "$sizes[$j], "; |
70 | } |
71 | print "0\n};\n"; |
72 | ===== PERL SCRIPT ==== |
73 | |
74 | * The input data is as follows: |
75 | other |
76 | org.freedesktop.DBus.Error.Failed |
77 | org.freedesktop.DBus.Error.NoMemory |
78 | org.freedesktop.DBus.Error.ServiceUnknown |
79 | org.freedesktop.DBus.Error.NoReply |
80 | org.freedesktop.DBus.Error.BadAddress |
81 | org.freedesktop.DBus.Error.NotSupported |
82 | org.freedesktop.DBus.Error.LimitsExceeded |
83 | org.freedesktop.DBus.Error.AccessDenied |
84 | org.freedesktop.DBus.Error.NoServer |
85 | org.freedesktop.DBus.Error.Timeout |
86 | org.freedesktop.DBus.Error.NoNetwork |
87 | org.freedesktop.DBus.Error.AddressInUse |
88 | org.freedesktop.DBus.Error.Disconnected |
89 | org.freedesktop.DBus.Error.InvalidArgs |
90 | org.freedesktop.DBus.Error.UnknownMethod |
91 | org.freedesktop.DBus.Error.TimedOut |
92 | org.freedesktop.DBus.Error.InvalidSignature |
93 | org.freedesktop.DBus.Error.UnknownInterface |
94 | com.trolltech.QtDBus.Error.InternalError |
95 | org.freedesktop.DBus.Error.UnknownObject |
96 | com.trolltech.QtDBus.Error.InvalidService |
97 | com.trolltech.QtDBus.Error.InvalidObjectPath |
98 | com.trolltech.QtDBus.Error.InvalidInterface |
99 | com.trolltech.QtDBus.Error.InvalidMember |
100 | */ |
101 | |
102 | // in the same order as KnownErrors! |
103 | static 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 | |
131 | static 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 | |
138 | static const int errorMessages_count = sizeof errorMessages_indices / |
139 | sizeof errorMessages_indices[0]; |
140 | |
141 | static 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 | |
147 | static 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 | */ |
246 | QDBusError::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 | */ |
261 | QDBusError::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 | */ |
276 | QDBusError::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 | */ |
287 | QDBusError::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 | |
297 | QDBusError &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 | |
311 | QDBusError::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 | |
323 | QString 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 | |
334 | QString 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 | |
344 | bool 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 | */ |
353 | QString QDBusError::errorString(ErrorType error) |
354 | { |
355 | return QLatin1String(::get(error)); |
356 | } |
357 | |
358 | #ifndef QT_NO_DEBUG_STREAM |
359 | QDebug operator<<(QDebug dbg, const QDBusError &msg) |
360 | { |
361 | dbg.nospace() << "QDBusError(" << msg.name() << ", " << msg.message() << ')'; |
362 | return dbg.space(); |
363 | } |
364 | #endif |
365 | |
366 | QT_END_NAMESPACE |
367 | |
368 | #endif // QT_NO_DBUS |
369 | |