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 | |
18 | QT_BEGIN_NAMESPACE |
19 | |
20 | QT_IMPL_METATYPE_EXTERN(QDBusError) |
21 | |
22 | static 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 |
55 | static 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 | */ |
160 | QDBusError::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 | */ |
173 | QDBusError::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 | */ |
188 | QDBusError::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 | */ |
204 | QDBusError::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 | */ |
215 | QDBusError::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 | |
225 | QDBusError &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 | */ |
238 | QDBusError &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 | |
259 | QDBusError::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 | |
271 | QString 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 | |
282 | QString 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 | |
292 | bool 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 | */ |
301 | QString QDBusError::errorString(ErrorType error) |
302 | { |
303 | return QLatin1StringView(errorMessages[error]); |
304 | } |
305 | |
306 | #ifndef QT_NO_DEBUG_STREAM |
307 | QDebug 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 | |
321 | QT_END_NAMESPACE |
322 | |
323 | #include "moc_qdbuserror.cpp" |
324 | |
325 | #endif // QT_NO_DBUS |
326 | |
327 | /* |
328 | MSVC2015 has the warning C4503 at the end of the file: |
329 | QtPrivate::StaticStringBuilder<QtPrivate::IndexesList<...> - decorated name length exceeded, name was truncated |
330 | It is used by qOffsetStringArray in a constexpr evaluation and this code does not exist in the object file, |
331 | but we still have the warning or even error with -WX flag |
332 | */ |
333 | QT_WARNING_DISABLE_MSVC(4503) |
334 | |