1 /* |
|
2 * gabble-error.c - Source for Gabble's error handling API |
|
3 * Copyright (C) 2006 Collabora Ltd. |
|
4 * |
|
5 * @author Ole Andre Vadla Ravnaas <ole.andre.ravnaas@collabora.co.uk> |
|
6 * |
|
7 * This library is free software; you can redistribute it and/or |
|
8 * modify it under the terms of the GNU Lesser General Public |
|
9 * License as published by the Free Software Foundation; either |
|
10 * version 2.1 of the License, or (at your option) any later version. |
|
11 * |
|
12 * This library is distributed in the hope that it will be useful, |
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
15 * Lesser General Public License for more details. |
|
16 * |
|
17 * You should have received a copy of the GNU Lesser General Public |
|
18 * License along with this library; if not, write to the Free Software |
|
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|
20 */ |
|
21 |
|
22 #include <stdlib.h> |
|
23 #include <stdio.h> |
|
24 |
|
25 #include "gabble-error.h" |
|
26 #include "namespaces.h" |
|
27 |
|
28 #ifdef EMULATOR |
|
29 #include "libgabble_wsd_solution.h" |
|
30 |
|
31 GET_STATIC_VAR_FROM_TLS(quark,gabble_error,GQuark) |
|
32 #define quark (*GET_WSD_VAR_NAME(quark,gabble_error,s)()) |
|
33 |
|
34 #endif |
|
35 |
|
36 #define MAX_LEGACY_ERRORS 3 |
|
37 |
|
38 typedef struct { |
|
39 const gchar *name; |
|
40 const gchar *description; |
|
41 const gchar *type; |
|
42 guint specialises; |
|
43 const gchar *namespace; |
|
44 const guint16 legacy_errors[MAX_LEGACY_ERRORS]; |
|
45 } XmppErrorSpec; |
|
46 |
|
47 static const XmppErrorSpec xmpp_errors[NUM_XMPP_ERRORS] = |
|
48 { |
|
49 { |
|
50 "redirect", |
|
51 "the recipient or server is redirecting requests for this information " |
|
52 "to another entity", |
|
53 "modify", |
|
54 0, |
|
55 NULL, |
|
56 { 302, 0, }, |
|
57 }, |
|
58 |
|
59 { |
|
60 "gone", |
|
61 "the recipient or server can no longer be contacted at this address", |
|
62 "modify", |
|
63 0, |
|
64 NULL, |
|
65 { 302, 0, }, |
|
66 }, |
|
67 |
|
68 { |
|
69 "bad-request", |
|
70 "the sender has sent XML that is malformed or that cannot be processed", |
|
71 "modify", |
|
72 0, |
|
73 NULL, |
|
74 { 400, 0, }, |
|
75 }, |
|
76 { |
|
77 "unexpected-request", |
|
78 "the recipient or server understood the request but was not expecting " |
|
79 "it at this time", |
|
80 "wait", |
|
81 0, |
|
82 NULL, |
|
83 { 400, 0, }, |
|
84 }, |
|
85 { |
|
86 "jid-malformed", |
|
87 "the sending entity has provided or communicated an XMPP address or " |
|
88 "aspect thereof (e.g., a resource identifier) that does not adhere " |
|
89 "to the syntax defined in Addressing Scheme (Section 3)", |
|
90 "modify", |
|
91 0, |
|
92 NULL, |
|
93 { 400, 0, }, |
|
94 }, |
|
95 |
|
96 { |
|
97 "not-authorized", |
|
98 "the sender must provide proper credentials before being allowed to " |
|
99 "perform the action, or has provided improper credentials", |
|
100 "auth", |
|
101 0, |
|
102 NULL, |
|
103 { 401, 0, }, |
|
104 }, |
|
105 |
|
106 { |
|
107 "payment-required", |
|
108 "the requesting entity is not authorized to access the requested " |
|
109 "service because payment is required", |
|
110 "auth", |
|
111 0, |
|
112 NULL, |
|
113 { 402, 0, }, |
|
114 }, |
|
115 |
|
116 { |
|
117 "forbidden", |
|
118 "the requesting entity does not possess the required permissions to " |
|
119 "perform the action", |
|
120 "auth", |
|
121 0, |
|
122 NULL, |
|
123 { 403, 0, }, |
|
124 }, |
|
125 |
|
126 { |
|
127 "item-not-found", |
|
128 "the addressed JID or item requested cannot be found", |
|
129 "cancel", |
|
130 0, |
|
131 NULL, |
|
132 { 404, 0, }, |
|
133 }, |
|
134 { |
|
135 "recipient-unavailable", |
|
136 "the intended recipient is temporarily unavailable", |
|
137 "wait", |
|
138 0, |
|
139 NULL, |
|
140 { 404, 0, }, |
|
141 }, |
|
142 { |
|
143 "remote-server-not-found", |
|
144 "a remote server or service specified as part or all of the JID of the " |
|
145 "intended recipient (or required to fulfill a request) could not be " |
|
146 "contacted within a reasonable amount of time", |
|
147 "cancel", |
|
148 0, |
|
149 NULL, |
|
150 { 404, 0, }, |
|
151 }, |
|
152 |
|
153 { |
|
154 "not-allowed", |
|
155 "the recipient or server does not allow any entity to perform the action", |
|
156 "cancel", |
|
157 0, |
|
158 NULL, |
|
159 { 405, 0, }, |
|
160 }, |
|
161 |
|
162 { |
|
163 "not-acceptable", |
|
164 "the recipient or server understands the request but is refusing to " |
|
165 "process it because it does not meet criteria defined by the recipient " |
|
166 "or server (e.g., a local policy regarding acceptable words in messages)", |
|
167 "modify", |
|
168 0, |
|
169 NULL, |
|
170 { 406, 0, }, |
|
171 }, |
|
172 |
|
173 { |
|
174 "registration-required", |
|
175 "the requesting entity is not authorized to access the requested service " |
|
176 "because registration is required", |
|
177 "auth", |
|
178 0, |
|
179 NULL, |
|
180 { 407, 0, }, |
|
181 }, |
|
182 { |
|
183 "subscription-required", |
|
184 "the requesting entity is not authorized to access the requested service " |
|
185 "because a subscription is required", |
|
186 "auth", |
|
187 0, |
|
188 NULL, |
|
189 { 407, 0, }, |
|
190 }, |
|
191 |
|
192 { |
|
193 "remote-server-timeout", |
|
194 "a remote server or service specified as part or all of the JID of the " |
|
195 "intended recipient (or required to fulfill a request) could not be " |
|
196 "contacted within a reasonable amount of time", |
|
197 "wait", |
|
198 0, |
|
199 NULL, |
|
200 { 408, 504, 0, }, |
|
201 }, |
|
202 |
|
203 { |
|
204 "conflict", |
|
205 "access cannot be granted because an existing resource or session exists " |
|
206 "with the same name or address", |
|
207 "cancel", |
|
208 0, |
|
209 NULL, |
|
210 { 409, 0, }, |
|
211 }, |
|
212 |
|
213 { |
|
214 "internal-server-error", |
|
215 "the server could not process the stanza because of a misconfiguration " |
|
216 "or an otherwise-undefined internal server error", |
|
217 "wait", |
|
218 0, |
|
219 NULL, |
|
220 { 500, 0, }, |
|
221 }, |
|
222 { |
|
223 "undefined-condition", |
|
224 "application-specific condition", |
|
225 NULL, |
|
226 0, |
|
227 NULL, |
|
228 { 500, 0, }, |
|
229 }, |
|
230 { |
|
231 "resource-constraint", |
|
232 "the server or recipient lacks the system resources necessary to service " |
|
233 "the request", |
|
234 "wait", |
|
235 0, |
|
236 NULL, |
|
237 { 500, 0, }, |
|
238 }, |
|
239 |
|
240 { |
|
241 "feature-not-implemented", |
|
242 "the feature requested is not implemented by the recipient or server and " |
|
243 "therefore cannot be processed", |
|
244 "cancel", |
|
245 0, |
|
246 NULL, |
|
247 { 501, 0, }, |
|
248 }, |
|
249 |
|
250 { |
|
251 "service-unavailable", |
|
252 "the server or recipient does not currently provide the requested " |
|
253 "service", |
|
254 "cancel", |
|
255 0, |
|
256 NULL, |
|
257 { 502, 503, 510, }, |
|
258 }, |
|
259 |
|
260 { |
|
261 "out-of-order", |
|
262 "the request cannot occur at this point in the state machine", |
|
263 "cancel", |
|
264 XMPP_ERROR_UNEXPECTED_REQUEST, |
|
265 NS_JINGLE_ERRORS, |
|
266 { 0, }, |
|
267 }, |
|
268 |
|
269 { |
|
270 "unknown-session", |
|
271 "the 'sid' attribute specifies a session that is unknown to the " |
|
272 "recipient", |
|
273 "cancel", |
|
274 XMPP_ERROR_BAD_REQUEST, |
|
275 NS_JINGLE_ERRORS, |
|
276 { 0, }, |
|
277 }, |
|
278 |
|
279 { |
|
280 "unsupported-transports", |
|
281 "the recipient does not support any of the desired content transport " |
|
282 "methods", |
|
283 "cancel", |
|
284 XMPP_ERROR_FEATURE_NOT_IMPLEMENTED, |
|
285 NS_JINGLE_ERRORS, |
|
286 { 0, }, |
|
287 }, |
|
288 |
|
289 { |
|
290 "unsupported-content", |
|
291 "the recipient does not support any of the desired content description" |
|
292 "formats", |
|
293 "cancel", |
|
294 XMPP_ERROR_FEATURE_NOT_IMPLEMENTED, |
|
295 NS_JINGLE_ERRORS, |
|
296 { 0, }, |
|
297 }, |
|
298 }; |
|
299 |
|
300 GQuark |
|
301 gabble_xmpp_error_quark (void) |
|
302 { |
|
303 |
|
304 #ifndef EMULATOR |
|
305 static GQuark quark = 0; |
|
306 #endif |
|
307 |
|
308 if (!quark) |
|
309 quark = g_quark_from_static_string ("gabble-xmpp-error"); |
|
310 return quark; |
|
311 } |
|
312 |
|
313 GabbleXmppError |
|
314 gabble_xmpp_error_from_node (LmMessageNode *error_node) |
|
315 { |
|
316 gint i, j; |
|
317 const gchar *error_code_str; |
|
318 |
|
319 /* First, try to look it up the modern way */ |
|
320 if (error_node->children) |
|
321 { |
|
322 for (i = 0; i < NUM_XMPP_ERRORS; i++) |
|
323 { |
|
324 if (lm_message_node_get_child (error_node, xmpp_errors[i].name)) |
|
325 { |
|
326 return i; |
|
327 } |
|
328 } |
|
329 } |
|
330 |
|
331 /* Ok, do it the legacy way */ |
|
332 error_code_str = lm_message_node_get_attribute (error_node, "code"); |
|
333 if (error_code_str) |
|
334 { |
|
335 gint error_code; |
|
336 |
|
337 error_code = atoi (error_code_str); |
|
338 |
|
339 for (i = 0; i < NUM_XMPP_ERRORS; i++) |
|
340 { |
|
341 const XmppErrorSpec *spec = &xmpp_errors[i]; |
|
342 |
|
343 for (j = 0; j < MAX_LEGACY_ERRORS; j++) |
|
344 { |
|
345 gint cur_code = spec->legacy_errors[j]; |
|
346 if (cur_code == 0) |
|
347 break; |
|
348 |
|
349 if (cur_code == error_code) |
|
350 return i; |
|
351 } |
|
352 } |
|
353 } |
|
354 |
|
355 return INVALID_XMPP_ERROR; |
|
356 } |
|
357 |
|
358 GError * |
|
359 gabble_xmpp_error_to_g_error (GabbleXmppError error) |
|
360 { |
|
361 if (error >= NUM_XMPP_ERRORS) |
|
362 return NULL; |
|
363 |
|
364 return g_error_new (GABBLE_XMPP_ERROR, |
|
365 error, |
|
366 xmpp_errors[error].description); |
|
367 } |
|
368 |
|
369 /* |
|
370 * See RFC 3920: 4.7 Stream Errors, 9.3 Stanza Errors. |
|
371 */ |
|
372 LmMessageNode * |
|
373 gabble_xmpp_error_to_node (GabbleXmppError error, |
|
374 LmMessageNode *parent_node, |
|
375 const gchar *errmsg) |
|
376 { |
|
377 const XmppErrorSpec *spec, *extra; |
|
378 LmMessageNode *error_node, *node; |
|
379 gchar str[6]; |
|
380 |
|
381 if (error >= NUM_XMPP_ERRORS) |
|
382 return NULL; |
|
383 |
|
384 if (xmpp_errors[error].specialises) |
|
385 { |
|
386 extra = &xmpp_errors[error]; |
|
387 spec = &xmpp_errors[extra->specialises]; |
|
388 } |
|
389 else |
|
390 { |
|
391 extra = NULL; |
|
392 spec = &xmpp_errors[error]; |
|
393 } |
|
394 |
|
395 error_node = lm_message_node_add_child (parent_node, "error", NULL); |
|
396 |
|
397 sprintf (str, "%d", spec->legacy_errors[0]); |
|
398 lm_message_node_set_attribute (error_node, "code", str); |
|
399 |
|
400 if (spec->type) |
|
401 { |
|
402 lm_message_node_set_attribute (error_node, "type", spec->type); |
|
403 } |
|
404 |
|
405 node = lm_message_node_add_child (error_node, spec->name, NULL); |
|
406 lm_message_node_set_attribute (node, "xmlns", NS_XMPP_STANZAS); |
|
407 |
|
408 if (extra != NULL) |
|
409 { |
|
410 node = lm_message_node_add_child (error_node, extra->name, NULL); |
|
411 lm_message_node_set_attribute (node, "xmlns", extra->namespace); |
|
412 } |
|
413 |
|
414 if (NULL != errmsg) |
|
415 lm_message_node_add_child (error_node, "text", errmsg); |
|
416 |
|
417 return error_node; |
|
418 } |
|
419 |
|
420 const gchar * |
|
421 gabble_xmpp_error_string (GabbleXmppError error) |
|
422 { |
|
423 if (error < NUM_XMPP_ERRORS) |
|
424 return xmpp_errors[error].name; |
|
425 else |
|
426 return NULL; |
|
427 } |
|
428 |
|
429 const gchar * |
|
430 gabble_xmpp_error_description (GabbleXmppError error) |
|
431 { |
|
432 if (error < NUM_XMPP_ERRORS) |
|
433 return xmpp_errors[error].description; |
|
434 else |
|
435 return NULL; |
|
436 } |
|
437 |
|