PageRenderTime 38ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/vendors/aws-sdk/services/s3.class.php

http://github.com/joebeeson/amazon
PHP | 3637 lines | 1508 code | 394 blank | 1735 comment | 241 complexity | c27938cdc812a42fe8018ad9cde9286e MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /*
  3. * Copyright 2010 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License").
  6. * You may not use this file except in compliance with the License.
  7. * A copy of the License is located at
  8. *
  9. * http://aws.amazon.com/apache2.0
  10. *
  11. * or in the "license" file accompanying this file. This file is distributed
  12. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  13. * express or implied. See the License for the specific language governing
  14. * permissions and limitations under the License.
  15. */
  16. /**
  17. * File: AmazonS3
  18. * Amazon S3 is a web service that enables you to store data in the cloud. You can then download the data
  19. * or use the data with other AWS services, such as Amazon Elastic Cloud Computer (EC2).
  20. *
  21. * Amazon Simple Storage Service (Amazon S3) is storage for the Internet. You can use Amazon S3 to store
  22. * and retrieve any amount of data at any time, from anywhere on the web. You can accomplish these tasks
  23. * using the AWS Management Console, which is a simple and intuitive web interface.
  24. *
  25. * To get the most out of Amazon S3, you need to understand a few simple concepts. Amazon S3 stores data
  26. * as objects in buckets. An object is comprised of a file and optionally any metadata that describes
  27. * that file.
  28. *
  29. * To store an object in Amazon S3, you upload the file you want to store to a bucket. When you upload a
  30. * file, you can set permissions on the object as well as any metadata.
  31. *
  32. * Buckets are the containers for objects. You can have one or more buckets. For each bucket, you can control
  33. * access to the bucket (who can create, delete, and list objects in the bucket), view access logs for the
  34. * bucket and its objects, and choose the geographical region where Amazon S3 will store the bucket and its
  35. * contents.
  36. *
  37. * Visit <http://aws.amazon.com/s3/> for more information.
  38. *
  39. * Version:
  40. * 2010.12.02
  41. *
  42. * License and Copyright:
  43. * See the included NOTICE.md file for more information.
  44. *
  45. * See Also:
  46. * [Amazon Simple Storage Service](http://aws.amazon.com/s3/)
  47. * [Amazon Simple Storage Service documentation](http://aws.amazon.com/documentation/s3/)
  48. */
  49. /*%******************************************************************************************%*/
  50. // EXCEPTIONS
  51. /**
  52. * Exception: S3_Exception
  53. * Default S3 Exception.
  54. */
  55. class S3_Exception extends Exception {}
  56. /*%******************************************************************************************%*/
  57. // MAIN CLASS
  58. /**
  59. * Class: AmazonS3
  60. * Container for all Amazon S3-related methods. Inherits additional methods from CFRuntime.
  61. */
  62. class AmazonS3 extends CFRuntime
  63. {
  64. /*%******************************************************************************************%*/
  65. // CLASS CONSTANTS
  66. /**
  67. * Constant: DEFAULT_URL
  68. * The default endpoint.
  69. */
  70. const DEFAULT_URL = 's3.amazonaws.com';
  71. /**
  72. * Constant: REGION_US_E1
  73. * Specify the queue URL for the US-East (Northern Virginia) Region.
  74. */
  75. const REGION_US_E1 = '';
  76. /**
  77. * Constant: REGION_US_W1
  78. * Specify the queue URL for the US-West (Northern California) Region.
  79. */
  80. const REGION_US_W1 = 'us-west-1';
  81. /**
  82. * Constant: REGION_EU_W1
  83. * Specify the queue URL for the EU (Ireland) Region.
  84. */
  85. const REGION_EU_W1 = 'EU';
  86. /**
  87. * Constant: REGION_APAC_SE1
  88. * Specify the queue URL for the Asia Pacific (Singapore) Region.
  89. */
  90. const REGION_APAC_SE1 = 'ap-southeast-1';
  91. /**
  92. * Constant: ACL_PRIVATE
  93. * ACL: Owner-only read/write.
  94. */
  95. const ACL_PRIVATE = 'private';
  96. /**
  97. * Constant: ACL_PUBLIC
  98. * ACL: Owner read/write, public read.
  99. */
  100. const ACL_PUBLIC = 'public-read';
  101. /**
  102. * Constant: ACL_OPEN
  103. * ACL: Public read/write.
  104. */
  105. const ACL_OPEN = 'public-read-write';
  106. /**
  107. * Constant: ACL_AUTH_READ
  108. * ACL: Owner read/write, authenticated read.
  109. */
  110. const ACL_AUTH_READ = 'authenticated-read';
  111. /**
  112. * Constant: ACL_OWNER_READ
  113. * ACL: Bucket owner read.
  114. */
  115. const ACL_OWNER_READ = 'bucket-owner-read';
  116. /**
  117. * Constant: ACL_OWNER_FULL_CONTROL
  118. * ACL: Bucket owner full control.
  119. */
  120. const ACL_OWNER_FULL_CONTROL = 'bucket-owner-full-control';
  121. /**
  122. * Constant: GRANT_READ
  123. * When applied to a bucket, grants permission to list the bucket. When applied to an object, this
  124. * grants permission to read the object data and/or metadata.
  125. */
  126. const GRANT_READ = 'READ';
  127. /**
  128. * Constant: GRANT_WRITE
  129. * When applied to a bucket, grants permission to create, overwrite, and delete any object in the
  130. * bucket. This permission is not supported for objects.
  131. */
  132. const GRANT_WRITE = 'WRITE';
  133. /**
  134. * Constant: GRANT_READ_ACP
  135. * Grants permission to read the ACL for the applicable bucket or object. The owner of a bucket or
  136. * object always has this permission implicitly.
  137. */
  138. const GRANT_READ_ACP = 'READ_ACP';
  139. /**
  140. * Constant: GRANT_WRITE_ACP
  141. * Gives permission to overwrite the ACP for the applicable bucket or object. The owner of a bucket
  142. * or object always has this permission implicitly. Granting this permission is equivalent to granting
  143. * FULL_CONTROL because the grant recipient can make any changes to the ACP.
  144. */
  145. const GRANT_WRITE_ACP = 'WRITE_ACP';
  146. /**
  147. * Constant: GRANT_FULL_CONTROL
  148. * Provides READ, WRITE, READ_ACP, and WRITE_ACP permissions. It does not convey additional rights and
  149. * is provided only for convenience.
  150. */
  151. const GRANT_FULL_CONTROL = 'FULL_CONTROL';
  152. /**
  153. * Constant: USERS_AUTH
  154. * The "AuthenticatedUsers" group for access control policies.
  155. */
  156. const USERS_AUTH = 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers';
  157. /**
  158. * Constant: USERS_ALL
  159. * The "AllUsers" group for access control policies.
  160. */
  161. const USERS_ALL = 'http://acs.amazonaws.com/groups/global/AllUsers';
  162. /**
  163. * Constant: USERS_LOGGING
  164. * The "LogDelivery" group for access control policies.
  165. */
  166. const USERS_LOGGING = 'http://acs.amazonaws.com/groups/s3/LogDelivery';
  167. /**
  168. * Constant: PCRE_ALL
  169. * PCRE: Match all items
  170. */
  171. const PCRE_ALL = '/.*/i';
  172. /**
  173. * Constant: STORAGE_STANDARD
  174. * Standard storage redundancy.
  175. */
  176. const STORAGE_STANDARD = 'STANDARD';
  177. /**
  178. * Constant: STORAGE_REDUCED
  179. * Reduced storage redundancy.
  180. */
  181. const STORAGE_REDUCED = 'REDUCED_REDUNDANCY';
  182. /*%******************************************************************************************%*/
  183. // PROPERTIES
  184. /**
  185. * Property: request_url
  186. * The request URL.
  187. */
  188. public $request_url;
  189. /**
  190. * Property: vhost
  191. * The virtual host setting.
  192. */
  193. public $vhost;
  194. /**
  195. * Property: base_acp_xml
  196. * The base XML elements to use for access control policy methods.
  197. */
  198. public $base_acp_xml;
  199. /**
  200. * Property: base_logging_xml
  201. * The base XML elements to use for logging methods.
  202. */
  203. public $base_logging_xml;
  204. /**
  205. * Property: base_notification_xml
  206. * The base XML elements to use for notifications.
  207. */
  208. public $base_notification_xml;
  209. /**
  210. * Property: base_versioning_xml
  211. * The base XML elements to use for versioning.
  212. */
  213. public $base_versioning_xml;
  214. /**
  215. * Property: complete_mpu_xml
  216. * The base XML elements to use for completing a multipart upload.
  217. */
  218. public $complete_mpu_xml;
  219. /**
  220. * Property: path_style
  221. * The DNS vs. Path-style setting.
  222. */
  223. public $path_style = false;
  224. /*%******************************************************************************************%*/
  225. // CONSTRUCTOR
  226. /**
  227. * Method: __construct()
  228. * Constructs a new instance of <AmazonS3>.
  229. *
  230. * Access:
  231. * public
  232. *
  233. * Parameters:
  234. * $key - _string_ (Optional) Amazon API Key. If blank, the <AWS_KEY> constant is used.
  235. * $secret_key - _string_ (Optional) Amazon API Secret Key. If blank, the <AWS_SECRET_KEY> constant is used.
  236. *
  237. * Returns:
  238. * _boolean_ A value of `false` if no valid values are set, otherwise `true`.
  239. */
  240. public function __construct($key = null, $secret_key = null)
  241. {
  242. $this->vhost = null;
  243. $this->api_version = '2006-03-01';
  244. $this->hostname = self::DEFAULT_URL;
  245. $this->base_acp_xml = '<?xml version="1.0" encoding="UTF-8"?><AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/latest/"></AccessControlPolicy>';
  246. $this->base_location_constraint = '<?xml version="1.0" encoding="UTF-8"?><CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><LocationConstraint></LocationConstraint></CreateBucketConfiguration>';
  247. $this->base_logging_xml = '<?xml version="1.0" encoding="utf-8"?><BucketLoggingStatus xmlns="http://doc.s3.amazonaws.com/' . $this->api_version . '"></BucketLoggingStatus>';
  248. $this->base_notification_xml = '<?xml version="1.0" encoding="utf-8"?><NotificationConfiguration></NotificationConfiguration>';
  249. $this->base_versioning_xml = '<?xml version="1.0" encoding="utf-8"?><VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"></VersioningConfiguration>';
  250. $this->complete_mpu_xml = '<?xml version="1.0" encoding="utf-8"?><CompleteMultipartUpload></CompleteMultipartUpload>';
  251. if (!$key && !defined('AWS_KEY'))
  252. {
  253. throw new S3_Exception('No account key was passed into the constructor, nor was it set in the AWS_KEY constant.');
  254. }
  255. if (!$secret_key && !defined('AWS_SECRET_KEY'))
  256. {
  257. throw new S3_Exception('No account secret was passed into the constructor, nor was it set in the AWS_SECRET_KEY constant.');
  258. }
  259. return parent::__construct($key, $secret_key);
  260. }
  261. /*%******************************************************************************************%*/
  262. // AUTHENTICATION
  263. /**
  264. * Method: authenticate()
  265. * Authenticates a connection to Amazon S3. Do not use directly unless implementing custom methods for
  266. * this class.
  267. *
  268. * Access:
  269. * public
  270. *
  271. * Parameters:
  272. * $bucket - _string_ (Required) The name of the bucket to use.
  273. * $opt - _array_ (Optional) An associative array of parameters for authenticating. See the individual methods for allowed keys.
  274. * $location - _string_ (Do Not Use) Used internally by this function on occasions when Amazon S3 returns a redirect code and it needs to call itself recursively.
  275. * $redirects - _integer_ (Do Not Use) Used internally by this function on occasions when Amazon S3 returns a redirect code and it needs to call itself recursively.
  276. *
  277. * Returns:
  278. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  279. *
  280. * See Also:
  281. * [REST authentication](http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html)
  282. */
  283. public function authenticate($bucket, $opt = null, $location = null, $redirects = 0, $nothing = null)
  284. {
  285. /*
  286. * Overriding or extending this class? You can pass the following "magic" keys into $opt.
  287. *
  288. * ## verb, resource, sub_resource and query_string ##
  289. * <verb> /<resource>?<sub_resource>&<query_string>
  290. * GET /filename.txt?versions&prefix=abc&max-items=1
  291. *
  292. * ## versionId, uploadId, partNumber ##
  293. * These don't follow the same rules as above, in that the they needs to be signed, while
  294. * other query_string values do not.
  295. *
  296. * ## curlopts ##
  297. * These values get passed directly to the cURL methods in RequestCore.
  298. *
  299. * ## fileUpload, fileDownload, seekTo, length ##
  300. * These are slightly modified and then passed to the cURL methods in RequestCore.
  301. *
  302. * ## headers ##
  303. * $opt['headers'] is an array, whose keys are HTTP headers to be sent.
  304. *
  305. * ## body ##
  306. * This is the request body that is sent to the server via PUT/POST.
  307. *
  308. * ## preauth ##
  309. * This is a hook that tells authenticate() to generate a pre-authenticated URL.
  310. *
  311. * ## returnCurlHandle ##
  312. * Tells authenticate() to return the cURL handle for the request instead of executing it.
  313. */
  314. /**
  315. * @todo: Handle duplicate headers with different values.
  316. */
  317. // Validate the S3 bucket name
  318. if (!$this->validate_bucketname_support($bucket))
  319. {
  320. throw new S3_Exception('S3 does not support "' . $bucket . '" as a valid bucket name. Review "Bucket Restrictions and Limitations" in the S3 Developer Guide for more information.');
  321. }
  322. // Die if $opt isn't set.
  323. if (!$opt) return false;
  324. $method_arguments = func_get_args();
  325. // Use the caching flow to determine if we need to do a round-trip to the server.
  326. if ($this->use_cache_flow)
  327. {
  328. // Generate an identifier specific to this particular set of arguments.
  329. $cache_id = $this->key . '_' . get_class($this) . '_' . $bucket . '_' . sha1(serialize($method_arguments));
  330. // Instantiate the appropriate caching object.
  331. $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
  332. if ($this->delete_cache)
  333. {
  334. $this->use_cache_flow = false;
  335. $this->delete_cache = false;
  336. return $this->cache_object->delete();
  337. }
  338. // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
  339. $data = $this->cache_object->response_manager(array($this, 'cache_callback'), $method_arguments);
  340. // Parse the XML body
  341. $data = $this->parse_callback($data);
  342. // End!
  343. return $data;
  344. }
  345. // If we haven't already set a resource prefix...
  346. if (!$this->resource_prefix || $this->path_style)
  347. {
  348. // And if the bucket name isn't DNS-valid...
  349. if (!$this->validate_bucketname_create($bucket) || $this->path_style)
  350. {
  351. // Fall back to the older path-style URI
  352. $this->set_resource_prefix('/' . $bucket);
  353. }
  354. }
  355. // Determine hostname
  356. $scheme = $this->use_ssl ? 'https://' : 'http://';
  357. if ($this->resource_prefix || $this->path_style) // Use bucket-in-path method.
  358. {
  359. $hostname = $this->hostname . $this->resource_prefix . (($bucket === '' || $this->resource_prefix === '/' . $bucket) ? '' : ('/' . $bucket));
  360. }
  361. else
  362. {
  363. $hostname = $this->vhost ? $this->vhost : (($bucket === '') ? $this->hostname : ($bucket . '.') . $this->hostname);
  364. }
  365. // Get the UTC timestamp in RFC 2616 format
  366. $date = gmdate($this->util->konst($this->util, 'DATE_FORMAT_RFC2616'), (time() + (integer) $this->adjust_offset));
  367. // Storage for request parameters.
  368. $resource = '';
  369. $sub_resource = '';
  370. $query_string_params = array();
  371. $signable_query_string_params = array();
  372. $string_to_sign = '';
  373. $headers = array(
  374. 'Content-MD5' => '',
  375. 'Content-Type' => 'application/x-www-form-urlencoded',
  376. 'Date' => $date
  377. );
  378. /*%******************************************************************************************%*/
  379. // Handle specific resources
  380. if (isset($opt['resource']))
  381. {
  382. $resource .= $opt['resource'];
  383. }
  384. // Merge query string values
  385. if (isset($opt['query_string']))
  386. {
  387. $query_string_params = array_merge($query_string_params, $opt['query_string']);
  388. }
  389. $query_string = $this->util->to_query_string($query_string_params);
  390. // Merge the signable query string values. Must be alphabetical.
  391. if (isset($opt['partNumber']))
  392. {
  393. $signable_query_string_params['partNumber'] = rawurlencode($opt['partNumber']);
  394. }
  395. if (isset($opt['uploadId']))
  396. {
  397. $signable_query_string_params['uploadId'] = rawurlencode($opt['uploadId']);
  398. }
  399. if (isset($opt['versionId']))
  400. {
  401. $signable_query_string_params['versionId'] = rawurlencode($opt['versionId']);
  402. }
  403. // ksort($signable_query_string_params);
  404. $signable_query_string = $this->util->to_query_string($signable_query_string_params);
  405. // Merge the HTTP headers
  406. if (isset($opt['headers']))
  407. {
  408. $headers = array_merge($headers, $opt['headers']);
  409. }
  410. // Compile the URI to request
  411. $conjunction = '?';
  412. $signable_resource = '/' . rawurlencode($resource);
  413. $non_signable_resource = '';
  414. if (isset($opt['sub_resource']))
  415. {
  416. $signable_resource .= $conjunction . rawurlencode($opt['sub_resource']);
  417. $conjunction = '&';
  418. }
  419. if ($signable_query_string !== '')
  420. {
  421. $signable_resource .= $conjunction . $signable_query_string;
  422. $conjunction = '&';
  423. }
  424. if ($query_string !== '')
  425. {
  426. $non_signable_resource .= $conjunction . $query_string;
  427. $conjunction = '&';
  428. }
  429. $this->request_url = $scheme . $hostname . $signable_resource . $non_signable_resource;
  430. // Instantiate the request class
  431. $request = new $this->request_class($this->request_url, $this->proxy);
  432. // Update RequestCore settings
  433. $request->request_class = $this->request_class;
  434. $request->response_class = $this->response_class;
  435. // Streaming uploads
  436. if (isset($opt['fileUpload']))
  437. {
  438. if (is_resource($opt['fileUpload']))
  439. {
  440. $request->set_read_stream($opt['fileUpload'], isset($opt['length']) ? $opt['length'] : -1);
  441. if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
  442. {
  443. $headers['Content-Type'] = 'application/octet-stream';
  444. }
  445. }
  446. else
  447. {
  448. $request->set_read_file($opt['fileUpload']);
  449. // Attempt to guess the correct mime-type
  450. if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
  451. {
  452. $extension = explode('.', $opt['fileUpload']);
  453. $extension = array_pop($extension);
  454. $mime_type = CFMimeTypes::get_mimetype($extension);
  455. $headers['Content-Type'] = $mime_type;
  456. }
  457. }
  458. $headers['Content-Length'] = $request->read_stream_size;
  459. $curlopts[CURLOPT_INFILESIZE] = $headers['Content-Length'];
  460. $headers['Content-MD5'] = '';
  461. }
  462. // Streaming downloads
  463. if (isset($opt['fileDownload']))
  464. {
  465. if (is_resource($opt['fileDownload']))
  466. {
  467. $request->set_write_stream($opt['fileDownload']);
  468. }
  469. else
  470. {
  471. $request->set_write_file($opt['fileDownload']);
  472. }
  473. }
  474. $curlopts = array();
  475. // Set custom CURLOPT settings
  476. if (isset($opt['curlopts']))
  477. {
  478. $curlopts = $opt['curlopts'];
  479. unset($opt['curlopts']);
  480. }
  481. // Debug mode
  482. if ($this->debug_mode)
  483. {
  484. $curlopts[CURLOPT_VERBOSE] = true;
  485. }
  486. // Handle streaming file offsets
  487. if (isset($opt['seekTo']))
  488. {
  489. // Pass the seek position to RequestCore
  490. $request->set_seek_position((integer) $opt['seekTo']);
  491. $headers['Content-Length'] = (!is_resource($opt['fileUpload']) ? (filesize($opt['fileUpload']) - (integer) $opt['seekTo']) : -1);
  492. $curlopts[CURLOPT_INFILESIZE] = $headers['Content-Length'];
  493. }
  494. // Override the content length
  495. if (isset($opt['length']))
  496. {
  497. $headers['Content-Length'] = (integer) $opt['length'];
  498. $curlopts[CURLOPT_INFILESIZE] = $headers['Content-Length'];
  499. }
  500. // Set the curl options.
  501. if (count($curlopts))
  502. {
  503. $request->set_curlopts($curlopts);
  504. }
  505. // Do we have a verb?
  506. if (isset($opt['verb']))
  507. {
  508. $request->set_method($opt['verb']);
  509. $string_to_sign .= $opt['verb'] . "\n";
  510. }
  511. // Add headers and content when we have a body
  512. if (isset($opt['body']))
  513. {
  514. $request->set_body($opt['body']);
  515. $headers['Content-Length'] = strlen($opt['body']);
  516. if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
  517. {
  518. $headers['Content-Type'] = 'application/octet-stream';
  519. }
  520. if (!isset($opt['NoContentMD5']) || $opt['NoContentMD5'] !== true)
  521. {
  522. $headers['Content-MD5'] = $this->util->hex_to_base64(md5($opt['body']));
  523. }
  524. }
  525. // Handle query-string authentication
  526. if (isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
  527. {
  528. unset($headers['Date']);
  529. $headers['Content-Type'] = '';
  530. $headers['Expires'] = strtotime($opt['preauth']);
  531. }
  532. // Sort headers
  533. uksort($headers, 'strnatcasecmp');
  534. // Add headers to request and compute the string to sign
  535. foreach ($headers as $header_key => $header_value)
  536. {
  537. // Strip linebreaks from header values as they're illegal and can allow for security issues
  538. $header_value = str_replace(array("\r", "\n"), '', $header_value);
  539. // Add the header if it has a value
  540. if ($header_value !== '')
  541. {
  542. $request->add_header($header_key, $header_value);
  543. }
  544. // Generate the string to sign
  545. if (
  546. strtolower($header_key) === 'content-md5' ||
  547. strtolower($header_key) === 'content-type' ||
  548. strtolower($header_key) === 'date' ||
  549. (strtolower($header_key) === 'expires' && isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
  550. )
  551. {
  552. $string_to_sign .= $header_value . "\n";
  553. }
  554. elseif (substr(strtolower($header_key), 0, 6) === 'x-amz-')
  555. {
  556. $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
  557. }
  558. }
  559. // Add the signable resource location
  560. $string_to_sign .= ($this->resource_prefix ? $this->resource_prefix : '');
  561. $string_to_sign .= (($bucket === '' || $this->resource_prefix === '/' . $bucket) ? '' : ('/' . $bucket)) . $signable_resource;
  562. // Hash the AWS secret key and generate a signature for the request.
  563. $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->secret_key, true));
  564. $request->add_header('Authorization', 'AWS ' . $this->key . ':' . $signature);
  565. // If we're generating a URL, return certain data to the calling method.
  566. if (isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
  567. {
  568. return $this->request_url . (isset($opt['sub_resource']) ? '&' : '?') . 'AWSAccessKeyId=' . $this->key . '&Expires=' . $headers['Expires'] . '&Signature=' . rawurlencode($signature);
  569. }
  570. elseif (isset($opt['preauth']))
  571. {
  572. return $this->request_url;
  573. }
  574. /*%******************************************************************************************%*/
  575. // Manage the (newer) batch request API or the (older) returnCurlHandle setting.
  576. if ($this->use_batch_flow)
  577. {
  578. $handle = $request->prep_request();
  579. $this->batch_object->add($handle);
  580. $this->use_batch_flow = false;
  581. return $handle;
  582. }
  583. elseif (isset($opt['returnCurlHandle']) && $opt['returnCurlHandle'] === true)
  584. {
  585. return $request->prep_request();
  586. }
  587. // Send!
  588. $request->send_request();
  589. // Prepare the response
  590. $headers = $request->get_response_header();
  591. $headers['x-aws-request-url'] = $this->request_url;
  592. $headers['x-aws-redirects'] = $redirects;
  593. $headers['x-aws-stringtosign'] = $string_to_sign;
  594. $headers['x-aws-requestheaders'] = $request->request_headers;
  595. // Did we have a request body?
  596. if (isset($opt['body']))
  597. {
  598. $headers['x-aws-requestbody'] = $opt['body'];
  599. }
  600. $data = new $this->response_class($headers, $this->parse_callback($request->get_response_body()), $request->get_response_code());
  601. // Did Amazon tell us to redirect? Typically happens for multiple rapid requests EU datacenters.
  602. // @see: http://docs.amazonwebservices.com/AmazonS3/latest/Redirects.html
  603. if ((integer) $request->get_response_code() === 307) // Temporary redirect to new endpoint.
  604. {
  605. $data = $this->authenticate($bucket, $opt, $headers['location'], ++$redirects);
  606. }
  607. // Was it Amazon's fault the request failed? Retry the request until we reach $max_retries.
  608. elseif ((integer) $request->get_response_code() === 500 || (integer) $request->get_response_code() === 503)
  609. {
  610. if ($redirects <= $this->max_retries)
  611. {
  612. // Exponential backoff
  613. $delay = (integer) (pow(4, $redirects) * 100000);
  614. usleep($delay);
  615. $data = $this->authenticate($bucket, $opt, null, ++$redirects);
  616. }
  617. }
  618. // Return!
  619. return $data;
  620. }
  621. /**
  622. * Method: validate_bucketname_create()
  623. * Validates whether or not the specified Amazon S3 bucket name is valid for DNS-style access. This
  624. * method is leveraged by any method that creates buckets.
  625. *
  626. * Access:
  627. * public
  628. *
  629. * Parameters:
  630. * $bucket - _string_ (Required) The name of the bucket to validate.
  631. *
  632. * Returns:
  633. * _boolean_ Whether or not the specified Amazon S3 bucket name is valid for DNS-style access. A value of `true` means that the bucket name is valid. A value of `false` means that the bucket name is invalid.
  634. */
  635. public function validate_bucketname_create($bucket)
  636. {
  637. // list_buckets() uses this. Let it pass.
  638. if ($bucket === '') return true;
  639. if (
  640. ($bucket === null || $bucket === false) || // Must not be null or false
  641. preg_match('/[^(a-z0-9\-\.)]/', $bucket) || // Must be in the lowercase Roman alphabet, period or hyphen
  642. !preg_match('/^([a-z]|\d)/', $bucket) || // Must start with a number or letter
  643. !(strlen($bucket) >= 3 && strlen($bucket) <= 63) || // Must be between 3 and 63 characters long
  644. (strpos($bucket, '..') !== false) || // Bucket names cannot contain two, adjacent periods
  645. (strpos($bucket, '-.') !== false) || // Bucket names cannot contain dashes next to periods
  646. (strpos($bucket, '.-') !== false) || // Bucket names cannot contain dashes next to periods
  647. preg_match('/(-|\.)$/', $bucket) || // Bucket names should not end with a dash or period
  648. preg_match('/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/', $bucket) // Must not be formatted as an IP address
  649. ) return false;
  650. return true;
  651. }
  652. /**
  653. * Method: validate_bucketname_support()
  654. * Validates whether or not the specified Amazon S3 bucket name is valid for path-style access. This
  655. * method is leveraged by any method that reads from buckets.
  656. *
  657. * Access:
  658. * public
  659. *
  660. * Parameters:
  661. * $bucket - _string_ (Required) The name of the bucket to validate.
  662. *
  663. * Returns:
  664. * _boolean_ Whether or not the bucket name is valid. A value of `true` means that the bucket name is valid. A valuf of `false` means that the bucket name is invalid.
  665. */
  666. public function validate_bucketname_support($bucket)
  667. {
  668. // list_buckets() uses this. Let it pass.
  669. if ($bucket === '') return true;
  670. // Validate
  671. if (
  672. ($bucket === null || $bucket === false) || // Must not be null or false
  673. preg_match('/[^(a-z0-9_\-\.)]/i', $bucket) || // Must be in the Roman alphabet, period, hyphen or underscore
  674. !preg_match('/^([a-z]|\d)/i', $bucket) || // Must start with a number or letter
  675. !(strlen($bucket) >= 3 && strlen($bucket) <= 255) || // Must be between 3 and 255 characters long
  676. preg_match('/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/', $bucket) // Must not be formatted as an IP address
  677. ) return false;
  678. return true;
  679. }
  680. /**
  681. * Method: cache_callback()
  682. * The callback function that is executed when the cache doesn't exist or has expired. The response of
  683. * this method is cached. Accepts identical parameters as the <authenticate()> method. Never call this
  684. * method directly -- it is used internally by the caching system.
  685. *
  686. * Access:
  687. * public
  688. *
  689. * Parameters:
  690. * $bucket - _string_ (Required) The name of the bucket to use.
  691. * $opt - _array_ (Optional) An associative array of parameters for authenticating. See the individual methods for allowed keys.
  692. * $location - _string_ (Optional) Used internally by this method when Amazon S3 returns a redirect code and needs to call itself recursively.
  693. * $redirects - _integer_ (Optional) Used internally by this method when Amazon S3 returns a redirect code and needs to call itself recursively.
  694. *
  695. * Returns:
  696. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  697. */
  698. public function cache_callback($bucket, $opt = null, $location = null, $redirects = 0)
  699. {
  700. // Disable the cache flow since it's already been handled.
  701. $this->use_cache_flow = false;
  702. // Make the request
  703. $response = $this->authenticate($bucket, $opt, $location, $redirects);
  704. if (isset($response->body) && ($response->body instanceof SimpleXMLElement))
  705. {
  706. $response->body = $response->body->asXML();
  707. }
  708. return $response;
  709. }
  710. /*%******************************************************************************************%*/
  711. // SETTERS
  712. /**
  713. * Method: set_region()
  714. * Sets the region to use for subsequent Amazon S3 operations. This will also reset any prior use of
  715. * <enable_path_style()>.
  716. *
  717. * Access:
  718. * public
  719. *
  720. * Parameters:
  721. * $region - _string_ (Required) The region to use for subsequent Amazon S3 operations. [Allowed values: `AmazonS3::REGION_US_E1 `, `AmazonS3::REGION_US_W1`, `AmazonS3::REGION_EU_W1`, `AmazonS3::REGION_APAC_SE1`]
  722. *
  723. * Returns:
  724. * `$this` A reference to the current instance.
  725. */
  726. public function set_region($region)
  727. {
  728. switch ($region)
  729. {
  730. case self::REGION_US_W1: // Northern California
  731. case self::REGION_APAC_SE1: // Singapore
  732. $this->set_hostname('s3-' . $region . '.amazonaws.com');
  733. $this->enable_path_style(false);
  734. break;
  735. case self::REGION_EU_W1: // Ireland
  736. $this->set_hostname('s3-eu-west-1.amazonaws.com');
  737. $this->enable_path_style(); // Always use path-style access for EU endpoint.
  738. break;
  739. default:
  740. // REGION_US_E1 // Northern Virginia
  741. $this->set_hostname(self::DEFAULT_URL);
  742. $this->enable_path_style(false);
  743. break;
  744. }
  745. return $this;
  746. }
  747. /**
  748. * Method: set_vhost()
  749. * Sets the virtual host to use in place of the default `bucket.s3.amazonaws.com` domain.
  750. *
  751. * Access:
  752. * public
  753. *
  754. * Parameters:
  755. * $vhost - _string_ (Required) The virtual host to use in place of the default `bucket.s3.amazonaws.com` domain.
  756. *
  757. * Returns:
  758. * `$this` A reference to the current instance.
  759. *
  760. * See Also:
  761. * [Virtual Hosting of Buckets](http://docs.amazonwebservices.com/AmazonS3/latest/VirtualHosting.html)
  762. */
  763. public function set_vhost($vhost)
  764. {
  765. $this->vhost = $vhost;
  766. return $this;
  767. }
  768. /**
  769. * Method: enable_path_style()
  770. * Enables the use of the older path-style URI access for all requests.
  771. *
  772. * Access:
  773. * public
  774. *
  775. * Parameters:
  776. * $style - _string_ (Optional) Whether or not to enable path-style URI access for all requests. The default value is `true`.
  777. *
  778. * Returns:
  779. * `$this` A reference to the current instance.
  780. */
  781. public function enable_path_style($style = true)
  782. {
  783. $this->path_style = $style;
  784. return $this;
  785. }
  786. /*%******************************************************************************************%*/
  787. // BUCKET METHODS
  788. /**
  789. * Method: create_bucket()
  790. * Creates an Amazon S3 bucket.
  791. *
  792. * Every object stored in Amazon S3 is contained in a bucket. Buckets partition the namespace of
  793. * objects stored in Amazon S3 at the top level. in a bucket, any name can be used for objects.
  794. * However, bucket names must be unique across all of Amazon S3.
  795. *
  796. * Access:
  797. * public
  798. *
  799. * Parameters:
  800. * $bucket - _string_ (Required) The name of the bucket to create.
  801. * $region - _string_ (Required) The preferred geographical location for the bucket. [Allowed values: `AmazonS3::REGION_US_E1 `, `AmazonS3::REGION_US_W1`, `AmazonS3::REGION_EU_W1`, `AmazonS3::REGION_APAC_SE1`]
  802. * $acl - _string_ (Optional) The ACL settings for the specified bucket. [Allowed values: `AmazonS3::ACL_PRIVATE`, `AmazonS3::ACL_PUBLIC`, `AmazonS3::ACL_OPEN`, `AmazonS3::ACL_AUTH_READ`, `AmazonS3::ACL_OWNER_READ`, `AmazonS3::ACL_OWNER_FULL_CONTROL`]. The default value is <ACL_PRIVATE>.
  803. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  804. *
  805. * Keys for the $opt parameter:
  806. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  807. *
  808. * Returns:
  809. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  810. *
  811. * See Also:
  812. * * [Working with Amazon S3 Buckets](http://docs.amazonwebservices.com/AmazonS3/latest/UsingBucket.html)
  813. */
  814. public function create_bucket($bucket, $region, $acl = self::ACL_PRIVATE, $opt = null)
  815. {
  816. // If the bucket contains uppercase letters...
  817. if (preg_match('/[A-Z]/', $bucket))
  818. {
  819. // Throw a warning
  820. trigger_error('Since DNS-valid bucket names cannot contain uppercase characters, "' . $bucket . '" has been automatically converted to "' . strtolower($bucket) . '"', E_USER_WARNING);
  821. // Force the bucketname to lowercase
  822. $bucket = strtolower($bucket);
  823. }
  824. // Validate the S3 bucket name for creation
  825. if (!$this->validate_bucketname_create($bucket))
  826. {
  827. throw new S3_Exception('"' . $bucket . '" is not DNS-valid (i.e., <bucketname>.s3.amazonaws.com), and cannot be used as an S3 bucket name. Review "Bucket Restrictions and Limitations" in the S3 Developer Guide for more information.');
  828. }
  829. if (!$opt) $opt = array();
  830. $opt['verb'] = 'PUT';
  831. $opt['headers'] = array(
  832. 'Content-Type' => 'application/xml',
  833. 'x-amz-acl' => $acl
  834. );
  835. // Defaults
  836. $this->set_region($region);
  837. $xml = simplexml_load_string($this->base_location_constraint);
  838. switch ($region)
  839. {
  840. case self::REGION_US_W1: // Northern California
  841. case self::REGION_APAC_SE1: // Singapore
  842. $xml->LocationConstraint = $region;
  843. $opt['body'] = $xml->asXML();
  844. break;
  845. case self::REGION_EU_W1: // Ireland
  846. $this->enable_path_style(); // DNS-style doesn't seem to work for creation, only in EU. Switch over to path-style.
  847. $xml->LocationConstraint = $region;
  848. $opt['body'] = $xml->asXML();
  849. break;
  850. default: // REGION_US_E1 // Northern Virginia
  851. $opt['body'] = '';
  852. break;
  853. }
  854. $response = $this->authenticate($bucket, $opt);
  855. return $response;
  856. }
  857. /**
  858. * Method: get_bucket_region()
  859. * Gets the region in which the specified Amazon S3 bucket is located.
  860. *
  861. * Access:
  862. * public
  863. *
  864. * Parameters:
  865. * $bucket - _string_ (Required) The name of the bucket to use.
  866. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  867. *
  868. * Keys for the $opt parameter:
  869. * preauth - _integer_|_string_ (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with `strtotime()`.
  870. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  871. *
  872. * Returns:
  873. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  874. */
  875. public function get_bucket_region($bucket, $opt = null)
  876. {
  877. // Add this to our request
  878. if (!$opt) $opt = array();
  879. $opt['verb'] = 'GET';
  880. $opt['sub_resource'] = 'location';
  881. // Authenticate to S3
  882. $response = $this->authenticate($bucket, $opt);
  883. if ($response->isOK())
  884. {
  885. // Handle body
  886. $response->body = (string) $response->body;
  887. }
  888. return $response;
  889. }
  890. /**
  891. * Method: get_bucket_headers()
  892. * Gets the HTTP headers for the specified Amazon S3 bucket.
  893. *
  894. * Access:
  895. * public
  896. *
  897. * Parameters:
  898. * $bucket - _string_ (Required) The name of the bucket to use.
  899. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  900. *
  901. * Keys for the $opt parameter:
  902. * preauth - _integer_|_string_ (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with `strtotime()`.
  903. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  904. *
  905. * Returns:
  906. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  907. */
  908. public function get_bucket_headers($bucket, $opt = null)
  909. {
  910. if (!$opt) $opt = array();
  911. $opt['verb'] = 'HEAD';
  912. return $this->authenticate($bucket, $opt);
  913. }
  914. /**
  915. * Method: delete_bucket()
  916. * Deletes a bucket from an Amazon S3 account. A bucket must be empty before the bucket itself can be
  917. * deleted.
  918. *
  919. * Access:
  920. * public
  921. *
  922. * Parameters:
  923. * $bucket - _string_ (Required) The name of the bucket to use.
  924. * $force - _boolean_ (Optional) Whether to force-delete the bucket and all of its contents. The default value is `false`.
  925. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  926. *
  927. * Keys for the $opt parameter:
  928. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  929. *
  930. * Returns:
  931. * _mixed_ A <CFResponse> object if the bucket was deleted successfully. Returns _boolean_ `false` if otherwise.
  932. */
  933. public function delete_bucket($bucket, $force = false, $opt = null)
  934. {
  935. // Set default value
  936. $success = true;
  937. if ($force)
  938. {
  939. // Delete all of the items from the bucket.
  940. $success = $this->delete_all_object_versions($bucket);
  941. }
  942. // As long as we were successful...
  943. if ($success)
  944. {
  945. if (!$opt) $opt = array();
  946. $opt['verb'] = 'DELETE';
  947. return $this->authenticate($bucket, $opt);
  948. }
  949. return false;
  950. }
  951. /**
  952. * Method: list_buckets()
  953. * Gets a list of all buckets contained in the caller's Amazon S3 account.
  954. *
  955. * Access:
  956. * public
  957. *
  958. * Parameters:
  959. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  960. *
  961. * Keys for the $opt parameter:
  962. * preauth - _integer_|_string_ (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with `strtotime()`.
  963. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  964. *
  965. * Returns:
  966. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  967. */
  968. public function list_buckets($opt = null)
  969. {
  970. if (!$opt) $opt = array();
  971. $opt['verb'] = 'GET';
  972. return $this->authenticate('', $opt);
  973. }
  974. /**
  975. * Method: get_bucket_acl()
  976. * Gets the access control list (ACL) settings for the specified Amazon S3 bucket.
  977. *
  978. * Access:
  979. * public
  980. *
  981. * Parameters:
  982. * $bucket - _string_ (Required) The name of the bucket to use.
  983. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  984. *
  985. * Keys for the $opt parameter:
  986. * preauth - _integer_|_string_ (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with `strtotime()`.
  987. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  988. *
  989. * Returns:
  990. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  991. *
  992. * See Also:
  993. * [REST Access Control Policy](http://docs.amazonwebservices.com/AmazonS3/latest/RESTAccessPolicy.html)
  994. */
  995. public function get_bucket_acl($bucket, $opt = null)
  996. {
  997. // Add this to our request
  998. if (!$opt) $opt = array();
  999. $opt['verb'] = 'GET';
  1000. $opt['sub_resource'] = 'acl';
  1001. // Authenticate to S3
  1002. return $this->authenticate($bucket, $opt);
  1003. }
  1004. /**
  1005. * Method: set_bucket_acl()
  1006. * Sets the access control list (ACL) settings for the specified Amazon S3 bucket.
  1007. *
  1008. * Access:
  1009. * public
  1010. *
  1011. * Parameters:
  1012. * $bucket - _string_ (Required) The name of the bucket to use.
  1013. * $acl - _string_ (Optional) The ACL settings for the specified bucket. [Allowed values: `AmazonS3::ACL_PRIVATE`, `AmazonS3::ACL_PUBLIC`, `AmazonS3::ACL_OPEN`, `AmazonS3::ACL_AUTH_READ`, `AmazonS3::ACL_OWNER_READ`, `AmazonS3::ACL_OWNER_FULL_CONTROL`]. Alternatively, an array of associative arrays. Each associative array contains an `id` and a `permission` key. The default value is <ACL_PRIVATE>.
  1014. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1015. *
  1016. * Keys for the $opt parameter:
  1017. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1018. *
  1019. * Returns:
  1020. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1021. *
  1022. * See Also:
  1023. * [REST Access Control Policy](http://docs.amazonwebservices.com/AmazonS3/latest/RESTAccessPolicy.html)
  1024. */
  1025. public function set_bucket_acl($bucket, $acl = self::ACL_PRIVATE, $opt = null)
  1026. {
  1027. // Add this to our request
  1028. if (!$opt) $opt = array();
  1029. $opt['verb'] = 'PUT';
  1030. $opt['sub_resource'] = 'acl';
  1031. $opt['headers'] = array(
  1032. 'Content-Type' => 'application/xml'
  1033. );
  1034. // Make sure these are defined.
  1035. if (!defined('AWS_CANONICAL_ID') || !defined('AWS_CANONICAL_NAME'))
  1036. {
  1037. // Fetch the data live.
  1038. $canonical = $this->get_canonical_user_id();
  1039. define('AWS_CANONICAL_ID', $canonical['id']);
  1040. define('AWS_CANONICAL_NAME', $canonical['display_name']);
  1041. }
  1042. if (is_array($acl))
  1043. {
  1044. $opt['body'] = $this->generate_access_policy(AWS_CANONICAL_ID, AWS_CANONICAL_NAME, $acl);
  1045. }
  1046. else
  1047. {
  1048. $opt['headers']['x-amz-acl'] = $acl;
  1049. }
  1050. // Authenticate to S3
  1051. return $this->authenticate($bucket, $opt);
  1052. }
  1053. /*%******************************************************************************************%*/
  1054. // OBJECT METHODS
  1055. /**
  1056. * Method: create_object()
  1057. * Creates an Amazon S3 object. After an Amazon S3 bucket is created, objects can be stored in it.
  1058. *
  1059. * Each object can hold up to 5 GB of data. When an object is stored in Amazon S3, the data is streamed
  1060. * to multiple storage servers in multiple data centers. This ensures the data remains available in the
  1061. * event of internal network or hardware failure.
  1062. *
  1063. * Access:
  1064. * public
  1065. *
  1066. * Parameters:
  1067. * $bucket - _string_ (Required) The name of the bucket to use.
  1068. * $filename - _string_ (Required) The file name for the object.
  1069. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1070. *
  1071. * Keys for the $opt parameter:
  1072. * body - _string_ (Required; Conditional) The data to be stored in the object. Either this parameter or `fileUpload` must be specified.
  1073. * fileUpload - _string_|_resource_ (Required; Conditional) The file system path for the local file to upload, or an open file resource. Either this parameter or `body` is required.
  1074. * acl - _string_ (Optional) The ACL settings for the specified object. [Allowed values: `AmazonS3::ACL_PRIVATE`, `AmazonS3::ACL_PUBLIC`, `AmazonS3::ACL_OPEN`, `AmazonS3::ACL_AUTH_READ`, `AmazonS3::ACL_OWNER_READ`, `AmazonS3::ACL_OWNER_FULL_CONTROL`]. The default value is <ACL_PRIVATE>.
  1075. * contentType - _string_ (Optional) The type of content that is being sent in the body. If a file is being uploaded via `fileUpload` as a file system path, it will attempt to determine the correct mime-type based on the file extension. The default value is `application/octet-stream`.
  1076. * headers - _array_ (Optional) The standard HTTP headers to send along in the request.
  1077. * meta - _array_ (Optional) An associative array of key-value pairs. Represented by `x-amz-meta-:` Any header starting with this prefix is considered user metadata. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.
  1078. * storage - _string_ (Optional) Whether to use Standard or Reduced Redundancy storage. [Allowed values: `AmazonS3::STORAGE_STANDARD`, `AmazonS3::STORAGE_REDUCED`]. The default value is <STORAGE_STANDARD>.
  1079. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1080. *
  1081. * Returns:
  1082. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1083. *
  1084. * See Also:
  1085. * [REST Access Control Policy](http://docs.amazonwebservices.com/AmazonS3/latest/RESTAccessPolicy.html)
  1086. */
  1087. public function create_object($bucket, $filename, $opt = null)
  1088. {
  1089. if (!$opt) $opt = array();
  1090. // Add this to our request
  1091. $opt['verb'] = 'PUT';
  1092. $opt['resource'] = $filename;
  1093. // Handle content type. Can also be passed as an HTTP header.
  1094. if (isset($opt['contentType']))
  1095. {
  1096. $opt['headers']['Content-Type'] = $opt['contentType'];
  1097. unset($opt['contentType']);
  1098. }
  1099. // Handle Access Control Lists. Can also be passed as an HTTP header.
  1100. if (isset($opt['acl']))
  1101. {
  1102. $opt['headers']['x-amz-acl'] = $opt['acl'];
  1103. unset($opt['acl']);
  1104. }
  1105. // Handle storage settings. Can also be passed as an HTTP header.
  1106. if (isset($opt['storage']))
  1107. {
  1108. $opt['headers']['x-amz-storage-class'] = $opt['storage'];
  1109. unset($opt['storage']);
  1110. }
  1111. // Handle meta tags. Can also be passed as an HTTP header.
  1112. if (isset($opt['meta']))
  1113. {
  1114. foreach ($opt['meta'] as $meta_key => $meta_value)
  1115. {
  1116. // e.g., `My Meta Header` is converted to `x-amz-meta-my-meta-header`.
  1117. $opt['headers']['x-amz-meta-' . strtolower(str_replace(' ', '-', $meta_key))] = $meta_value;
  1118. }
  1119. unset($opt['meta']);
  1120. }
  1121. // Authenticate to S3
  1122. return $this->authenticate($bucket, $opt);
  1123. }
  1124. /**
  1125. * Method: get_object()
  1126. * Gets the contents of an Amazon S3 object in the specified bucket.
  1127. *
  1128. * Access:
  1129. * public
  1130. *
  1131. * Parameters:
  1132. * $bucket - _string_ (Required) The name of the bucket to use.
  1133. * $filename - _string_ (Required) The file name for the object.
  1134. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1135. *
  1136. * Keys for the $opt parameter:
  1137. * etag - _string_ (Optional) The `ETag` header passed in from a previous request. If specified, request `lastmodified` option must be specified as well. Will trigger a `304 Not Modified` status code if the file hasn't changed.
  1138. * fileDownload - _string_|_resource_ (Optional) The file system location to download the file to, or an open file resource. Must be a server-writable location.
  1139. * headers - _array_ (Optional) Standard HTTP headers to send along in the request.
  1140. * lastmodified - _string_ (Optional) The `LastModified` header passed in from a previous request. If specified, request `etag` option must be specified as well. Will trigger a `304 Not Modified` status code if the file hasn't changed.
  1141. * preauth - _integer_|_string_ (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with `strtotime()`.
  1142. * range - _string_ (Optional) The range of bytes to fetch from the object. Specify this parameter when downloading partial bits or completing incomplete object downloads. The specified range must be notated with a hyphen (e.g., 0-10485759). Defaults to the byte range of the complete Amazon S3 object.
  1143. * versionId - _string_ (Optional) The version of the object to retrieve. Version IDs are returned in the `x-amz-version-id` header of any previous object-related request.
  1144. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1145. *
  1146. * Returns:
  1147. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1148. */
  1149. public function get_object($bucket, $filename, $opt = null)
  1150. {
  1151. if (!$opt) $opt = array();
  1152. // Add this to our request
  1153. $opt['verb'] = 'GET';
  1154. $opt['resource'] = $filename;
  1155. if (!isset($opt['headers']) || !is_array($opt['headers']))
  1156. {
  1157. $opt['headers'] = array();
  1158. }
  1159. // Are we checking for changes?
  1160. if (isset($opt['lastmodified']) && isset($opt['etag']))
  1161. {
  1162. $opt['headers']['If-Modified-Since'] = $opt['lastmodified'];
  1163. $opt['headers']['If-None-Match'] = $opt['etag'];
  1164. }
  1165. // Partial content range
  1166. if (isset($opt['range']))
  1167. {
  1168. $opt['headers']['Range'] = 'bytes=' . $opt['range'];
  1169. }
  1170. // Authenticate to S3
  1171. return $this->authenticate($bucket, $opt);
  1172. }
  1173. /**
  1174. * Method: get_object_headers()
  1175. * Gets the HTTP headers for the specified Amazon S3 object.
  1176. *
  1177. * Access:
  1178. * public
  1179. *
  1180. * Parameters:
  1181. * $bucket - _string_ (Required) The name of the bucket to use.
  1182. * $filename - _string_ (Required) The file name for the object.
  1183. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1184. *
  1185. * Keys for the $opt parameter:
  1186. * versionId - _string_ (Optional) The version of the object to retrieve. Version IDs are returned in the `x-amz-version-id` header of any previous object-related request.
  1187. * preauth - _integer_|_string_ (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with `strtotime()`.
  1188. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1189. *
  1190. * Returns:
  1191. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1192. */
  1193. public function get_object_headers($bucket, $filename, $opt = null)
  1194. {
  1195. // Add this to our request
  1196. if (!$opt) $opt = array();
  1197. $opt['verb'] = 'HEAD';
  1198. $opt['resource'] = $filename;
  1199. // Authenticate to S3
  1200. return $this->authenticate($bucket, $opt);
  1201. }
  1202. /**
  1203. * Method: delete_object()
  1204. * Deletes an Amazon S3 object from the specified bucket.
  1205. *
  1206. * Access:
  1207. * public
  1208. *
  1209. * Parameters:
  1210. * $bucket - _string_ (Required) The name of the bucket to use.
  1211. * $filename - _string_ (Required) The file name for the object.
  1212. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1213. *
  1214. * Keys for the $opt parameter:
  1215. * versionId - _string_ (Optional) The version of the object to delete. Version IDs are returned in the `x-amz-version-id` header of any previous object-related request.
  1216. * MFASerial - _string_ (Optional) The serial number on the back of the Gemalto device. `MFASerial` and `MFAToken` must both be set for MFA to work.
  1217. * MFAToken - _string_ (Optional) The current token displayed on the Gemalto device. `MFASerial` and `MFAToken` must both be set for MFA to work.
  1218. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1219. *
  1220. * Returns:
  1221. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1222. *
  1223. * See Also:
  1224. * * [Multi-Factor Authentication](http://aws.amazon.com/mfa/)
  1225. */
  1226. public function delete_object($bucket, $filename, $opt = null)
  1227. {
  1228. // Add this to our request
  1229. if (!$opt) $opt = array();
  1230. $opt['verb'] = 'DELETE';
  1231. $opt['resource'] = $filename;
  1232. // Enable MFA delete?
  1233. if (isset($opt['MFASerial']) && isset($opt['MFAToken']))
  1234. {
  1235. $opt['headers'] = array(
  1236. 'x-amz-mfa' => ($opt['MFASerial'] . ' ' . $opt['MFAToken'])
  1237. );
  1238. }
  1239. // Authenticate to S3
  1240. return $this->authenticate($bucket, $opt);
  1241. }
  1242. /**
  1243. * Method: list_objects()
  1244. * Gets a list of all Amazon S3 objects in the specified bucket.
  1245. *
  1246. * Access:
  1247. * public
  1248. *
  1249. * Parameters:
  1250. * $bucket - _string_ (Required) The name of the bucket to use.
  1251. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1252. *
  1253. * Keys for the $opt parameter:
  1254. * delimiter - _string_ (Optional) Keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection.
  1255. * marker - _string_ (Optional) Restricts the response to contain results that only occur alphabetically after the value of the marker.
  1256. * max-keys - _string_ (Optional) The maximum number of results returned by the method call. The returned list will contain no more results than the specified value, but may return less.
  1257. * preauth - _integer_|_string_ (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with `strtotime()`.
  1258. * prefix - _string_ (Optional) Restricts the response to contain results that begin only with the specified prefix.
  1259. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1260. *
  1261. * Returns:
  1262. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1263. */
  1264. public function list_objects($bucket, $opt = null)
  1265. {
  1266. if (!$opt) $opt = array();
  1267. // Add this to our request
  1268. $opt['verb'] = 'GET';
  1269. foreach (array('delimiter', 'marker', 'max-keys', 'prefix') as $param)
  1270. {
  1271. if (isset($opt[$param]))
  1272. {
  1273. $opt['query_string'][$param] = $opt[$param];
  1274. unset($opt[$param]);
  1275. }
  1276. }
  1277. // Authenticate to S3
  1278. return $this->authenticate($bucket, $opt);
  1279. }
  1280. /**
  1281. * Method: copy_object()
  1282. * Copies an Amazon S3 object to a new location, whether in the same Amazon S3 region, bucket, or
  1283. * otherwise.
  1284. *
  1285. * Access:
  1286. * public
  1287. *
  1288. * Parameters:
  1289. * $source - _ComplexType_ (Required) The bucket and file name to copy from. A required ComplexType is a set of key-value pairs which must be set by passing an associative array with certain entries as keys. See below for a list.
  1290. * $dest - _ComplexType_ (Required) The bucket and file name to copy to. A required ComplexType is a set of key-value pairs which must be set by passing an associative array with certain entries as keys. See below for a list.
  1291. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1292. *
  1293. * Keys for the $source parameter:
  1294. * bucket - _string_ (Required) Specifies the name of the bucket containing the source object.
  1295. * filename - _string_ (Required) Specifies the file name of the source object to copy.
  1296. *
  1297. * Keys for the $dest parameter:
  1298. * bucket - _string_ (Required) Specifies the name of the bucket to copy the object to.
  1299. * filename - _string_ (Required) Specifies the file name to copy the object to.
  1300. *
  1301. * Keys for the $opt parameter:
  1302. * acl - _string_ (Optional) The ACL settings for the specified object. [Allowed values: `AmazonS3::ACL_PRIVATE`, `AmazonS3::ACL_PUBLIC`, `AmazonS3::ACL_OPEN`, `AmazonS3::ACL_AUTH_READ`, `AmazonS3::ACL_OWNER_READ`, `AmazonS3::ACL_OWNER_FULL_CONTROL`]. Alternatively, an array of associative arrays. Each associative array contains an `id` and a `permission` key. The default value is <ACL_PRIVATE>.
  1303. * storage - _string_ (Optional) Whether to use Standard or Reduced Redundancy storage. [Allowed values: `AmazonS3::STORAGE_STANDARD`, `AmazonS3::STORAGE_REDUCED`]. The default value is <STORAGE_STANDARD>.
  1304. * versionId - _string_ (Optional) The version of the object to copy. Version IDs are returned in the `x-amz-version-id` header of any previous object-related request.
  1305. * ifMatch - _string_ (Optional) The ETag header from a previous request. Copies the object if its entity tag (ETag) matches the specified tag; otherwise, the request returns a `412` HTTP status code error (precondition failed). Used in conjunction with `ifUnmodifiedSince`.
  1306. * ifUnmodifiedSince - _string_ (Optional) The LastModified header from a previous request. Copies the object if it hasn't been modified since the specified time; otherwise, the request returns a `412` HTTP status code error (precondition failed). Used in conjunction with `ifMatch`.
  1307. * ifNoneMatch - _string_ (Optional) The ETag header from a previous request. Copies the object if its entity tag (ETag) is different than the specified ETag; otherwise, the request returns a `412` HTTP status code error (failed condition). Used in conjunction with `ifModifiedSince`.
  1308. * ifModifiedSince - _string_ (Optional) The LastModified header from a previous request. Copies the object if it has been modified since the specified time; otherwise, the request returns a `412` HTTP status code error (failed condition). Used in conjunction with `ifNoneMatch`.
  1309. * headers - _array_ (Optional) Standard HTTP headers to send along in the request.
  1310. * meta - _array_ (Optional) Associative array of key-value pairs. Represented by `x-amz-meta-:` Any header starting with this prefix is considered user metadata. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.
  1311. * metadataDirective - _string_ (Optional) Accepts either COPY or REPLACE. You will likely never need to use this, as it manages itself with no issues.
  1312. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1313. *
  1314. * Returns:
  1315. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1316. *
  1317. * See Also:
  1318. * [Copying Amazon S3 Objects](http://docs.amazonwebservices.com/AmazonS3/latest/UsingCopyingObjects.html)
  1319. */
  1320. public function copy_object($source, $dest, $opt = null)
  1321. {
  1322. if (!$opt) $opt = array();
  1323. $batch = array();
  1324. // Add this to our request
  1325. $opt['verb'] = 'PUT';
  1326. $opt['resource'] = $dest['filename'];
  1327. // Handle copy source
  1328. if (isset($source['bucket']) && isset($source['filename']))
  1329. {
  1330. $opt['headers']['x-amz-copy-source'] = '/' . $source['bucket'] . '/' . rawurlencode($source['filename'])
  1331. . (isset($opt['versionId']) ? ('?' . 'versionId=' . rawurlencode($opt['versionId'])) : ''); // Append the versionId to copy, if available
  1332. unset($opt['versionId']);
  1333. // Determine if we need to lookup the pre-existing content-type.
  1334. if (
  1335. (!$this->use_batch_flow && !isset($opt['returnCurlHandle'])) &&
  1336. !in_array(strtolower('content-type'), array_map('strtolower', array_keys($opt['headers'])))
  1337. )
  1338. {
  1339. $response = $this->get_object_headers($source['bucket'], $source['filename']);
  1340. if ($response->isOK())
  1341. {
  1342. $opt['headers']['Content-Type'] = $response->header['content-type'];
  1343. }
  1344. }
  1345. }
  1346. // Handle metadata directive
  1347. $opt['headers']['x-amz-metadata-directive'] = 'COPY';
  1348. if ($source['bucket'] === $dest['bucket'] && $source['filename'] === $dest['filename'])
  1349. {
  1350. $opt['headers']['x-amz-metadata-directive'] = 'REPLACE';
  1351. }
  1352. if (isset($opt['metadataDirective']))
  1353. {
  1354. $opt['headers']['x-amz-metadata-directive'] = $opt['metadataDirective'];
  1355. unset($opt['metadataDirective']);
  1356. }
  1357. // Handle Access Control Lists. Can also pass canned ACLs as an HTTP header.
  1358. if (isset($opt['acl']) && is_array($opt['acl']))
  1359. {
  1360. $batch[] = $this->set_object_acl($dest['bucket'], $dest['filename'], $opt['acl'], array(
  1361. 'returnCurlHandle' => true
  1362. ));
  1363. unset($opt['acl']);
  1364. }
  1365. elseif (isset($opt['acl']))
  1366. {
  1367. $opt['headers']['x-amz-acl'] = $opt['acl'];
  1368. unset($opt['acl']);
  1369. }
  1370. // Handle storage settings. Can also be passed as an HTTP header.
  1371. if (isset($opt['storage']))
  1372. {
  1373. $opt['headers']['x-amz-storage-class'] = $opt['storage'];
  1374. unset($opt['storage']);
  1375. }
  1376. // Handle conditional-copy parameters
  1377. if (isset($opt['ifMatch']))
  1378. {
  1379. $opt['headers']['x-amz-copy-source-if-match'] = $opt['ifMatch'];
  1380. unset($opt['ifMatch']);
  1381. }
  1382. if (isset($opt['ifNoneMatch']))
  1383. {
  1384. $opt['headers']['x-amz-copy-source-if-none-match'] = $opt['ifNoneMatch'];
  1385. unset($opt['ifNoneMatch']);
  1386. }
  1387. if (isset($opt['ifUnmodifiedSince']))
  1388. {
  1389. $opt['headers']['x-amz-copy-source-if-unmodified-since'] = $opt['ifUnmodifiedSince'];
  1390. unset($opt['ifUnmodifiedSince']);
  1391. }
  1392. if (isset($opt['ifModifiedSince']))
  1393. {
  1394. $opt['headers']['x-amz-copy-source-if-modified-since'] = $opt['ifModifiedSince'];
  1395. unset($opt['ifModifiedSince']);
  1396. }
  1397. // Handle meta tags. Can also be passed as an HTTP header.
  1398. if (isset($opt['meta']))
  1399. {
  1400. foreach ($opt['meta'] as $meta_key => $meta_value)
  1401. {
  1402. // e.g., `My Meta Header` is converted to `x-amz-meta-my-meta-header`.
  1403. $opt['headers']['x-amz-meta-' . strtolower(str_replace(' ', '-', $meta_key))] = $meta_value;
  1404. }
  1405. unset($opt['meta']);
  1406. }
  1407. // Authenticate to S3
  1408. $response = $this->authenticate($dest['bucket'], $opt);
  1409. // Attempt to reset ACLs
  1410. $http = new RequestCore();
  1411. $http->send_multi_request($batch);
  1412. return $response;
  1413. }
  1414. /**
  1415. * Method: update_object()
  1416. * Updates an Amazon S3 object with new headers or other metadata.
  1417. *
  1418. * To replace the content of the specified Amazon S3 object, call <create_object()> with the same bucket
  1419. * and file name parameters.
  1420. *
  1421. * Access:
  1422. * public
  1423. *
  1424. * Parameters:
  1425. * $bucket - _string_ (Required) The name of the bucket that contains the source file.
  1426. * $filename - _string_ (Required) The source file name that you want to update.
  1427. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1428. *
  1429. * Keys for the $opt parameter:
  1430. * acl - _string_ (Optional) The ACL settings for the specified object. [Allowed values: `AmazonS3::ACL_PRIVATE`, `AmazonS3::ACL_PUBLIC`, `AmazonS3::ACL_OPEN`, `AmazonS3::ACL_AUTH_READ`, `AmazonS3::ACL_OWNER_READ`, `AmazonS3::ACL_OWNER_FULL_CONTROL`]. The default value is <ACL_PRIVATE>.
  1431. * headers - _array_ (Optional) The standard HTTP headers to update the Amazon S3 object with.
  1432. * meta - _array_ (Optional) An associative array of key-value pairs. Any header with the `x-amz-meta-` prefix is considered user metadata and is stored with the Amazon S3 object. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.
  1433. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1434. *
  1435. * Returns:
  1436. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1437. *
  1438. * See Also:
  1439. * [Copying Amazon S3 Objects](http://docs.amazonwebservices.com/AmazonS3/latest/UsingCopyingObjects.html)
  1440. */
  1441. public function update_object($bucket, $filename, $opt = null)
  1442. {
  1443. if (!$opt) $opt = array();
  1444. $opt['metadataDirective'] = 'REPLACE';
  1445. // Authenticate to S3
  1446. return $this->copy_object(
  1447. array('bucket' => $bucket, 'filename' => $filename),
  1448. array('bucket' => $bucket, 'filename' => $filename),
  1449. $opt
  1450. );
  1451. }
  1452. /*%******************************************************************************************%*/
  1453. // ACCESS CONTROL LISTS
  1454. /**
  1455. * Method: get_object_acl()
  1456. * Gets the access control list (ACL) settings for the specified Amazon S3 object.
  1457. *
  1458. * Access:
  1459. * public
  1460. *
  1461. * Parameters:
  1462. * $bucket - _string_ (Required) The name of the bucket to use.
  1463. * $filename - _string_ (Required) The file name for the object.
  1464. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1465. *
  1466. * Keys for the $opt parameter:
  1467. * versionId - _string_ (Optional) The version of the object to retrieve. Version IDs are returned in the `x-amz-version-id` header of any previous object-related request.
  1468. * preauth - _integer_|_string_ (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with `strtotime()`.
  1469. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1470. *
  1471. * Returns:
  1472. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1473. *
  1474. * See Also:
  1475. * [REST Access Control Policy](http://docs.amazonwebservices.com/AmazonS3/latest/RESTAccessPolicy.html)
  1476. */
  1477. public function get_object_acl($bucket, $filename, $opt = null)
  1478. {
  1479. // Add this to our request
  1480. if (!$opt) $opt = array();
  1481. $opt['verb'] = 'GET';
  1482. $opt['resource'] = $filename;
  1483. $opt['sub_resource'] = 'acl';
  1484. // Authenticate to S3
  1485. return $this->authenticate($bucket, $opt);
  1486. }
  1487. /**
  1488. * Method: set_object_acl()
  1489. * Sets the access control list (ACL) settings for the specified Amazon S3 object.
  1490. *
  1491. * Access:
  1492. * public
  1493. *
  1494. * Parameters:
  1495. * $bucket - _string_ (Required) The name of the bucket to use.
  1496. * $filename - _string_ (Required) The file name for the object.
  1497. * $acl - _string_ (Optional) The ACL settings for the specified object. Accepts any of the following constants: [Allowed values: `AmazonS3::ACL_PRIVATE`, `AmazonS3::ACL_PUBLIC`, `AmazonS3::ACL_OPEN`, `AmazonS3::ACL_AUTH_READ`, `AmazonS3::ACL_OWNER_READ`, `AmazonS3::ACL_OWNER_FULL_CONTROL`]. Alternatively, an array of associative arrays. Each associative array contains an `id` and a `permission` key. The default value is <ACL_PRIVATE>.
  1498. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1499. *
  1500. * Keys for the $opt parameter:
  1501. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1502. *
  1503. * Returns:
  1504. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1505. *
  1506. * See Also:
  1507. * [REST Access Control Policy](http://docs.amazonwebservices.com/AmazonS3/latest/RESTAccessPolicy.html)
  1508. */
  1509. public function set_object_acl($bucket, $filename, $acl = self::ACL_PRIVATE, $opt = null)
  1510. {
  1511. // Add this to our request
  1512. if (!$opt) $opt = array();
  1513. $opt['verb'] = 'PUT';
  1514. $opt['resource'] = $filename;
  1515. $opt['sub_resource'] = 'acl';
  1516. // Retrieve the original metadata
  1517. $metadata = $this->get_object_metadata($bucket, $filename);
  1518. if ($metadata && $metadata['ContentType'])
  1519. {
  1520. $opt['headers']['Content-Type'] = $metadata['ContentType'];
  1521. }
  1522. if ($metadata && $metadata['StorageClass'])
  1523. {
  1524. $opt['headers']['x-amz-storage-class'] = $metadata['StorageClass'];
  1525. }
  1526. // Make sure these are defined.
  1527. if (!defined('AWS_CANONICAL_ID') || !defined('AWS_CANONICAL_NAME'))
  1528. {
  1529. // Fetch the data live.
  1530. $canonical = $this->get_canonical_user_id();
  1531. define('AWS_CANONICAL_ID', $canonical['id']);
  1532. define('AWS_CANONICAL_NAME', $canonical['display_name']);
  1533. }
  1534. if (is_array($acl))
  1535. {
  1536. $opt['body'] = $this->generate_access_policy(AWS_CANONICAL_ID, AWS_CANONICAL_NAME, $acl);
  1537. }
  1538. else
  1539. {
  1540. $opt['headers']['x-amz-acl'] = $acl;
  1541. }
  1542. // Authenticate to S3
  1543. return $this->authenticate($bucket, $opt);
  1544. }
  1545. /**
  1546. * Method: generate_access_policy()
  1547. * Generates the XML to be used for the Access Control Policy.
  1548. *
  1549. * Access:
  1550. * public
  1551. *
  1552. * Parameters:
  1553. * $canonical_id - _string_ (Required) The canonical ID for the bucket owner. Use the `AWS_CANONICAL_ID` constant or the `id` return value from <get_canonical_user_id()>.
  1554. * $canonical_name - _string_ (Required) The canonical display name for the bucket owner. Use the `AWS_CANONICAL_NAME` constant or the `display_name` value from <get_canonical_user_id()>.
  1555. * $users - _array_ (Optional) An array of associative arrays. Each associative array contains an `id` value and a `permission` value.
  1556. *
  1557. * Returns:
  1558. * _string_ Access Control Policy XML.
  1559. *
  1560. * See Also:
  1561. * [Access Control Lists](http://docs.amazonwebservices.com/AmazonS3/latest/S3_ACLs.html)
  1562. */
  1563. public function generate_access_policy($canonical_id, $canonical_name, $users)
  1564. {
  1565. $xml = simplexml_load_string($this->base_acp_xml);
  1566. $owner = $xml->addChild('Owner');
  1567. $owner->addChild('ID', $canonical_id);
  1568. $owner->addChild('DisplayName', $canonical_name);
  1569. $acl = $xml->addChild('AccessControlList');
  1570. foreach ($users as $user)
  1571. {
  1572. $grant = $acl->addChild('Grant');
  1573. $grantee = $grant->addChild('Grantee');
  1574. switch ($user['id'])
  1575. {
  1576. // Authorized Users
  1577. case self::USERS_AUTH:
  1578. $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
  1579. $grantee->addChild('URI', self::USERS_AUTH);
  1580. break;
  1581. // All Users
  1582. case self::USERS_ALL:
  1583. $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
  1584. $grantee->addChild('URI', self::USERS_ALL);
  1585. break;
  1586. // The Logging User
  1587. case self::USERS_LOGGING:
  1588. $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
  1589. $grantee->addChild('URI', self::USERS_LOGGING);
  1590. break;
  1591. // Email Address or Canonical Id
  1592. default:
  1593. if (strpos($user['id'], '@'))
  1594. {
  1595. $grantee->addAttribute('xsi:type', 'AmazonCustomerByEmail', 'http://www.w3.org/2001/XMLSchema-instance');
  1596. $grantee->addChild('EmailAddress', $user['id']);
  1597. }
  1598. else
  1599. {
  1600. // Assume Canonical Id
  1601. $grantee->addAttribute('xsi:type', 'CanonicalUser', 'http://www.w3.org/2001/XMLSchema-instance');
  1602. $grantee->addChild('ID', $user['id']);
  1603. }
  1604. break;
  1605. }
  1606. $grant->addChild('Permission', $user['permission']);
  1607. }
  1608. return $xml->asXML();
  1609. }
  1610. /*%******************************************************************************************%*/
  1611. // LOGGING METHODS
  1612. /**
  1613. * Method: get_logs()
  1614. * Gets the access logs associated with the specified Amazon S3 bucket.
  1615. *
  1616. * Access:
  1617. * public
  1618. *
  1619. * Parameters:
  1620. * $bucket - _string_ (Required) The name of the bucket to use. Pass a `null` value when using the <set_vhost()> method.
  1621. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1622. *
  1623. * Keys for the $opt parameter:
  1624. * preauth - _integer_|_string_ (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with `strtotime()`.
  1625. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1626. *
  1627. * Returns:
  1628. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1629. *
  1630. * See Also:
  1631. * [Server Access Logging](http://docs.amazonwebservices.com/AmazonS3/latest/ServerLogs.html)
  1632. */
  1633. public function get_logs($bucket, $opt = null)
  1634. {
  1635. // Add this to our request
  1636. if (!$opt) $opt = array();
  1637. $opt['verb'] = 'GET';
  1638. $opt['sub_resource'] = 'logging';
  1639. // Authenticate to S3
  1640. return $this->authenticate($bucket, $opt);
  1641. }
  1642. /**
  1643. * Method: enable_logging()
  1644. * Enables access logging for the specified Amazon S3 bucket.
  1645. *
  1646. * Access:
  1647. * public
  1648. *
  1649. * Parameters:
  1650. * $bucket - _string_ (Required) The name of the bucket to enable logging for. Pass a `null` value when using the <set_vhost()> method.
  1651. * $target_bucket - _string_ (Required) The name of the bucket to store the logs in.
  1652. * $target_prefix - _string_ (Required) The prefix to give to the log file names.
  1653. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1654. *
  1655. * Keys for the $opt parameter:
  1656. * users - _array_ (Optional) An array of associative arrays specifying any user to give access to. Each associative array contains an `id` and `permission` value.
  1657. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1658. *
  1659. * Returns:
  1660. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1661. *
  1662. * See Also:
  1663. * * [Server Access Logging Configuration API](http://docs.amazonwebservices.com/AmazonS3/latest/LoggingAPI.html)
  1664. */
  1665. public function enable_logging($bucket, $target_bucket, $target_prefix, $opt = null)
  1666. {
  1667. // Add this to our request
  1668. if (!$opt) $opt = array();
  1669. $opt['verb'] = 'PUT';
  1670. $opt['sub_resource'] = 'logging';
  1671. $opt['headers'] = array(
  1672. 'Content-Type' => 'application/xml'
  1673. );
  1674. $xml = simplexml_load_string($this->base_logging_xml);
  1675. $LoggingEnabled = $xml->addChild('LoggingEnabled');
  1676. $LoggingEnabled->addChild('TargetBucket', $target_bucket);
  1677. $LoggingEnabled->addChild('TargetPrefix', $target_prefix);
  1678. $TargetGrants = $LoggingEnabled->addChild('TargetGrants');
  1679. if (isset($opt['users']) && is_array($opt['users']))
  1680. {
  1681. foreach ($opt['users'] as $user)
  1682. {
  1683. $grant = $TargetGrants->addChild('Grant');
  1684. $grantee = $grant->addChild('Grantee');
  1685. switch ($user['id'])
  1686. {
  1687. // Authorized Users
  1688. case self::USERS_AUTH:
  1689. $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
  1690. $grantee->addChild('URI', self::USERS_AUTH);
  1691. break;
  1692. // All Users
  1693. case self::USERS_ALL:
  1694. $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
  1695. $grantee->addChild('URI', self::USERS_ALL);
  1696. break;
  1697. // The Logging User
  1698. case self::USERS_LOGGING:
  1699. $grantee->addAttribute('xsi:type', 'Group', 'http://www.w3.org/2001/XMLSchema-instance');
  1700. $grantee->addChild('URI', self::USERS_LOGGING);
  1701. break;
  1702. // Email Address or Canonical Id
  1703. default:
  1704. if (strpos($user['id'], '@'))
  1705. {
  1706. $grantee->addAttribute('xsi:type', 'AmazonCustomerByEmail', 'http://www.w3.org/2001/XMLSchema-instance');
  1707. $grantee->addChild('EmailAddress', $user['id']);
  1708. }
  1709. else
  1710. {
  1711. // Assume Canonical Id
  1712. $grantee->addAttribute('xsi:type', 'CanonicalUser', 'http://www.w3.org/2001/XMLSchema-instance');
  1713. $grantee->addChild('ID', $user['id']);
  1714. }
  1715. break;
  1716. }
  1717. $grant->addChild('Permission', $user['permission']);
  1718. }
  1719. }
  1720. $opt['body'] = $xml->asXML();
  1721. // Authenticate to S3
  1722. return $this->authenticate($bucket, $opt);
  1723. }
  1724. /**
  1725. * Method: disable_logging()
  1726. * Disables access logging for the specified Amazon S3 bucket.
  1727. *
  1728. * Access:
  1729. * public
  1730. *
  1731. * Parameters:
  1732. * $bucket - _string_ (Required) The name of the bucket to use. Pass `null` if using <set_vhost()>.
  1733. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1734. *
  1735. * Keys for the $opt parameter:
  1736. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1737. *
  1738. * Returns:
  1739. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1740. *
  1741. * See Also:
  1742. * [Server Access Logging Configuration API](http://docs.amazonwebservices.com/AmazonS3/latest/LoggingAPI.html)
  1743. */
  1744. public function disable_logging($bucket, $opt = null)
  1745. {
  1746. // Add this to our request
  1747. if (!$opt) $opt = array();
  1748. $opt['verb'] = 'PUT';
  1749. $opt['sub_resource'] = 'logging';
  1750. $opt['headers'] = array(
  1751. 'Content-Type' => 'application/xml'
  1752. );
  1753. $opt['body'] = $this->base_logging_xml;
  1754. // Authenticate to S3
  1755. return $this->authenticate($bucket, $opt);
  1756. }
  1757. /*%******************************************************************************************%*/
  1758. // CONVENIENCE METHODS
  1759. /**
  1760. * Method: if_bucket_exists()
  1761. * Gets whether or not the specified Amazon S3 bucket exists in Amazon S3. This includes buckets
  1762. * that do not belong to the caller.
  1763. *
  1764. * Access:
  1765. * public
  1766. *
  1767. * Parameters:
  1768. * $bucket - _string_ (Required) The name of the bucket to use.
  1769. *
  1770. * Returns:
  1771. * _boolean_ A value of `true` if the bucket exists, or a value of `false` if it does not.
  1772. */
  1773. public function if_bucket_exists($bucket)
  1774. {
  1775. if ($this->use_batch_flow)
  1776. {
  1777. throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
  1778. }
  1779. $header = $this->get_bucket_headers($bucket);
  1780. return (bool) $header->isOK();
  1781. }
  1782. /**
  1783. * Method: if_object_exists()
  1784. * Gets whether or not the specified Amazon S3 object exists in the specified bucket.
  1785. *
  1786. * Access:
  1787. * public
  1788. *
  1789. * Parameters:
  1790. * $bucket - _string_ (Required) The name of the bucket to use.
  1791. * $filename - _string_ (Required) The file name for the object.
  1792. *
  1793. * Returns:
  1794. * _boolean_ A value of `true` if the object exists, or a value of `false` if it does not.
  1795. */
  1796. public function if_object_exists($bucket, $filename)
  1797. {
  1798. if ($this->use_batch_flow)
  1799. {
  1800. throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
  1801. }
  1802. $header = $this->get_object_headers($bucket, $filename);
  1803. if ($header->isOK()) { return true; }
  1804. elseif ($header->status === 404) { return false; }
  1805. return null;
  1806. }
  1807. /**
  1808. * Method: if_bucket_policy_exists()
  1809. * Gets whether or not the specified Amazon S3 bucket has a bucket policy associated with it.
  1810. *
  1811. * Access:
  1812. * public
  1813. *
  1814. * Parameters:
  1815. * $bucket - _string_ (Required) The name of the bucket to use.
  1816. *
  1817. * Returns:
  1818. * _boolean_ A value of `true` if a bucket policy exists, or a value of `false` if one does not.
  1819. */
  1820. public function if_bucket_policy_exists($bucket)
  1821. {
  1822. if ($this->use_batch_flow)
  1823. {
  1824. throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
  1825. }
  1826. $response = $this->get_bucket_policy($bucket);
  1827. if ($response->isOK()) { return true; }
  1828. elseif ($response->status === 404) { return false; }
  1829. return null;
  1830. }
  1831. /**
  1832. * Method: get_bucket_object_count()
  1833. * Gets the number of Amazon S3 objects in the specified bucket.
  1834. *
  1835. * Access:
  1836. * public
  1837. *
  1838. * Parameters:
  1839. * $bucket - _string_ (Required) The name of the bucket to use.
  1840. *
  1841. * Returns:
  1842. * _integer_ The number of Amazon S3 objects in the bucket.
  1843. */
  1844. public function get_bucket_object_count($bucket)
  1845. {
  1846. if ($this->use_batch_flow)
  1847. {
  1848. throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
  1849. }
  1850. return count($this->get_object_list($bucket));
  1851. }
  1852. /**
  1853. * Method: get_bucket_filesize()
  1854. * Gets the cumulative file size of the contents of the Amazon S3 bucket.
  1855. *
  1856. * Access:
  1857. * public
  1858. *
  1859. * Parameters:
  1860. * $bucket - _string_ (Required) The name of the bucket to use.
  1861. * $friendly_format - _boolean_ (Optional) A value of `true` will format the return value to 2 decimal points using the largest possible unit (i.e., 3.42 GB). A value of `false` will format the return value as the raw number of bytes.
  1862. *
  1863. * Returns:
  1864. * _integer_|_string_ The number of bytes as an integer, or the friendly format as a string.
  1865. */
  1866. public function get_bucket_filesize($bucket, $friendly_format = false)
  1867. {
  1868. if ($this->use_batch_flow)
  1869. {
  1870. throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
  1871. }
  1872. $filesize = 0;
  1873. $list = $this->list_objects($bucket);
  1874. foreach ($list->body->Contents as $filename)
  1875. {
  1876. $filesize += (integer) $filename->Size;
  1877. }
  1878. while ((string) $list->body->IsTruncated === 'true')
  1879. {
  1880. $body = (array) $list->body;
  1881. $list = $this->list_objects($bucket, array(
  1882. 'marker' => (string) end($body['Contents'])->Key
  1883. ));
  1884. foreach ($list->body->Contents as $object)
  1885. {
  1886. $filesize += (integer) $object->Size;
  1887. }
  1888. }
  1889. if ($friendly_format)
  1890. {
  1891. $filesize = $this->util->size_readable($filesize);
  1892. }
  1893. return $filesize;
  1894. }
  1895. /**
  1896. * Method: get_object_filesize()
  1897. * Gets the file size of the specified Amazon S3 object.
  1898. *
  1899. * Access:
  1900. * public
  1901. *
  1902. * Parameters:
  1903. * $bucket - _string_ (Required) The name of the bucket to use.
  1904. * $filename - _string_ (Required) The file name for the object.
  1905. * $friendly_format - _boolean_ (Optional) A value of `true` will format the return value to 2 decimal points using the largest possible unit (i.e., 3.42 GB). A value of `false` will format the return value as the raw number of bytes.
  1906. *
  1907. * Returns:
  1908. * _integer_|_string_ The number of bytes as an integer, or the friendly format as a string.
  1909. */
  1910. public function get_object_filesize($bucket, $filename, $friendly_format = false)
  1911. {
  1912. if ($this->use_batch_flow)
  1913. {
  1914. throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
  1915. }
  1916. $object = $this->get_object_headers($bucket, $filename);
  1917. $filesize = (integer) $object->header['content-length'];
  1918. if ($friendly_format)
  1919. {
  1920. $filesize = $this->util->size_readable($filesize);
  1921. }
  1922. return $filesize;
  1923. }
  1924. /**
  1925. * Method: change_content_type()
  1926. * Changes the content type for an existing Amazon S3 object.
  1927. *
  1928. * Access:
  1929. * public
  1930. *
  1931. * Parameters:
  1932. * $bucket - _string_ (Required) The name of the bucket to use.
  1933. * $filename - _string_ (Required) The file name for the object.
  1934. * $contentType - _string_ (Required) The content-type to apply to the object.
  1935. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1936. *
  1937. * Keys for the $opt parameter:
  1938. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1939. *
  1940. * Returns:
  1941. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1942. */
  1943. public function change_content_type($bucket, $filename, $contentType, $opt = null)
  1944. {
  1945. if (!$opt) $opt = array();
  1946. // Retrieve the original metadata
  1947. $metadata = $this->get_object_metadata($bucket, $filename);
  1948. if ($metadata && $metadata['ACL'])
  1949. {
  1950. $opt['acl'] = $metadata['ACL'];
  1951. }
  1952. if ($metadata && $metadata['StorageClass'])
  1953. {
  1954. $opt['headers']['x-amz-storage-class'] = $metadata['StorageClass'];
  1955. }
  1956. // Merge optional parameters
  1957. $opt = array_merge(array(
  1958. 'headers' => array(
  1959. 'Content-Type' => $contentType
  1960. ),
  1961. 'metadataDirective' => 'REPLACE'
  1962. ), $opt);
  1963. return $this->copy_object(
  1964. array('bucket' => $bucket, 'filename' => $filename),
  1965. array('bucket' => $bucket, 'filename' => $filename),
  1966. $opt
  1967. );
  1968. }
  1969. /**
  1970. * Method: change_storage_redundancy()
  1971. * Changes the storage redundancy for an existing object.
  1972. *
  1973. * Access:
  1974. * public
  1975. *
  1976. * Parameters:
  1977. * $bucket - _string_ (Required) The name of the bucket to use.
  1978. * $filename - _string_ (Required) The file name for the object.
  1979. * $storage - _string_ (Required) The storage setting to apply to the object. [Allowed values: `AmazonS3::STORAGE_STANDARD`, `AmazonS3::STORAGE_REDUCED`]
  1980. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  1981. *
  1982. * Keys for the $opt parameter:
  1983. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  1984. *
  1985. * Returns:
  1986. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  1987. */
  1988. public function change_storage_redundancy($bucket, $filename, $storage, $opt = null)
  1989. {
  1990. if (!$opt) $opt = array();
  1991. // Retrieve the original metadata
  1992. $metadata = $this->get_object_metadata($bucket, $filename);
  1993. if ($metadata && $metadata['ACL'])
  1994. {
  1995. $opt['acl'] = $metadata['ACL'];
  1996. }
  1997. if ($metadata && $metadata['ContentType'])
  1998. {
  1999. $opt['headers']['Content-Type'] = $metadata['ContentType'];
  2000. }
  2001. // Merge optional parameters
  2002. $opt = array_merge(array(
  2003. 'storage' => $storage,
  2004. 'metadataDirective' => 'COPY',
  2005. ), $opt);
  2006. return $this->copy_object(
  2007. array('bucket' => $bucket, 'filename' => $filename),
  2008. array('bucket' => $bucket, 'filename' => $filename),
  2009. $opt
  2010. );
  2011. }
  2012. /**
  2013. * Method: get_bucket_list()
  2014. * Gets a simplified list of bucket names on an Amazon S3 account.
  2015. *
  2016. * Access:
  2017. * public
  2018. *
  2019. * Parameters:
  2020. * $pcre - _string_ (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the bucket names against.
  2021. *
  2022. * Returns:
  2023. * _array_ The list of matching bucket names. If there are no results, the method will return an empty array.
  2024. *
  2025. * See Also:
  2026. * [Regular Expressions (Perl-Compatible)](http://php.net/pcre)
  2027. */
  2028. public function get_bucket_list($pcre = null)
  2029. {
  2030. if ($this->use_batch_flow)
  2031. {
  2032. throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
  2033. }
  2034. // Get a list of buckets.
  2035. $list = $this->list_buckets();
  2036. if ($list = $list->body->query('descendant-or-self::Name'))
  2037. {
  2038. $list = $list->map_string($pcre);
  2039. return $list;
  2040. }
  2041. return array();
  2042. }
  2043. /**
  2044. * Method: get_object_list()
  2045. * Gets a simplified list of Amazon S3 object file names contained in a bucket.
  2046. *
  2047. * Access:
  2048. * public
  2049. *
  2050. * Parameters:
  2051. * $bucket - _string_ (Required) The name of the bucket to use.
  2052. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2053. *
  2054. * Keys for the $opt parameter:
  2055. * delimiter - _string_ (Optional) Keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection.
  2056. * marker - _string_ (Optional) Restricts the response to contain results that only occur alphabetically after the value of the marker.
  2057. * max-keys - _string_ (Optional) The maximum number of results returned by the method call. The returned list will contain no more results than the specified value, but may return less.
  2058. * pcre - _string_ (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the names against. This is applied only AFTER any native Amazon S3 filtering from specified `prefix`, `marker`, `max-keys`, or `delimiter` values are applied.
  2059. * prefix - _string_ (Optional) Restricts the response to contain results that begin only with the specified prefix.
  2060. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2061. *
  2062. * Returns:
  2063. * _array_ The list of matching object names. If there are no results, the method will return an empty array.
  2064. *
  2065. * See Also:
  2066. * [Regular Expressions (Perl-Compatible)](http://php.net/pcre)
  2067. */
  2068. public function get_object_list($bucket, $opt = null)
  2069. {
  2070. if ($this->use_batch_flow)
  2071. {
  2072. throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
  2073. }
  2074. if (!$opt) $opt = array();
  2075. // Set some default values
  2076. $pcre = isset($opt['pcre']) ? $opt['pcre'] : null;
  2077. $max_keys = isset($opt['max-keys']) ? (integer) $opt['max-keys'] : 'all';
  2078. $objects = array();
  2079. if ($max_keys === 'all')
  2080. {
  2081. do
  2082. {
  2083. $list = $this->list_objects($bucket, $opt);
  2084. if ($keys = $list->body->query('descendant-or-self::Key')->map_string($pcre))
  2085. {
  2086. $objects = array_merge($objects, $keys);
  2087. }
  2088. $body = (array) $list->body;
  2089. $opt = array_merge($opt, array(
  2090. 'marker' => (isset($body['Contents']) && is_array($body['Contents'])) ?
  2091. ((string) end($body['Contents'])->Key) :
  2092. ((string) $list->body->Contents->Key)
  2093. ));
  2094. }
  2095. while ((string) $list->body->IsTruncated === 'true');
  2096. }
  2097. else
  2098. {
  2099. $loops = ceil($max_keys / 1000);
  2100. do
  2101. {
  2102. $list = $this->list_objects($bucket, $opt);
  2103. if ($keys = $list->body->query('descendant-or-self::Key')->map_string($pcre))
  2104. {
  2105. $objects = array_merge($objects, $keys);
  2106. }
  2107. if ($max_keys > 1000)
  2108. {
  2109. $max_keys -= 1000;
  2110. }
  2111. $body = (array) $list->body;
  2112. $opt = array_merge($opt, array(
  2113. 'max-keys' => $max_keys,
  2114. 'marker' => (isset($body['Contents']) && is_array($body['Contents'])) ?
  2115. ((string) end($body['Contents'])->Key) :
  2116. ((string) $list->body->Contents->Key)
  2117. ));
  2118. }
  2119. while (--$loops);
  2120. }
  2121. if (count($objects) > 0)
  2122. {
  2123. return $objects;
  2124. }
  2125. return array();
  2126. }
  2127. /**
  2128. * Method: delete_all_objects()
  2129. * Deletes all Amazon S3 objects inside the specified bucket.
  2130. *
  2131. * Access:
  2132. * public
  2133. *
  2134. * Parameters:
  2135. * $bucket - _string_ (Required) The name of the bucket to use.
  2136. * $pcre - _string_ (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the names against. The default value is <PCRE_ALL>.
  2137. *
  2138. * Returns:
  2139. * _boolean_ A value of `true` means that all objects were successfully deleted. A value of `false` means that at least one object failed to delete.
  2140. *
  2141. * See Also:
  2142. * [Regular Expressions (Perl-Compatible)](http://php.net/pcre)
  2143. */
  2144. public function delete_all_objects($bucket, $pcre = self::PCRE_ALL)
  2145. {
  2146. if ($this->use_batch_flow)
  2147. {
  2148. throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
  2149. }
  2150. // Collect all matches
  2151. $list = $this->get_object_list($bucket, array('pcre' => $pcre));
  2152. // As long as we have at least one match...
  2153. if (count($list) > 0)
  2154. {
  2155. // Create new batch request object
  2156. $q = new $this->batch_class();
  2157. // Go through all of the items and delete them.
  2158. foreach ($list as $item)
  2159. {
  2160. $this->batch($q)->delete_object($bucket, $item);
  2161. }
  2162. return $this->batch($q)->send()->areOK();
  2163. }
  2164. // If there are no matches, return true
  2165. return true;
  2166. }
  2167. /**
  2168. * Method: delete_all_object_versions()
  2169. * Deletes all of the versions of all Amazon S3 objects inside the specified bucket.
  2170. *
  2171. * Access:
  2172. * public
  2173. *
  2174. * Parameters:
  2175. * $bucket - _string_ (Required) The name of the bucket to use.
  2176. * $pcre - _string_ (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the names against. The default value is <PCRE_ALL>.
  2177. *
  2178. * Returns:
  2179. * _boolean_ A value of `true` means that all object versions were successfully deleted. A value of `false` means that at least one object/version failed to delete.
  2180. *
  2181. * See Also:
  2182. * [Regular Expressions (Perl-Compatible)](http://php.net/pcre)
  2183. */
  2184. public function delete_all_object_versions($bucket, $pcre = null)
  2185. {
  2186. if ($this->use_batch_flow)
  2187. {
  2188. throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
  2189. }
  2190. // Instantiate
  2191. $q = new CFBatchRequest(200);
  2192. $response = $this->list_bucket_object_versions($bucket);
  2193. // Gather all nodes together into a single array
  2194. if ($response->body->DeleteMarker() && $response->body->Version())
  2195. {
  2196. $markers = array_merge($response->body->DeleteMarker()->getArrayCopy(), $response->body->Version()->getArrayCopy());
  2197. }
  2198. elseif ($response->body->DeleteMarker())
  2199. {
  2200. $markers = $response->body->DeleteMarker()->getArrayCopy();
  2201. }
  2202. elseif ($response->body->Version())
  2203. {
  2204. $markers = $response->body->Version()->getArrayCopy();
  2205. }
  2206. else
  2207. {
  2208. $markers = array();
  2209. }
  2210. while ((string) $response->body->IsTruncated === 'true')
  2211. {
  2212. $response = $this->list_bucket_object_versions($bucket, array(
  2213. 'key-marker' => (string) $response->body->NextKeyMarker
  2214. ));
  2215. // Gather all nodes together into a single array
  2216. if ($response->body->DeleteMarker() && $response->body->Version())
  2217. {
  2218. $markers = array_merge($markers, $response->body->DeleteMarker()->getArrayCopy(), $response->body->Version()->getArrayCopy());
  2219. }
  2220. elseif ($response->body->DeleteMarker())
  2221. {
  2222. $markers = array_merge($markers, $response->body->DeleteMarker()->getArrayCopy());
  2223. }
  2224. elseif ($response->body->Version())
  2225. {
  2226. $markers = array_merge($markers, $response->body->Version()->getArrayCopy());
  2227. }
  2228. }
  2229. // Loop through markers
  2230. foreach ($markers as $marker)
  2231. {
  2232. if ($pcre)
  2233. {
  2234. if (preg_match($pcre, (string) $marker->Key))
  2235. {
  2236. $this->batch($q)->delete_object($bucket, (string) $marker->Key, array(
  2237. 'versionId' => (string) $marker->VersionId
  2238. ));
  2239. }
  2240. }
  2241. else
  2242. {
  2243. $this->batch($q)->delete_object($bucket, (string) $marker->Key, array(
  2244. 'versionId' => (string) $marker->VersionId
  2245. ));
  2246. }
  2247. }
  2248. return $this->batch($q)->send();
  2249. }
  2250. /**
  2251. * Method: get_object_metadata()
  2252. * Gets the collective metadata for the given Amazon S3 object.
  2253. *
  2254. * Access:
  2255. * public
  2256. *
  2257. * Parameters:
  2258. * $bucket - _string_ (Required) The name of the bucket to use.
  2259. * $filename - _string_ (Required) The file name for the Amazon S3 object.
  2260. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2261. *
  2262. * Keys for the $opt parameter:
  2263. * versionId - _string_ (Optional) The version of the object to retrieve. Version IDs are returned in the `x-amz-version-id` header of any previous object-related request.
  2264. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2265. *
  2266. * Returns:
  2267. * _mixed_ If the object exists, the method returns the collective metadata for the Amazon S3 object. If the object does not exist, the method returns boolean `false`.
  2268. */
  2269. public function get_object_metadata($bucket, $filename, $opt = null)
  2270. {
  2271. $batch = new CFBatchRequest();
  2272. $this->batch($batch)->get_object_acl($bucket, $filename); // Get ACL info
  2273. $this->batch($batch)->get_object_headers($bucket, $filename); // Get content-type
  2274. $this->batch($batch)->list_objects($bucket, array( // Get other metadata
  2275. 'max-keys' => 1,
  2276. 'prefix' => $filename
  2277. ));
  2278. $response = $this->batch($batch)->send();
  2279. // Fail if any requests were unsuccessful
  2280. if (!$response->areOK())
  2281. {
  2282. return false;
  2283. }
  2284. $data = array(
  2285. 'ACL' => array(),
  2286. 'ContentType' => null,
  2287. 'ETag' => null,
  2288. 'Headers' => null,
  2289. 'Key' => null,
  2290. 'LastModified' => null,
  2291. 'Owner' => array(),
  2292. 'Size' => null,
  2293. 'StorageClass' => null,
  2294. );
  2295. // Add the content type
  2296. $data['ContentType'] = (string) $response[1]->header['content-type'];
  2297. // Add the other metadata (including storage type)
  2298. $contents = json_decode(json_encode($response[2]->body->query('descendant-or-self::Contents')->first()), true);
  2299. $data = array_merge($data, (is_array($contents) ? $contents : array()));
  2300. // Add ACL info
  2301. $grants = $response[0]->body->query('descendant-or-self::Grant');
  2302. $max = count($grants);
  2303. // Add raw header info
  2304. $data['Headers'] = $response[1]->header;
  2305. foreach (array('_info', 'x-amz-id-2', 'x-amz-request-id', 'cneonction', 'server', 'content-length', 'content-type', 'etag') as $header)
  2306. {
  2307. unset($data['Headers'][$header]);
  2308. }
  2309. ksort($data['Headers']);
  2310. foreach ($grants as $grant)
  2311. {
  2312. $dgrant = array(
  2313. 'id' => (string) $this->util->try_these(array('ID', 'URI'), $grant->Grantee),
  2314. 'permission' => (string) $grant->Permission
  2315. );
  2316. $data['ACL'][] = $dgrant;
  2317. }
  2318. return $data;
  2319. }
  2320. /*%******************************************************************************************%*/
  2321. // URLS
  2322. /**
  2323. * Method: get_object_url()
  2324. * Gets the web-accessible URL for the Amazon S3 object or generates a time-limited signed request for
  2325. * a private file.
  2326. *
  2327. * Access:
  2328. * public
  2329. *
  2330. * Parameters:
  2331. * $bucket - _string_ (Required) The name of the bucket to use.
  2332. * $filename - _string_ (Required) The file name for the Amazon S3 object.
  2333. * $preauth - _integer_|_string_ (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with `strtotime()`.
  2334. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2335. *
  2336. * Keys for the $opt parameter:
  2337. * method - _string_ (Optional) The HTTP method to use for the request. Defaults to a value of `GET`.
  2338. * torrent - _boolean_ (Optional) A value of `true` will return a URL to a torrent of the Amazon S3 object. A value of `false` will return a non-torrent URL. Defaults to `false`.
  2339. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2340. *
  2341. * Returns:
  2342. * _string_ The file URL, with authentication and/or torrent parameters if requested.
  2343. *
  2344. * See Also:
  2345. * [Using Query String Authentication](http://docs.amazonwebservices.com/AmazonS3/latest/S3_QSAuth.html)
  2346. */
  2347. public function get_object_url($bucket, $filename, $preauth = 0, $opt = null)
  2348. {
  2349. // Add this to our request
  2350. if (!$opt) $opt = array();
  2351. $opt['verb'] = isset($opt['method']) ? $opt['method'] : 'GET';
  2352. $opt['resource'] = $filename;
  2353. $opt['preauth'] = $preauth;
  2354. if (isset($opt['torrent']) && $opt['torrent'])
  2355. {
  2356. $opt['sub_resource'] = 'torrent';
  2357. unset($opt['torrent']);
  2358. }
  2359. // Authenticate to S3
  2360. $current_ssl_setting = $this->use_ssl;
  2361. $this->use_ssl = false;
  2362. $response = $this->authenticate($bucket, $opt);
  2363. $this->use_ssl = $current_ssl_setting;
  2364. return $response;
  2365. }
  2366. /**
  2367. * Method: get_torrent_url()
  2368. * Gets the web-accessible URL to a torrent of the Amazon S3 object. The Amazon S3 object's access
  2369. * control list settings (ACL) MUST be set to <ACL_PUBLIC> for a valid URL to be returned.
  2370. *
  2371. * Access:
  2372. * public
  2373. *
  2374. * Parameters:
  2375. * $bucket - _string_ (Required) The name of the bucket to use.
  2376. * $filename - _string_ (Required) The file name for the object.
  2377. * $preauth - _integer_|_string_ (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with `strtotime()`.
  2378. *
  2379. * Returns:
  2380. * _string_ The torrent URL, with authentication parameters if requested.
  2381. *
  2382. * See Also:
  2383. * [Using BitTorrent to Retrieve Objects Stored in Amazon S3](http://docs.amazonwebservices.com/AmazonS3/latest/index.html?S3TorrentRetrieve.html)
  2384. */
  2385. public function get_torrent_url($bucket, $filename, $preauth = 0)
  2386. {
  2387. return $this->get_object_url($bucket, $filename, $preauth, array(
  2388. 'torrent' => true
  2389. ));
  2390. }
  2391. /*%******************************************************************************************%*/
  2392. // VERSIONING
  2393. /**
  2394. * Method: enable_versioning()
  2395. * Enables versioning support for the specified Amazon S3 bucket.
  2396. *
  2397. * Access:
  2398. * public
  2399. *
  2400. * Parameters:
  2401. * $bucket - _string_ (Required) The name of the bucket to use.
  2402. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2403. *
  2404. * Keys for the $opt parameter:
  2405. * MFASerial - _string_ (Optional) The serial number on the back of the Gemalto device. `MFASerial`, `MFAToken` and `MFAStatus` must all be set for MFA to work.
  2406. * MFAToken - _string_ (Optional) The current token displayed on the Gemalto device. `MFASerial`, `MFAToken` and `MFAStatus` must all be set for MFA to work.
  2407. * MFAStatus - _string_ (Optional) The MFA Delete status. Can be `Enabled` or `Disabled`. `MFASerial`, `MFAToken` and `MFAStatus` must all be set for MFA to work.
  2408. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2409. *
  2410. * Returns:
  2411. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  2412. *
  2413. * See Also:
  2414. * * [Multi-Factor Authentication](http://aws.amazon.com/mfa/)
  2415. */
  2416. public function enable_versioning($bucket, $opt = null)
  2417. {
  2418. if (!$opt) $opt = array();
  2419. // Add this to our request
  2420. $opt['verb'] = 'PUT';
  2421. $opt['sub_resource'] = 'versioning';
  2422. $opt['headers'] = array(
  2423. 'Content-Type' => 'application/xml'
  2424. );
  2425. $xml = simplexml_load_string($this->base_versioning_xml);
  2426. $xml->addChild('Status', 'Enabled');
  2427. // Enable MFA delete?
  2428. if (isset($opt['MFASerial']) && isset($opt['MFAToken']) && isset($opt['MFAStatus']))
  2429. {
  2430. $xml->addChild('MfaDelete', $opt['MFAStatus']);
  2431. $opt['headers']['x-amz-mfa'] = ($opt['MFASerial'] . ' ' . $opt['MFAToken']);
  2432. }
  2433. $opt['body'] = $xml->asXML();
  2434. // Authenticate to S3
  2435. return $this->authenticate($bucket, $opt);
  2436. }
  2437. /**
  2438. * Method: disable_versioning()
  2439. * Disables versioning support for the specified Amazon S3 bucket.
  2440. *
  2441. * Access:
  2442. * public
  2443. *
  2444. * Parameters:
  2445. * $bucket - _string_ (Required) The name of the bucket to use.
  2446. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2447. *
  2448. * Keys for the $opt parameter:
  2449. * MFASerial - _string_ (Optional) The serial number on the back of the Gemalto device. `MFASerial`, `MFAToken` and `MFAStatus` must all be set for MFA to work.
  2450. * MFAToken - _string_ (Optional) The current token displayed on the Gemalto device. `MFASerial`, `MFAToken` and `MFAStatus` must all be set for MFA to work.
  2451. * MFAStatus - _string_ (Optional) The MFA Delete status. Can be `Enabled` or `Disabled`. `MFASerial`, `MFAToken` and `MFAStatus` must all be set for MFA to work.
  2452. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2453. *
  2454. * Returns:
  2455. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  2456. *
  2457. * See Also:
  2458. * * [Multi-Factor Authentication](http://aws.amazon.com/mfa/)
  2459. */
  2460. public function disable_versioning($bucket, $opt = null)
  2461. {
  2462. if (!$opt) $opt = array();
  2463. // Add this to our request
  2464. $opt['verb'] = 'PUT';
  2465. $opt['sub_resource'] = 'versioning';
  2466. $opt['headers'] = array(
  2467. 'Content-Type' => 'application/xml'
  2468. );
  2469. $xml = simplexml_load_string($this->base_versioning_xml);
  2470. $xml->addChild('Status', 'Suspended');
  2471. // Enable MFA delete?
  2472. if (isset($opt['MFASerial']) && isset($opt['MFAToken']) && isset($opt['MFAStatus']))
  2473. {
  2474. $xml->addChild('MfaDelete', $opt['MFAStatus']);
  2475. $opt['headers']['x-amz-mfa'] = ($opt['MFASerial'] . ' ' . $opt['MFAToken']);
  2476. }
  2477. $opt['body'] = $xml->asXML();
  2478. // Authenticate to S3
  2479. return $this->authenticate($bucket, $opt);
  2480. }
  2481. /**
  2482. * Method: get_versioning_status()
  2483. * Gets an Amazon S3 bucket's versioning status.
  2484. *
  2485. * Access:
  2486. * public
  2487. *
  2488. * Parameters:
  2489. * $bucket - _string_ (Required) The name of the bucket to use.
  2490. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2491. *
  2492. * Keys for the $opt parameter:
  2493. * preauth - _integer_|_string_ (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with `strtotime()`.
  2494. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2495. *
  2496. * Returns:
  2497. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  2498. */
  2499. public function get_versioning_status($bucket, $opt = null)
  2500. {
  2501. if (!$opt) $opt = array();
  2502. $opt['verb'] = 'GET';
  2503. $opt['sub_resource'] = 'versioning';
  2504. // Authenticate to S3
  2505. return $this->authenticate($bucket, $opt);
  2506. }
  2507. /**
  2508. * Method: list_bucket_object_versions()
  2509. * Gets a list of all the versions of Amazon S3 objects in the specified bucket.
  2510. *
  2511. * Access:
  2512. * public
  2513. *
  2514. * Parameters:
  2515. * $bucket - _string_ (Required) The name of the bucket to use.
  2516. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2517. *
  2518. * Keys for the $opt parameter:
  2519. * delimiter - _string_ (Optional) Unicode string parameter. Keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection.
  2520. * key-marker - _string_ (Optional) Restricts the response to contain results that only occur alphabetically after the value of the `key-marker`.
  2521. * max-keys - _string_ (Optional) Limits the number of results returned in response to your query. Will return no more than this number of results, but possibly less.
  2522. * prefix - _string_ (Optional) Restricts the response to only contain results that begin with the specified prefix.
  2523. * version-id-marker - _string_ (Optional) Restricts the response to contain results that only occur alphabetically after the value of the `version-id-marker`.
  2524. * preauth - _integer_|_string_ (Optional) Specifies that a presigned URL for this request should be returned. May be passed as a number of seconds since UNIX Epoch, or any string compatible with `strtotime()`.
  2525. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2526. *
  2527. * Returns:
  2528. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  2529. */
  2530. public function list_bucket_object_versions($bucket, $opt = null)
  2531. {
  2532. if (!$opt) $opt = array();
  2533. $opt['verb'] = 'GET';
  2534. $opt['sub_resource'] = 'versions';
  2535. foreach (array('delimiter', 'key-marker', 'max-keys', 'prefix', 'version-id-marker') as $param)
  2536. {
  2537. if (isset($opt[$param]))
  2538. {
  2539. $opt['query_string'][$param] = $opt[$param];
  2540. unset($opt[$param]);
  2541. }
  2542. }
  2543. // Authenticate to S3
  2544. return $this->authenticate($bucket, $opt);
  2545. }
  2546. /*%******************************************************************************************%*/
  2547. // BUCKET POLICIES
  2548. /**
  2549. * Method: set_bucket_policy()
  2550. * Sets the policy sub-resource for the specified Amazon S3 bucket. The specified policy replaces any
  2551. * policy the bucket already has.
  2552. *
  2553. * To perform this operation, the caller must be authorized to set a policy for the bucket and have
  2554. * PutPolicy permissions. If the caller does not have PutPolicy permissions for the bucket, Amazon S3
  2555. * returns a `403 Access Denied` error. If the caller has the correct permissions but has not been
  2556. * authorized by the bucket owner, Amazon S3 returns a `405 Method Not Allowed` error.
  2557. *
  2558. * Access:
  2559. * public
  2560. *
  2561. * Parameters:
  2562. * $bucket - _string_ (Required) The name of the bucket to use.
  2563. * $policy - _CFPolicy_ (Required) The JSON policy to use.
  2564. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2565. *
  2566. * Keys for the $opt parameter:
  2567. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2568. *
  2569. * Returns:
  2570. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  2571. *
  2572. * See Also:
  2573. * - [Appendix: The Access Policy Language](http://docs.amazonwebservices.com/AmazonS3/latest/dev/AccessPolicyLanguage.html)
  2574. */
  2575. public function set_bucket_policy($bucket, CFPolicy $policy, $opt = null)
  2576. {
  2577. if (!$opt) $opt = array();
  2578. $opt['verb'] = 'PUT';
  2579. $opt['sub_resource'] = 'policy';
  2580. $opt['body'] = $policy->get_json();
  2581. // Authenticate to S3
  2582. return $this->authenticate($bucket, $opt);
  2583. }
  2584. /**
  2585. * Method: get_bucket_policy()
  2586. * Gets the policy of the specified Amazon S3 bucket.
  2587. *
  2588. * To use this operation, the caller must have GetPolicy permissions for the specified bucket and must be
  2589. * the bucket owner. If the caller does not have GetPolicy permissions, this method will generate a
  2590. * `403 Access Denied` error. If the caller has the correct permissions but is not the bucket owner, this
  2591. * method will generate a `405 Method Not Allowed` error. If the bucket does not have a policy defined for
  2592. * it, this method will generate a `404 Policy Not Found` error.
  2593. *
  2594. * Access:
  2595. * public
  2596. *
  2597. * Parameters:
  2598. * $bucket - _string_ (Required) The name of the bucket to use.
  2599. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2600. *
  2601. * Keys for the $opt parameter:
  2602. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2603. *
  2604. * Returns:
  2605. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  2606. */
  2607. public function get_bucket_policy($bucket, $opt = null)
  2608. {
  2609. if (!$opt) $opt = array();
  2610. $opt['verb'] = 'GET';
  2611. $opt['sub_resource'] = 'policy';
  2612. // Authenticate to S3
  2613. return $this->authenticate($bucket, $opt);
  2614. }
  2615. /**
  2616. * Method: delete_bucket_policy()
  2617. * Deletes the bucket policy for the specified Amazon S3 bucket. To delete the policy, the caller must
  2618. * be the bucket owner and have `DeletePolicy` permissions for the specified bucket.
  2619. *
  2620. * Access:
  2621. * public
  2622. *
  2623. * Parameters:
  2624. * $bucket - _string_ (Required) The name of the bucket to use.
  2625. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2626. *
  2627. * Keys for the $opt parameter:
  2628. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2629. *
  2630. * Returns:
  2631. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response. If you do not have `DeletePolicy` permissions, Amazon S3 returns a `403 Access Denied` error. If you have the correct permissions, but are not the bucket owner, Amazon S3 returns a `405 Method Not Allowed` error. If the bucket doesn't have a policy, Amazon S3 returns a `204 No Content` error.
  2632. */
  2633. public function delete_bucket_policy($bucket, $opt = null)
  2634. {
  2635. if (!$opt) $opt = array();
  2636. $opt['verb'] = 'DELETE';
  2637. $opt['sub_resource'] = 'policy';
  2638. // Authenticate to S3
  2639. return $this->authenticate($bucket, $opt);
  2640. }
  2641. /*%******************************************************************************************%*/
  2642. // BUCKET NOTIFICATIONS
  2643. /**
  2644. * Method: create_bucket_notification()
  2645. * Enables notifications of specified events for an Amazon S3 bucket. Currently, the
  2646. * `s3:ReducedRedundancyLostObject` event is the only event supported for notifications. The
  2647. * `s3:ReducedRedundancyLostObject` event is triggered when Amazon S3 detects that it has lost all
  2648. * copies of an Amazon S3 object and can no longer service requests for that object.
  2649. *
  2650. * If the bucket owner and Amazon SNS topic owner are the same, the bucket owner has permission to
  2651. * publish notifications to the topic by default. Otherwise, the owner of the topic must create a
  2652. * policy to enable the bucket owner to publish to the topic.
  2653. *
  2654. * By default, only the bucket owner can configure notifications on a bucket. However, bucket owners
  2655. * can use bucket policies to grant permission to other users to set this configuration with the
  2656. * `s3:PutBucketNotification` permission.
  2657. *
  2658. * After a PUT operation is called to configure notifications on a bucket, Amazon S3 publishes a test
  2659. * notification to ensure that the topic exists and that the bucket owner has permission to publish
  2660. * to the specified topic. If the notification is successfully published to the SNS topic, the PUT
  2661. * operation updates the bucket configuration and returns the 200 OK responses with a
  2662. * `x-amz-sns-test-message-id` header containing the message ID of the test notification sent to topic.
  2663. *
  2664. * Access:
  2665. * public
  2666. *
  2667. * Parameters:
  2668. * $bucket - _string_ (Required) The name of the bucket to create bucket notifications for.
  2669. * $topic_arn - _string_ (Required) The SNS topic ARN to send notifications to.
  2670. * $event - _string_ (Required) The event type to listen for.
  2671. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2672. *
  2673. * Keys for the $opt parameter:
  2674. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2675. *
  2676. * Returns:
  2677. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  2678. *
  2679. * See Also:
  2680. * - [Setting Up Notification of Bucket Events](http://docs.amazonwebservices.com/AmazonS3/latest/dev/NotificationHowTo.html)
  2681. */
  2682. public function create_bucket_notification($bucket, $topic_arn, $event, $opt = null)
  2683. {
  2684. if (!$opt) $opt = array();
  2685. $opt['verb'] = 'PUT';
  2686. $opt['sub_resource'] = 'notification';
  2687. $opt['headers'] = array(
  2688. 'Content-Type' => 'application/xml'
  2689. );
  2690. $xml = simplexml_load_string($this->base_notification_xml);
  2691. $topic_config = $xml->addChild('TopicConfiguration');
  2692. $topic_config->addChild('Topic', $topic_arn);
  2693. $topic_config->addChild('Event', $event);
  2694. $opt['body'] = $xml->asXML();
  2695. // Authenticate to S3
  2696. return $this->authenticate($bucket, $opt);
  2697. }
  2698. /**
  2699. * Method: get_bucket_notifications()
  2700. * Gets the notification configuration of a bucket. Currently, the `s3:ReducedRedundancyLostObject` event
  2701. * is the only event supported for notifications. The `s3:ReducedRedundancyLostObject` event is triggered
  2702. * when Amazon S3 detects that it has lost all replicas of a Reduced Redundancy Storage object and can no
  2703. * longer service requests for that object.
  2704. *
  2705. * If notifications are not enabled on the bucket, the operation returns an empty
  2706. * `NotificatonConfiguration` element.
  2707. *
  2708. * By default, you must be the bucket owner to read the notification configuration of a bucket. However,
  2709. * the bucket owner can use a bucket policy to grant permission to other users to read this configuration
  2710. * with the `s3:GetBucketNotification` permission.
  2711. *
  2712. * Access:
  2713. * public
  2714. *
  2715. * Parameters:
  2716. * $bucket - _string_ (Required) The name of the bucket to use.
  2717. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2718. *
  2719. * Keys for the $opt parameter:
  2720. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2721. *
  2722. * Returns:
  2723. * _CFResponse_ A _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  2724. *
  2725. * See Also:
  2726. * - [Setting Up Notification of Bucket Events](http://docs.amazonwebservices.com/AmazonS3/latest/dev/NotificationHowTo.html)
  2727. */
  2728. public function get_bucket_notifications($bucket, $opt = null)
  2729. {
  2730. if (!$opt) $opt = array();
  2731. $opt['verb'] = 'GET';
  2732. $opt['sub_resource'] = 'notification';
  2733. // Authenticate to S3
  2734. return $this->authenticate($bucket, $opt);
  2735. }
  2736. /**
  2737. * Method: delete_bucket_notification()
  2738. * Empties the list of SNS topics to send notifications to.
  2739. *
  2740. * Access:
  2741. * public
  2742. *
  2743. * Parameters:
  2744. * $bucket - _string_ (Required) The name of the bucket to use.
  2745. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2746. *
  2747. * Keys for the $opt parameter:
  2748. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2749. *
  2750. * Returns:
  2751. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  2752. *
  2753. * See Also:
  2754. * - [Setting Up Notification of Bucket Events](http://docs.amazonwebservices.com/AmazonS3/latest/dev/NotificationHowTo.html)
  2755. */
  2756. public function delete_bucket_notification($bucket, $opt = null)
  2757. {
  2758. if (!$opt) $opt = array();
  2759. $opt['verb'] = 'PUT';
  2760. $opt['sub_resource'] = 'notification';
  2761. $opt['body'] = $this->base_notification_xml;
  2762. // Authenticate to S3
  2763. return $this->authenticate($bucket, $opt);
  2764. }
  2765. /*%******************************************************************************************%*/
  2766. // MULTIPART UPLOAD
  2767. /**
  2768. * Method: get_multipart_counts()
  2769. * Calculates the correct values for sequentially reading a file for multipart upload. This method should
  2770. * be used in conjunction with <upload_part()>.
  2771. *
  2772. * Access:
  2773. * public
  2774. *
  2775. * Parameters:
  2776. * $filesize - _integer_ (Required) The size in bytes of the entire file.
  2777. * $part_size - _integer_ (Required) The size in bytes of the part of the file to send.
  2778. *
  2779. * Returns:
  2780. * _array_ An array containing key-value pairs. The keys are `seekTo` and `length`.
  2781. */
  2782. public function get_multipart_counts($filesize, $part_size)
  2783. {
  2784. $i = 0;
  2785. $sizecount = $filesize;
  2786. $values = array();
  2787. while ($sizecount > 0)
  2788. {
  2789. $sizecount -= $part_size;
  2790. $values[] = array(
  2791. 'seekTo' => ($part_size * $i),
  2792. 'length' => (($sizecount > 0) ? $part_size : ($sizecount + $part_size)),
  2793. );
  2794. $i++;
  2795. }
  2796. return $values;
  2797. }
  2798. /**
  2799. * Method: initiate_multipart_upload()
  2800. * Initiates a multipart upload and returns an `UploadId`.
  2801. *
  2802. * Access:
  2803. * public
  2804. *
  2805. * Parameters:
  2806. * $bucket - _string_ (Required) The name of the bucket to use.
  2807. * $filename - _string_ (Required) The file name for the object.
  2808. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2809. *
  2810. * Keys for the $opt parameter:
  2811. * acl - _string_ (Optional) The ACL settings for the specified object. [Allowed values: `AmazonS3::ACL_PRIVATE`, `AmazonS3::ACL_PUBLIC`, `AmazonS3::ACL_OPEN`, `AmazonS3::ACL_AUTH_READ`, `AmazonS3::ACL_OWNER_READ`, `AmazonS3::ACL_OWNER_FULL_CONTROL`]. The default value is <ACL_PRIVATE>.
  2812. * contentType - _string_ (Optional) The type of content that is being sent. The default value is `application/octet-stream`.
  2813. * headers - _array_ (Optional) The standard HTTP headers to send along in the request.
  2814. * meta - _array_ (Optional) An associative array of key-value pairs. Any header starting with `x-amz-meta-:` is considered user metadata. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.
  2815. * storage - _string_ (Optional) Whether to use Standard or Reduced Redundancy storage. [Allowed values: `AmazonS3::STORAGE_STANDARD`, `AmazonS3::STORAGE_REDUCED`]. The default value is <STORAGE_STANDARD>.
  2816. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2817. *
  2818. * Returns:
  2819. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  2820. *
  2821. * See Also:
  2822. * [REST Access Control Policy](http://docs.amazonwebservices.com/AmazonS3/latest/RESTAccessPolicy.html)
  2823. */
  2824. public function initiate_multipart_upload($bucket, $filename, $opt = null)
  2825. {
  2826. if (!$opt) $opt = array();
  2827. // Add this to our request
  2828. $opt['verb'] = 'POST';
  2829. $opt['resource'] = $filename;
  2830. $opt['sub_resource'] = 'uploads';
  2831. // Handle content type. Can also be passed as an HTTP header.
  2832. if (isset($opt['contentType']))
  2833. {
  2834. $opt['headers']['Content-Type'] = $opt['contentType'];
  2835. unset($opt['contentType']);
  2836. }
  2837. // Handle Access Control Lists. Can also be passed as an HTTP header.
  2838. if (isset($opt['acl']))
  2839. {
  2840. $opt['headers']['x-amz-acl'] = $opt['acl'];
  2841. unset($opt['acl']);
  2842. }
  2843. // Handle storage settings. Can also be passed as an HTTP header.
  2844. if (isset($opt['storage']))
  2845. {
  2846. $opt['headers']['x-amz-storage-class'] = $opt['storage'];
  2847. unset($opt['storage']);
  2848. }
  2849. // Handle meta tags. Can also be passed as an HTTP header.
  2850. if (isset($opt['meta']))
  2851. {
  2852. foreach ($opt['meta'] as $meta_key => $meta_value)
  2853. {
  2854. // e.g., `My Meta Header` is converted to `x-amz-meta-my-meta-header`.
  2855. $opt['headers']['x-amz-meta-' . strtolower(str_replace(' ', '-', $meta_key))] = $meta_value;
  2856. }
  2857. unset($opt['meta']);
  2858. }
  2859. // Authenticate to S3
  2860. return $this->authenticate($bucket, $opt);
  2861. }
  2862. /**
  2863. * Method: upload_part()
  2864. * Uploads a single part of a multipart upload. The part size cannot be smaller than 5 MB
  2865. * or larger than 5 GB. A multipart upload can have no more than 10,000 parts.
  2866. *
  2867. * Amazon S3 charges for storage as well as requests to the service. Smaller part sizes (and more
  2868. * requests) allow for faster failures and better upload reliability. Larger part sizes (and fewer
  2869. * requests) costs slightly less but has lower upload reliability.
  2870. *
  2871. * Access:
  2872. * public
  2873. *
  2874. * Parameters:
  2875. * $bucket - _string_ (Required) The name of the bucket to use.
  2876. * $filename - _string_ (Required) The file name for the object.
  2877. * $upload_id - _string_ (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
  2878. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2879. *
  2880. * Keys for the $opt parameter:
  2881. * fileUpload - _string_|_resource_ (Required) The file system path for the local file to upload or an open file resource.
  2882. * partNumber - _integer_ (Required) The part number order of the multipart upload.
  2883. * expect - _string_ (Optional) Specifies that the SDK not send the request body until it receives an acknowledgement. If the message is rejected based on the headers, the body of the message is not sent. For more information, see [RFC 2616, section 14.20](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.20). The value can also be passed to the `header` option as `Expect`. [Allowed values: `100-continue`]
  2884. * headers - _array_ (Optional) The standard HTTP headers to send along in the request.
  2885. * length - _integer_ (Optional) The size of the part in bytes. For more information, see [RFC 2616, section 14.13](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13). The value can also be passed to the `header` option as `Content-Length`.
  2886. * md5 - _string_ (Optional) The base64 encoded 128-bit MD5 digest of the part data. This header can be used as a message integrity check to verify that the part data is the same data that was originally sent. Although it is optional, we recommend using this mechanism as an end-to-end integrity check. For more information, see [RFC 1864](http://www.ietf.org/rfc/rfc1864.txt). The value can also be passed to the `header` option as `Content-MD5`.
  2887. * seekTo - _integer_ (Optional) The starting position in bytes for the piece of the file to upload.
  2888. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2889. *
  2890. * Returns:
  2891. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  2892. */
  2893. public function upload_part($bucket, $filename, $upload_id, $opt = null)
  2894. {
  2895. if (!$opt) $opt = array();
  2896. // Add this to our request
  2897. $opt['verb'] = 'PUT';
  2898. $opt['resource'] = $filename;
  2899. $opt['uploadId'] = $upload_id;
  2900. if (!isset($opt['fileUpload']) || !isset($opt['partNumber']))
  2901. {
  2902. throw new S3_Exception('The `fileUpload` and `partNumber` options are both required in ' . __FUNCTION__ . '().');
  2903. }
  2904. // Handle expectation. Can also be passed as an HTTP header.
  2905. if (isset($opt['expect']))
  2906. {
  2907. $opt['headers']['Expect'] = $opt['expect'];
  2908. unset($opt['expect']);
  2909. }
  2910. // Handle content md5. Can also be passed as an HTTP header.
  2911. if (isset($opt['md5']))
  2912. {
  2913. $opt['headers']['Content-MD5'] = $opt['md5'];
  2914. unset($opt['md5']);
  2915. }
  2916. // Authenticate to S3
  2917. return $this->authenticate($bucket, $opt);
  2918. }
  2919. /**
  2920. * Method: list_parts()
  2921. * Lists the completed parts of an in-progress multipart upload.
  2922. *
  2923. * Access:
  2924. * public
  2925. *
  2926. * Parameters:
  2927. * $bucket - _string_ (Required) The name of the bucket to use.
  2928. * $filename - _string_ (Required) The file name for the object.
  2929. * $upload_id - _string_ (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
  2930. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2931. *
  2932. * Keys for the $opt parameter:
  2933. * max-parts - _string_ (Optional) The maximum number of parts to return in the response body.
  2934. * part-number-marker - _string_ (Optional) Restricts the response to contain results that only occur numerically after the value of the `part-number-marker`.
  2935. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2936. *
  2937. * Returns:
  2938. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  2939. */
  2940. public function list_parts($bucket, $filename, $upload_id, $opt = null)
  2941. {
  2942. if (!$opt) $opt = array();
  2943. // Add this to our request
  2944. $opt['verb'] = 'GET';
  2945. $opt['resource'] = $filename;
  2946. $opt['uploadId'] = $upload_id;
  2947. $opt['query_string'] = array();
  2948. foreach (array('max-parts', 'part-number-marker') as $param)
  2949. {
  2950. if (isset($opt[$param]))
  2951. {
  2952. $opt['query_string'][$param] = $opt[$param];
  2953. unset($opt[$param]);
  2954. }
  2955. }
  2956. // Authenticate to S3
  2957. return $this->authenticate($bucket, $opt);
  2958. }
  2959. /**
  2960. * Method: abort_multipart_upload()
  2961. * Aborts an in-progress multipart upload. This operation cannot be reversed.
  2962. *
  2963. * Access:
  2964. * public
  2965. *
  2966. * Parameters:
  2967. * $bucket - _string_ (Required) The name of the bucket to use.
  2968. * $filename - _string_ (Required) The file name for the object.
  2969. * $upload_id - _string_ (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
  2970. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  2971. *
  2972. * Keys for the $opt parameter:
  2973. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  2974. *
  2975. * Returns:
  2976. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  2977. */
  2978. public function abort_multipart_upload($bucket, $filename, $upload_id, $opt = null)
  2979. {
  2980. if (!$opt) $opt = array();
  2981. // Add this to our request
  2982. $opt['verb'] = 'DELETE';
  2983. $opt['resource'] = $filename;
  2984. $opt['uploadId'] = $upload_id;
  2985. // Authenticate to S3
  2986. return $this->authenticate($bucket, $opt);
  2987. }
  2988. /**
  2989. * Method: complete_multipart_upload()
  2990. * Completes an in-progress multipart upload.
  2991. *
  2992. * A multipart upload is completed by describing the part numbers and corresponding ETag values in order, and submitting that data to Amazon S3 as an XML document.
  2993. *
  2994. * Access:
  2995. * public
  2996. *
  2997. * Parameters:
  2998. * $bucket - _string_ (Required) The name of the bucket to use.
  2999. * $filename - _string_ (Required) The file name for the object.
  3000. * $upload_id - _string_ (Required) The upload ID identifying the multipart upload whose parts are being listed. The upload ID is retrieved from a call to <initiate_multipart_upload()>.
  3001. * $parts - _string_|_array_|_SimpleXMLElement_|_CFResponse_ (Required) The completion XML document. This document can be provided in multiple ways; as a string of XML, as a `SimpleXMLElement` object representing the XML document, as an indexed array of associative arrays where the keys are `PartNumber` and `ETag`, or as a `CFResponse` object returned by <list_parts()>.
  3002. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  3003. *
  3004. * Keys for the $opt parameter:
  3005. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  3006. *
  3007. * Returns:
  3008. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  3009. */
  3010. public function complete_multipart_upload($bucket, $filename, $upload_id, $parts, $opt = null)
  3011. {
  3012. if (!$opt) $opt = array();
  3013. // Add this to our request
  3014. $opt['verb'] = 'POST';
  3015. $opt['resource'] = $filename;
  3016. $opt['uploadId'] = $upload_id;
  3017. $opt['headers'] = array(
  3018. 'Content-Type' => 'application/xml'
  3019. );
  3020. // Disable Content-MD5 calculation for this operation
  3021. $opt['NoContentMD5'] = true;
  3022. if (is_string($parts))
  3023. {
  3024. // Assume it's the intended XML.
  3025. $opt['body'] = $xml;
  3026. }
  3027. elseif ($parts instanceof SimpleXMLElement)
  3028. {
  3029. // Assume it's a SimpleXMLElement object representing the XML.
  3030. $opt['body'] = $xml->asXML();
  3031. }
  3032. elseif (is_array($parts) || $parts instanceof CFResponse)
  3033. {
  3034. $xml = simplexml_load_string($this->complete_mpu_xml);
  3035. if (is_array($parts))
  3036. {
  3037. // Generate the appropriate XML.
  3038. foreach ($parts as $node)
  3039. {
  3040. $part = $xml->addChild('Part');
  3041. $part->addChild('PartNumber', $node['PartNumber']);
  3042. $part->addChild('ETag', $node['ETag']);
  3043. }
  3044. }
  3045. elseif ($parts instanceof CFResponse)
  3046. {
  3047. // Assume it's a response from list_parts().
  3048. foreach ($parts->body->Part as $node)
  3049. {
  3050. $part = $xml->addChild('Part');
  3051. $part->addChild('PartNumber', (string) $node->PartNumber);
  3052. $part->addChild('ETag', (string) $node->ETag);
  3053. }
  3054. }
  3055. $opt['body'] = $xml->asXML();
  3056. }
  3057. // Authenticate to S3
  3058. return $this->authenticate($bucket, $opt);
  3059. }
  3060. /**
  3061. * Method: list_multipart_uploads()
  3062. * Lists the in-progress multipart uploads.
  3063. *
  3064. * Access:
  3065. * public
  3066. *
  3067. * Parameters:
  3068. * $bucket - _string_ (Required) The name of the bucket to use.
  3069. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  3070. *
  3071. * Keys for the $opt parameter:
  3072. * delimiter - _string_ (Optional) Keys that contain the same string between the prefix and the first occurrence of the delimiter will be rolled up into a single result element in the CommonPrefixes collection.
  3073. * key-marker - _string_ (Optional) Restricts the response to contain results that only occur alphabetically after the value of the `key-marker`. If used in conjunction with `upload-id-marker`, the results will be filtered to include keys whose upload ID is alphabetically after the value of `upload-id-marker`.
  3074. * upload-id-marker - _string_ (Optional) Restricts the response to contain results that only occur alphabetically after the value of the `upload-id-marker`. Must be used in conjunction with `key-marker`.
  3075. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  3076. *
  3077. * Returns:
  3078. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  3079. */
  3080. public function list_multipart_uploads($bucket, $opt = null)
  3081. {
  3082. if (!$opt) $opt = array();
  3083. // Add this to our request
  3084. $opt['verb'] = 'GET';
  3085. $opt['sub_resource'] = 'uploads';
  3086. foreach (array('key-marker', 'max-uploads', 'upload-id-marker') as $param)
  3087. {
  3088. if (isset($opt[$param]))
  3089. {
  3090. $opt['query_string'][$param] = $opt[$param];
  3091. unset($opt[$param]);
  3092. }
  3093. }
  3094. // Authenticate to S3
  3095. return $this->authenticate($bucket, $opt);
  3096. }
  3097. /**
  3098. * Method: create_mpu_object()
  3099. * Creates an Amazon S3 object using the multipart upload APIs. It is analogous to <create_object()>.
  3100. *
  3101. * While each individual part of a multipart upload can hold up to 5 GB of data, this method limits the
  3102. * part size to a maximum of 500 MB. The combined size of all parts can not exceed 5 GB of data. When an
  3103. * object is stored in Amazon S3, the data is streamed to multiple storage servers in multiple data
  3104. * centers. This ensures the data remains available in the event of internal network or hardware failure.
  3105. *
  3106. * Amazon S3 charges for storage as well as requests to the service. Smaller part sizes (and more
  3107. * requests) allow for faster failures and better upload reliability. Larger part sizes (and fewer
  3108. * requests) costs slightly less but has lower upload reliability.
  3109. *
  3110. * Access:
  3111. * public
  3112. *
  3113. * Parameters:
  3114. * $bucket - _string_ (Required) The name of the bucket to use.
  3115. * $filename - _string_ (Required) The file name for the object.
  3116. * $opt - _array_ (Optional) An associative array of parameters that can have the keys listed in the following section.
  3117. *
  3118. * Keys for the $opt parameter:
  3119. * fileUpload - _string_|_resource_ (Required) The file system path for the local file to upload or an open file resource.
  3120. * acl - _string_ (Optional) The ACL settings for the specified object. [Allowed values: `AmazonS3::ACL_PRIVATE`, `AmazonS3::ACL_PUBLIC`, `AmazonS3::ACL_OPEN`, `AmazonS3::ACL_AUTH_READ`, `AmazonS3::ACL_OWNER_READ`, `AmazonS3::ACL_OWNER_FULL_CONTROL`]. The default value is <ACL_PRIVATE>.
  3121. * contentType - _string_ (Optional) The type of content that is being sent in the body. The default value is `application/octet-stream`.
  3122. * headers - _array_ (Optional) The standard HTTP headers to send along in the request.
  3123. * meta - _array_ (Optional) An associative array of key-value pairs. Any header starting with `x-amz-meta-:` is considered user metadata. It will be stored with the object and returned when you retrieve the object. The total size of the HTTP request, not including the body, must be less than 4 KB.
  3124. * partSize - _integer_ (Optional) The size of an individual part. The size may not be smaller than 5 MB or larger than 500 MB. The default value is 50 MB.
  3125. * storage - _string_ (Optional) Whether to use Standard or Reduced Redundancy storage. [Allowed values: `AmazonS3::STORAGE_STANDARD`, `AmazonS3::STORAGE_REDUCED`]. The default value is <STORAGE_STANDARD>.
  3126. * uploadId - _string_ (Optional) An upload ID identifying an existing multipart upload to use. If this option is not set, one will be created automatically.
  3127. * returnCurlHandle - _boolean_ (Optional) A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.
  3128. *
  3129. * Returns:
  3130. * _CFResponse_ A <CFResponse> object containing a parsed HTTP response.
  3131. *
  3132. * See Also:
  3133. * [REST Access Control Policy](http://docs.amazonwebservices.com/AmazonS3/latest/RESTAccessPolicy.html)
  3134. */
  3135. public function create_mpu_object($bucket, $filename, $opt = null)
  3136. {
  3137. // Don't timeout!
  3138. set_time_limit(0);
  3139. if (!isset($opt['fileUpload']))
  3140. {
  3141. throw new S3_Exception('The `fileUpload` option is required in ' . __FUNCTION__ . '().');
  3142. }
  3143. // Handle part size
  3144. if (isset($opt['partSize']))
  3145. {
  3146. // If less that 5 MB...
  3147. if ((integer) $opt['partSize'] < 5242880)
  3148. {
  3149. $opt['partSize'] = 5242880; // 5 MB
  3150. }
  3151. // If more than 500 MB...
  3152. elseif ((integer) $opt['partSize'] > 524288000)
  3153. {
  3154. $opt['partSize'] = 524288000; // 500 MB
  3155. }
  3156. }
  3157. else
  3158. {
  3159. $opt['partSize'] = 52428800; // 50 MB
  3160. }
  3161. $upload_filesize = filesize($opt['fileUpload']);
  3162. // If the upload size is smaller than the piece size, failover to create_object().
  3163. if ($upload_filesize < $opt['partSize'])
  3164. {
  3165. return $this->create_object($bucket, $filename, $opt);
  3166. }
  3167. // Initiate multipart upload
  3168. if (isset($opt['uploadId']))
  3169. {
  3170. $upload_id = $opt['uploadId'];
  3171. }
  3172. else
  3173. {
  3174. // Compose options for initiate_multipart_upload().
  3175. $_opt = array();
  3176. foreach (array('contentType', 'acl', 'storage', 'headers', 'meta') as $param)
  3177. {
  3178. if (isset($opt[$param]))
  3179. {
  3180. $_opt[$param] = $opt[$param];
  3181. }
  3182. }
  3183. $upload = $this->initiate_multipart_upload($bucket, $filename, $_opt);
  3184. if (!$upload->isOK())
  3185. {
  3186. return false;
  3187. }
  3188. // Fetch the UploadId
  3189. $upload_id = (string) $upload->body->UploadId;
  3190. }
  3191. // Get the list of pieces
  3192. $pieces = $this->get_multipart_counts($upload_filesize, (integer) $opt['partSize']);
  3193. // Queue batch requests
  3194. $batch = new CFBatchRequest();
  3195. foreach ($pieces as $i => $piece)
  3196. {
  3197. $this->batch($batch)->upload_part($bucket, $filename, $upload_id, array(
  3198. 'expect' => '100-continue',
  3199. 'fileUpload' => $opt['fileUpload'],
  3200. 'partNumber' => ($i + 1),
  3201. 'seekTo' => (integer) $piece['seekTo'],
  3202. 'length' => (integer) $piece['length'],
  3203. ));
  3204. }
  3205. // Send batch requests
  3206. $batch_responses = $this->batch($batch)->send();
  3207. if (!$batch_responses->areOK())
  3208. {
  3209. return false;
  3210. }
  3211. // Compose completion XML
  3212. $parts = array();
  3213. foreach ($batch_responses as $i => $response)
  3214. {
  3215. $parts[] = array('PartNumber' => ($i + 1), 'ETag' => $response->header['etag']);
  3216. }
  3217. return $this->complete_multipart_upload($bucket, $filename, $upload_id, $parts);
  3218. }
  3219. /*%******************************************************************************************%*/
  3220. // MISCELLANEOUS
  3221. /**
  3222. * Method: get_canonical_user_id()
  3223. * Gets the canonical user ID and display name from the Amazon S3 server.
  3224. *
  3225. * Access:
  3226. * public
  3227. *
  3228. * Returns:
  3229. * _array_ An associative array containing the `id` and `display_name` values.
  3230. */
  3231. public function get_canonical_user_id()
  3232. {
  3233. if ($this->use_batch_flow)
  3234. {
  3235. throw new S3_Exception(__FUNCTION__ . '() cannot be batch requested');
  3236. }
  3237. $id = $this->list_buckets();
  3238. return array(
  3239. 'id' => (string) $id->body->Owner->ID,
  3240. 'display_name' => (string) $id->body->Owner->DisplayName
  3241. );
  3242. }
  3243. }