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 | |
54 | QT_BEGIN_NAMESPACE |
55 | |
56 | static 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 |
89 | static 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 | */ |
194 | QDBusError::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 | */ |
207 | QDBusError::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 | */ |
222 | QDBusError::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 | */ |
238 | QDBusError::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 | */ |
249 | QDBusError::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 | |
259 | QDBusError &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 | */ |
272 | QDBusError &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 | |
293 | QDBusError::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 | |
305 | QString 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 | |
316 | QString 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 | |
326 | bool 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 | */ |
335 | QString QDBusError::errorString(ErrorType error) |
336 | { |
337 | return QLatin1String(errorMessages[error]); |
338 | } |
339 | |
340 | #ifndef QT_NO_DEBUG_STREAM |
341 | QDebug 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 | |
355 | QT_END_NAMESPACE |
356 | |
357 | #endif // QT_NO_DBUS |
358 | |
359 | /* |
360 | MSVC2015 has the warning C4503 at the end of the file: |
361 | QtPrivate::StaticStringBuilder<QtPrivate::IndexesList<...> - decorated name length exceeded, name was truncated |
362 | It is used by qOffsetStringArray in a constexpr evaulation and this code does not exist in the object file, |
363 | but we still have the warning or even error with -WX flag |
364 | */ |
365 | QT_WARNING_DISABLE_MSVC(4503) |
366 | |