libsyncml 0.5.4

- Main Page
- Modules
- Data Structures
- Files

- File List

sml_error.c
1 /*
2 * libsyncml - A syncml protocol implementation
3 * Copyright (C) 2005 Armin Bauer <armin.bauer@opensync.org>
4 * Copyright (C) 2008-2009 Michael Bell <michael.bell@opensync.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22 #include "syncml.h"
23
24 #include "syncml_internals.h"
25 #include "sml_error_internals.h"
26
34
47 const char *smlErrorTypeGetMessage(SmlErrorType type)
48 {
49 if (SML_ERROR_UNKNOWN)
50 return "An unkown error occured.";
51
52 /* return NULL if this is not an error */
53 if (type < 300)
54 return NULL;
55
56 /* Errors according to SyncML Representation Protocol 1.2.1
57 * The error messages are the original phrases like specified
58 * by the OMA in the original specifications.
59 */
60 switch (type)
61 {
62 /* Retry error */
63 case SML_ERROR_MULTIPLE_CHOICES:
64 return "Multiple choices. The requested target is one of a number of " \
65 "multiple alternatives requested target. The alternative SHOULD " \
66 "also be returned in the Item element type in the Status.";
67 case SML_ERROR_MOVED_PERMANENTLY:
68 return "Moved permanently. The requested target has a new URI. The new " \
69 "URI SHOULD also be returned in the Item element type in the " \
70 "Status.";
71 case SML_ERROR_FOUND_RETRY:
72 return "Found. The requested target has temporarily moved to a different " \
73 "URI. The original URI SHOULD continue to be used. The URI of " \
74 "the temporary location SHOULD also be returned in the Item " \
75 "element type in the Status. The requestor SHOULD confirm the " \
76 "identity and authority of the temporary URI to act on behalf of the " \
77 "original target URI.";
78 case SML_ERROR_SEE_OTHER_RETRY:
79 return "See other. The requested target can be found at another URI. The " \
80 "other URI SHOULD be returned in the Item element type in the " \
81 "Status.";
82 case SML_ERROR_NOT_MODIFIED:
83 return "Not modified. The requested SyncML command was not executed " \
84 "on the target. This is an additional response that can be added to " \
85 "any of the other Redirection response codes.";
86 case SML_ERROR_USE_PROXY:
87 return "Use proxy. The requested target MUST be accessed through the " \
88 "specified proxy URI. The proxy URI SHOULD also be returned in " \
89 "the Item element type in the Status.";
90
91 /* Errors */
92 case SML_ERROR_BAD_REQUEST:
93 return "Bad request. The requested command could not be performed " \
94 "because of malformed syntax in the command. The malformed " \
95 "command MAY also be returned in the Item element type in the " \
96 "Status.";
97 case SML_ERROR_AUTH_REJECTED:
98 return "Invalid credentials. The requested command failed because the " \
99 "requestor MUST provide proper authentication. If the property type " \
100 "of authentication was presented in the original request, then the " \
101 "response code indicates that the requested command has been " \
102 "refused for those credentials.";
103 case SML_ERROR_PAYMENT_NEEDED:
104 return "Paymentneeded. The requested command failed because proper " \
105 "payment isneeded. This version of SyncML does not standardize " \
106 "the payment mechanism.";
107 case SML_ERROR_FORBIDDEN:
108 return "Forbidden. The requested command failed, but the recipient " \
109 "understood the requested command. Authentication will not help " \
110 "and the request SHOULD NOT be repeated. If the recipient wishes " \
111 "to make public why the request was denied, then a description " \
112 "MAY be specified in the Item element type in the Status. If the " \
113 "recipient does not wish to make public why the request was denied " \
114 "then the response code 404 MAY be used instead.";
115 case SML_ERROR_NOT_FOUND:
116 return "Not found. The requested target was not found. No indication is " \
117 "given as to whether this is a temporary or permanent condition. The " \
118 "response code 410 SHOULD be used when the condition is " \
119 "permanent and the recipient wishes to make this fact public. This " \
120 "response code is also used when the recipient does not want to " \
121 "make public the reason for why a requested command is not " \
122 "allowed or when no other response code is appropriate.";
123 case SML_ERROR_UNSUPPORTED_FEATURE:
124 return "Optional feature not supported. The requested command failed " \
125 "because an OPTIONAL feature in the request was not supported. " \
126 "The unsupported feature SHOULD be specified by the Item " \
127 "element type in the Status.";
128 case SML_ERROR_RETRY_LATER:
129 return "Retry later. The request failed at this time and the originator " \
130 "SHOULD retry the request later. The recipient SHOULD specify a " \
131 "RespURI with the response URI and the date/time that the " \
132 "command SHOULD be repeated.";
133 case SML_ERROR_ALREADY_EXISTS:
134 return "Already exists. The requested Put or Add command failed " \
135 "because the target already exists.";
136 case SML_ERROR_SIZE_MISMATCH:
137 return "Size mismatch. The chunked object was received, but the size of " \
138 "the received object did not match the size declared within the first " \
139 "chunk.";
140
141 /* Standard errors */
142 case SML_ERROR_GENERIC:
143 return "Command failed. The recipient encountered an unexpected " \
144 "condition which prevented it from fulfilling the request.";
145 case SML_ERROR_NOT_IMPLEMENTED:
146 return "Command not implemented. The recipient does not support the " \
147 "command REQUIRED to fulfill the request. This is the appropriate " \
148 "response when the recipient does not recognize the requested " \
149 "command and is not capable of supporting it for any resource.";
150 case SML_ERROR_SERVICE_UNAVAILABLE:
151 return "Service unavailable. The recipient is currently unable to handle the " \
152 "request due to a temporary overloading or maintenance of the " \
153 "recipient. The implication is that this is a temporary condition; " \
154 "which will be alleviated after some delay. The recipient SHOULD " \
155 "specify the URI and date/time after which the originator SHOULD " \
156 "retry in the RespURI in the response.";
157 case SML_ERROR_REQUIRE_REFRESH:
158 return "RefreshREQUIRED. An error occurred that necessitates a refresh " \
159 "of the current synchronization state of the client with the server. " \
160 "Client is requested to initiate the session type specified in the " \
161 "server's ALERT (which is included in the same package as the " \
162 "Status 508). The only valid values for this ALERT are either a slow " \
163 "sync (201) or a refresh with the server.";
164 case SML_ERROR_SERVER_FAILURE:
165 return "Server failure. A severe error occurred in the server while " \
166 "processing the request. The originator SHOULD NOT retry the " \
167 "request.";
168
169 /* Internal errors */
170 case SML_ERROR_INTERNAL_IO_ERROR:
171 return "An internal I/O error occured.";
172 case SML_ERROR_INTERNAL_TIMEOUT:
173 return "An internal timeout occured.";
174 case SML_ERROR_INTERNAL_FILE_NOT_FOUND:
175 return "An internal error occured because of a missing file.";
176 case SML_ERROR_INTERNAL_MISCONFIGURATION:
177 return "An internal misconfiguration was detected.";
178 case SML_ERROR_INTERNAL_NO_MEMORY:
179 return "An internal I/O error occured.";
180
181 default:
182 return "";
183 }
184 }
185
194 void smlErrorSetVargs(SmlError **error, SmlErrorType type, const char *format, va_list args)
195 {
196 return_if_fail(error);
197 return_if_fail(smlErrorIsSet(error) == FALSE);
198 return_if_fail(format);
199
200 *error = (SmlError *) malloc(sizeof(SmlError));
201 return_if_fail(*error);
202 (*error)->message = g_strdup_vprintf(format, args);
203 (*error)->type = type;
204 const char *msg = smlErrorTypeGetMessage(type);
205 if (!msg) {
206 (*error)->printMessage = g_strdup((*error)->message);
207 } else if (strlen(msg) == 0) {
208 (*error)->printMessage = g_strdup_printf(
209 "Error %d: %s",
210 (*error)->type,
211 (*error)->message);
212 } else {
213 (*error)->printMessage = g_strdup_printf(
214 "%s %s",
215 msg,
216 (*error)->message);
217 }
218 (*error)->refCount = 1;
219
220 return;
221 }
222
232
233 SmlError **smlErrorRef(SmlError **error)
234 {
235 if (!smlErrorIsSet(error))
236 return error;
237
238 g_atomic_int_inc(&(*error)->refCount);
239
240 return error;
241 }
242
243 void smlErrorDeref(SmlError **error)
244 {
245 if (!smlErrorIsSet(error))
246 return;
247
248 if (!g_atomic_int_dec_and_test(&((*error)->refCount))) {
249 *error = NULL;
250 return;
251 }
252
253 if ((*error)->message)
254 smlSafeCFree (&((*error)->message));
255
256 if ((*error)->printMessage)
257 smlSafeCFree (&((*error)->printMessage));
258
259 smlSafeFree((gpointer *)error);
260 }
261
268 SmlBool smlErrorIsSet(SmlError **error)
269 {
270 if (!error)
271 return FALSE;
272
273 if (*error == NULL)
274 return FALSE;
275
276 return TRUE;
277 }
278
285 SmlErrorType smlErrorGetType(SmlError **error)
286 {
287 if (!smlErrorIsSet(error))
288 return SML_NO_ERROR;
289
290 return (*error)->type;
291 }
292
299 const char *smlErrorPrint(SmlError **error)
300 {
301 if (!smlErrorIsSet(error))
302 return NULL;
303
304 return (*error)->printMessage;
305 }
306
317 void smlErrorUpdate(SmlError **error, const char *format, ...)
318 {
319 return_if_fail(smlErrorIsSet(error));
320
321 char *old = (*error)->message;
322 va_list args;
323 va_start(args, format);
324 (*error)->message = g_strdup_vprintf(format, args);
325 va_end (args);
326
327 smlSafeCFree(&old);
328 }
329
337 void smlErrorDuplicate(SmlError **target, SmlError **source)
338 {
339 return_if_fail(target != NULL);
340 return_if_fail(smlErrorIsSet(source));
341 return_if_fail(!smlErrorIsSet(target));
342
343 smlErrorSet(target, (*source)->type, (*source)->message);
344 }
345
355 void smlErrorSet(SmlError **error, SmlErrorType type, const char *format, ...)
356 {
357 va_list args;
358 va_start(args, format);
359 smlErrorSetVargs(error, type, format, args);
360 va_end (args);
361 }
362
369 void smlErrorSetType(SmlError **error, SmlErrorType type)
370 {
371 return_if_fail(error != NULL);
372
373 (*error)->type = type;
374 }
375
382 SmlErrorClass smlErrorGetClass(SmlError **error)
383 {
384 if (!smlErrorIsSet(error))
385 return SML_ERRORCLASS_SUCCESS;
386
387 if ((*error)->type == SML_NO_ERROR)
388 return SML_ERRORCLASS_SUCCESS;
389
390 return (int)((*error)->type / 100);
391 }
392