error_parser.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /** **************************************************************************
  2. * error_parser.c
  3. *
  4. * Copyright 2008 Bryan Ischo <[email protected]>
  5. *
  6. * This file is part of libs3.
  7. *
  8. * libs3 is free software: you can redistribute it and/or modify it under the
  9. * terms of the GNU Lesser General Public License as published by the Free
  10. * Software Foundation, version 3 or above of the License. You can also
  11. * redistribute and/or modify it under the terms of the GNU General Public
  12. * License, version 2 or above of the License.
  13. *
  14. * In addition, as a special exception, the copyright holders give
  15. * permission to link the code of this library and its programs with the
  16. * OpenSSL library, and distribute linked combinations including the two.
  17. *
  18. * libs3 is distributed in the hope that it will be useful, but WITHOUT ANY
  19. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  20. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  21. * details.
  22. *
  23. * You should have received a copy of the GNU Lesser General Public License
  24. * version 3 along with libs3, in a file named COPYING. If not, see
  25. * <http://www.gnu.org/licenses/>.
  26. *
  27. * You should also have received a copy of the GNU General Public License
  28. * version 2 along with libs3, in a file named COPYING-GPLv2. If not, see
  29. * <http://www.gnu.org/licenses/>.
  30. *
  31. ************************************************************************** **/
  32. #include <string.h>
  33. #include "error_parser.h"
  34. static S3Status errorXmlCallback(const char *elementPath, const char *data,
  35. int dataLen, void *callbackData)
  36. {
  37. // We ignore end of element callbacks because we don't care about them
  38. if (!data) {
  39. return S3StatusOK;
  40. }
  41. ErrorParser *errorParser = (ErrorParser *) callbackData;
  42. int fit;
  43. if (!strcmp(elementPath, "Error")) {
  44. // Ignore, this is the Error element itself, we only care about subs
  45. }
  46. else if (!strcmp(elementPath, "Error/Code")) {
  47. string_buffer_append(errorParser->code, data, dataLen, fit);
  48. }
  49. else if (!strcmp(elementPath, "Error/Message")) {
  50. string_buffer_append(errorParser->message, data, dataLen, fit);
  51. errorParser->s3ErrorDetails.message = errorParser->message;
  52. }
  53. else if (!strcmp(elementPath, "Error/Resource")) {
  54. string_buffer_append(errorParser->resource, data, dataLen, fit);
  55. errorParser->s3ErrorDetails.resource = errorParser->resource;
  56. }
  57. else if (!strcmp(elementPath, "Error/FurtherDetails")) {
  58. string_buffer_append(errorParser->furtherDetails, data, dataLen, fit);
  59. errorParser->s3ErrorDetails.furtherDetails =
  60. errorParser->furtherDetails;
  61. }
  62. else {
  63. if (strncmp(elementPath, "Error/", sizeof("Error/") - 1)) {
  64. // If for some weird reason it's not within the Error element,
  65. // ignore it
  66. return S3StatusOK;
  67. }
  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)) {
  74. // Append the value
  75. string_multibuffer_append(errorParser->extraDetailsNamesValues,
  76. data, dataLen, fit);
  77. // If it didn't fit, remove this extra
  78. if (!fit) {
  79. errorParser->s3ErrorDetails.extraDetailsCount--;
  80. }
  81. return S3StatusOK;
  82. }
  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.
  87. return S3StatusOK;
  88. }
  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);
  95. if (!fit) {
  96. // Name didn't fit; ignore this one.
  97. return S3StatusOK;
  98. }
  99. char *value = string_multibuffer_current
  100. (errorParser->extraDetailsNamesValues);
  101. string_multibuffer_add(errorParser->extraDetailsNamesValues,
  102. data, dataLen, fit);
  103. if (!fit) {
  104. // Value didn't fit; ignore this one.
  105. return S3StatusOK;
  106. }
  107. S3NameValue *nv =
  108. &(errorParser->extraDetails
  109. [errorParser->s3ErrorDetails.extraDetailsCount++]);
  110. nv->name = name;
  111. nv->value = value;
  112. }
  113. return S3StatusOK;
  114. }
  115. void error_parser_initialize(ErrorParser *errorParser)
  116. {
  117. errorParser->s3ErrorDetails.message = 0;
  118. errorParser->s3ErrorDetails.resource = 0;
  119. errorParser->s3ErrorDetails.furtherDetails = 0;
  120. errorParser->s3ErrorDetails.extraDetailsCount = 0;
  121. errorParser->s3ErrorDetails.extraDetails = errorParser->extraDetails;
  122. errorParser->errorXmlParserInitialized = 0;
  123. string_buffer_initialize(errorParser->code);
  124. string_buffer_initialize(errorParser->message);
  125. string_buffer_initialize(errorParser->resource);
  126. string_buffer_initialize(errorParser->furtherDetails);
  127. string_multibuffer_initialize(errorParser->extraDetailsNamesValues);
  128. }
  129. S3Status error_parser_add(ErrorParser *errorParser, char *buffer,
  130. int bufferSize)
  131. {
  132. if (!errorParser->errorXmlParserInitialized) {
  133. simplexml_initialize(&(errorParser->errorXmlParser), &errorXmlCallback,
  134. errorParser);
  135. errorParser->errorXmlParserInitialized = 1;
  136. }
  137. return simplexml_add(&(errorParser->errorXmlParser), buffer, bufferSize);
  138. }
  139. void error_parser_convert_status(ErrorParser *errorParser, S3Status *status)
  140. {
  141. // Convert the error status string into a code
  142. if (!errorParser->codeLen) {
  143. return;
  144. }
  145. #define HANDLE_CODE(name) \
  146. do { \
  147. if (!strcmp(errorParser->code, #name)) { \
  148. *status = S3StatusError##name; \
  149. goto code_set; \
  150. } \
  151. } while (0)
  152. HANDLE_CODE(AccessDenied);
  153. HANDLE_CODE(AccountProblem);
  154. HANDLE_CODE(AmbiguousGrantByEmailAddress);
  155. HANDLE_CODE(BadDigest);
  156. HANDLE_CODE(BucketAlreadyExists);
  157. HANDLE_CODE(BucketAlreadyOwnedByYou);
  158. HANDLE_CODE(BucketNotEmpty);
  159. HANDLE_CODE(CredentialsNotSupported);
  160. HANDLE_CODE(CrossLocationLoggingProhibited);
  161. HANDLE_CODE(EntityTooSmall);
  162. HANDLE_CODE(EntityTooLarge);
  163. HANDLE_CODE(ExpiredToken);
  164. HANDLE_CODE(IllegalVersioningConfigurationException);
  165. HANDLE_CODE(IncompleteBody);
  166. HANDLE_CODE(IncorrectNumberOfFilesInPostRequest);
  167. HANDLE_CODE(InlineDataTooLarge);
  168. HANDLE_CODE(InternalError);
  169. HANDLE_CODE(InvalidAccessKeyId);
  170. HANDLE_CODE(InvalidAddressingHeader);
  171. HANDLE_CODE(InvalidArgument);
  172. HANDLE_CODE(InvalidBucketName);
  173. HANDLE_CODE(InvalidBucketState);
  174. HANDLE_CODE(InvalidDigest);
  175. HANDLE_CODE(InvalidEncryptionAlgorithmError);
  176. HANDLE_CODE(InvalidLocationConstraint);
  177. HANDLE_CODE(InvalidObjectState);
  178. HANDLE_CODE(InvalidPart);
  179. HANDLE_CODE(InvalidPartOrder);
  180. HANDLE_CODE(InvalidPayer);
  181. HANDLE_CODE(InvalidPolicyDocument);
  182. HANDLE_CODE(InvalidRange);
  183. HANDLE_CODE(InvalidRequest);
  184. HANDLE_CODE(InvalidSecurity);
  185. HANDLE_CODE(InvalidSOAPRequest);
  186. HANDLE_CODE(InvalidStorageClass);
  187. HANDLE_CODE(InvalidTargetBucketForLogging);
  188. HANDLE_CODE(InvalidToken);
  189. HANDLE_CODE(InvalidURI);
  190. HANDLE_CODE(KeyTooLong);
  191. HANDLE_CODE(MalformedACLError);
  192. HANDLE_CODE(MalformedPOSTRequest);
  193. HANDLE_CODE(MalformedXML);
  194. HANDLE_CODE(MaxMessageLengthExceeded);
  195. HANDLE_CODE(MaxPostPreDataLengthExceededError);
  196. HANDLE_CODE(MetadataTooLarge);
  197. HANDLE_CODE(MethodNotAllowed);
  198. HANDLE_CODE(MissingAttachment);
  199. HANDLE_CODE(MissingContentLength);
  200. HANDLE_CODE(MissingRequestBodyError);
  201. HANDLE_CODE(MissingSecurityElement);
  202. HANDLE_CODE(MissingSecurityHeader);
  203. HANDLE_CODE(NoLoggingStatusForKey);
  204. HANDLE_CODE(NoSuchBucket);
  205. HANDLE_CODE(NoSuchKey);
  206. HANDLE_CODE(NoSuchLifecycleConfiguration);
  207. HANDLE_CODE(NoSuchUpload);
  208. HANDLE_CODE(NoSuchVersion);
  209. HANDLE_CODE(NotImplemented);
  210. HANDLE_CODE(NotSignedUp);
  211. HANDLE_CODE(NoSuchBucketPolicy);
  212. HANDLE_CODE(OperationAborted);
  213. HANDLE_CODE(PermanentRedirect);
  214. HANDLE_CODE(PreconditionFailed);
  215. HANDLE_CODE(Redirect);
  216. HANDLE_CODE(RestoreAlreadyInProgress);
  217. HANDLE_CODE(RequestIsNotMultiPartContent);
  218. HANDLE_CODE(RequestTimeout);
  219. HANDLE_CODE(RequestTimeTooSkewed);
  220. HANDLE_CODE(RequestTorrentOfBucketError);
  221. HANDLE_CODE(SignatureDoesNotMatch);
  222. HANDLE_CODE(ServiceUnavailable);
  223. HANDLE_CODE(SlowDown);
  224. HANDLE_CODE(TemporaryRedirect);
  225. HANDLE_CODE(TokenRefreshRequired);
  226. HANDLE_CODE(TooManyBuckets);
  227. HANDLE_CODE(UnexpectedContent);
  228. HANDLE_CODE(UnresolvableGrantByEmailAddress);
  229. HANDLE_CODE(UserKeyMustBeSpecified);
  230. HANDLE_CODE(QuotaExceeded);
  231. *status = S3StatusErrorUnknown;
  232. code_set:
  233. return;
  234. }
  235. // Always call this
  236. void error_parser_deinitialize(ErrorParser *errorParser)
  237. {
  238. if (errorParser->errorXmlParserInitialized) {
  239. simplexml_deinitialize(&(errorParser->errorXmlParser));
  240. }
  241. }