object.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /** **************************************************************************
  2. * object.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. * <https://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. * <https://www.gnu.org/licenses/>.
  30. *
  31. ************************************************************************** **/
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include "libs3.h"
  35. #include "request.h"
  36. // put object ----------------------------------------------------------------
  37. void S3_put_object(const S3BucketContext *bucketContext, const char *key,
  38. uint64_t contentLength,
  39. const S3PutProperties *putProperties,
  40. S3RequestContext *requestContext,
  41. int timeoutMs,
  42. const S3PutObjectHandler *handler, void *callbackData)
  43. {
  44. // Set up the RequestParams
  45. RequestParams params =
  46. {
  47. HttpRequestTypePUT, // httpRequestType
  48. { bucketContext->hostName, // hostName
  49. bucketContext->bucketName, // bucketName
  50. bucketContext->protocol, // protocol
  51. bucketContext->uriStyle, // uriStyle
  52. bucketContext->accessKeyId, // accessKeyId
  53. bucketContext->secretAccessKey, // secretAccessKey
  54. bucketContext->securityToken, // securityToken
  55. bucketContext->authRegion }, // authRegion
  56. key, // key
  57. 0, // queryParams
  58. 0, // subResource
  59. 0, // copySourceBucketName
  60. 0, // copySourceKey
  61. 0, // getConditions
  62. 0, // startByte
  63. 0, // byteCount
  64. putProperties, // putProperties
  65. handler->responseHandler.propertiesCallback, // propertiesCallback
  66. handler->putObjectDataCallback, // toS3Callback
  67. static_cast<int64_t>(contentLength), // toS3CallbackTotalSize (WINSCP cast)
  68. 0, // fromS3Callback
  69. handler->responseHandler.completeCallback, // completeCallback
  70. callbackData, // callbackData
  71. timeoutMs // timeoutMs
  72. };
  73. // Perform the request
  74. request_perform(&params, requestContext);
  75. }
  76. // copy object ---------------------------------------------------------------
  77. typedef struct CopyObjectData
  78. {
  79. SimpleXml simpleXml;
  80. S3ResponsePropertiesCallback *responsePropertiesCallback;
  81. S3ResponseCompleteCallback *responseCompleteCallback;
  82. void *callbackData;
  83. int64_t *lastModifiedReturn;
  84. int eTagReturnSize;
  85. char *eTagReturn;
  86. int eTagReturnLen;
  87. string_buffer(lastModified, 256);
  88. } CopyObjectData;
  89. static S3Status copyObjectXmlCallback(const char *elementPath,
  90. const char *data, int dataLen,
  91. void *callbackData)
  92. {
  93. CopyObjectData *coData = (CopyObjectData *) callbackData;
  94. int fit;
  95. if (data) {
  96. if (!strcmp(elementPath, "CopyObjectResult/LastModified")) {
  97. string_buffer_append(coData->lastModified, data, dataLen, fit);
  98. }
  99. else if (!strcmp(elementPath, "CopyObjectResult/ETag")) {
  100. if (coData->eTagReturnSize && coData->eTagReturn) {
  101. coData->eTagReturnLen +=
  102. snprintf(&(coData->eTagReturn[coData->eTagReturnLen]),
  103. coData->eTagReturnSize -
  104. coData->eTagReturnLen - 1,
  105. "%.*s", dataLen, data);
  106. if (coData->eTagReturnLen >= coData->eTagReturnSize) {
  107. return S3StatusXmlParseFailure;
  108. }
  109. }
  110. }
  111. }
  112. /* Avoid compiler error about variable set but not used */
  113. (void) fit;
  114. return S3StatusOK;
  115. }
  116. static S3Status copyObjectPropertiesCallback
  117. (const S3ResponseProperties *responseProperties, void *callbackData)
  118. {
  119. CopyObjectData *coData = (CopyObjectData *) callbackData;
  120. return (*(coData->responsePropertiesCallback))
  121. (responseProperties, coData->callbackData);
  122. }
  123. static S3Status copyObjectDataCallback(int bufferSize, const char *buffer,
  124. void *callbackData)
  125. {
  126. CopyObjectData *coData = (CopyObjectData *) callbackData;
  127. return simplexml_add(&(coData->simpleXml), buffer, bufferSize);
  128. }
  129. static void copyObjectCompleteCallback(S3Status requestStatus,
  130. const S3ErrorDetails *s3ErrorDetails,
  131. void *callbackData)
  132. {
  133. CopyObjectData *coData = (CopyObjectData *) callbackData;
  134. if (coData->lastModifiedReturn) {
  135. time_t lastModified = -1;
  136. if (coData->lastModifiedLen) {
  137. lastModified = parseIso8601Time(coData->lastModified);
  138. }
  139. *(coData->lastModifiedReturn) = lastModified;
  140. }
  141. (*(coData->responseCompleteCallback))
  142. (requestStatus, s3ErrorDetails, coData->callbackData);
  143. simplexml_deinitialize(&(coData->simpleXml));
  144. free(coData);
  145. }
  146. void S3_copy_object(const S3BucketContext *bucketContext, const char *key,
  147. const char *destinationBucket, const char *destinationKey,
  148. const S3PutProperties *putProperties,
  149. int64_t *lastModifiedReturn, int eTagReturnSize,
  150. char *eTagReturn, S3RequestContext *requestContext,
  151. int timeoutMs,
  152. const S3ResponseHandler *handler, void *callbackData)
  153. {
  154. /* Use the range copier with 0 length */
  155. S3_copy_object_range(bucketContext, key,
  156. destinationBucket, destinationKey,
  157. 0, NULL, // No multipart
  158. 0, 0, // No length => std. copy of < 5GB
  159. putProperties,
  160. lastModifiedReturn, eTagReturnSize,
  161. eTagReturn, requestContext,
  162. timeoutMs,
  163. handler, callbackData);
  164. }
  165. void S3_copy_object_range(const S3BucketContext *bucketContext, const char *key,
  166. const char *destinationBucket,
  167. const char *destinationKey, const int partNo,
  168. const char *uploadId, const unsigned long startOffset,
  169. const unsigned long count,
  170. const S3PutProperties *putProperties,
  171. int64_t *lastModifiedReturn, int eTagReturnSize,
  172. char *eTagReturn, S3RequestContext *requestContext,
  173. int timeoutMs,
  174. const S3ResponseHandler *handler, void *callbackData)
  175. {
  176. // Create the callback data
  177. CopyObjectData *data =
  178. (CopyObjectData *) malloc(sizeof(CopyObjectData));
  179. if (!data) {
  180. (*(handler->completeCallback))(S3StatusOutOfMemory, 0, callbackData);
  181. return;
  182. }
  183. simplexml_initialize(&(data->simpleXml), &copyObjectXmlCallback, data);
  184. data->responsePropertiesCallback = handler->propertiesCallback;
  185. data->responseCompleteCallback = handler->completeCallback;
  186. data->callbackData = callbackData;
  187. data->lastModifiedReturn = lastModifiedReturn;
  188. data->eTagReturnSize = eTagReturnSize;
  189. data->eTagReturn = eTagReturn;
  190. if (data->eTagReturnSize && data->eTagReturn) {
  191. data->eTagReturn[0] = 0;
  192. }
  193. data->eTagReturnLen = 0;
  194. string_buffer_initialize(data->lastModified);
  195. // If there's a sequence ID > 0 then add a subResource, OTW pass in NULL
  196. char queryParams[512];
  197. char *qp = NULL;
  198. if (partNo > 0) {
  199. snprintf(queryParams, 512, "partNumber=%d&uploadId=%s", partNo, uploadId);
  200. qp = queryParams;
  201. }
  202. // Set up the RequestParams
  203. RequestParams params =
  204. {
  205. HttpRequestTypeCOPY, // httpRequestType
  206. { bucketContext->hostName, // hostName
  207. destinationBucket ? destinationBucket :
  208. bucketContext->bucketName, // bucketName
  209. bucketContext->protocol, // protocol
  210. bucketContext->uriStyle, // uriStyle
  211. bucketContext->accessKeyId, // accessKeyId
  212. bucketContext->secretAccessKey, // secretAccessKey
  213. bucketContext->securityToken, // securityToken
  214. bucketContext->authRegion }, // authRegion
  215. destinationKey ? destinationKey : key, // key
  216. qp, // queryParams
  217. 0, // subResource
  218. bucketContext->bucketName, // copySourceBucketName
  219. key, // copySourceKey
  220. 0, // getConditions
  221. startOffset, // startByte
  222. count, // byteCount
  223. putProperties, // putProperties
  224. &copyObjectPropertiesCallback, // propertiesCallback
  225. 0, // toS3Callback
  226. 0, // toS3CallbackTotalSize
  227. &copyObjectDataCallback, // fromS3Callback
  228. &copyObjectCompleteCallback, // completeCallback
  229. data, // callbackData
  230. timeoutMs // timeoutMs
  231. };
  232. // Perform the request
  233. request_perform(&params, requestContext);
  234. }
  235. // get object ----------------------------------------------------------------
  236. void S3_get_object(const S3BucketContext *bucketContext, const char *key,
  237. const S3GetConditions *getConditions,
  238. uint64_t startByte, uint64_t byteCount,
  239. S3RequestContext *requestContext,
  240. int timeoutMs,
  241. const S3GetObjectHandler *handler, void *callbackData)
  242. {
  243. // Set up the RequestParams
  244. RequestParams params =
  245. {
  246. HttpRequestTypeGET, // httpRequestType
  247. { bucketContext->hostName, // hostName
  248. bucketContext->bucketName, // bucketName
  249. bucketContext->protocol, // protocol
  250. bucketContext->uriStyle, // uriStyle
  251. bucketContext->accessKeyId, // accessKeyId
  252. bucketContext->secretAccessKey, // secretAccessKey
  253. bucketContext->securityToken, // securityToken
  254. bucketContext->authRegion }, // authRegion
  255. key, // key
  256. 0, // queryParams
  257. 0, // subResource
  258. 0, // copySourceBucketName
  259. 0, // copySourceKey
  260. getConditions, // getConditions
  261. static_cast<size_t>(startByte), // startByte (WINSCP cast)
  262. static_cast<size_t>(byteCount), // byteCount (WINSCP cast)
  263. 0, // putProperties
  264. handler->responseHandler.propertiesCallback, // propertiesCallback
  265. 0, // toS3Callback
  266. 0, // toS3CallbackTotalSize
  267. handler->getObjectDataCallback, // fromS3Callback
  268. handler->responseHandler.completeCallback, // completeCallback
  269. callbackData, // callbackData
  270. timeoutMs // timeoutMs
  271. };
  272. // Perform the request
  273. request_perform(&params, requestContext);
  274. }
  275. // head object ---------------------------------------------------------------
  276. void S3_head_object(const S3BucketContext *bucketContext, const char *key,
  277. S3RequestContext *requestContext,
  278. int timeoutMs,
  279. const S3ResponseHandler *handler, void *callbackData)
  280. {
  281. // Set up the RequestParams
  282. RequestParams params =
  283. {
  284. HttpRequestTypeHEAD, // httpRequestType
  285. { bucketContext->hostName, // hostName
  286. bucketContext->bucketName, // bucketName
  287. bucketContext->protocol, // protocol
  288. bucketContext->uriStyle, // uriStyle
  289. bucketContext->accessKeyId, // accessKeyId
  290. bucketContext->secretAccessKey, // secretAccessKey
  291. bucketContext->securityToken, // securityToken
  292. bucketContext->authRegion }, // authRegion
  293. key, // key
  294. 0, // queryParams
  295. 0, // subResource
  296. 0, // copySourceBucketName
  297. 0, // copySourceKey
  298. 0, // getConditions
  299. 0, // startByte
  300. 0, // byteCount
  301. 0, // putProperties
  302. handler->propertiesCallback, // propertiesCallback
  303. 0, // toS3Callback
  304. 0, // toS3CallbackTotalSize
  305. 0, // fromS3Callback
  306. handler->completeCallback, // completeCallback
  307. callbackData, // callbackData
  308. timeoutMs // timeoutMs
  309. };
  310. // Perform the request
  311. request_perform(&params, requestContext);
  312. }
  313. // delete object --------------------------------------------------------------
  314. void S3_delete_object(const S3BucketContext *bucketContext, const char *key,
  315. S3RequestContext *requestContext,
  316. int timeoutMs,
  317. const S3ResponseHandler *handler, void *callbackData)
  318. {
  319. // Set up the RequestParams
  320. RequestParams params =
  321. {
  322. HttpRequestTypeDELETE, // httpRequestType
  323. { bucketContext->hostName, // hostName
  324. bucketContext->bucketName, // bucketName
  325. bucketContext->protocol, // protocol
  326. bucketContext->uriStyle, // uriStyle
  327. bucketContext->accessKeyId, // accessKeyId
  328. bucketContext->secretAccessKey, // secretAccessKey
  329. bucketContext->securityToken, // securityToken
  330. bucketContext->authRegion }, // authRegion
  331. key, // key
  332. 0, // queryParams
  333. 0, // subResource
  334. 0, // copySourceBucketName
  335. 0, // copySourceKey
  336. 0, // getConditions
  337. 0, // startByte
  338. 0, // byteCount
  339. 0, // putProperties
  340. handler->propertiesCallback, // propertiesCallback
  341. 0, // toS3Callback
  342. 0, // toS3CallbackTotalSize
  343. 0, // fromS3Callback
  344. handler->completeCallback, // completeCallback
  345. callbackData, // callbackData
  346. timeoutMs // timeoutMs
  347. };
  348. // Perform the request
  349. request_perform(&params, requestContext);
  350. }