00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "syncml.h"
00023
00024 #include "syncml_internals.h"
00025 #include "sml_error_internals.h"
00026
00034
00047 const char *smlErrorTypeGetMessage(SmlErrorType type)
00048 {
00049 if (SML_ERROR_UNKNOWN)
00050 return "An unkown error occured.";
00051
00052
00053 if (type < 300)
00054 return NULL;
00055
00056
00057
00058
00059
00060 switch (type)
00061 {
00062
00063 case SML_ERROR_MULTIPLE_CHOICES:
00064 return "Multiple choices. The requested target is one of a number of " \
00065 "multiple alternatives requested target. The alternative SHOULD " \
00066 "also be returned in the Item element type in the Status.";
00067 case SML_ERROR_MOVED_PERMANENTLY:
00068 return "Moved permanently. The requested target has a new URI. The new " \
00069 "URI SHOULD also be returned in the Item element type in the " \
00070 "Status.";
00071 case SML_ERROR_FOUND_RETRY:
00072 return "Found. The requested target has temporarily moved to a different " \
00073 "URI. The original URI SHOULD continue to be used. The URI of " \
00074 "the temporary location SHOULD also be returned in the Item " \
00075 "element type in the Status. The requestor SHOULD confirm the " \
00076 "identity and authority of the temporary URI to act on behalf of the " \
00077 "original target URI.";
00078 case SML_ERROR_SEE_OTHER_RETRY:
00079 return "See other. The requested target can be found at another URI. The " \
00080 "other URI SHOULD be returned in the Item element type in the " \
00081 "Status.";
00082 case SML_ERROR_NOT_MODIFIED:
00083 return "Not modified. The requested SyncML command was not executed " \
00084 "on the target. This is an additional response that can be added to " \
00085 "any of the other Redirection response codes.";
00086 case SML_ERROR_USE_PROXY:
00087 return "Use proxy. The requested target MUST be accessed through the " \
00088 "specified proxy URI. The proxy URI SHOULD also be returned in " \
00089 "the Item element type in the Status.";
00090
00091
00092 case SML_ERROR_BAD_REQUEST:
00093 return "Bad request. The requested command could not be performed " \
00094 "because of malformed syntax in the command. The malformed " \
00095 "command MAY also be returned in the Item element type in the " \
00096 "Status.";
00097 case SML_ERROR_AUTH_REJECTED:
00098 return "Invalid credentials. The requested command failed because the " \
00099 "requestor MUST provide proper authentication. If the property type " \
00100 "of authentication was presented in the original request, then the " \
00101 "response code indicates that the requested command has been " \
00102 "refused for those credentials.";
00103 case SML_ERROR_PAYMENT_NEEDED:
00104 return "Paymentneeded. The requested command failed because proper " \
00105 "payment isneeded. This version of SyncML does not standardize " \
00106 "the payment mechanism.";
00107 case SML_ERROR_FORBIDDEN:
00108 return "Forbidden. The requested command failed, but the recipient " \
00109 "understood the requested command. Authentication will not help " \
00110 "and the request SHOULD NOT be repeated. If the recipient wishes " \
00111 "to make public why the request was denied, then a description " \
00112 "MAY be specified in the Item element type in the Status. If the " \
00113 "recipient does not wish to make public why the request was denied " \
00114 "then the response code 404 MAY be used instead.";
00115 case SML_ERROR_NOT_FOUND:
00116 return "Not found. The requested target was not found. No indication is " \
00117 "given as to whether this is a temporary or permanent condition. The " \
00118 "response code 410 SHOULD be used when the condition is " \
00119 "permanent and the recipient wishes to make this fact public. This " \
00120 "response code is also used when the recipient does not want to " \
00121 "make public the reason for why a requested command is not " \
00122 "allowed or when no other response code is appropriate.";
00123 case SML_ERROR_UNSUPPORTED_FEATURE:
00124 return "Optional feature not supported. The requested command failed " \
00125 "because an OPTIONAL feature in the request was not supported. " \
00126 "The unsupported feature SHOULD be specified by the Item " \
00127 "element type in the Status.";
00128 case SML_ERROR_RETRY_LATER:
00129 return "Retry later. The request failed at this time and the originator " \
00130 "SHOULD retry the request later. The recipient SHOULD specify a " \
00131 "RespURI with the response URI and the date/time that the " \
00132 "command SHOULD be repeated.";
00133 case SML_ERROR_ALREADY_EXISTS:
00134 return "Already exists. The requested Put or Add command failed " \
00135 "because the target already exists.";
00136 case SML_ERROR_SIZE_MISMATCH:
00137 return "Size mismatch. The chunked object was received, but the size of " \
00138 "the received object did not match the size declared within the first " \
00139 "chunk.";
00140
00141
00142 case SML_ERROR_GENERIC:
00143 return "Command failed. The recipient encountered an unexpected " \
00144 "condition which prevented it from fulfilling the request.";
00145 case SML_ERROR_NOT_IMPLEMENTED:
00146 return "Command not implemented. The recipient does not support the " \
00147 "command REQUIRED to fulfill the request. This is the appropriate " \
00148 "response when the recipient does not recognize the requested " \
00149 "command and is not capable of supporting it for any resource.";
00150 case SML_ERROR_SERVICE_UNAVAILABLE:
00151 return "Service unavailable. The recipient is currently unable to handle the " \
00152 "request due to a temporary overloading or maintenance of the " \
00153 "recipient. The implication is that this is a temporary condition; " \
00154 "which will be alleviated after some delay. The recipient SHOULD " \
00155 "specify the URI and date/time after which the originator SHOULD " \
00156 "retry in the RespURI in the response.";
00157 case SML_ERROR_REQUIRE_REFRESH:
00158 return "RefreshREQUIRED. An error occurred that necessitates a refresh " \
00159 "of the current synchronization state of the client with the server. " \
00160 "Client is requested to initiate the session type specified in the " \
00161 "server's ALERT (which is included in the same package as the " \
00162 "Status 508). The only valid values for this ALERT are either a slow " \
00163 "sync (201) or a refresh with the server.";
00164 case SML_ERROR_SERVER_FAILURE:
00165 return "Server failure. A severe error occurred in the server while " \
00166 "processing the request. The originator SHOULD NOT retry the " \
00167 "request.";
00168
00169
00170 case SML_ERROR_INTERNAL_IO_ERROR:
00171 return "An internal I/O error occured.";
00172 case SML_ERROR_INTERNAL_TIMEOUT:
00173 return "An internal timeout occured.";
00174 case SML_ERROR_INTERNAL_FILE_NOT_FOUND:
00175 return "An internal error occured because of a missing file.";
00176 case SML_ERROR_INTERNAL_MISCONFIGURATION:
00177 return "An internal misconfiguration was detected.";
00178 case SML_ERROR_INTERNAL_NO_MEMORY:
00179 return "An internal I/O error occured.";
00180
00181 default:
00182 return "";
00183 }
00184 }
00185
00194 void smlErrorSetVargs(SmlError **error, SmlErrorType type, const char *format, va_list args)
00195 {
00196 return_if_fail(error);
00197 return_if_fail(smlErrorIsSet(error) == FALSE);
00198 return_if_fail(format);
00199
00200 *error = (SmlError *) malloc(sizeof(SmlError));
00201 return_if_fail(*error);
00202 (*error)->message = g_strdup_vprintf(format, args);
00203 (*error)->type = type;
00204 const char *msg = smlErrorTypeGetMessage(type);
00205 if (!msg) {
00206 (*error)->printMessage = g_strdup((*error)->message);
00207 } else if (strlen(msg) == 0) {
00208 (*error)->printMessage = g_strdup_printf(
00209 "Error %d: %s",
00210 (*error)->type,
00211 (*error)->message);
00212 } else {
00213 (*error)->printMessage = g_strdup_printf(
00214 "%s %s",
00215 msg,
00216 (*error)->message);
00217 }
00218 (*error)->refCount = 1;
00219
00220 return;
00221 }
00222
00232
00233 SmlError **smlErrorRef(SmlError **error)
00234 {
00235 if (!smlErrorIsSet(error))
00236 return error;
00237
00238 g_atomic_int_inc(&(*error)->refCount);
00239
00240 return error;
00241 }
00242
00243 void smlErrorDeref(SmlError **error)
00244 {
00245 if (!smlErrorIsSet(error))
00246 return;
00247
00248 if (!g_atomic_int_dec_and_test(&((*error)->refCount))) {
00249 *error = NULL;
00250 return;
00251 }
00252
00253 if ((*error)->message)
00254 smlSafeCFree (&((*error)->message));
00255
00256 if ((*error)->printMessage)
00257 smlSafeCFree (&((*error)->printMessage));
00258
00259 smlSafeFree((gpointer *)error);
00260 }
00261
00268 SmlBool smlErrorIsSet(SmlError **error)
00269 {
00270 if (!error)
00271 return FALSE;
00272
00273 if (*error == NULL)
00274 return FALSE;
00275
00276 return TRUE;
00277 }
00278
00285 SmlErrorType smlErrorGetType(SmlError **error)
00286 {
00287 if (!smlErrorIsSet(error))
00288 return SML_NO_ERROR;
00289
00290 return (*error)->type;
00291 }
00292
00299 const char *smlErrorPrint(SmlError **error)
00300 {
00301 if (!smlErrorIsSet(error))
00302 return NULL;
00303
00304 return (*error)->printMessage;
00305 }
00306
00317 void smlErrorUpdate(SmlError **error, const char *format, ...)
00318 {
00319 return_if_fail(smlErrorIsSet(error));
00320
00321 char *old = (*error)->message;
00322 va_list args;
00323 va_start(args, format);
00324 (*error)->message = g_strdup_vprintf(format, args);
00325 va_end (args);
00326
00327 smlSafeCFree(&old);
00328 }
00329
00337 void smlErrorDuplicate(SmlError **target, SmlError **source)
00338 {
00339 return_if_fail(target != NULL);
00340 return_if_fail(smlErrorIsSet(source));
00341 return_if_fail(!smlErrorIsSet(target));
00342
00343 smlErrorSet(target, (*source)->type, (*source)->message);
00344 }
00345
00355 void smlErrorSet(SmlError **error, SmlErrorType type, const char *format, ...)
00356 {
00357 va_list args;
00358 va_start(args, format);
00359 smlErrorSetVargs(error, type, format, args);
00360 va_end (args);
00361 }
00362
00369 void smlErrorSetType(SmlError **error, SmlErrorType type)
00370 {
00371 return_if_fail(error != NULL);
00372
00373 (*error)->type = type;
00374 }
00375
00382 SmlErrorClass smlErrorGetClass(SmlError **error)
00383 {
00384 if (!smlErrorIsSet(error))
00385 return SML_ERRORCLASS_SUCCESS;
00386
00387 if ((*error)->type == SML_NO_ERROR)
00388 return SML_ERRORCLASS_SUCCESS;
00389
00390 return (int)((*error)->type / 100);
00391 }
00392