summaryrefslogtreecommitdiff
path: root/src/error_parser.c
diff options
context:
space:
mode:
authorBryan Ischo <bryan@ischo.com>2008-07-10 21:12:21 +0000
committerBryan Ischo <bryan@ischo.com>2008-07-10 21:12:21 +0000
commitc0535eabe25706904711f1453e724e659b93318c (patch)
tree55e2a2acc6fbc71e4c1a55489aaeed7f2cc919e2 /src/error_parser.c
parente9e38ab98e38b35725d85cbe6101bfbbd34d1418 (diff)
downloadceph-libs3-c0535eabe25706904711f1453e724e659b93318c.tar.gz
* Work in progress - reorganized alot, completed list bucket, create bucket,
delete bucket, test bucket
Diffstat (limited to 'src/error_parser.c')
-rw-r--r--src/error_parser.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/src/error_parser.c b/src/error_parser.c
new file mode 100644
index 0000000..d26bba8
--- /dev/null
+++ b/src/error_parser.c
@@ -0,0 +1,239 @@
+/** **************************************************************************
+ * error_parser.c
+ *
+ * Copyright 2008 Bryan Ischo <bryan@ischo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the
+ *
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ ************************************************************************** **/
+
+#include <string.h>
+#include "error_parser.h"
+
+
+static S3Status errorXmlCallback(const char *elementPath, const char *data,
+ int dataLen, void *callbackData)
+{
+ // We ignore end of element callbacks because we don't care about them
+ if (!data) {
+ return S3StatusOK;
+ }
+
+ ErrorParser *errorParser = (ErrorParser *) callbackData;
+
+ int fit;
+
+ if (!strcmp(elementPath, "Error")) {
+ // Ignore, this is the Error element itself, we only care about subs
+ }
+ else if (!strcmp(elementPath, "Error/Code")) {
+ string_buffer_append(errorParser->code, data, dataLen, fit);
+ }
+ else if (!strcmp(elementPath, "Error/Message")) {
+ string_buffer_append(errorParser->message, data, dataLen, fit);
+ errorParser->s3ErrorDetails.message = errorParser->message;
+ }
+ else if (!strcmp(elementPath, "Error/Resource")) {
+ string_buffer_append(errorParser->resource, data, dataLen, fit);
+ errorParser->s3ErrorDetails.resource = errorParser->resource;
+ }
+ else if (!strcmp(elementPath, "Error/FurtherDetails")) {
+ string_buffer_append(errorParser->furtherDetails, data, dataLen, fit);
+ errorParser->s3ErrorDetails.furtherDetails =
+ errorParser->furtherDetails;
+ }
+ else {
+ if (strncmp(elementPath, "Error/", sizeof("Error/") - 1)) {
+ // If for some weird reason it's not within the Error element,
+ // ignore it
+ return S3StatusOK;
+ }
+ // It's an unknown error element. See if it matches the most
+ // recent error element.
+ const char *elementName = &(elementPath[sizeof("Error/") - 1]);
+ if (errorParser->s3ErrorDetails.extraDetailsCount &&
+ !strcmp(elementName, errorParser->s3ErrorDetails.extraDetails
+ [errorParser->s3ErrorDetails.extraDetailsCount - 1].name)) {
+ // Append the value
+ string_multibuffer_append(errorParser->extraDetailsNamesValues,
+ data, dataLen, fit);
+ // If it didn't fit, remove this extra
+ if (!fit) {
+ errorParser->s3ErrorDetails.extraDetailsCount--;
+ }
+ return S3StatusOK;
+ }
+ // OK, must add another unknown error element, if it will fit.
+ if (errorParser->s3ErrorDetails.extraDetailsCount ==
+ sizeof(errorParser->extraDetails)) {
+ // Won't fit. Ignore this one.
+ return S3StatusOK;
+ }
+ // Copy in the name and value
+ char *name = string_multibuffer_current
+ (errorParser->extraDetailsNamesValues);
+ int nameLen = strlen(elementName);
+ string_multibuffer_add(errorParser->extraDetailsNamesValues,
+ elementName, nameLen, fit);
+ if (!fit) {
+ // Name didn't fit; ignore this one.
+ return S3StatusOK;
+ }
+ char *value = string_multibuffer_current
+ (errorParser->extraDetailsNamesValues);
+ string_multibuffer_add(errorParser->extraDetailsNamesValues,
+ data, dataLen, fit);
+ if (!fit) {
+ // Value didn't fit; ignore this one.
+ return S3StatusOK;
+ }
+ S3NameValue *nv = &(errorParser->extraDetails
+ [errorParser->s3ErrorDetails.extraDetailsCount++]);
+ nv->name = name;
+ nv->value = value;
+ }
+
+ return S3StatusOK;
+}
+
+
+void error_parser_initialize(ErrorParser *errorParser)
+{
+ errorParser->s3ErrorDetails.message = 0;
+ errorParser->s3ErrorDetails.resource = 0;
+ errorParser->s3ErrorDetails.furtherDetails = 0;
+ errorParser->s3ErrorDetails.extraDetailsCount = 0;
+ errorParser->s3ErrorDetails.extraDetails = errorParser->extraDetails;
+ errorParser->errorXmlParserInitialized = 0;
+ string_buffer_initialize(errorParser->code);
+ string_buffer_initialize(errorParser->message);
+ string_buffer_initialize(errorParser->resource);
+ string_buffer_initialize(errorParser->furtherDetails);
+ string_multibuffer_initialize(errorParser->extraDetailsNamesValues);
+}
+
+
+S3Status error_parser_add(ErrorParser *errorParser, char *buffer,
+ int bufferSize)
+{
+ if (!errorParser->errorXmlParserInitialized) {
+ S3Status status = simplexml_initialize
+ (&(errorParser->errorXmlParser), &errorXmlCallback, errorParser);
+ if (status != S3StatusOK) {
+ return status;
+ }
+ errorParser->errorXmlParserInitialized = 1;
+ }
+
+ return simplexml_add(&(errorParser->errorXmlParser), buffer, bufferSize);
+}
+
+
+void error_parser_convert_status(ErrorParser *errorParser, S3Status *status)
+{
+ // Convert the error status string into a code
+ if (!errorParser->codeLen) {
+ return;
+ }
+
+#define HANDLE_CODE(name) \
+ do { \
+ if (!strcmp(errorParser->code, #name)) { \
+ *status = S3StatusError##name; \
+ goto code_set; \
+ } \
+ } while (0)
+
+ HANDLE_CODE(AccessDenied);
+ HANDLE_CODE(AccountProblem);
+ HANDLE_CODE(AmbiguousGrantByEmailAddress);
+ HANDLE_CODE(BadDigest);
+ HANDLE_CODE(BucketAlreadyExists);
+ HANDLE_CODE(BucketAlreadyOwnedByYou);
+ HANDLE_CODE(BucketNotEmpty);
+ HANDLE_CODE(CredentialsNotSupported);
+ HANDLE_CODE(CrossLocationLoggingProhibited);
+ HANDLE_CODE(EntityTooSmall);
+ HANDLE_CODE(EntityTooLarge);
+ HANDLE_CODE(ExpiredToken);
+ HANDLE_CODE(IncompleteBody);
+ HANDLE_CODE(IncorrectNumberOfFilesInPostRequest);
+ HANDLE_CODE(InlineDataTooLarge);
+ HANDLE_CODE(InternalError);
+ HANDLE_CODE(InvalidAccessKeyId);
+ HANDLE_CODE(InvalidAddressingHeader);
+ HANDLE_CODE(InvalidArgument);
+ HANDLE_CODE(InvalidBucketName);
+ HANDLE_CODE(InvalidDigest);
+ HANDLE_CODE(InvalidLocationConstraint);
+ HANDLE_CODE(InvalidPayer);
+ HANDLE_CODE(InvalidPolicyDocument);
+ HANDLE_CODE(InvalidRange);
+ HANDLE_CODE(InvalidSecurity);
+ HANDLE_CODE(InvalidSOAPRequest);
+ HANDLE_CODE(InvalidStorageClass);
+ HANDLE_CODE(InvalidTargetBucketForLogging);
+ HANDLE_CODE(InvalidToken);
+ HANDLE_CODE(InvalidURI);
+ HANDLE_CODE(KeyTooLong);
+ HANDLE_CODE(MalformedACLError);
+ HANDLE_CODE(MalformedXML);
+ HANDLE_CODE(MaxMessageLengthExceeded);
+ HANDLE_CODE(MaxPostPreDataLengthExceededError);
+ HANDLE_CODE(MetadataTooLarge);
+ HANDLE_CODE(MethodNotAllowed);
+ HANDLE_CODE(MissingAttachment);
+ HANDLE_CODE(MissingContentLength);
+ HANDLE_CODE(MissingSecurityElement);
+ HANDLE_CODE(MissingSecurityHeader);
+ HANDLE_CODE(NoLoggingStatusForKey);
+ HANDLE_CODE(NoSuchBucket);
+ HANDLE_CODE(NoSuchKey);
+ HANDLE_CODE(NotImplemented);
+ HANDLE_CODE(NotSignedUp);
+ HANDLE_CODE(OperationAborted);
+ HANDLE_CODE(PermanentRedirect);
+ HANDLE_CODE(PreconditionFailed);
+ HANDLE_CODE(Redirect);
+ HANDLE_CODE(RequestIsNotMultiPartContent);
+ HANDLE_CODE(RequestTimeout);
+ HANDLE_CODE(RequestTimeTooSkewed);
+ HANDLE_CODE(RequestTorrentOfBucketError);
+ HANDLE_CODE(SignatureDoesNotMatch);
+ HANDLE_CODE(SlowDown);
+ HANDLE_CODE(TemporaryRedirect);
+ HANDLE_CODE(TokenRefreshRequired);
+ HANDLE_CODE(TooManyBuckets);
+ HANDLE_CODE(UnexpectedContent);
+ HANDLE_CODE(UnresolvableGrantByEmailAddress);
+ HANDLE_CODE(UserKeyMustBeSpecified);
+ *status = S3StatusErrorUnknown;
+
+ code_set:
+
+ return;
+}
+
+
+// Always call this
+void error_parser_deinitialize(ErrorParser *errorParser)
+{
+ if (errorParser->errorXmlParserInitialized) {
+ simplexml_deinitialize(&(errorParser->errorXmlParser));
+ }
+}