1 /** **************************************************************************
4 * Copyright 2008 Bryan Ischo <bryan@ischo.com>
6 * This file is part of libs3.
8 * libs3 is free software: you can redistribute it and/or modify it under the
9 * terms of the GNU General Public License as published by the Free Software
10 * Foundation, version 3 of the License.
12 * In addition, as a special exception, the copyright holders give
13 * permission to link the code of this library and its programs with the
14 * OpenSSL library, and distribute linked combinations including the two.
16 * libs3 is distributed in the hope that it will be useful, but WITHOUT ANY
17 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
21 * You should have received a copy of the GNU General Public License version 3
22 * along with libs3, in a file named COPYING. If not, see
23 * <http://www.gnu.org/licenses/>.
25 ************************************************************************** **/
28 #include "error_parser.h"
31 static S3Status errorXmlCallback(const char *elementPath, const char *data,
32 int dataLen, void *callbackData)
34 // We ignore end of element callbacks because we don't care about them
39 ErrorParser *errorParser = (ErrorParser *) callbackData;
43 if (!strcmp(elementPath, "Error")) {
44 // Ignore, this is the Error element itself, we only care about subs
46 else if (!strcmp(elementPath, "Error/Code")) {
47 string_buffer_append(errorParser->code, data, dataLen, fit);
49 else if (!strcmp(elementPath, "Error/Message")) {
50 string_buffer_append(errorParser->message, data, dataLen, fit);
51 errorParser->s3ErrorDetails.message = errorParser->message;
53 else if (!strcmp(elementPath, "Error/Resource")) {
54 string_buffer_append(errorParser->resource, data, dataLen, fit);
55 errorParser->s3ErrorDetails.resource = errorParser->resource;
57 else if (!strcmp(elementPath, "Error/FurtherDetails")) {
58 string_buffer_append(errorParser->furtherDetails, data, dataLen, fit);
59 errorParser->s3ErrorDetails.furtherDetails =
60 errorParser->furtherDetails;
63 if (strncmp(elementPath, "Error/", sizeof("Error/") - 1)) {
64 // If for some weird reason it's not within the Error element,
68 // It's an unknown error element. See if it matches the most
69 // recent error element.
70 const char *elementName = &(elementPath[sizeof("Error/") - 1]);
71 if (errorParser->s3ErrorDetails.extraDetailsCount &&
72 !strcmp(elementName, errorParser->s3ErrorDetails.extraDetails
73 [errorParser->s3ErrorDetails.extraDetailsCount - 1].name)) {
75 string_multibuffer_append(errorParser->extraDetailsNamesValues,
77 // If it didn't fit, remove this extra
79 errorParser->s3ErrorDetails.extraDetailsCount--;
83 // OK, must add another unknown error element, if it will fit.
84 if (errorParser->s3ErrorDetails.extraDetailsCount ==
85 sizeof(errorParser->extraDetails)) {
86 // Won't fit. Ignore this one.
89 // Copy in the name and value
90 char *name = string_multibuffer_current
91 (errorParser->extraDetailsNamesValues);
92 int nameLen = strlen(elementName);
93 string_multibuffer_add(errorParser->extraDetailsNamesValues,
94 elementName, nameLen, fit);
96 // Name didn't fit; ignore this one.
99 char *value = string_multibuffer_current
100 (errorParser->extraDetailsNamesValues);
101 string_multibuffer_add(errorParser->extraDetailsNamesValues,
104 // Value didn't fit; ignore this one.
108 &(errorParser->extraDetails
109 [errorParser->s3ErrorDetails.extraDetailsCount++]);
118 void error_parser_initialize(ErrorParser *errorParser)
120 errorParser->s3ErrorDetails.message = 0;
121 errorParser->s3ErrorDetails.resource = 0;
122 errorParser->s3ErrorDetails.furtherDetails = 0;
123 errorParser->s3ErrorDetails.extraDetailsCount = 0;
124 errorParser->s3ErrorDetails.extraDetails = errorParser->extraDetails;
125 errorParser->errorXmlParserInitialized = 0;
126 string_buffer_initialize(errorParser->code);
127 string_buffer_initialize(errorParser->message);
128 string_buffer_initialize(errorParser->resource);
129 string_buffer_initialize(errorParser->furtherDetails);
130 string_multibuffer_initialize(errorParser->extraDetailsNamesValues);
134 S3Status error_parser_add(ErrorParser *errorParser, char *buffer,
137 if (!errorParser->errorXmlParserInitialized) {
138 simplexml_initialize(&(errorParser->errorXmlParser), &errorXmlCallback,
140 errorParser->errorXmlParserInitialized = 1;
143 return simplexml_add(&(errorParser->errorXmlParser), buffer, bufferSize);
147 void error_parser_convert_status(ErrorParser *errorParser, S3Status *status)
149 // Convert the error status string into a code
150 if (!errorParser->codeLen) {
154 #define HANDLE_CODE(name) \
156 if (!strcmp(errorParser->code, #name)) { \
157 *status = S3StatusError##name; \
162 HANDLE_CODE(AccessDenied);
163 HANDLE_CODE(AccountProblem);
164 HANDLE_CODE(AmbiguousGrantByEmailAddress);
165 HANDLE_CODE(BadDigest);
166 HANDLE_CODE(BucketAlreadyExists);
167 HANDLE_CODE(BucketAlreadyOwnedByYou);
168 HANDLE_CODE(BucketNotEmpty);
169 HANDLE_CODE(CredentialsNotSupported);
170 HANDLE_CODE(CrossLocationLoggingProhibited);
171 HANDLE_CODE(EntityTooSmall);
172 HANDLE_CODE(EntityTooLarge);
173 HANDLE_CODE(ExpiredToken);
174 HANDLE_CODE(IncompleteBody);
175 HANDLE_CODE(IncorrectNumberOfFilesInPostRequest);
176 HANDLE_CODE(InlineDataTooLarge);
177 HANDLE_CODE(InternalError);
178 HANDLE_CODE(InvalidAccessKeyId);
179 HANDLE_CODE(InvalidAddressingHeader);
180 HANDLE_CODE(InvalidArgument);
181 HANDLE_CODE(InvalidBucketName);
182 HANDLE_CODE(InvalidDigest);
183 HANDLE_CODE(InvalidLocationConstraint);
184 HANDLE_CODE(InvalidPayer);
185 HANDLE_CODE(InvalidPolicyDocument);
186 HANDLE_CODE(InvalidRange);
187 HANDLE_CODE(InvalidSecurity);
188 HANDLE_CODE(InvalidSOAPRequest);
189 HANDLE_CODE(InvalidStorageClass);
190 HANDLE_CODE(InvalidTargetBucketForLogging);
191 HANDLE_CODE(InvalidToken);
192 HANDLE_CODE(InvalidURI);
193 HANDLE_CODE(KeyTooLong);
194 HANDLE_CODE(MalformedACLError);
195 HANDLE_CODE(MalformedXML);
196 HANDLE_CODE(MaxMessageLengthExceeded);
197 HANDLE_CODE(MaxPostPreDataLengthExceededError);
198 HANDLE_CODE(MetadataTooLarge);
199 HANDLE_CODE(MethodNotAllowed);
200 HANDLE_CODE(MissingAttachment);
201 HANDLE_CODE(MissingContentLength);
202 HANDLE_CODE(MissingSecurityElement);
203 HANDLE_CODE(MissingSecurityHeader);
204 HANDLE_CODE(NoLoggingStatusForKey);
205 HANDLE_CODE(NoSuchBucket);
206 HANDLE_CODE(NoSuchKey);
207 HANDLE_CODE(NotImplemented);
208 HANDLE_CODE(NotSignedUp);
209 HANDLE_CODE(OperationAborted);
210 HANDLE_CODE(PermanentRedirect);
211 HANDLE_CODE(PreconditionFailed);
212 HANDLE_CODE(Redirect);
213 HANDLE_CODE(RequestIsNotMultiPartContent);
214 HANDLE_CODE(RequestTimeout);
215 HANDLE_CODE(RequestTimeTooSkewed);
216 HANDLE_CODE(RequestTorrentOfBucketError);
217 HANDLE_CODE(SignatureDoesNotMatch);
218 HANDLE_CODE(SlowDown);
219 HANDLE_CODE(TemporaryRedirect);
220 HANDLE_CODE(TokenRefreshRequired);
221 HANDLE_CODE(TooManyBuckets);
222 HANDLE_CODE(UnexpectedContent);
223 HANDLE_CODE(UnresolvableGrantByEmailAddress);
224 HANDLE_CODE(UserKeyMustBeSpecified);
225 *status = S3StatusErrorUnknown;
234 void error_parser_deinitialize(ErrorParser *errorParser)
236 if (errorParser->errorXmlParserInitialized) {
237 simplexml_deinitialize(&(errorParser->errorXmlParser));