PageRenderTime 61ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/sdk-1.5.5/services/s3.class.php

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

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