PageRenderTime 57ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/protected/vendors/AWS/services/s3.class.php

https://bitbucket.org/ctala/yiiaws
PHP | 4351 lines | 2161 code | 573 blank | 1617 comment | 343 complexity | df3de4acb51948003854795c7a924f3b MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause-No-Nuclear-License-2014, 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 bucket tagging.
  326. */
  327. public $bucket_tagging_xml;
  328. /**
  329. * The base XML elements to use for CORS support.
  330. */
  331. public $cors_config_xml;
  332. /**
  333. * The DNS vs. Path-style setting.
  334. */
  335. public $path_style = false;
  336. /**
  337. * The state of whether the prefix change is temporary or permanent.
  338. */
  339. public $temporary_prefix = false;
  340. /*%******************************************************************************************%*/
  341. // CONSTRUCTOR
  342. /**
  343. * Constructs a new instance of <AmazonS3>.
  344. *
  345. * @param array $options (Optional) An associative array of parameters that can have the following keys: <ul>
  346. * <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>
  347. * <li><code>credentials</code> - <code>string</code> - Optional - The name of the credential set to use for authentication.</li>
  348. * <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>
  349. * <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>
  350. * <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>
  351. * <li><code>token</code> - <code>string</code> - Optional - An AWS session token.</li></ul>
  352. * @return void
  353. */
  354. public function __construct(array $options = array())
  355. {
  356. $this->vhost = null;
  357. $this->api_version = '2006-03-01';
  358. $this->hostname = self::DEFAULT_URL;
  359. $this->base_acp_xml = '<?xml version="1.0" encoding="UTF-8"?><AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/latest/"/>';
  360. $this->base_location_constraint = '<?xml version="1.0" encoding="UTF-8"?><CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/' . $this->api_version . '/"><LocationConstraint/></CreateBucketConfiguration>';
  361. $this->base_logging_xml = '<?xml version="1.0" encoding="utf-8"?><BucketLoggingStatus xmlns="http://doc.s3.amazonaws.com/' . $this->api_version . '"/>';
  362. $this->base_notification_xml = '<?xml version="1.0" encoding="utf-8"?><NotificationConfiguration/>';
  363. $this->base_versioning_xml = '<?xml version="1.0" encoding="utf-8"?><VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/' . $this->api_version . '/"/>';
  364. $this->complete_mpu_xml = '<?xml version="1.0" encoding="utf-8"?><CompleteMultipartUpload/>';
  365. $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>';
  366. $this->multi_object_delete_xml = '<?xml version="1.0" encoding="utf-8"?><Delete/>';
  367. $this->object_expiration_xml = '<?xml version="1.0" encoding="utf-8"?><LifecycleConfiguration/>';
  368. $this->bucket_tagging_xml = '<?xml version="1.0" encoding="utf-8"?><Tagging><TagSet/></Tagging>';
  369. $this->cors_config_xml = '<?xml version="1.0" encoding="utf-8"?><CORSConfiguration />';
  370. parent::__construct($options);
  371. }
  372. /*%******************************************************************************************%*/
  373. // AUTHENTICATION
  374. /**
  375. * Authenticates a connection to Amazon S3. Do not use directly unless implementing custom methods for
  376. * this class.
  377. *
  378. * @param string $operation (Required) The name of the bucket to operate on (S3 Only).
  379. * @param array $payload (Required) An associative array of parameters for authenticating. See inline comments for allowed keys.
  380. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  381. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/S3_Authentication.html REST authentication
  382. */
  383. public function authenticate($operation, $payload)
  384. {
  385. /*
  386. * Overriding or extending this class? You can pass the following "magic" keys into $opt.
  387. *
  388. * ## verb, resource, sub_resource and query_string ##
  389. * <verb> /<resource>?<sub_resource>&<query_string>
  390. * GET /filename.txt?versions&prefix=abc&max-items=1
  391. *
  392. * ## versionId, uploadId, partNumber, response-* ##
  393. * These don't follow the same rules as above, in that the they needs to be signed, while
  394. * other query_string values do not.
  395. *
  396. * ## curlopts ##
  397. * These values get passed directly to the cURL methods in RequestCore.
  398. *
  399. * ## fileUpload, fileDownload, seekTo ##
  400. * These are slightly modified and then passed to the cURL methods in RequestCore.
  401. *
  402. * ## headers ##
  403. * $opt['headers'] is an array, whose keys are HTTP headers to be sent.
  404. *
  405. * ## body ##
  406. * This is the request body that is sent to the server via PUT/POST.
  407. *
  408. * ## preauth ##
  409. * This is a hook that tells authenticate() to generate a pre-authenticated URL.
  410. *
  411. * ## returnCurlHandle ##
  412. * Tells authenticate() to return the cURL handle for the request instead of executing it.
  413. */
  414. // Rename variables (to overcome inheritence issues)
  415. $bucket = $operation;
  416. $opt = $payload;
  417. // Validate the S3 bucket name
  418. if (!$this->validate_bucketname_support($bucket))
  419. {
  420. // @codeCoverageIgnoreStart
  421. 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.');
  422. // @codeCoverageIgnoreEnd
  423. }
  424. // Die if $opt isn't set.
  425. if (!$opt) return false;
  426. $method_arguments = func_get_args();
  427. // Use the caching flow to determine if we need to do a round-trip to the server.
  428. if ($this->use_cache_flow)
  429. {
  430. // Generate an identifier specific to this particular set of arguments.
  431. $cache_id = $this->key . '_' . get_class($this) . '_' . $bucket . '_' . sha1(serialize($method_arguments));
  432. // Instantiate the appropriate caching object.
  433. $this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
  434. if ($this->delete_cache)
  435. {
  436. $this->use_cache_flow = false;
  437. $this->delete_cache = false;
  438. return $this->cache_object->delete();
  439. }
  440. // Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
  441. $data = $this->cache_object->response_manager(array($this, 'cache_callback'), $method_arguments);
  442. if ($this->parse_the_response)
  443. {
  444. // Parse the XML body
  445. $data = $this->parse_callback($data);
  446. }
  447. // End!
  448. return $data;
  449. }
  450. // If we haven't already set a resource prefix and the bucket name isn't DNS-valid...
  451. if ((!$this->resource_prefix && !$this->validate_bucketname_create($bucket)) || $this->path_style)
  452. {
  453. // Fall back to the older path-style URI
  454. $this->set_resource_prefix('/' . $bucket);
  455. $this->temporary_prefix = true;
  456. }
  457. // If the bucket name has periods and we are using SSL, we need to switch to path style URLs
  458. $bucket_name_may_cause_ssl_wildcard_failures = false;
  459. if ($this->use_ssl && strpos($bucket, '.') !== false)
  460. {
  461. $bucket_name_may_cause_ssl_wildcard_failures = true;
  462. }
  463. // Determine hostname
  464. $scheme = $this->use_ssl ? 'https://' : 'http://';
  465. if ($bucket_name_may_cause_ssl_wildcard_failures || $this->resource_prefix || $this->path_style)
  466. {
  467. // Use bucket-in-path method
  468. $hostname = $this->hostname . $this->resource_prefix . (($bucket === '' || $this->resource_prefix === '/' . $bucket) ? '' : ('/' . $bucket));
  469. }
  470. else
  471. {
  472. $hostname = $this->vhost ? $this->vhost : (($bucket === '') ? $this->hostname : ($bucket . '.') . $this->hostname);
  473. }
  474. // Get the UTC timestamp in RFC 2616 format
  475. $date = gmdate(CFUtilities::DATE_FORMAT_RFC2616, time());
  476. // Storage for request parameters.
  477. $resource = '';
  478. $sub_resource = '';
  479. $querystringparams = array();
  480. $signable_querystringparams = array();
  481. $string_to_sign = '';
  482. $headers = array(
  483. 'Content-MD5' => '',
  484. 'Content-Type' => 'application/x-www-form-urlencoded',
  485. 'Date' => $date
  486. );
  487. /*%******************************************************************************************%*/
  488. // Do we have an authentication token?
  489. if ($this->auth_token)
  490. {
  491. $headers['X-Amz-Security-Token'] = $this->auth_token;
  492. }
  493. // Handle specific resources
  494. if (isset($opt['resource']))
  495. {
  496. $resource .= $opt['resource'];
  497. }
  498. // Merge query string values
  499. if (isset($opt['query_string']))
  500. {
  501. $querystringparams = array_merge($querystringparams, $opt['query_string']);
  502. }
  503. $query_string = $this->util->to_query_string($querystringparams);
  504. // Merge the signable query string values. Must be alphabetical.
  505. $signable_list = array(
  506. 'partNumber',
  507. 'response-cache-control',
  508. 'response-content-disposition',
  509. 'response-content-encoding',
  510. 'response-content-language',
  511. 'response-content-type',
  512. 'response-expires',
  513. 'uploadId',
  514. 'versionId'
  515. );
  516. foreach ($signable_list as $item)
  517. {
  518. if (isset($opt[$item]))
  519. {
  520. $signable_querystringparams[$item] = $opt[$item];
  521. }
  522. }
  523. $signable_query_string = $this->util->to_query_string($signable_querystringparams);
  524. // Merge the HTTP headers
  525. if (isset($opt['headers']))
  526. {
  527. $headers = array_merge($headers, $opt['headers']);
  528. }
  529. // Compile the URI to request
  530. $conjunction = '?';
  531. $signable_resource = '/' . str_replace('%2F', '/', rawurlencode($resource));
  532. $non_signable_resource = '';
  533. if (isset($opt['sub_resource']))
  534. {
  535. $signable_resource .= $conjunction . rawurlencode($opt['sub_resource']);
  536. $conjunction = '&';
  537. }
  538. if ($signable_query_string !== '')
  539. {
  540. $signable_query_string = $conjunction . $signable_query_string;
  541. $conjunction = '&';
  542. }
  543. if ($query_string !== '')
  544. {
  545. $non_signable_resource .= $conjunction . $query_string;
  546. $conjunction = '&';
  547. }
  548. if (substr($hostname, -1) === substr($signable_resource, 0, 1))
  549. {
  550. $signable_resource = ltrim($signable_resource, '/');
  551. }
  552. $this->request_url = $scheme . $hostname . $signable_resource . $signable_query_string . $non_signable_resource;
  553. if (isset($opt['location']))
  554. {
  555. $this->request_url = $opt['location'];
  556. }
  557. // Gather information to pass along to other classes.
  558. $helpers = array(
  559. 'utilities' => $this->utilities_class,
  560. 'request' => $this->request_class,
  561. 'response' => $this->response_class,
  562. );
  563. // Instantiate the request class
  564. $request = new $this->request_class($this->request_url, $this->proxy, $helpers, $this->credentials);
  565. // Update RequestCore settings
  566. $request->request_class = $this->request_class;
  567. $request->response_class = $this->response_class;
  568. $request->ssl_verification = $this->ssl_verification;
  569. // Pass along registered stream callbacks
  570. if ($this->registered_streaming_read_callback)
  571. {
  572. $request->register_streaming_read_callback($this->registered_streaming_read_callback);
  573. }
  574. if ($this->registered_streaming_write_callback)
  575. {
  576. $request->register_streaming_write_callback($this->registered_streaming_write_callback);
  577. }
  578. // Streaming uploads
  579. if (isset($opt['fileUpload']))
  580. {
  581. if (is_resource($opt['fileUpload']))
  582. {
  583. // Determine the length to read from the stream
  584. $length = null; // From current position until EOF by default, size determined by set_read_stream()
  585. if (isset($headers['Content-Length']))
  586. {
  587. $length = $headers['Content-Length'];
  588. }
  589. elseif (isset($opt['seekTo']))
  590. {
  591. // Read from seekTo until EOF by default
  592. $stats = fstat($opt['fileUpload']);
  593. if ($stats && $stats['size'] >= 0)
  594. {
  595. $length = $stats['size'] - (integer) $opt['seekTo'];
  596. }
  597. }
  598. $request->set_read_stream($opt['fileUpload'], $length);
  599. if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
  600. {
  601. $headers['Content-Type'] = 'application/octet-stream';
  602. }
  603. }
  604. else
  605. {
  606. $request->set_read_file($opt['fileUpload']);
  607. // Determine the length to read from the file
  608. $length = $request->read_stream_size; // The file size by default
  609. if (isset($headers['Content-Length']))
  610. {
  611. $length = $headers['Content-Length'];
  612. }
  613. elseif (isset($opt['seekTo']) && isset($length))
  614. {
  615. // Read from seekTo until EOF by default
  616. $length -= (integer) $opt['seekTo'];
  617. }
  618. $request->set_read_stream_size($length);
  619. // Attempt to guess the correct mime-type
  620. if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
  621. {
  622. $extension = explode('.', $opt['fileUpload']);
  623. $extension = array_pop($extension);
  624. $mime_type = CFMimeTypes::get_mimetype($extension);
  625. $headers['Content-Type'] = $mime_type;
  626. }
  627. }
  628. $headers['Content-Length'] = $request->read_stream_size;
  629. $headers['Content-MD5'] = '';
  630. }
  631. // Handle streaming file offsets
  632. if (isset($opt['seekTo']))
  633. {
  634. // Pass the seek position to RequestCore
  635. $request->set_seek_position((integer) $opt['seekTo']);
  636. }
  637. // Streaming downloads
  638. if (isset($opt['fileDownload']))
  639. {
  640. if (is_resource($opt['fileDownload']))
  641. {
  642. $request->set_write_stream($opt['fileDownload']);
  643. }
  644. else
  645. {
  646. $request->set_write_file($opt['fileDownload']);
  647. }
  648. }
  649. $curlopts = array();
  650. // Set custom CURLOPT settings
  651. if (isset($opt['curlopts']))
  652. {
  653. $curlopts = $opt['curlopts'];
  654. }
  655. // Debug mode
  656. if ($this->debug_mode)
  657. {
  658. $curlopts[CURLOPT_VERBOSE] = true;
  659. }
  660. // Set the curl options.
  661. if (count($curlopts))
  662. {
  663. $request->set_curlopts($curlopts);
  664. }
  665. // Do we have a verb?
  666. if (isset($opt['verb']))
  667. {
  668. $request->set_method($opt['verb']);
  669. $string_to_sign .= $opt['verb'] . "\n";
  670. }
  671. // Add headers and content when we have a body
  672. if (isset($opt['body']))
  673. {
  674. $request->set_body($opt['body']);
  675. $headers['Content-Length'] = strlen($opt['body']);
  676. if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
  677. {
  678. $headers['Content-Type'] = 'application/octet-stream';
  679. }
  680. if (!isset($opt['NoContentMD5']) || $opt['NoContentMD5'] !== true)
  681. {
  682. $headers['Content-MD5'] = $this->util->hex_to_base64(md5($opt['body']));
  683. }
  684. }
  685. // Handle query-string authentication
  686. if (isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
  687. {
  688. unset($headers['Date']);
  689. $headers['Content-Type'] = '';
  690. $headers['Expires'] = is_int($opt['preauth']) ? $opt['preauth'] : strtotime($opt['preauth']);
  691. }
  692. // Sort headers
  693. uksort($headers, 'strnatcasecmp');
  694. // Add headers to request and compute the string to sign
  695. foreach ($headers as $header_key => $header_value)
  696. {
  697. // Strip linebreaks from header values as they're illegal and can allow for security issues
  698. $header_value = str_replace(array("\r", "\n"), '', $header_value);
  699. // Add the header if it has a value
  700. if ($header_value !== '')
  701. {
  702. $request->add_header($header_key, $header_value);
  703. }
  704. // Generate the string to sign
  705. if (
  706. strtolower($header_key) === 'content-md5' ||
  707. strtolower($header_key) === 'content-type' ||
  708. strtolower($header_key) === 'date' ||
  709. (strtolower($header_key) === 'expires' && isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
  710. )
  711. {
  712. $string_to_sign .= $header_value . "\n";
  713. }
  714. elseif (substr(strtolower($header_key), 0, 6) === 'x-amz-')
  715. {
  716. $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
  717. }
  718. }
  719. // Add the signable resource location
  720. $string_to_sign .= ($this->resource_prefix ? $this->resource_prefix : '');
  721. $string_to_sign .= (($bucket === '' || $this->resource_prefix === '/' . $bucket) ? '' : ('/' . $bucket)) . $signable_resource . urldecode($signable_query_string);
  722. // Hash the AWS secret key and generate a signature for the request.
  723. $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->secret_key, true));
  724. $request->add_header('Authorization', 'AWS ' . $this->key . ':' . $signature);
  725. // If we're generating a URL, return the URL to the calling method.
  726. if (isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
  727. {
  728. $query_params = array(
  729. 'AWSAccessKeyId' => $this->key,
  730. 'Expires' => $headers['Expires'],
  731. 'Signature' => $signature,
  732. );
  733. // If using short-term credentials, add the token to the query string
  734. if ($this->auth_token)
  735. {
  736. $query_params['x-amz-security-token'] = $this->auth_token;
  737. }
  738. return $this->request_url . $conjunction . http_build_query($query_params, '', '&');
  739. }
  740. elseif (isset($opt['preauth']))
  741. {
  742. return $this->request_url;
  743. }
  744. /*%******************************************************************************************%*/
  745. // If our changes were temporary, reset them.
  746. if ($this->temporary_prefix)
  747. {
  748. $this->temporary_prefix = false;
  749. $this->resource_prefix = null;
  750. }
  751. // Manage the (newer) batch request API or the (older) returnCurlHandle setting.
  752. if ($this->use_batch_flow)
  753. {
  754. $handle = $request->prep_request();
  755. $this->batch_object->add($handle);
  756. $this->use_batch_flow = false;
  757. return $handle;
  758. }
  759. elseif (isset($opt['returnCurlHandle']) && $opt['returnCurlHandle'] === true)
  760. {
  761. return $request->prep_request();
  762. }
  763. // Send!
  764. $request->send_request();
  765. // Prepare the response
  766. $headers = $request->get_response_header();
  767. $headers['x-aws-request-url'] = $this->request_url;
  768. $headers['x-aws-redirects'] = $this->redirects;
  769. $headers['x-aws-stringtosign'] = $string_to_sign;
  770. $headers['x-aws-requestheaders'] = $request->request_headers;
  771. // Did we have a request body?
  772. if (isset($opt['body']))
  773. {
  774. $headers['x-aws-requestbody'] = $opt['body'];
  775. }
  776. $data = new $this->response_class($headers, $this->parse_callback($request->get_response_body()), $request->get_response_code());
  777. // Did Amazon tell us to redirect? Typically happens for multiple rapid requests EU datacenters.
  778. // @see: http://docs.amazonwebservices.com/AmazonS3/latest/dev/Redirects.html
  779. // @codeCoverageIgnoreStart
  780. if ((integer) $request->get_response_code() === 307) // Temporary redirect to new endpoint.
  781. {
  782. $this->redirects++;
  783. $opt['location'] = $headers['location'];
  784. $data = $this->authenticate($bucket, $opt);
  785. }
  786. // Was it Amazon's fault the request failed? Retry the request until we reach $max_retries.
  787. elseif ((integer) $request->get_response_code() === 500 || (integer) $request->get_response_code() === 503)
  788. {
  789. if ($this->redirects <= $this->max_retries)
  790. {
  791. // Exponential backoff
  792. $delay = (integer) (pow(4, $this->redirects) * 100000);
  793. usleep($delay);
  794. $this->redirects++;
  795. $data = $this->authenticate($bucket, $opt);
  796. }
  797. }
  798. // @codeCoverageIgnoreEnd
  799. // Return!
  800. $this->redirects = 0;
  801. return $data;
  802. }
  803. /**
  804. * Validates whether or not the specified Amazon S3 bucket name is valid for DNS-style access. This
  805. * method is leveraged by any method that creates buckets.
  806. *
  807. * @param string $bucket (Required) The name of the bucket to validate.
  808. * @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.
  809. */
  810. public function validate_bucketname_create($bucket)
  811. {
  812. // list_buckets() uses this. Let it pass.
  813. if ($bucket === '') return true;
  814. if (
  815. ($bucket === null || $bucket === false) || // Must not be null or false
  816. preg_match('/[^(a-z0-9\-\.)]/', $bucket) || // Must be in the lowercase Roman alphabet, period or hyphen
  817. !preg_match('/^([a-z]|\d)/', $bucket) || // Must start with a number or letter
  818. !(strlen($bucket) >= 3 && strlen($bucket) <= 63) || // Must be between 3 and 63 characters long
  819. (strpos($bucket, '..') !== false) || // Bucket names cannot contain two, adjacent periods
  820. (strpos($bucket, '-.') !== false) || // Bucket names cannot contain dashes next to periods
  821. (strpos($bucket, '.-') !== false) || // Bucket names cannot contain dashes next to periods
  822. preg_match('/(-|\.)$/', $bucket) || // Bucket names should not end with a dash or period
  823. preg_match('/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/', $bucket) // Must not be formatted as an IP address
  824. ) return false;
  825. return true;
  826. }
  827. /**
  828. * Validates whether or not the specified Amazon S3 bucket name is valid for path-style access. This
  829. * method is leveraged by any method that reads from buckets.
  830. *
  831. * @param string $bucket (Required) The name of the bucket to validate.
  832. * @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.
  833. */
  834. public function validate_bucketname_support($bucket)
  835. {
  836. // list_buckets() uses this. Let it pass.
  837. if ($bucket === '') return true;
  838. // Validate
  839. if (
  840. ($bucket === null || $bucket === false) || // Must not be null or false
  841. preg_match('/[^(a-z0-9_\-\.)]/i', $bucket) || // Must be in the Roman alphabet, period, hyphen or underscore
  842. !preg_match('/^([a-z]|\d)/i', $bucket) || // Must start with a number or letter
  843. !(strlen($bucket) >= 3 && strlen($bucket) <= 255) || // Must be between 3 and 255 characters long
  844. preg_match('/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/', $bucket) // Must not be formatted as an IP address
  845. ) return false;
  846. return true;
  847. }
  848. /*%******************************************************************************************%*/
  849. // SETTERS
  850. /**
  851. * Sets the region to use for subsequent Amazon S3 operations. This will also reset any prior use of
  852. * <enable_path_style()>.
  853. *
  854. * @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.
  855. * @return $this A reference to the current instance.
  856. */
  857. public function set_region($region)
  858. {
  859. // @codeCoverageIgnoreStart
  860. $this->set_hostname($region);
  861. switch ($region)
  862. {
  863. case self::REGION_US_E1: // Northern Virginia
  864. $this->enable_path_style(false);
  865. break;
  866. case self::REGION_EU_W1: // Ireland
  867. $this->enable_path_style(); // Always use path-style access for EU endpoint.
  868. break;
  869. default:
  870. $this->enable_path_style(false);
  871. break;
  872. }
  873. // @codeCoverageIgnoreEnd
  874. return $this;
  875. }
  876. /**
  877. * Sets the virtual host to use in place of the default `bucket.s3.amazonaws.com` domain.
  878. *
  879. * @param string $vhost (Required) The virtual host to use in place of the default `bucket.s3.amazonaws.com` domain.
  880. * @return $this A reference to the current instance.
  881. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/VirtualHosting.html Virtual Hosting of Buckets
  882. */
  883. public function set_vhost($vhost)
  884. {
  885. $this->vhost = $vhost;
  886. return $this;
  887. }
  888. /**
  889. * Enables the use of the older path-style URI access for all requests.
  890. *
  891. * @param string $style (Optional) Whether or not to enable path-style URI access for all requests. The default value is <code>true</code>.
  892. * @return $this A reference to the current instance.
  893. */
  894. public function enable_path_style($style = true)
  895. {
  896. $this->path_style = $style;
  897. return $this;
  898. }
  899. /*%******************************************************************************************%*/
  900. // BUCKET METHODS
  901. /**
  902. * Creates an Amazon S3 bucket.
  903. *
  904. * Every object stored in Amazon S3 is contained in a bucket. Buckets partition the namespace of
  905. * objects stored in Amazon S3 at the top level. in a bucket, any name can be used for objects.
  906. * However, bucket names must be unique across all of Amazon S3.
  907. *
  908. * @param string $bucket (Required) The name of the bucket to create.
  909. * @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`]
  910. * @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>.
  911. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  912. * <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>
  913. * <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>
  914. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  915. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/UsingBucket.html Working with Amazon S3 Buckets
  916. */
  917. public function create_bucket($bucket, $region, $acl = self::ACL_PRIVATE, $opt = null)
  918. {
  919. // If the bucket contains uppercase letters...
  920. if (preg_match('/[A-Z]/', $bucket))
  921. {
  922. // Throw a warning
  923. trigger_error('Since DNS-valid bucket names cannot contain uppercase characters, "' . $bucket . '" has been automatically converted to "' . strtolower($bucket) . '"', E_USER_WARNING);
  924. // Force the bucketname to lowercase
  925. $bucket = strtolower($bucket);
  926. }
  927. // Validate the S3 bucket name for creation
  928. if (!$this->validate_bucketname_create($bucket))
  929. {
  930. // @codeCoverageIgnoreStart
  931. 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.');
  932. // @codeCoverageIgnoreEnd
  933. }
  934. if (!$opt) $opt = array();
  935. $opt['verb'] = 'PUT';
  936. $opt['headers'] = array(
  937. 'Content-Type' => 'application/xml'
  938. );
  939. // Handle Access Control Lists. Can also be passed as an HTTP header.
  940. if (isset($acl))
  941. {
  942. if (is_array($acl))
  943. {
  944. $opt['headers'] = array_merge($opt['headers'], $this->generate_access_policy_headers($acl));
  945. }
  946. else
  947. {
  948. $opt['headers']['x-amz-acl'] = $acl;
  949. }
  950. }
  951. // Defaults
  952. $this->set_region($region); // Also sets path-style
  953. $xml = simplexml_load_string($this->base_location_constraint);
  954. switch ($region)
  955. {
  956. case self::REGION_US_E1: // Northern Virginia
  957. $opt['body'] = '';
  958. break;
  959. case self::REGION_EU_W1: // Ireland
  960. $xml->LocationConstraint = 'EU';
  961. $opt['body'] = $xml->asXML();
  962. break;
  963. default:
  964. $xml->LocationConstraint = str_replace(array('s3-', '.amazonaws.com'), '', $region);
  965. $opt['body'] = $xml->asXML();
  966. break;
  967. }
  968. $response = $this->authenticate($bucket, $opt);
  969. // Make sure we're set back to DNS-style URLs
  970. $this->enable_path_style(false);
  971. return $response;
  972. }
  973. /**
  974. * Gets the region in which the specified Amazon S3 bucket is located.
  975. *
  976. * @param string $bucket (Required) The name of the bucket to use.
  977. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  978. * <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>
  979. * <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>
  980. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  981. */
  982. public function get_bucket_region($bucket, $opt = null)
  983. {
  984. // Add this to our request
  985. if (!$opt) $opt = array();
  986. $opt['verb'] = 'GET';
  987. $opt['sub_resource'] = 'location';
  988. // Authenticate to S3
  989. $response = $this->authenticate($bucket, $opt);
  990. if ($response->isOK())
  991. {
  992. // Handle body
  993. $response->body = (string) $response->body;
  994. }
  995. return $response;
  996. }
  997. /**
  998. * Gets the HTTP headers for the specified Amazon S3 bucket.
  999. *
  1000. * @param string $bucket (Required) The name of the bucket to use.
  1001. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1002. * <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>
  1003. * <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>
  1004. * <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>
  1005. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  1006. */
  1007. public function get_bucket_headers($bucket, $opt = null)
  1008. {
  1009. if (!$opt) $opt = array();
  1010. $opt['verb'] = 'HEAD';
  1011. return $this->authenticate($bucket, $opt);
  1012. }
  1013. /**
  1014. * Deletes a bucket from an Amazon S3 account. A bucket must be empty before the bucket itself can be deleted.
  1015. *
  1016. * @param string $bucket (Required) The name of the bucket to use.
  1017. * @param boolean $force (Optional) Whether to force-delete the bucket and all of its contents. The default value is <code>false</code>.
  1018. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1019. * <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>
  1020. * <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>
  1021. * @return mixed A <CFResponse> object if the bucket was deleted successfully. Returns boolean <code>false</code> if otherwise.
  1022. */
  1023. public function delete_bucket($bucket, $force = false, $opt = null)
  1024. {
  1025. // Set default value
  1026. $success = true;
  1027. if ($force)
  1028. {
  1029. // Delete all of the items from the bucket.
  1030. $success = $this->delete_all_object_versions($bucket);
  1031. }
  1032. // As long as we were successful...
  1033. if ($success)
  1034. {
  1035. if (!$opt) $opt = array();
  1036. $opt['verb'] = 'DELETE';
  1037. return $this->authenticate($bucket, $opt);
  1038. }
  1039. // @codeCoverageIgnoreStart
  1040. return false;
  1041. // @codeCoverageIgnoreEnd
  1042. }
  1043. /**
  1044. * Gets a list of all buckets contained in the caller's Amazon S3 account.
  1045. *
  1046. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1047. * <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>
  1048. * <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>
  1049. * <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>
  1050. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  1051. */
  1052. public function list_buckets($opt = null)
  1053. {
  1054. if (!$opt) $opt = array();
  1055. $opt['verb'] = 'GET';
  1056. return $this->authenticate('', $opt);
  1057. }
  1058. /**
  1059. * Gets the access control list (ACL) settings for the specified Amazon S3 bucket.
  1060. *
  1061. * @param string $bucket (Required) The name of the bucket to use.
  1062. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1063. * <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>
  1064. * <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>
  1065. * <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>
  1066. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  1067. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
  1068. */
  1069. public function get_bucket_acl($bucket, $opt = null)
  1070. {
  1071. // Add this to our request
  1072. if (!$opt) $opt = array();
  1073. $opt['verb'] = 'GET';
  1074. $opt['sub_resource'] = 'acl';
  1075. // Authenticate to S3
  1076. return $this->authenticate($bucket, $opt);
  1077. }
  1078. /**
  1079. * Sets the access control list (ACL) settings for the specified Amazon S3 bucket.
  1080. *
  1081. * @param string $bucket (Required) The name of the bucket to use.
  1082. * @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>.
  1083. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1084. * <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>
  1085. * <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>
  1086. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  1087. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
  1088. */
  1089. public function set_bucket_acl($bucket, $acl = self::ACL_PRIVATE, $opt = null)
  1090. {
  1091. // Add this to our request
  1092. if (!$opt) $opt = array();
  1093. $opt['verb'] = 'PUT';
  1094. $opt['sub_resource'] = 'acl';
  1095. $opt['headers'] = array(
  1096. 'Content-Type' => 'application/xml'
  1097. );
  1098. // Make sure these are defined.
  1099. // @codeCoverageIgnoreStart
  1100. if (!$this->credentials->canonical_id || !$this->credentials->canonical_name)
  1101. {
  1102. // Fetch the data live.
  1103. $canonical = $this->get_canonical_user_id();
  1104. $this->credentials->canonical_id = $canonical['id'];
  1105. $this->credentials->canonical_name = $canonical['display_name'];
  1106. }
  1107. // @codeCoverageIgnoreEnd
  1108. if (is_array($acl))
  1109. {
  1110. $opt['headers'] = array_merge($opt['headers'], $this->generate_access_policy_headers($acl));
  1111. }
  1112. else
  1113. {
  1114. $opt['body'] = '';
  1115. $opt['headers']['x-amz-acl'] = $acl;
  1116. }
  1117. // Authenticate to S3
  1118. return $this->authenticate($bucket, $opt);
  1119. }
  1120. /*%******************************************************************************************%*/
  1121. // OBJECT METHODS
  1122. /**
  1123. * Creates an Amazon S3 object. After an Amazon S3 bucket is created, objects can be stored in it.
  1124. *
  1125. * Each standard object can hold up to 5 GB of data. When an object is stored in Amazon S3, the data is streamed
  1126. * to multiple storage servers in multiple data centers. This ensures the data remains available in the
  1127. * event of internal network or hardware failure.
  1128. *
  1129. * @param string $bucket (Required) The name of the bucket to use.
  1130. * @param string $filename (Required) The file name for the object.
  1131. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1132. * <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>
  1133. * <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>
  1134. * <li><code>contentType</code> - <code>string</code> - Optional - The type of cont…

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