PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/plugins/backupbuddy/destinations/stash/lib/aws-sdk/services/s3.class.php

https://bitbucket.org/betaimages/chakalos
PHP | 4305 lines | 2127 code | 568 blank | 1610 comment | 334 complexity | d8c2ead3b17bc6051d2ba15b225f5165 MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. * Copyright 2010-2012 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. // EXCEPTIONS
  18. /**
  19. * Default S3 Exception.
  20. */
  21. class S3_Exception extends Exception {}
  22. /*%******************************************************************************************%*/
  23. // MAIN CLASS
  24. /**
  25. * Amazon S3 is a web service that enables you to store data in the cloud. You can then download the data
  26. * or use the data with other AWS services, such as Amazon Elastic Cloud Computer (EC2).
  27. *
  28. * Amazon Simple Storage Service (Amazon S3) is storage for the Internet. You can use Amazon S3 to store
  29. * and retrieve any amount of data at any time, from anywhere on the web. You can accomplish these tasks
  30. * using the AWS Management Console, which is a simple and intuitive web interface.
  31. *
  32. * To get the most out of Amazon S3, you need to understand a few simple concepts. Amazon S3 stores data
  33. * as objects in buckets. An object is comprised of a file and optionally any metadata that describes
  34. * that file.
  35. *
  36. * To store an object in Amazon S3, you upload the file you want to store to a bucket. When you upload a
  37. * file, you can set permissions on the object as well as any metadata.
  38. *
  39. * Buckets are the containers for objects. You can have one or more buckets. For each bucket, you can control
  40. * access to the bucket (who can create, delete, and list objects in the bucket), view access logs for the
  41. * bucket and its objects, and choose the geographical region where Amazon S3 will store the bucket and its
  42. * contents.
  43. *
  44. * Visit <http://aws.amazon.com/s3/> for more information.
  45. *
  46. * @version 2012.08.28
  47. * @license See the included NOTICE.md file for more information.
  48. * @copyright See the included NOTICE.md file for more information.
  49. * @link http://aws.amazon.com/s3/ Amazon Simple Storage Service
  50. * @link http://aws.amazon.com/documentation/s3/ Amazon Simple Storage Service documentation
  51. */
  52. class AmazonS3 extends CFRuntime
  53. {
  54. /*%******************************************************************************************%*/
  55. // REGIONAL ENDPOINTS
  56. /**
  57. * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Region.
  58. */
  59. const REGION_US_E1 = 's3.amazonaws.com';
  60. /**
  61. * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Region.
  62. */
  63. const REGION_VIRGINIA = self::REGION_US_E1;
  64. /**
  65. * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Region.
  66. */
  67. const REGION_US_STANDARD = self::REGION_US_E1;
  68. /**
  69. * Specify the queue URL for the US-West 1 (Northern California) Region.
  70. */
  71. const REGION_US_W1 = 's3-us-west-1.amazonaws.com';
  72. /**
  73. * Specify the queue URL for the US-West 1 (Northern California) Region.
  74. */
  75. const REGION_CALIFORNIA = self::REGION_US_W1;
  76. /**
  77. * Specify the queue URL for the US-West 2 (Oregon) Region.
  78. */
  79. const REGION_US_W2 = 's3-us-west-2.amazonaws.com';
  80. /**
  81. * Specify the queue URL for the US-West 2 (Oregon) Region.
  82. */
  83. const REGION_OREGON = self::REGION_US_W2;
  84. /**
  85. * Specify the queue URL for the EU (Ireland) Region.
  86. */
  87. const REGION_EU_W1 = 's3-eu-west-1.amazonaws.com';
  88. /**
  89. * Specify the queue URL for the EU (Ireland) Region.
  90. */
  91. const REGION_IRELAND = self::REGION_EU_W1;
  92. /**
  93. * Specify the queue URL for the Asia Pacific (Singapore) Region.
  94. */
  95. const REGION_APAC_SE1 = 's3-ap-southeast-1.amazonaws.com';
  96. /**
  97. * Specify the queue URL for the Asia Pacific (Singapore) Region.
  98. */
  99. const REGION_SINGAPORE = self::REGION_APAC_SE1;
  100. /**
  101. * Specify the queue URL for the Asia Pacific (Japan) Region.
  102. */
  103. const REGION_APAC_NE1 = 's3-ap-northeast-1.amazonaws.com';
  104. /**
  105. * Specify the queue URL for the Asia Pacific (Japan) Region.
  106. */
  107. const REGION_TOKYO = self::REGION_APAC_NE1;
  108. /**
  109. * Specify the queue URL for the South America (Sao Paulo) Region.
  110. */
  111. const REGION_SA_E1 = 's3-sa-east-1.amazonaws.com';
  112. /**
  113. * Specify the queue URL for the South America (Sao Paulo) Region.
  114. */
  115. const REGION_SAO_PAULO = self::REGION_SA_E1;
  116. /**
  117. * Specify the queue URL for the United States GovCloud Region.
  118. */
  119. const REGION_US_GOV1 = 's3-us-gov-west-1.amazonaws.com';
  120. /**
  121. * Specify the queue URL for the United States GovCloud FIPS 140-2 Region.
  122. */
  123. const REGION_US_GOV1_FIPS = 's3-fips-us-gov-west-1.amazonaws.com';
  124. /**
  125. * The default endpoint.
  126. */
  127. const DEFAULT_URL = self::REGION_US_E1;
  128. /*%******************************************************************************************%*/
  129. // REGIONAL WEBSITE ENDPOINTS
  130. /**
  131. * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Website Region.
  132. */
  133. const REGION_US_E1_WEBSITE = 's3-website-us-east-1.amazonaws.com';
  134. /**
  135. * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Website Region.
  136. */
  137. const REGION_VIRGINIA_WEBSITE = self::REGION_US_E1_WEBSITE;
  138. /**
  139. * Specify the queue URL for the US-Standard (Northern Virginia & Washington State) Website Region.
  140. */
  141. const REGION_US_STANDARD_WEBSITE = self::REGION_US_E1_WEBSITE;
  142. /**
  143. * Specify the queue URL for the US-West 1 (Northern California) Website Region.
  144. */
  145. const REGION_US_W1_WEBSITE = 's3-website-us-west-1.amazonaws.com';
  146. /**
  147. * Specify the queue URL for the US-West 1 (Northern California) Website Region.
  148. */
  149. const REGION_CALIFORNIA_WEBSITE = self::REGION_US_W1_WEBSITE;
  150. /**
  151. * Specify the queue URL for the US-West 2 (Oregon) Website Region.
  152. */
  153. const REGION_US_W2_WEBSITE = 's3-website-us-west-2.amazonaws.com';
  154. /**
  155. * Specify the queue URL for the US-West 2 (Oregon) Website Region.
  156. */
  157. const REGION_OREGON_WEBSITE = self::REGION_US_W2_WEBSITE;
  158. /**
  159. * Specify the queue URL for the EU (Ireland) Website Region.
  160. */
  161. const REGION_EU_W1_WEBSITE = 's3-website-eu-west-1.amazonaws.com';
  162. /**
  163. * Specify the queue URL for the EU (Ireland) Website Region.
  164. */
  165. const REGION_IRELAND_WEBSITE = self::REGION_EU_W1_WEBSITE;
  166. /**
  167. * Specify the queue URL for the Asia Pacific (Singapore) Website Region.
  168. */
  169. const REGION_APAC_SE1_WEBSITE = 's3-website-ap-southeast-1.amazonaws.com';
  170. /**
  171. * Specify the queue URL for the Asia Pacific (Singapore) Website Region.
  172. */
  173. const REGION_SINGAPORE_WEBSITE = self::REGION_APAC_SE1_WEBSITE;
  174. /**
  175. * Specify the queue URL for the Asia Pacific (Japan) Website Region.
  176. */
  177. const REGION_APAC_NE1_WEBSITE = 's3-website-ap-northeast-1.amazonaws.com';
  178. /**
  179. * Specify the queue URL for the Asia Pacific (Japan) Website Region.
  180. */
  181. const REGION_TOKYO_WEBSITE = self::REGION_APAC_NE1_WEBSITE;
  182. /**
  183. * Specify the queue URL for the South America (Sao Paulo) Website Region.
  184. */
  185. const REGION_SA_E1_WEBSITE = 's3-website-sa-east-1.amazonaws.com';
  186. /**
  187. * Specify the queue URL for the South America (Sao Paulo) Website Region.
  188. */
  189. const REGION_SAO_PAULO_WEBSITE = self::REGION_SA_E1_WEBSITE;
  190. /**
  191. * Specify the queue URL for the United States GovCloud Website Region.
  192. */
  193. const REGION_US_GOV1_WEBSITE = 's3-website-us-gov-west-1.amazonaws.com';
  194. /*%******************************************************************************************%*/
  195. // ACL
  196. /**
  197. * ACL: Owner-only read/write.
  198. */
  199. const ACL_PRIVATE = 'private';
  200. /**
  201. * ACL: Owner read/write, public read.
  202. */
  203. const ACL_PUBLIC = 'public-read';
  204. /**
  205. * ACL: Public read/write.
  206. */
  207. const ACL_OPEN = 'public-read-write';
  208. /**
  209. * ACL: Owner read/write, authenticated read.
  210. */
  211. const ACL_AUTH_READ = 'authenticated-read';
  212. /**
  213. * ACL: Bucket owner read.
  214. */
  215. const ACL_OWNER_READ = 'bucket-owner-read';
  216. /**
  217. * ACL: Bucket owner full control.
  218. */
  219. const ACL_OWNER_FULL_CONTROL = 'bucket-owner-full-control';
  220. /*%******************************************************************************************%*/
  221. // GRANTS
  222. /**
  223. * When applied to a bucket, grants permission to list the bucket. When applied to an object, this
  224. * grants permission to read the object data and/or metadata.
  225. */
  226. const GRANT_READ = 'READ';
  227. /**
  228. * When applied to a bucket, grants permission to create, overwrite, and delete any object in the
  229. * bucket. This permission is not supported for objects.
  230. */
  231. const GRANT_WRITE = 'WRITE';
  232. /**
  233. * Grants permission to read the ACL for the applicable bucket or object. The owner of a bucket or
  234. * object always has this permission implicitly.
  235. */
  236. const GRANT_READ_ACP = 'READ_ACP';
  237. /**
  238. * Gives permission to overwrite the ACP for the applicable bucket or object. The owner of a bucket
  239. * or object always has this permission implicitly. Granting this permission is equivalent to granting
  240. * FULL_CONTROL because the grant recipient can make any changes to the ACP.
  241. */
  242. const GRANT_WRITE_ACP = 'WRITE_ACP';
  243. /**
  244. * Provides READ, WRITE, READ_ACP, and WRITE_ACP permissions. It does not convey additional rights and
  245. * is provided only for convenience.
  246. */
  247. const GRANT_FULL_CONTROL = 'FULL_CONTROL';
  248. /*%******************************************************************************************%*/
  249. // USERS
  250. /**
  251. * The "AuthenticatedUsers" group for access control policies.
  252. */
  253. const USERS_AUTH = 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers';
  254. /**
  255. * The "AllUsers" group for access control policies.
  256. */
  257. const USERS_ALL = 'http://acs.amazonaws.com/groups/global/AllUsers';
  258. /**
  259. * The "LogDelivery" group for access control policies.
  260. */
  261. const USERS_LOGGING = 'http://acs.amazonaws.com/groups/s3/LogDelivery';
  262. /*%******************************************************************************************%*/
  263. // PATTERNS
  264. /**
  265. * PCRE: Match all items
  266. */
  267. const PCRE_ALL = '/.*/i';
  268. /*%******************************************************************************************%*/
  269. // STORAGE
  270. /**
  271. * Standard storage redundancy.
  272. */
  273. const STORAGE_STANDARD = 'STANDARD';
  274. /**
  275. * Reduced storage redundancy.
  276. */
  277. const STORAGE_REDUCED = 'REDUCED_REDUNDANCY';
  278. /*%******************************************************************************************%*/
  279. // PROPERTIES
  280. /**
  281. * The request URL.
  282. */
  283. public $request_url;
  284. /**
  285. * The virtual host setting.
  286. */
  287. public $vhost;
  288. /**
  289. * The base XML elements to use for access control policy methods.
  290. */
  291. public $base_acp_xml;
  292. /**
  293. * The base XML elements to use for creating buckets in regions.
  294. */
  295. public $base_location_constraint;
  296. /**
  297. * The base XML elements to use for logging methods.
  298. */
  299. public $base_logging_xml;
  300. /**
  301. * The base XML elements to use for notifications.
  302. */
  303. public $base_notification_xml;
  304. /**
  305. * The base XML elements to use for versioning.
  306. */
  307. public $base_versioning_xml;
  308. /**
  309. * The base XML elements to use for completing a multipart upload.
  310. */
  311. public $complete_mpu_xml;
  312. /**
  313. * The base XML elements to use for website support.
  314. */
  315. public $website_config_xml;
  316. /**
  317. * The base XML elements to use for multi-object delete support.
  318. */
  319. public $multi_object_delete_xml;
  320. /**
  321. * The base XML elements to use for object expiration support.
  322. */
  323. public $object_expiration_xml;
  324. /**
  325. * The base XML elements to use for CORS support.
  326. */
  327. public $cors_config_xml;
  328. /**
  329. * The DNS vs. Path-style setting.
  330. */
  331. public $path_style = false;
  332. /**
  333. * The state of whether the prefix change is temporary or permanent.
  334. */
  335. public $temporary_prefix = false;
  336. /*%******************************************************************************************%*/
  337. // CONSTRUCTOR
  338. /**
  339. * Constructs a new instance of <AmazonS3>.
  340. *
  341. * @param array $options (Optional) An associative array of parameters that can have the following keys: <ul>
  342. * <li><code>certificate_authority</code> - <code>boolean</code> - Optional - Determines which Cerificate Authority file to use. A value of boolean <code>false</code> will use the Certificate Authority file available on the system. A value of boolean <code>true</code> will use the Certificate Authority provided by the SDK. Passing a file system path to a Certificate Authority file (chmodded to <code>0755</code>) will use that. Leave this set to <code>false</code> if you're not sure.</li>
  343. * <li><code>credentials</code> - <code>string</code> - Optional - The name of the credential set to use for authentication.</li>
  344. * <li><code>default_cache_config</code> - <code>string</code> - Optional - This option allows a preferred storage type to be configured for long-term caching. This can be changed later using the <set_cache_config()> method. Valid values are: <code>apc</code>, <code>xcache</code>, or a file system path such as <code>./cache</code> or <code>/tmp/cache/</code>.</li>
  345. * <li><code>key</code> - <code>string</code> - Optional - Your AWS key, or a session key. If blank, the default credential set will be used.</li>
  346. * <li><code>secret</code> - <code>string</code> - Optional - Your AWS secret key, or a session secret key. If blank, the default credential set will be used.</li>
  347. * <li><code>token</code> - <code>string</code> - Optional - An AWS session token.</li></ul>
  348. * @return void
  349. */
  350. public function __construct(array $options = array())
  351. {
  352. $this->vhost = null;
  353. $this->api_version = '2006-03-01';
  354. $this->hostname = self::DEFAULT_URL;
  355. $this->base_acp_xml = '<?xml version="1.0" encoding="UTF-8"?><AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/latest/"/>';
  356. $this->base_location_constraint = '<?xml version="1.0" encoding="UTF-8"?><CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/' . $this->api_version . '/"><LocationConstraint/></CreateBucketConfiguration>';
  357. $this->base_logging_xml = '<?xml version="1.0" encoding="utf-8"?><BucketLoggingStatus xmlns="http://doc.s3.amazonaws.com/' . $this->api_version . '"/>';
  358. $this->base_notification_xml = '<?xml version="1.0" encoding="utf-8"?><NotificationConfiguration/>';
  359. $this->base_versioning_xml = '<?xml version="1.0" encoding="utf-8"?><VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/' . $this->api_version . '/"/>';
  360. $this->complete_mpu_xml = '<?xml version="1.0" encoding="utf-8"?><CompleteMultipartUpload/>';
  361. $this->website_config_xml = '<?xml version="1.0" encoding="utf-8"?><WebsiteConfiguration xmlns="http://s3.amazonaws.com/doc/' . $this->api_version . '/"><IndexDocument><Suffix>index.html</Suffix></IndexDocument><ErrorDocument><Key>error.html</Key></ErrorDocument></WebsiteConfiguration>';
  362. $this->multi_object_delete_xml = '<?xml version="1.0" encoding="utf-8"?><Delete/>';
  363. $this->object_expiration_xml = '<?xml version="1.0" encoding="utf-8"?><LifecycleConfiguration/>';
  364. $this->bucket_tagging_xml = '<?xml version="1.0" encoding="utf-8"?><Tagging><TagSet/></Tagging>';
  365. $this->cors_config_xml = '<?xml version="1.0" encoding="utf-8"?><CORSConfiguration />';
  366. parent::__construct($options);
  367. }
  368. /*%******************************************************************************************%*/
  369. // AUTHENTICATION
  370. /**
  371. * Authenticates a connection to Amazon S3. Do not use directly unless implementing custom methods for
  372. * this class.
  373. *
  374. * @param string $operation (Required) The name of the bucket to operate on (S3 Only).
  375. * @param array $payload (Required) An associative array of parameters for authenticating. See inline comments for allowed keys.
  376. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  377. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/S3_Authentication.html REST authentication
  378. */
  379. public function authenticate($operation, $payload)
  380. {
  381. /*
  382. * Overriding or extending this class? You can pass the following "magic" keys into $opt.
  383. *
  384. * ## verb, resource, sub_resource and query_string ##
  385. * <verb> /<resource>?<sub_resource>&<query_string>
  386. * GET /filename.txt?versions&prefix=abc&max-items=1
  387. *
  388. * ## versionId, uploadId, partNumber, response-* ##
  389. * These don't follow the same rules as above, in that the they needs to be signed, while
  390. * other query_string values do not.
  391. *
  392. * ## curlopts ##
  393. * These values get passed directly to the cURL methods in RequestCore.
  394. *
  395. * ## fileUpload, fileDownload, seekTo ##
  396. * These are slightly modified and then passed to the cURL methods in RequestCore.
  397. *
  398. * ## headers ##
  399. * $opt['headers'] is an array, whose keys are HTTP headers to be sent.
  400. *
  401. * ## body ##
  402. * This is the request body that is sent to the server via PUT/POST.
  403. *
  404. * ## preauth ##
  405. * This is a hook that tells authenticate() to generate a pre-authenticated URL.
  406. *
  407. * ## returnCurlHandle ##
  408. * Tells authenticate() to return the cURL handle for the request instead of executing it.
  409. */
  410. // Rename variables (to overcome inheritence issues)
  411. $bucket = $operation;
  412. $opt = $payload;
  413. // Validate the S3 bucket name
  414. if (!$this->validate_bucketname_support($bucket))
  415. {
  416. // @codeCoverageIgnoreStart
  417. 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.');
  418. // @codeCoverageIgnoreEnd
  419. }
  420. // Die if $opt isn't set.
  421. if (!$opt) return false;
  422. $method_arguments = func_get_args();
  423. // Use the caching flow to determine if we need to do a round-trip to the server.
  424. if ($this->use_cache_flow)
  425. {
  426. // Generate an identifier specific to this particular set of arguments.
  427. $cache_id = $this->key . '_' . get_class($this) . '_' . $bucket . '_' . sha1(serialize($method_arguments));
  428. // Instantiate the appropriate caching object.
  429. $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
  430. if ($this->delete_cache)
  431. {
  432. $this->use_cache_flow = false;
  433. $this->delete_cache = false;
  434. return $this->cache_object->delete();
  435. }
  436. // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
  437. $data = $this->cache_object->response_manager(array($this, 'cache_callback'), $method_arguments);
  438. if ($this->parse_the_response)
  439. {
  440. // Parse the XML body
  441. $data = $this->parse_callback($data);
  442. }
  443. // End!
  444. return $data;
  445. }
  446. // If we haven't already set a resource prefix and the bucket name isn't DNS-valid...
  447. if ((!$this->resource_prefix && !$this->validate_bucketname_create($bucket)) || $this->path_style)
  448. {
  449. // Fall back to the older path-style URI
  450. $this->set_resource_prefix('/' . $bucket);
  451. $this->temporary_prefix = true;
  452. }
  453. // Determine hostname
  454. $scheme = $this->use_ssl ? 'https://' : 'http://';
  455. if ($this->resource_prefix || $this->path_style) // Use bucket-in-path method.
  456. {
  457. $hostname = $this->hostname . $this->resource_prefix . (($bucket === '' || $this->resource_prefix === '/' . $bucket) ? '' : ('/' . $bucket));
  458. }
  459. else
  460. {
  461. $hostname = $this->vhost ? $this->vhost : (($bucket === '') ? $this->hostname : ($bucket . '.') . $this->hostname);
  462. }
  463. // Get the UTC timestamp in RFC 2616 format
  464. $date = gmdate(CFUtilities::DATE_FORMAT_RFC2616, time());
  465. // Storage for request parameters.
  466. $resource = '';
  467. $sub_resource = '';
  468. $querystringparams = array();
  469. $signable_querystringparams = array();
  470. $string_to_sign = '';
  471. $headers = array(
  472. 'Content-MD5' => '',
  473. 'Content-Type' => 'application/x-www-form-urlencoded',
  474. 'Date' => $date
  475. );
  476. /*%******************************************************************************************%*/
  477. // Do we have an authentication token?
  478. if ($this->auth_token)
  479. {
  480. $headers['X-Amz-Security-Token'] = $this->auth_token;
  481. }
  482. // Handle specific resources
  483. if (isset($opt['resource']))
  484. {
  485. $resource .= $opt['resource'];
  486. }
  487. // Merge query string values
  488. if (isset($opt['query_string']))
  489. {
  490. $querystringparams = array_merge($querystringparams, $opt['query_string']);
  491. }
  492. $query_string = $this->util->to_query_string($querystringparams);
  493. // Merge the signable query string values. Must be alphabetical.
  494. $signable_list = array(
  495. 'partNumber',
  496. 'response-cache-control',
  497. 'response-content-disposition',
  498. 'response-content-encoding',
  499. 'response-content-language',
  500. 'response-content-type',
  501. 'response-expires',
  502. 'uploadId',
  503. 'versionId'
  504. );
  505. foreach ($signable_list as $item)
  506. {
  507. if (isset($opt[$item]))
  508. {
  509. $signable_querystringparams[$item] = $opt[$item];
  510. }
  511. }
  512. $signable_query_string = $this->util->to_query_string($signable_querystringparams);
  513. // Merge the HTTP headers
  514. if (isset($opt['headers']))
  515. {
  516. $headers = array_merge($headers, $opt['headers']);
  517. }
  518. // Compile the URI to request
  519. $conjunction = '?';
  520. $signable_resource = '/' . str_replace('%2F', '/', rawurlencode($resource));
  521. $non_signable_resource = '';
  522. if (isset($opt['sub_resource']))
  523. {
  524. $signable_resource .= $conjunction . rawurlencode($opt['sub_resource']);
  525. $conjunction = '&';
  526. }
  527. if ($signable_query_string !== '')
  528. {
  529. $signable_query_string = $conjunction . $signable_query_string;
  530. $conjunction = '&';
  531. }
  532. if ($query_string !== '')
  533. {
  534. $non_signable_resource .= $conjunction . $query_string;
  535. $conjunction = '&';
  536. }
  537. if (substr($hostname, -1) === substr($signable_resource, 0, 1))
  538. {
  539. $signable_resource = ltrim($signable_resource, '/');
  540. }
  541. $this->request_url = $scheme . $hostname . $signable_resource . $signable_query_string . $non_signable_resource;
  542. if (isset($opt['location']))
  543. {
  544. $this->request_url = $opt['location'];
  545. }
  546. // Gather information to pass along to other classes.
  547. $helpers = array(
  548. 'utilities' => $this->utilities_class,
  549. 'request' => $this->request_class,
  550. 'response' => $this->response_class,
  551. );
  552. // Instantiate the request class
  553. $request = new $this->request_class($this->request_url, $this->proxy, $helpers, $this->credentials);
  554. // Update RequestCore settings
  555. $request->request_class = $this->request_class;
  556. $request->response_class = $this->response_class;
  557. $request->ssl_verification = $this->ssl_verification;
  558. // Pass along registered stream callbacks
  559. if ($this->registered_streaming_read_callback)
  560. {
  561. $request->register_streaming_read_callback($this->registered_streaming_read_callback);
  562. }
  563. if ($this->registered_streaming_write_callback)
  564. {
  565. $request->register_streaming_write_callback($this->registered_streaming_write_callback);
  566. }
  567. // Streaming uploads
  568. if (isset($opt['fileUpload']))
  569. {
  570. if (is_resource($opt['fileUpload']))
  571. {
  572. // Determine the length to read from the stream
  573. $length = null; // From current position until EOF by default, size determined by set_read_stream()
  574. if (isset($headers['Content-Length']))
  575. {
  576. $length = $headers['Content-Length'];
  577. }
  578. elseif (isset($opt['seekTo']))
  579. {
  580. // Read from seekTo until EOF by default
  581. $stats = fstat($opt['fileUpload']);
  582. if ($stats && $stats['size'] >= 0)
  583. {
  584. $length = $stats['size'] - (integer) $opt['seekTo'];
  585. }
  586. }
  587. $request->set_read_stream($opt['fileUpload'], $length);
  588. if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
  589. {
  590. $headers['Content-Type'] = 'application/octet-stream';
  591. }
  592. }
  593. else
  594. {
  595. $request->set_read_file($opt['fileUpload']);
  596. // Determine the length to read from the file
  597. $length = $request->read_stream_size; // The file size by default
  598. if (isset($headers['Content-Length']))
  599. {
  600. $length = $headers['Content-Length'];
  601. }
  602. elseif (isset($opt['seekTo']) && isset($length))
  603. {
  604. // Read from seekTo until EOF by default
  605. $length -= (integer) $opt['seekTo'];
  606. }
  607. $request->set_read_stream_size($length);
  608. // Attempt to guess the correct mime-type
  609. if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
  610. {
  611. $extension = explode('.', $opt['fileUpload']);
  612. $extension = array_pop($extension);
  613. $mime_type = CFMimeTypes::get_mimetype($extension);
  614. $headers['Content-Type'] = $mime_type;
  615. }
  616. }
  617. $headers['Content-Length'] = $request->read_stream_size;
  618. $headers['Content-MD5'] = '';
  619. }
  620. // Handle streaming file offsets
  621. if (isset($opt['seekTo']))
  622. {
  623. // Pass the seek position to RequestCore
  624. $request->set_seek_position((integer) $opt['seekTo']);
  625. }
  626. // Streaming downloads
  627. if (isset($opt['fileDownload']))
  628. {
  629. if (is_resource($opt['fileDownload']))
  630. {
  631. $request->set_write_stream($opt['fileDownload']);
  632. }
  633. else
  634. {
  635. $request->set_write_file($opt['fileDownload']);
  636. }
  637. }
  638. $curlopts = array();
  639. // Set custom CURLOPT settings
  640. if (isset($opt['curlopts']))
  641. {
  642. $curlopts = $opt['curlopts'];
  643. }
  644. // Debug mode
  645. if ($this->debug_mode)
  646. {
  647. $curlopts[CURLOPT_VERBOSE] = true;
  648. }
  649. // Set the curl options.
  650. if (count($curlopts))
  651. {
  652. $request->set_curlopts($curlopts);
  653. }
  654. // Do we have a verb?
  655. if (isset($opt['verb']))
  656. {
  657. $request->set_method($opt['verb']);
  658. $string_to_sign .= $opt['verb'] . "\n";
  659. }
  660. // Add headers and content when we have a body
  661. if (isset($opt['body']))
  662. {
  663. $request->set_body($opt['body']);
  664. $headers['Content-Length'] = strlen($opt['body']);
  665. if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
  666. {
  667. $headers['Content-Type'] = 'application/octet-stream';
  668. }
  669. if (!isset($opt['NoContentMD5']) || $opt['NoContentMD5'] !== true)
  670. {
  671. $headers['Content-MD5'] = $this->util->hex_to_base64(md5($opt['body']));
  672. }
  673. }
  674. // Handle query-string authentication
  675. if (isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
  676. {
  677. unset($headers['Date']);
  678. $headers['Content-Type'] = '';
  679. $headers['Expires'] = is_int($opt['preauth']) ? $opt['preauth'] : strtotime($opt['preauth']);
  680. }
  681. // Sort headers
  682. uksort($headers, 'strnatcasecmp');
  683. // Add headers to request and compute the string to sign
  684. foreach ($headers as $header_key => $header_value)
  685. {
  686. // Strip linebreaks from header values as they're illegal and can allow for security issues
  687. $header_value = str_replace(array("\r", "\n"), '', $header_value);
  688. // Add the header if it has a value
  689. if ($header_value !== '')
  690. {
  691. $request->add_header($header_key, $header_value);
  692. }
  693. // Generate the string to sign
  694. if (
  695. strtolower($header_key) === 'content-md5' ||
  696. strtolower($header_key) === 'content-type' ||
  697. strtolower($header_key) === 'date' ||
  698. (strtolower($header_key) === 'expires' && isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
  699. )
  700. {
  701. $string_to_sign .= $header_value . "\n";
  702. }
  703. elseif (substr(strtolower($header_key), 0, 6) === 'x-amz-')
  704. {
  705. $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
  706. }
  707. }
  708. // Add the signable resource location
  709. $string_to_sign .= ($this->resource_prefix ? $this->resource_prefix : '');
  710. $string_to_sign .= (($bucket === '' || $this->resource_prefix === '/' . $bucket) ? '' : ('/' . $bucket)) . $signable_resource . urldecode($signable_query_string);
  711. // Hash the AWS secret key and generate a signature for the request.
  712. $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->secret_key, true));
  713. $request->add_header('Authorization', 'AWS ' . $this->key . ':' . $signature);
  714. // If we're generating a URL, return the URL to the calling method.
  715. if (isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
  716. {
  717. $query_params = array(
  718. 'AWSAccessKeyId' => $this->key,
  719. 'Expires' => $headers['Expires'],
  720. 'Signature' => $signature,
  721. );
  722. // If using short-term credentials, add the token to the query string
  723. if ($this->auth_token)
  724. {
  725. $query_params['x-amz-security-token'] = $this->auth_token;
  726. }
  727. return $this->request_url . $conjunction . http_build_query($query_params, '', '&');
  728. }
  729. elseif (isset($opt['preauth']))
  730. {
  731. return $this->request_url;
  732. }
  733. /*%******************************************************************************************%*/
  734. // If our changes were temporary, reset them.
  735. if ($this->temporary_prefix)
  736. {
  737. $this->temporary_prefix = false;
  738. $this->resource_prefix = null;
  739. }
  740. // Manage the (newer) batch request API or the (older) returnCurlHandle setting.
  741. if ($this->use_batch_flow)
  742. {
  743. $handle = $request->prep_request();
  744. $this->batch_object->add($handle);
  745. $this->use_batch_flow = false;
  746. return $handle;
  747. }
  748. elseif (isset($opt['returnCurlHandle']) && $opt['returnCurlHandle'] === true)
  749. {
  750. return $request->prep_request();
  751. }
  752. // Send!
  753. $request->send_request();
  754. // Prepare the response
  755. $headers = $request->get_response_header();
  756. $headers['x-aws-request-url'] = $this->request_url;
  757. $headers['x-aws-redirects'] = $this->redirects;
  758. $headers['x-aws-stringtosign'] = $string_to_sign;
  759. $headers['x-aws-requestheaders'] = $request->request_headers;
  760. // Did we have a request body?
  761. if (isset($opt['body']))
  762. {
  763. $headers['x-aws-requestbody'] = $opt['body'];
  764. }
  765. $data = new $this->response_class($headers, $this->parse_callback($request->get_response_body()), $request->get_response_code());
  766. // Did Amazon tell us to redirect? Typically happens for multiple rapid requests EU datacenters.
  767. // @see: http://docs.amazonwebservices.com/AmazonS3/latest/dev/Redirects.html
  768. // @codeCoverageIgnoreStart
  769. if ((integer) $request->get_response_code() === 307) // Temporary redirect to new endpoint.
  770. {
  771. $this->redirects++;
  772. $opt['location'] = $headers['location'];
  773. $data = $this->authenticate($bucket, $opt);
  774. }
  775. // Was it Amazon's fault the request failed? Retry the request until we reach $max_retries.
  776. elseif ((integer) $request->get_response_code() === 500 || (integer) $request->get_response_code() === 503)
  777. {
  778. if ($this->redirects <= $this->max_retries)
  779. {
  780. // Exponential backoff
  781. $delay = (integer) (pow(4, $this->redirects) * 100000);
  782. usleep($delay);
  783. $this->redirects++;
  784. $data = $this->authenticate($bucket, $opt);
  785. }
  786. }
  787. // @codeCoverageIgnoreEnd
  788. // Return!
  789. $this->redirects = 0;
  790. return $data;
  791. }
  792. /**
  793. * Validates whether or not the specified Amazon S3 bucket name is valid for DNS-style access. This
  794. * method is leveraged by any method that creates buckets.
  795. *
  796. * @param string $bucket (Required) The name of the bucket to validate.
  797. * @return boolean Whether or not the specified Amazon S3 bucket name is valid for DNS-style access. A value of <code>true</code> means that the bucket name is valid. A value of <code>false</code> means that the bucket name is invalid.
  798. */
  799. public function validate_bucketname_create($bucket)
  800. {
  801. // list_buckets() uses this. Let it pass.
  802. if ($bucket === '') return true;
  803. if (
  804. ($bucket === null || $bucket === false) || // Must not be null or false
  805. preg_match('/[^(a-z0-9\-\.)]/', $bucket) || // Must be in the lowercase Roman alphabet, period or hyphen
  806. !preg_match('/^([a-z]|\d)/', $bucket) || // Must start with a number or letter
  807. !(strlen($bucket) >= 3 && strlen($bucket) <= 63) || // Must be between 3 and 63 characters long
  808. (strpos($bucket, '..') !== false) || // Bucket names cannot contain two, adjacent periods
  809. (strpos($bucket, '-.') !== false) || // Bucket names cannot contain dashes next to periods
  810. (strpos($bucket, '.-') !== false) || // Bucket names cannot contain dashes next to periods
  811. preg_match('/(-|\.)$/', $bucket) || // Bucket names should not end with a dash or period
  812. preg_match('/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/', $bucket) // Must not be formatted as an IP address
  813. ) return false;
  814. return true;
  815. }
  816. /**
  817. * Validates whether or not the specified Amazon S3 bucket name is valid for path-style access. This
  818. * method is leveraged by any method that reads from buckets.
  819. *
  820. * @param string $bucket (Required) The name of the bucket to validate.
  821. * @return boolean Whether or not the bucket name is valid. A value of <code>true</code> means that the bucket name is valid. A value of <code>false</code> means that the bucket name is invalid.
  822. */
  823. public function validate_bucketname_support($bucket)
  824. {
  825. // list_buckets() uses this. Let it pass.
  826. if ($bucket === '') return true;
  827. // Validate
  828. if (
  829. ($bucket === null || $bucket === false) || // Must not be null or false
  830. preg_match('/[^(a-z0-9_\-\.)]/i', $bucket) || // Must be in the Roman alphabet, period, hyphen or underscore
  831. !preg_match('/^([a-z]|\d)/i', $bucket) || // Must start with a number or letter
  832. !(strlen($bucket) >= 3 && strlen($bucket) <= 255) || // Must be between 3 and 255 characters long
  833. preg_match('/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/', $bucket) // Must not be formatted as an IP address
  834. ) return false;
  835. return true;
  836. }
  837. /*%******************************************************************************************%*/
  838. // SETTERS
  839. /**
  840. * Sets the region to use for subsequent Amazon S3 operations. This will also reset any prior use of
  841. * <enable_path_style()>.
  842. *
  843. * @param string $region (Required) The region to use for subsequent Amazon S3 operations. For a complete list of REGION constants, see the <code>AmazonS3</code> Constants page in the API reference.
  844. * @return $this A reference to the current instance.
  845. */
  846. public function set_region($region)
  847. {
  848. // @codeCoverageIgnoreStart
  849. $this->set_hostname($region);
  850. switch ($region)
  851. {
  852. case self::REGION_US_E1: // Northern Virginia
  853. $this->enable_path_style(false);
  854. break;
  855. case self::REGION_EU_W1: // Ireland
  856. $this->enable_path_style(); // Always use path-style access for EU endpoint.
  857. break;
  858. default:
  859. $this->enable_path_style(false);
  860. break;
  861. }
  862. // @codeCoverageIgnoreEnd
  863. return $this;
  864. }
  865. /**
  866. * Sets the virtual host to use in place of the default `bucket.s3.amazonaws.com` domain.
  867. *
  868. * @param string $vhost (Required) The virtual host to use in place of the default `bucket.s3.amazonaws.com` domain.
  869. * @return $this A reference to the current instance.
  870. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/VirtualHosting.html Virtual Hosting of Buckets
  871. */
  872. public function set_vhost($vhost)
  873. {
  874. $this->vhost = $vhost;
  875. return $this;
  876. }
  877. /**
  878. * Enables the use of the older path-style URI access for all requests.
  879. *
  880. * @param string $style (Optional) Whether or not to enable path-style URI access for all requests. The default value is <code>true</code>.
  881. * @return $this A reference to the current instance.
  882. */
  883. public function enable_path_style($style = true)
  884. {
  885. $this->path_style = $style;
  886. return $this;
  887. }
  888. /*%******************************************************************************************%*/
  889. // BUCKET METHODS
  890. /**
  891. * Creates an Amazon S3 bucket.
  892. *
  893. * Every object stored in Amazon S3 is contained in a bucket. Buckets partition the namespace of
  894. * objects stored in Amazon S3 at the top level. in a bucket, any name can be used for objects.
  895. * However, bucket names must be unique across all of Amazon S3.
  896. *
  897. * @param string $bucket (Required) The name of the bucket to create.
  898. * @param string $region (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`, `AmazonS3::REGION_APAC_NE1`]
  899. * @param string $acl (Optional) The ACL settings for the specified object. Accepts any of the following constants: [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. Alternatively, an array of associative arrays. Each associative array contains an <code>id</code> and a <code>permission</code> key. The default value is <code>ACL_PRIVATE</code>.
  900. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  901. * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
  902. * <li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request.</li></ul>
  903. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  904. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/UsingBucket.html Working with Amazon S3 Buckets
  905. */
  906. public function create_bucket($bucket, $region, $acl = self::ACL_PRIVATE, $opt = null)
  907. {
  908. // If the bucket contains uppercase letters...
  909. if (preg_match('/[A-Z]/', $bucket))
  910. {
  911. // Throw a warning
  912. trigger_error('Since DNS-valid bucket names cannot contain uppercase characters, "' . $bucket . '" has been automatically converted to "' . strtolower($bucket) . '"', E_USER_WARNING);
  913. // Force the bucketname to lowercase
  914. $bucket = strtolower($bucket);
  915. }
  916. // Validate the S3 bucket name for creation
  917. if (!$this->validate_bucketname_create($bucket))
  918. {
  919. // @codeCoverageIgnoreStart
  920. 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.');
  921. // @codeCoverageIgnoreEnd
  922. }
  923. if (!$opt) $opt = array();
  924. $opt['verb'] = 'PUT';
  925. $opt['headers'] = array(
  926. 'Content-Type' => 'application/xml'
  927. );
  928. // Handle Access Control Lists. Can also be passed as an HTTP header.
  929. if (isset($acl))
  930. {
  931. if (is_array($acl))
  932. {
  933. $opt['headers'] = array_merge($opt['headers'], $this->generate_access_policy_headers($acl));
  934. }
  935. else
  936. {
  937. $opt['headers']['x-amz-acl'] = $acl;
  938. }
  939. }
  940. // Defaults
  941. $this->set_region($region); // Also sets path-style
  942. $xml = simplexml_load_string($this->base_location_constraint);
  943. switch ($region)
  944. {
  945. case self::REGION_US_E1: // Northern Virginia
  946. $opt['body'] = '';
  947. break;
  948. case self::REGION_EU_W1: // Ireland
  949. $xml->LocationConstraint = 'EU';
  950. $opt['body'] = $xml->asXML();
  951. break;
  952. default:
  953. $xml->LocationConstraint = str_replace(array('s3-', '.amazonaws.com'), '', $region);
  954. $opt['body'] = $xml->asXML();
  955. break;
  956. }
  957. $response = $this->authenticate($bucket, $opt);
  958. // Make sure we're set back to DNS-style URLs
  959. $this->enable_path_style(false);
  960. return $response;
  961. }
  962. /**
  963. * Gets the region in which the specified Amazon S3 bucket is located.
  964. *
  965. * @param string $bucket (Required) The name of the bucket to use.
  966. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  967. * <li><code>preauth</code> - <code>integer|string</code> - 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 <php:strtotime()>.</li>
  968. * <li><code>returnCurlHandle</code> - <code>boolean</code> - 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.</li></ul>
  969. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  970. */
  971. public function get_bucket_region($bucket, $opt = null)
  972. {
  973. // Add this to our request
  974. if (!$opt) $opt = array();
  975. $opt['verb'] = 'GET';
  976. $opt['sub_resource'] = 'location';
  977. // Authenticate to S3
  978. $response = $this->authenticate($bucket, $opt);
  979. if ($response->isOK())
  980. {
  981. // Handle body
  982. $response->body = (string) $response->body;
  983. }
  984. return $response;
  985. }
  986. /**
  987. * Gets the HTTP headers for the specified Amazon S3 bucket.
  988. *
  989. * @param string $bucket (Required) The name of the bucket to use.
  990. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  991. * <li><code>preauth</code> - <code>integer|string</code> - 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 <php:strtotime()>.</li>
  992. * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
  993. * <li><code>returnCurlHandle</code> - <code>boolean</code> - 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.</li></ul>
  994. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  995. */
  996. public function get_bucket_headers($bucket, $opt = null)
  997. {
  998. if (!$opt) $opt = array();
  999. $opt['verb'] = 'HEAD';
  1000. return $this->authenticate($bucket, $opt);
  1001. }
  1002. /**
  1003. * Deletes a bucket from an Amazon S3 account. A bucket must be empty before the bucket itself can be deleted.
  1004. *
  1005. * @param string $bucket (Required) The name of the bucket to use.
  1006. * @param boolean $force (Optional) Whether to force-delete the bucket and all of its contents. The default value is <code>false</code>.
  1007. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1008. * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
  1009. * <li><code>returnCurlHandle</code> - <code>boolean</code> - 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.</li></ul>
  1010. * @return mixed A <CFResponse> object if the bucket was deleted successfully. Returns boolean <code>false</code> if otherwise.
  1011. */
  1012. public function delete_bucket($bucket, $force = false, $opt = null)
  1013. {
  1014. // Set default value
  1015. $success = true;
  1016. if ($force)
  1017. {
  1018. // Delete all of the items from the bucket.
  1019. $success = $this->delete_all_object_versions($bucket);
  1020. }
  1021. // As long as we were successful...
  1022. if ($success)
  1023. {
  1024. if (!$opt) $opt = array();
  1025. $opt['verb'] = 'DELETE';
  1026. return $this->authenticate($bucket, $opt);
  1027. }
  1028. // @codeCoverageIgnoreStart
  1029. return false;
  1030. // @codeCoverageIgnoreEnd
  1031. }
  1032. /**
  1033. * Gets a list of all buckets contained in the caller's Amazon S3 account.
  1034. *
  1035. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1036. * <li><code>preauth</code> - <code>integer|string</code> - 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 <php:strtotime()>.</li>
  1037. * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
  1038. * <li><code>returnCurlHandle</code> - <code>boolean</code> - 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.</li></ul>
  1039. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  1040. */
  1041. public function list_buckets($opt = null)
  1042. {
  1043. if (!$opt) $opt = array();
  1044. $opt['verb'] = 'GET';
  1045. return $this->authenticate('', $opt);
  1046. }
  1047. /**
  1048. * Gets the access control list (ACL) settings for the specified Amazon S3 bucket.
  1049. *
  1050. * @param string $bucket (Required) The name of the bucket to use.
  1051. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1052. * <li><code>preauth</code> - <code>integer|string</code> - 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 <php:strtotime()>.</li>
  1053. * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
  1054. * <li><code>returnCurlHandle</code> - <code>boolean</code> - 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.</li></ul>
  1055. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  1056. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
  1057. */
  1058. public function get_bucket_acl($bucket, $opt = null)
  1059. {
  1060. // Add this to our request
  1061. if (!$opt) $opt = array();
  1062. $opt['verb'] = 'GET';
  1063. $opt['sub_resource'] = 'acl';
  1064. // Authenticate to S3
  1065. return $this->authenticate($bucket, $opt);
  1066. }
  1067. /**
  1068. * Sets the access control list (ACL) settings for the specified Amazon S3 bucket.
  1069. *
  1070. * @param string $bucket (Required) The name of the bucket to use.
  1071. * @param string $acl (Optional) The ACL settings for the specified bucket. [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. Alternatively, an array of associative arrays. Each associative array contains an `id` and a `permission` key. The default value is <ACL_PRIVATE>.
  1072. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1073. * <li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
  1074. * <li><code>returnCurlHandle</code> - <code>boolean</code> - 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.</li></ul>
  1075. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  1076. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
  1077. */
  1078. public function set_bucket_acl($bucket, $acl = self::ACL_PRIVATE, $opt = null)
  1079. {
  1080. // Add this to our request
  1081. if (!$opt) $opt = array();
  1082. $opt['verb'] = 'PUT';
  1083. $opt['sub_resource'] = 'acl';
  1084. $opt['headers'] = array(
  1085. 'Content-Type' => 'application/xml'
  1086. );
  1087. // Make sure these are defined.
  1088. // @codeCoverageIgnoreStart
  1089. if (!$this->credentials->canonical_id || !$this->credentials->canonical_name)
  1090. {
  1091. // Fetch the data live.
  1092. $canonical = $this->get_canonical_user_id();
  1093. $this->credentials->canonical_id = $canonical['id'];
  1094. $this->credentials->canonical_name = $canonical['display_name'];
  1095. }
  1096. // @codeCoverageIgnoreEnd
  1097. if (is_array($acl))
  1098. {
  1099. $opt['headers'] = array_merge($opt['headers'], $this->generate_access_policy_headers($acl));
  1100. }
  1101. else
  1102. {
  1103. $opt['body'] = '';
  1104. $opt['headers']['x-amz-acl'] = $acl;
  1105. }
  1106. // Authenticate to S3
  1107. return $this->authenticate($bucket, $opt);
  1108. }
  1109. /*%******************************************************************************************%*/
  1110. // OBJECT METHODS
  1111. /**
  1112. * Creates an Amazon S3 object. After an Amazon S3 bucket is created, objects can be stored in it.
  1113. *
  1114. * Each standard object can hold up to 5 GB of data. When an object is stored in Amazon S3, the data is streamed
  1115. * to multiple storage servers in multiple data centers. This ensures the data remains available in the
  1116. * event of internal network or hardware failure.
  1117. *
  1118. * @param string $bucket (Required) The name of the bucket to use.
  1119. * @param string $filename (Required) The file name for the object.
  1120. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1121. * <li><code>acl</code> - <code>string</code> - Optional - The ACL settings for the specified object. Accepts any of the following constants: [Allowed values: <code>AmazonS3::ACL_PRIVATE</code>, <code>AmazonS3::ACL_PUBLIC</code>, <code>AmazonS3::ACL_OPEN</code>, <code>AmazonS3::ACL_AUTH_READ</code>, <code>AmazonS3::ACL_OWNER_READ</code>, <code>AmazonS3::ACL_OWNER_FULL_CONTROL</code>]. Alternatively, an array of associative arrays. Each associative array contains an <code>id</code> and a <code>permission</code> key. The default value is <code>ACL_PRIVATE</code>.</li>
  1122. * <li><code>body</code> - <code>string</code> - Required; Conditional - The data to be stored in the object. Either this parameter or <code>fileUpload</code> must be specified.</li>
  1123. * <li><code>contentType</code> - <code>string</code> - Optional - The type of content that is being sent in the body. If a file is being uploaded via <code>fileUpload</code> as a file system path, it will attempt to determine the correct mime-type based on the file extension. The default value is <code>application/octet-stream</code>.</li>
  1124. * <li><code>encryption</code> - <code>string</code> - Optional - The algorithm to use for encrypting the object. [Allowed values: <code>AES256</code>]</li>
  1125. * …

Large files files are truncated, but you can click here to view the full file