PageRenderTime 86ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/frontend/protected/vendors/amazon/services/s3.class.php

https://bitbucket.org/asdtech/cloudike
PHP | 4316 lines | 2134 code | 569 blank | 1613 comment | 337 complexity | 863a067f89a43fced913cdb6ff662610 MD5 | raw file
Possible License(s): MIT, AGPL-3.0, AGPL-1.0, 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. * ACL: Log delivery (only for logging target bucket)
  222. */
  223. const ACL_LOG_DELIVERY = 'log-delivery-write';
  224. /*%******************************************************************************************%*/
  225. // GRANTS
  226. /**
  227. * When applied to a bucket, grants permission to list the bucket. When applied to an object, this
  228. * grants permission to read the object data and/or metadata.
  229. */
  230. const GRANT_READ = 'READ';
  231. /**
  232. * When applied to a bucket, grants permission to create, overwrite, and delete any object in the
  233. * bucket. This permission is not supported for objects.
  234. */
  235. const GRANT_WRITE = 'WRITE';
  236. /**
  237. * Grants permission to read the ACL for the applicable bucket or object. The owner of a bucket or
  238. * object always has this permission implicitly.
  239. */
  240. const GRANT_READ_ACP = 'READ_ACP';
  241. /**
  242. * Gives permission to overwrite the ACP for the applicable bucket or object. The owner of a bucket
  243. * or object always has this permission implicitly. Granting this permission is equivalent to granting
  244. * FULL_CONTROL because the grant recipient can make any changes to the ACP.
  245. */
  246. const GRANT_WRITE_ACP = 'WRITE_ACP';
  247. /**
  248. * Provides READ, WRITE, READ_ACP, and WRITE_ACP permissions. It does not convey additional rights and
  249. * is provided only for convenience.
  250. */
  251. const GRANT_FULL_CONTROL = 'FULL_CONTROL';
  252. /*%******************************************************************************************%*/
  253. // USERS
  254. /**
  255. * The "AuthenticatedUsers" group for access control policies.
  256. */
  257. const USERS_AUTH = 'http://acs.amazonaws.com/groups/global/AuthenticatedUsers';
  258. /**
  259. * The "AllUsers" group for access control policies.
  260. */
  261. const USERS_ALL = 'http://acs.amazonaws.com/groups/global/AllUsers';
  262. /**
  263. * The "LogDelivery" group for access control policies.
  264. */
  265. const USERS_LOGGING = 'http://acs.amazonaws.com/groups/s3/LogDelivery';
  266. /*%******************************************************************************************%*/
  267. // PATTERNS
  268. /**
  269. * PCRE: Match all items
  270. */
  271. const PCRE_ALL = '/.*/i';
  272. /*%******************************************************************************************%*/
  273. // STORAGE
  274. /**
  275. * Standard storage redundancy.
  276. */
  277. const STORAGE_STANDARD = 'STANDARD';
  278. /**
  279. * Reduced storage redundancy.
  280. */
  281. const STORAGE_REDUCED = 'REDUCED_REDUNDANCY';
  282. /*%******************************************************************************************%*/
  283. // PROPERTIES
  284. /**
  285. * The request URL.
  286. */
  287. public $request_url;
  288. /**
  289. * The virtual host setting.
  290. */
  291. public $vhost;
  292. /**
  293. * The base XML elements to use for access control policy methods.
  294. */
  295. public $base_acp_xml;
  296. /**
  297. * The base XML elements to use for creating buckets in regions.
  298. */
  299. public $base_location_constraint;
  300. /**
  301. * The base XML elements to use for logging methods.
  302. */
  303. public $base_logging_xml;
  304. /**
  305. * The base XML elements to use for notifications.
  306. */
  307. public $base_notification_xml;
  308. /**
  309. * The base XML elements to use for versioning.
  310. */
  311. public $base_versioning_xml;
  312. /**
  313. * The base XML elements to use for completing a multipart upload.
  314. */
  315. public $complete_mpu_xml;
  316. /**
  317. * The base XML elements to use for website support.
  318. */
  319. public $website_config_xml;
  320. /**
  321. * The base XML elements to use for multi-object delete support.
  322. */
  323. public $multi_object_delete_xml;
  324. /**
  325. * The base XML elements to use for object expiration support.
  326. */
  327. public $object_expiration_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. // Determine hostname
  458. $scheme = $this->use_ssl ? 'https://' : 'http://';
  459. if ($this->resource_prefix || $this->path_style) // Use bucket-in-path method.
  460. {
  461. $hostname = $this->hostname . $this->resource_prefix . (($bucket === '' || $this->resource_prefix === '/' . $bucket) ? '' : ('/' . $bucket));
  462. }
  463. else
  464. {
  465. $hostname = $this->vhost ? $this->vhost : (($bucket === '') ? $this->hostname : ($bucket . '.') . $this->hostname);
  466. }
  467. // Get the UTC timestamp in RFC 2616 format
  468. $date = gmdate(CFUtilities::DATE_FORMAT_RFC2616, time());
  469. // Storage for request parameters.
  470. $resource = '';
  471. $sub_resource = '';
  472. $querystringparams = array();
  473. $signable_querystringparams = array();
  474. $string_to_sign = '';
  475. $headers = array(
  476. 'Content-MD5' => '',
  477. 'Content-Type' => 'application/x-www-form-urlencoded',
  478. 'Date' => $date
  479. );
  480. /*%******************************************************************************************%*/
  481. // Do we have an authentication token?
  482. if ($this->auth_token)
  483. {
  484. $headers['X-Amz-Security-Token'] = $this->auth_token;
  485. }
  486. // Handle specific resources
  487. if (isset($opt['resource']))
  488. {
  489. $resource .= $opt['resource'];
  490. }
  491. // Merge query string values
  492. if (isset($opt['query_string']))
  493. {
  494. $querystringparams = array_merge($querystringparams, $opt['query_string']);
  495. }
  496. $query_string = $this->util->to_query_string($querystringparams);
  497. // Merge the signable query string values. Must be alphabetical.
  498. $signable_list = array(
  499. 'partNumber',
  500. 'response-cache-control',
  501. 'response-content-disposition',
  502. 'response-content-encoding',
  503. 'response-content-language',
  504. 'response-content-type',
  505. 'response-expires',
  506. 'uploadId',
  507. 'versionId'
  508. );
  509. foreach ($signable_list as $item)
  510. {
  511. if (isset($opt[$item]))
  512. {
  513. $signable_querystringparams[$item] = $opt[$item];
  514. }
  515. }
  516. $signable_query_string = $this->util->to_query_string($signable_querystringparams);
  517. // Merge the HTTP headers
  518. if (isset($opt['headers']))
  519. {
  520. $headers = array_merge($headers, $opt['headers']);
  521. }
  522. // Compile the URI to request
  523. $conjunction = '?';
  524. $signable_resource = '/' . str_replace('%2F', '/', rawurlencode($resource));
  525. $non_signable_resource = '';
  526. if (isset($opt['sub_resource']))
  527. {
  528. $signable_resource .= $conjunction . rawurlencode($opt['sub_resource']);
  529. $conjunction = '&';
  530. }
  531. if ($signable_query_string !== '')
  532. {
  533. $signable_query_string = $conjunction . $signable_query_string;
  534. $conjunction = '&';
  535. }
  536. if ($query_string !== '')
  537. {
  538. $non_signable_resource .= $conjunction . $query_string;
  539. $conjunction = '&';
  540. }
  541. if (substr($hostname, -1) === substr($signable_resource, 0, 1))
  542. {
  543. $signable_resource = ltrim($signable_resource, '/');
  544. }
  545. $this->request_url = $scheme . $hostname . $signable_resource . $signable_query_string . $non_signable_resource;
  546. if (isset($opt['location']))
  547. {
  548. $this->request_url = $opt['location'];
  549. }
  550. // Gather information to pass along to other classes.
  551. $helpers = array(
  552. 'utilities' => $this->utilities_class,
  553. 'request' => $this->request_class,
  554. 'response' => $this->response_class,
  555. );
  556. // Instantiate the request class
  557. $request = new $this->request_class($this->request_url, $this->proxy, $helpers, $this->credentials);
  558. // Update RequestCore settings
  559. $request->request_class = $this->request_class;
  560. $request->response_class = $this->response_class;
  561. $request->ssl_verification = $this->ssl_verification;
  562. // Pass along registered stream callbacks
  563. if ($this->registered_streaming_read_callback)
  564. {
  565. $request->register_streaming_read_callback($this->registered_streaming_read_callback);
  566. }
  567. if ($this->registered_streaming_write_callback)
  568. {
  569. $request->register_streaming_write_callback($this->registered_streaming_write_callback);
  570. }
  571. // Streaming uploads
  572. if (isset($opt['fileUpload']))
  573. {
  574. if (is_resource($opt['fileUpload']))
  575. {
  576. // Determine the length to read from the stream
  577. $length = null; // From current position until EOF by default, size determined by set_read_stream()
  578. if (isset($headers['Content-Length']))
  579. {
  580. $length = $headers['Content-Length'];
  581. }
  582. elseif (isset($opt['seekTo']))
  583. {
  584. // Read from seekTo until EOF by default
  585. $stats = fstat($opt['fileUpload']);
  586. if ($stats && $stats['size'] >= 0)
  587. {
  588. $length = $stats['size'] - (integer) $opt['seekTo'];
  589. }
  590. }
  591. $request->set_read_stream($opt['fileUpload'], $length);
  592. if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
  593. {
  594. $headers['Content-Type'] = 'application/octet-stream';
  595. }
  596. }
  597. else
  598. {
  599. $request->set_read_file($opt['fileUpload']);
  600. // Determine the length to read from the file
  601. $length = $request->read_stream_size; // The file size by default
  602. if (isset($headers['Content-Length']))
  603. {
  604. $length = $headers['Content-Length'];
  605. }
  606. elseif (isset($opt['seekTo']) && isset($length))
  607. {
  608. // Read from seekTo until EOF by default
  609. $length -= (integer) $opt['seekTo'];
  610. }
  611. $request->set_read_stream_size($length);
  612. // Attempt to guess the correct mime-type
  613. if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
  614. {
  615. $extension = explode('.', $opt['fileUpload']);
  616. $extension = array_pop($extension);
  617. $mime_type = CFMimeTypes::get_mimetype($extension);
  618. $headers['Content-Type'] = $mime_type;
  619. }
  620. }
  621. $headers['Content-Length'] = $request->read_stream_size;
  622. $headers['Content-MD5'] = '';
  623. }
  624. // Handle streaming file offsets
  625. if (isset($opt['seekTo']))
  626. {
  627. // Pass the seek position to RequestCore
  628. $request->set_seek_position((integer) $opt['seekTo']);
  629. }
  630. // Streaming downloads
  631. if (isset($opt['fileDownload']))
  632. {
  633. if (is_resource($opt['fileDownload']))
  634. {
  635. $request->set_write_stream($opt['fileDownload']);
  636. }
  637. else
  638. {
  639. $request->set_write_file($opt['fileDownload']);
  640. }
  641. }
  642. $curlopts = array();
  643. // Set custom CURLOPT settings
  644. if (isset($opt['curlopts']))
  645. {
  646. $curlopts = $opt['curlopts'];
  647. }
  648. // Debug mode
  649. if ($this->debug_mode)
  650. {
  651. $curlopts[CURLOPT_VERBOSE] = true;
  652. }
  653. // Set the curl options.
  654. if (count($curlopts))
  655. {
  656. $request->set_curlopts($curlopts);
  657. }
  658. // Do we have a verb?
  659. if (isset($opt['verb']))
  660. {
  661. $request->set_method($opt['verb']);
  662. $string_to_sign .= $opt['verb'] . "\n";
  663. }
  664. // Add headers and content when we have a body
  665. if (isset($opt['body']))
  666. {
  667. $request->set_body($opt['body']);
  668. $headers['Content-Length'] = strlen($opt['body']);
  669. if ($headers['Content-Type'] === 'application/x-www-form-urlencoded')
  670. {
  671. $headers['Content-Type'] = 'application/octet-stream';
  672. }
  673. if (!isset($opt['NoContentMD5']) || $opt['NoContentMD5'] !== true)
  674. {
  675. $headers['Content-MD5'] = $this->util->hex_to_base64(md5($opt['body']));
  676. }
  677. }
  678. // Handle query-string authentication
  679. if (isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
  680. {
  681. unset($headers['Date']);
  682. $headers['Content-Type'] = '';
  683. $headers['Expires'] = is_int($opt['preauth']) ? $opt['preauth'] : strtotime($opt['preauth']);
  684. }
  685. // Sort headers
  686. uksort($headers, 'strnatcasecmp');
  687. // Add headers to request and compute the string to sign
  688. foreach ($headers as $header_key => $header_value)
  689. {
  690. // Strip linebreaks from header values as they're illegal and can allow for security issues
  691. $header_value = str_replace(array("\r", "\n"), '', $header_value);
  692. // Add the header if it has a value
  693. if ($header_value !== '')
  694. {
  695. $request->add_header($header_key, $header_value);
  696. }
  697. // Generate the string to sign
  698. if (
  699. strtolower($header_key) === 'content-md5' ||
  700. strtolower($header_key) === 'content-type' ||
  701. strtolower($header_key) === 'date' ||
  702. (strtolower($header_key) === 'expires' && isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
  703. )
  704. {
  705. $string_to_sign .= $header_value . "\n";
  706. }
  707. elseif (substr(strtolower($header_key), 0, 6) === 'x-amz-')
  708. {
  709. $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
  710. }
  711. }
  712. // Add the signable resource location
  713. $string_to_sign .= ($this->resource_prefix ? $this->resource_prefix : '');
  714. $string_to_sign .= (($bucket === '' || $this->resource_prefix === '/' . $bucket) ? '' : ('/' . $bucket)) . $signable_resource . urldecode($signable_query_string);
  715. // Hash the AWS secret key and generate a signature for the request.
  716. $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->secret_key, true));
  717. $request->add_header('Authorization', 'AWS ' . $this->key . ':' . $signature);
  718. // If we're generating a URL, return the URL to the calling method.
  719. if (isset($opt['preauth']) && (integer) $opt['preauth'] > 0)
  720. {
  721. $query_params = array(
  722. 'AWSAccessKeyId' => $this->key,
  723. 'Expires' => $headers['Expires'],
  724. 'Signature' => $signature,
  725. );
  726. // If using short-term credentials, add the token to the query string
  727. if ($this->auth_token)
  728. {
  729. $query_params['x-amz-security-token'] = $this->auth_token;
  730. }
  731. return $this->request_url . $conjunction . http_build_query($query_params, '', '&');
  732. }
  733. elseif (isset($opt['preauth']))
  734. {
  735. return $this->request_url;
  736. }
  737. /*%******************************************************************************************%*/
  738. // If our changes were temporary, reset them.
  739. if ($this->temporary_prefix)
  740. {
  741. $this->temporary_prefix = false;
  742. $this->resource_prefix = null;
  743. }
  744. // Manage the (newer) batch request API or the (older) returnCurlHandle setting.
  745. if ($this->use_batch_flow)
  746. {
  747. $handle = $request->prep_request();
  748. $this->batch_object->add($handle);
  749. $this->use_batch_flow = false;
  750. return $handle;
  751. }
  752. elseif (isset($opt['returnCurlHandle']) && $opt['returnCurlHandle'] === true)
  753. {
  754. return $request->prep_request();
  755. }
  756. // Send!
  757. $request->send_request();
  758. // Prepare the response
  759. $headers = $request->get_response_header();
  760. $headers['x-aws-request-url'] = $this->request_url;
  761. $headers['x-aws-redirects'] = $this->redirects;
  762. $headers['x-aws-stringtosign'] = $string_to_sign;
  763. $headers['x-aws-requestheaders'] = $request->request_headers;
  764. // Did we have a request body?
  765. if (isset($opt['body']))
  766. {
  767. $headers['x-aws-requestbody'] = $opt['body'];
  768. }
  769. $data = new $this->response_class($headers, $this->parse_callback($request->get_response_body()), $request->get_response_code());
  770. // Did Amazon tell us to redirect? Typically happens for multiple rapid requests EU datacenters.
  771. // @see: http://docs.amazonwebservices.com/AmazonS3/latest/dev/Redirects.html
  772. // @codeCoverageIgnoreStart
  773. if ((integer) $request->get_response_code() === 307) // Temporary redirect to new endpoint.
  774. {
  775. $this->redirects++;
  776. $opt['location'] = $headers['location'];
  777. $data = $this->authenticate($bucket, $opt);
  778. }
  779. // Was it Amazon's fault the request failed? Retry the request until we reach $max_retries.
  780. elseif ((integer) $request->get_response_code() === 500 || (integer) $request->get_response_code() === 503)
  781. {
  782. if ($this->redirects <= $this->max_retries)
  783. {
  784. // Exponential backoff
  785. $delay = (integer) (pow(4, $this->redirects) * 100000);
  786. usleep($delay);
  787. $this->redirects++;
  788. $data = $this->authenticate($bucket, $opt);
  789. }
  790. }
  791. // @codeCoverageIgnoreEnd
  792. // Return!
  793. $this->redirects = 0;
  794. return $data;
  795. }
  796. /**
  797. * Validates whether or not the specified Amazon S3 bucket name is valid for DNS-style access. This
  798. * method is leveraged by any method that creates buckets.
  799. *
  800. * @param string $bucket (Required) The name of the bucket to validate.
  801. * @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.
  802. */
  803. public function validate_bucketname_create($bucket)
  804. {
  805. // list_buckets() uses this. Let it pass.
  806. if ($bucket === '') return true;
  807. if (
  808. ($bucket === null || $bucket === false) || // Must not be null or false
  809. preg_match('/[^(a-z0-9\-\.)]/', $bucket) || // Must be in the lowercase Roman alphabet, period or hyphen
  810. !preg_match('/^([a-z]|\d)/', $bucket) || // Must start with a number or letter
  811. !(strlen($bucket) >= 3 && strlen($bucket) <= 63) || // Must be between 3 and 63 characters long
  812. (strpos($bucket, '..') !== false) || // Bucket names cannot contain two, adjacent periods
  813. (strpos($bucket, '-.') !== false) || // Bucket names cannot contain dashes next to periods
  814. (strpos($bucket, '.-') !== false) || // Bucket names cannot contain dashes next to periods
  815. preg_match('/(-|\.)$/', $bucket) || // Bucket names should not end with a dash or period
  816. preg_match('/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/', $bucket) // Must not be formatted as an IP address
  817. ) return false;
  818. return true;
  819. }
  820. /**
  821. * Validates whether or not the specified Amazon S3 bucket name is valid for path-style access. This
  822. * method is leveraged by any method that reads from buckets.
  823. *
  824. * @param string $bucket (Required) The name of the bucket to validate.
  825. * @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.
  826. */
  827. public function validate_bucketname_support($bucket)
  828. {
  829. // list_buckets() uses this. Let it pass.
  830. if ($bucket === '') return true;
  831. // Validate
  832. if (
  833. ($bucket === null || $bucket === false) || // Must not be null or false
  834. preg_match('/[^(a-z0-9_\-\.)]/i', $bucket) || // Must be in the Roman alphabet, period, hyphen or underscore
  835. !preg_match('/^([a-z]|\d)/i', $bucket) || // Must start with a number or letter
  836. !(strlen($bucket) >= 3 && strlen($bucket) <= 255) || // Must be between 3 and 255 characters long
  837. preg_match('/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/', $bucket) // Must not be formatted as an IP address
  838. ) return false;
  839. return true;
  840. }
  841. /*%******************************************************************************************%*/
  842. // SETTERS
  843. /**
  844. * Sets the region to use for subsequent Amazon S3 operations. This will also reset any prior use of
  845. * <enable_path_style()>.
  846. *
  847. * @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.
  848. * @return $this A reference to the current instance.
  849. */
  850. public function set_region($region)
  851. {
  852. // @codeCoverageIgnoreStart
  853. $this->set_hostname($region);
  854. switch ($region)
  855. {
  856. case self::REGION_US_E1: // Northern Virginia
  857. $this->enable_path_style(false);
  858. break;
  859. case self::REGION_EU_W1: // Ireland
  860. $this->enable_path_style(); // Always use path-style access for EU endpoint.
  861. break;
  862. default:
  863. $this->enable_path_style(false);
  864. break;
  865. }
  866. // @codeCoverageIgnoreEnd
  867. return $this;
  868. }
  869. /**
  870. * Sets the virtual host to use in place of the default `bucket.s3.amazonaws.com` domain.
  871. *
  872. * @param string $vhost (Required) The virtual host to use in place of the default `bucket.s3.amazonaws.com` domain.
  873. * @return $this A reference to the current instance.
  874. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/VirtualHosting.html Virtual Hosting of Buckets
  875. */
  876. public function set_vhost($vhost)
  877. {
  878. $this->vhost = $vhost;
  879. return $this;
  880. }
  881. /**
  882. * Enables the use of the older path-style URI access for all requests.
  883. *
  884. * @param string $style (Optional) Whether or not to enable path-style URI access for all requests. The default value is <code>true</code>.
  885. * @return $this A reference to the current instance.
  886. */
  887. public function enable_path_style($style = true)
  888. {
  889. $this->path_style = $style;
  890. return $this;
  891. }
  892. /*%******************************************************************************************%*/
  893. // BUCKET METHODS
  894. /**
  895. * Creates an Amazon S3 bucket.
  896. *
  897. * Every object stored in Amazon S3 is contained in a bucket. Buckets partition the namespace of
  898. * objects stored in Amazon S3 at the top level. in a bucket, any name can be used for objects.
  899. * However, bucket names must be unique across all of Amazon S3.
  900. *
  901. * @param string $bucket (Required) The name of the bucket to create.
  902. * @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`]
  903. * @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>.
  904. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  905. * <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>
  906. * <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>
  907. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  908. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/UsingBucket.html Working with Amazon S3 Buckets
  909. */
  910. public function create_bucket($bucket, $region, $acl = self::ACL_PRIVATE, $opt = null)
  911. {
  912. // If the bucket contains uppercase letters...
  913. if (preg_match('/[A-Z]/', $bucket))
  914. {
  915. // Throw a warning
  916. trigger_error('Since DNS-valid bucket names cannot contain uppercase characters, "' . $bucket . '" has been automatically converted to "' . strtolower($bucket) . '"', E_USER_WARNING);
  917. // Force the bucketname to lowercase
  918. $bucket = strtolower($bucket);
  919. }
  920. // Validate the S3 bucket name for creation
  921. if (!$this->validate_bucketname_create($bucket))
  922. {
  923. // @codeCoverageIgnoreStart
  924. 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.');
  925. // @codeCoverageIgnoreEnd
  926. }
  927. if (!$opt) $opt = array();
  928. $opt['verb'] = 'PUT';
  929. $opt['headers'] = array(
  930. 'Content-Type' => 'application/xml'
  931. );
  932. // Handle Access Control Lists. Can also be passed as an HTTP header.
  933. if (isset($acl))
  934. {
  935. if (is_array($acl))
  936. {
  937. $opt['headers'] = array_merge($opt['headers'], $this->generate_access_policy_headers($acl));
  938. }
  939. else
  940. {
  941. $opt['headers']['x-amz-acl'] = $acl;
  942. }
  943. }
  944. // Defaults
  945. $this->set_region($region); // Also sets path-style
  946. $xml = simplexml_load_string($this->base_location_constraint);
  947. switch ($region)
  948. {
  949. case self::REGION_US_E1: // Northern Virginia
  950. $opt['body'] = '';
  951. break;
  952. case self::REGION_EU_W1: // Ireland
  953. $xml->LocationConstraint = 'EU';
  954. $opt['body'] = $xml->asXML();
  955. break;
  956. default:
  957. $xml->LocationConstraint = str_replace(array('s3-', '.amazonaws.com'), '', $region);
  958. $opt['body'] = $xml->asXML();
  959. break;
  960. }
  961. $response = $this->authenticate($bucket, $opt);
  962. // Make sure we're set back to DNS-style URLs
  963. $this->enable_path_style(false);
  964. return $response;
  965. }
  966. /**
  967. * Gets the region in which the specified Amazon S3 bucket is located.
  968. *
  969. * @param string $bucket (Required) The name of the bucket to use.
  970. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  971. * <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>
  972. * <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>
  973. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  974. */
  975. public function get_bucket_region($bucket, $opt = null)
  976. {
  977. // Add this to our request
  978. if (!$opt) $opt = array();
  979. $opt['verb'] = 'GET';
  980. $opt['sub_resource'] = 'location';
  981. // Authenticate to S3
  982. $response = $this->authenticate($bucket, $opt);
  983. if ($response->isOK())
  984. {
  985. // Handle body
  986. $response->body = (string) $response->body;
  987. }
  988. return $response;
  989. }
  990. /**
  991. * Gets the HTTP headers for the specified Amazon S3 bucket.
  992. *
  993. * @param string $bucket (Required) The name of the bucket to use.
  994. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  995. * <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>
  996. * <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>
  997. * <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>
  998. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  999. */
  1000. public function get_bucket_headers($bucket, $opt = null)
  1001. {
  1002. if (!$opt) $opt = array();
  1003. $opt['verb'] = 'HEAD';
  1004. return $this->authenticate($bucket, $opt);
  1005. }
  1006. /**
  1007. * Deletes a bucket from an Amazon S3 account. A bucket must be empty before the bucket itself can be deleted.
  1008. *
  1009. * @param string $bucket (Required) The name of the bucket to use.
  1010. * @param boolean $force (Optional) Whether to force-delete the bucket and all of its contents. The default value is <code>false</code>.
  1011. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1012. * <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>
  1013. * <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>
  1014. * @return mixed A <CFResponse> object if the bucket was deleted successfully. Returns boolean <code>false</code> if otherwise.
  1015. */
  1016. public function delete_bucket($bucket, $force = false, $opt = null)
  1017. {
  1018. // Set default value
  1019. $success = true;
  1020. if ($force)
  1021. {
  1022. // Delete all of the items from the bucket.
  1023. $success = $this->delete_all_object_versions($bucket);
  1024. }
  1025. // As long as we were successful...
  1026. if ($success)
  1027. {
  1028. if (!$opt) $opt = array();
  1029. $opt['verb'] = 'DELETE';
  1030. return $this->authenticate($bucket, $opt);
  1031. }
  1032. // @codeCoverageIgnoreStart
  1033. return false;
  1034. // @codeCoverageIgnoreEnd
  1035. }
  1036. /**
  1037. * Gets a list of all buckets contained in the caller's Amazon S3 account.
  1038. *
  1039. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1040. * <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>
  1041. * <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>
  1042. * <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>
  1043. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  1044. */
  1045. public function list_buckets($opt = null)
  1046. {
  1047. if (!$opt) $opt = array();
  1048. $opt['verb'] = 'GET';
  1049. return $this->authenticate('', $opt);
  1050. }
  1051. /**
  1052. * Gets the access control list (ACL) settings for the specified Amazon S3 bucket.
  1053. *
  1054. * @param string $bucket (Required) The name of the bucket to use.
  1055. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1056. * <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>
  1057. * <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>
  1058. * <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>
  1059. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  1060. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
  1061. */
  1062. public function get_bucket_acl($bucket, $opt = null)
  1063. {
  1064. // Add this to our request
  1065. if (!$opt) $opt = array();
  1066. $opt['verb'] = 'GET';
  1067. $opt['sub_resource'] = 'acl';
  1068. // Authenticate to S3
  1069. return $this->authenticate($bucket, $opt);
  1070. }
  1071. /**
  1072. * Sets the access control list (ACL) settings for the specified Amazon S3 bucket.
  1073. *
  1074. * @param string $bucket (Required) The name of the bucket to use.
  1075. * @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>.
  1076. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1077. * <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>
  1078. * <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>
  1079. * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
  1080. * @link http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAccessPolicy.html REST Access Control Policy
  1081. */
  1082. public function set_bucket_acl($bucket, $acl = self::ACL_PRIVATE, $opt = null)
  1083. {
  1084. // Add this to our request
  1085. if (!$opt) $opt = array();
  1086. $opt['verb'] = 'PUT';
  1087. $opt['sub_resource'] = 'acl';
  1088. $opt['headers'] = array(
  1089. 'Content-Type' => 'application/xml'
  1090. );
  1091. // Make sure these are defined.
  1092. // @codeCoverageIgnoreStart
  1093. if (!$this->credentials->canonical_id || !$this->credentials->canonical_name)
  1094. {
  1095. // Fetch the data live.
  1096. $canonical = $this->get_canonical_user_id();
  1097. $this->credentials->canonical_id = $canonical['id'];
  1098. $this->credentials->canonical_name = $canonical['display_name'];
  1099. }
  1100. // @codeCoverageIgnoreEnd
  1101. if (is_array($acl))
  1102. {
  1103. $opt['headers'] = array_merge($opt['headers'], $this->generate_access_policy_headers($acl));
  1104. }
  1105. else
  1106. {
  1107. $opt['body'] = '';
  1108. $opt['headers']['x-amz-acl'] = $acl;
  1109. }
  1110. // Authenticate to S3
  1111. return $this->authenticate($bucket, $opt);
  1112. }
  1113. /*%******************************************************************************************%*/
  1114. // OBJECT METHODS
  1115. /**
  1116. * Creates an Amazon S3 object. After an Amazon S3 bucket is created, objects can be stored in it.
  1117. *
  1118. * Each standard object can hold up to 5 GB of data. When an object is stored in Amazon S3, the data is streamed
  1119. * to multiple storage servers in multiple data centers. This ensures the data remains available in the
  1120. * event of internal network or hardware failure.
  1121. *
  1122. * @param string $bucket (Required) The name of the bucket to use.
  1123. * @param string $filename (Required) The file name for the object.
  1124. * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
  1125. * <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>
  1126. * <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>
  1127. * <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>
  1128. * <li><code>encryption</code> - <code>string</…

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