error_parser.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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 of the License.
  11. *
  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.
  15. *
  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
  19. * details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public License
  22. * version 3 along with libs3, in a file named COPYING. If not, see
  23. * <https://www.gnu.org/licenses/>.
  24. *
  25. ************************************************************************** **/
  26. #include <string.h>
  27. #include "error_parser.h"
  28. static S3Status errorXmlCallback(const char *elementPath, const char *data,
  29. int dataLen, void *callbackData)
  30. {
  31. // We ignore end of element callbacks because we don't care about them
  32. if (!data) {
  33. return S3StatusOK;
  34. }
  35. ErrorParser *errorParser = (ErrorParser *) callbackData;
  36. int fit;
  37. if (!strcmp(elementPath, "Error")) {
  38. // Ignore, this is the Error element itself, we only care about subs
  39. }
  40. else if (!strcmp(elementPath, "Error/Code")) {
  41. string_buffer_append(errorParser->code, data, dataLen, fit);
  42. }
  43. else if (!strcmp(elementPath, "Error/Message")) {
  44. string_buffer_append(errorParser->message, data, dataLen, fit);
  45. errorParser->s3ErrorDetails.message = errorParser->message;
  46. }
  47. else if (!strcmp(elementPath, "Error/Resource")) {
  48. string_buffer_append(errorParser->resource, data, dataLen, fit);
  49. errorParser->s3ErrorDetails.resource = errorParser->resource;
  50. }
  51. else if (!strcmp(elementPath, "Error/FurtherDetails")) {
  52. string_buffer_append(errorParser->furtherDetails, data, dataLen, fit);
  53. errorParser->s3ErrorDetails.furtherDetails =
  54. errorParser->furtherDetails;
  55. }
  56. else {
  57. if (strncmp(elementPath, "Error/", sizeof("Error/") - 1)) {
  58. // If for some weird reason it's not within the Error element,
  59. // ignore it
  60. return S3StatusOK;
  61. }
  62. // It's an unknown error element. See if it matches the most
  63. // recent error element.
  64. const char *elementName = &(elementPath[sizeof("Error/") - 1]);
  65. if (errorParser->s3ErrorDetails.extraDetailsCount &&
  66. !strcmp(elementName, errorParser->s3ErrorDetails.extraDetails
  67. [errorParser->s3ErrorDetails.extraDetailsCount - 1].name)) {
  68. // Append the value
  69. string_multibuffer_append(errorParser->extraDetailsNamesValues,
  70. data, dataLen, fit);
  71. // If it didn't fit, remove this extra
  72. if (!fit) {
  73. errorParser->s3ErrorDetails.extraDetailsCount--;
  74. }
  75. return S3StatusOK;
  76. }
  77. // OK, must add another unknown error element, if it will fit.
  78. if (errorParser->s3ErrorDetails.extraDetailsCount ==
  79. (int)sizeof(errorParser->extraDetails)) { // WINSCP (cast)
  80. // Won't fit. Ignore this one.
  81. return S3StatusOK;
  82. }
  83. // Copy in the name and value
  84. char *name = string_multibuffer_current
  85. (errorParser->extraDetailsNamesValues);
  86. int nameLen = strlen(elementName);
  87. string_multibuffer_add(errorParser->extraDetailsNamesValues,
  88. elementName, nameLen, fit);
  89. if (!fit) {
  90. // Name didn't fit; ignore this one.
  91. return S3StatusOK;
  92. }
  93. char *value = string_multibuffer_current
  94. (errorParser->extraDetailsNamesValues);
  95. string_multibuffer_add(errorParser->extraDetailsNamesValues,
  96. data, dataLen, fit);
  97. if (!fit) {
  98. // Value didn't fit; ignore this one.
  99. return S3StatusOK;
  100. }
  101. S3NameValue *nv =
  102. &(errorParser->extraDetails
  103. [errorParser->s3ErrorDetails.extraDetailsCount++]);
  104. nv->name = name;
  105. nv->value = value;
  106. }
  107. return S3StatusOK;
  108. }
  109. void error_parser_initialize(ErrorParser *errorParser)
  110. {
  111. errorParser->s3ErrorDetails.message = 0;
  112. errorParser->s3ErrorDetails.resource = 0;
  113. errorParser->s3ErrorDetails.furtherDetails = 0;
  114. errorParser->s3ErrorDetails.extraDetailsCount = 0;
  115. errorParser->s3ErrorDetails.extraDetails = errorParser->extraDetails;
  116. errorParser->errorXmlParserInitialized = 0;
  117. string_buffer_initialize(errorParser->code);
  118. string_buffer_initialize(errorParser->message);
  119. string_buffer_initialize(errorParser->resource);
  120. string_buffer_initialize(errorParser->furtherDetails);
  121. string_multibuffer_initialize(errorParser->extraDetailsNamesValues);
  122. }
  123. S3Status error_parser_add(ErrorParser *errorParser, const /*WINSCP (const)*/ char *buffer,
  124. int bufferSize)
  125. {
  126. if (!errorParser->errorXmlParserInitialized) {
  127. simplexml_initialize(&(errorParser->errorXmlParser), &errorXmlCallback,
  128. errorParser);
  129. errorParser->errorXmlParserInitialized = 1;
  130. }
  131. return simplexml_add(&(errorParser->errorXmlParser), buffer, bufferSize);
  132. }
  133. void error_parser_convert_status(ErrorParser *errorParser, S3Status *status)
  134. {
  135. // Convert the error status string into a code
  136. if (!errorParser->codeLen) {
  137. return;
  138. }
  139. #define HANDLE_CODE(name) \
  140. do { \
  141. if (!strcmp(errorParser->code, #name)) { \
  142. *status = S3StatusError##name; \
  143. goto code_set; \
  144. } \
  145. } while (0)
  146. HANDLE_CODE(AccessDenied);
  147. HANDLE_CODE(AccountProblem);
  148. HANDLE_CODE(AmbiguousGrantByEmailAddress);
  149. HANDLE_CODE(BadDigest);
  150. HANDLE_CODE(BucketAlreadyExists);
  151. HANDLE_CODE(BucketAlreadyOwnedByYou);
  152. HANDLE_CODE(BucketNotEmpty);
  153. HANDLE_CODE(CredentialsNotSupported);
  154. HANDLE_CODE(CrossLocationLoggingProhibited);
  155. HANDLE_CODE(EntityTooSmall);
  156. HANDLE_CODE(EntityTooLarge);
  157. HANDLE_CODE(ExpiredToken);
  158. HANDLE_CODE(IllegalVersioningConfigurationException);
  159. HANDLE_CODE(IncompleteBody);
  160. HANDLE_CODE(IncorrectNumberOfFilesInPostRequest);
  161. HANDLE_CODE(InlineDataTooLarge);
  162. HANDLE_CODE(InternalError);
  163. HANDLE_CODE(InvalidAccessKeyId);
  164. HANDLE_CODE(InvalidAddressingHeader);
  165. HANDLE_CODE(InvalidArgument);
  166. HANDLE_CODE(InvalidBucketName);
  167. HANDLE_CODE(InvalidBucketState);
  168. HANDLE_CODE(InvalidDigest);
  169. HANDLE_CODE(InvalidEncryptionAlgorithmError);
  170. HANDLE_CODE(InvalidLocationConstraint);
  171. HANDLE_CODE(InvalidObjectState);
  172. HANDLE_CODE(InvalidPart);
  173. HANDLE_CODE(InvalidPartOrder);
  174. HANDLE_CODE(InvalidPayer);
  175. HANDLE_CODE(InvalidPolicyDocument);
  176. HANDLE_CODE(InvalidRange);
  177. HANDLE_CODE(InvalidRequest);
  178. HANDLE_CODE(InvalidSecurity);
  179. HANDLE_CODE(InvalidSOAPRequest);
  180. HANDLE_CODE(InvalidStorageClass);
  181. HANDLE_CODE(InvalidTargetBucketForLogging);
  182. HANDLE_CODE(InvalidToken);
  183. HANDLE_CODE(InvalidURI);
  184. HANDLE_CODE(KeyTooLong);
  185. HANDLE_CODE(MalformedACLError);
  186. HANDLE_CODE(MalformedPOSTRequest);
  187. HANDLE_CODE(MalformedXML);
  188. HANDLE_CODE(MaxMessageLengthExceeded);
  189. HANDLE_CODE(MaxPostPreDataLengthExceededError);
  190. HANDLE_CODE(MetadataTooLarge);
  191. HANDLE_CODE(MethodNotAllowed);
  192. HANDLE_CODE(MissingAttachment);
  193. HANDLE_CODE(MissingContentLength);
  194. HANDLE_CODE(MissingRequestBodyError);
  195. HANDLE_CODE(MissingSecurityElement);
  196. HANDLE_CODE(MissingSecurityHeader);
  197. HANDLE_CODE(NoLoggingStatusForKey);
  198. HANDLE_CODE(NoSuchBucket);
  199. HANDLE_CODE(NoSuchKey);
  200. HANDLE_CODE(NoSuchLifecycleConfiguration);
  201. HANDLE_CODE(NoSuchUpload);
  202. HANDLE_CODE(NoSuchVersion);
  203. HANDLE_CODE(NotImplemented);
  204. HANDLE_CODE(NotSignedUp);
  205. HANDLE_CODE(NoSuchBucketPolicy);
  206. HANDLE_CODE(OperationAborted);
  207. HANDLE_CODE(PermanentRedirect);
  208. HANDLE_CODE(PreconditionFailed);
  209. HANDLE_CODE(Redirect);
  210. HANDLE_CODE(RestoreAlreadyInProgress);
  211. HANDLE_CODE(RequestIsNotMultiPartContent);
  212. HANDLE_CODE(RequestTimeout);
  213. HANDLE_CODE(RequestTimeTooSkewed);
  214. HANDLE_CODE(RequestTorrentOfBucketError);
  215. HANDLE_CODE(SignatureDoesNotMatch);
  216. HANDLE_CODE(ServiceUnavailable);
  217. HANDLE_CODE(SlowDown);
  218. HANDLE_CODE(TemporaryRedirect);
  219. HANDLE_CODE(TokenRefreshRequired);
  220. HANDLE_CODE(TooManyBuckets);
  221. HANDLE_CODE(UnexpectedContent);
  222. HANDLE_CODE(UnresolvableGrantByEmailAddress);
  223. HANDLE_CODE(UserKeyMustBeSpecified);
  224. HANDLE_CODE(QuotaExceeded);
  225. HANDLE_CODE(AuthorizationHeaderMalformed); // WINSCP
  226. *status = S3StatusErrorUnknown;
  227. code_set:
  228. return;
  229. }
  230. // Always call this
  231. void error_parser_deinitialize(ErrorParser *errorParser)
  232. {
  233. if (errorParser->errorXmlParserInitialized) {
  234. simplexml_deinitialize(&(errorParser->errorXmlParser));
  235. }
  236. }