libsyncml  0.5.4
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 
const char * smlErrorPrint(SmlError **error)
Returns the message of the error.
Definition: sml_error.c:299
SmlErrorType smlErrorGetType(SmlError **error)
Returns the type of the error.
Definition: sml_error.c:285
SmlErrorType type
void smlErrorUpdate(SmlError **error, const char *format,...)
Updates the error message.
Definition: sml_error.c:317
const char * smlErrorTypeGetMessage(SmlErrorType type)
Returns a string representation for a SyncML error.
Definition: sml_error.c:47
void smlErrorDuplicate(SmlError **target, SmlError **source)
Duplicates the error into the target.
Definition: sml_error.c:337
SmlErrorClass smlErrorGetClass(SmlError **error)
Gets the error class.
Definition: sml_error.c:382
void smlErrorSetVargs(SmlError **error, SmlErrorType type, const char *format, va_list args)
Sets a error from a va_list.
Definition: sml_error.c:194
SmlBool smlErrorIsSet(SmlError **error)
Checks if the error is set.
Definition: sml_error.c:268
void smlErrorSetType(SmlError **error, SmlErrorType type)
Sets the type of an error.
Definition: sml_error.c:369
void smlErrorSet(SmlError **error, SmlErrorType type, const char *format,...)
Sets the error.
Definition: sml_error.c:355
Represent an error.