Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 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
 
18
/*%******************************************************************************************%*/
19
// EXCEPTIONS
20
 
21
/**
22
 * Default CloudFront Exception.
23
 */
24
class CloudFront_Exception extends Exception {}
25
 
26
 
27
/*%******************************************************************************************%*/
28
// MAIN CLASS
29
 
30
/**
31
 * Amazon CloudFront is a web service for content delivery. It makes it easier for you to distribute content
32
 * to end users quickly, with low latency and high data transfer speeds.
33
 *
34
 * CloudFront delivers your content through a worldwide network of edge locations. End users are routed to
35
 * the nearest edge location, so content is delivered with the best possible performance. CloudFront works
36
 * seamlessly with the Amazon Simple Storage Service, which durably stores the original, definitive versions
37
 * of your files.
38
 *
39
 * @version 2012.01.17
40
 * @license See the included NOTICE.md file for more information.
41
 * @copyright See the included NOTICE.md file for more information.
42
 * @link http://aws.amazon.com/cloudfront/ Amazon CloudFront
43
 * @link http://aws.amazon.com/documentation/cloudfront/ Amazon CloudFront documentation
44
 */
45
class AmazonCloudFront extends CFRuntime
46
{
47
	/**
48
	 * Specify the default queue URL.
49
	 */
50
	const DEFAULT_URL = 'cloudfront.amazonaws.com';
51
 
52
	/**
53
	 * The InProgress state.
54
	 */
55
	const STATE_INPROGRESS = 'InProgress';
56
 
57
	/**
58
	 * The Deployed state.
59
	 */
60
	const STATE_DEPLOYED = 'Deployed';
61
 
62
	/**
63
	 * The base content to use for generating the DistributionConfig XML.
64
	 */
65
	var $base_xml;
66
 
67
	/**
68
	 * The CloudFront distribution domain to use.
69
	 */
70
	var $domain;
71
 
72
	/**
73
	 * The RSA key pair ID to use.
74
	 */
75
	var $key_pair_id;
76
 
77
	/**
78
	 * The RSA private key resource locator.
79
	 */
80
	var $private_key;
81
 
82
 
83
	/*%******************************************************************************************%*/
84
	// CONSTRUCTOR
85
 
86
	/**
87
	 * Constructs a new instance of <AmazonCloudFront>.
88
	 *
89
	 * @param array $options (Optional) An associative array of parameters that can have the following keys: <ul>
90
	 * 	<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>
91
	 * 	<li><code>credentials</code> - <code>string</code> - Optional - The name of the credential set to use for authentication.</li>
92
	 * 	<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>
93
	 * 	<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>
94
	 * 	<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>
95
	 * 	<li><code>token</code> - <code>string</code> - Optional - An AWS session token.</li></ul>
96
	 * @return void
97
	 */
98
	public function __construct(array $options = array())
99
	{
100
		$this->api_version = '2010-11-01';
101
		$this->hostname = self::DEFAULT_URL;
102
		$this->auth_class = 'AuthV2REST';
103
 
104
		$this->base_xml = '<?xml version="1.0" encoding="UTF-8"?><%s xmlns="http://cloudfront.amazonaws.com/doc/' . $this->api_version . '/"></%1$s>';
105
 
106
		parent::__construct($options);
107
 
108
		// Set a default key pair ID and private key
109
		$this->key_pair_id = $this->credentials->cloudfront_keypair;
110
		$this->private_key = $this->credentials->cloudfront_pem;
111
	}
112
 
113
 
114
	/*%******************************************************************************************%*/
115
	// AUTHENTICATION
116
 
117
	/**
118
	 * Authenticates a connection to Amazon CloudFront. This method should not be used directly unless
119
	 * you're writing custom methods for this class.
120
	 *
121
	 * @param string $operation (Required) The HTTP method to use to connect. Accepts <code>GET</code>, <code>POST</code>, <code>PUT</code>, <code>DELETE</code>, and <code>HEAD</code>.
122
	 * @param array $payload (Required) An associative array of parameters for authenticating. See the individual methods for allowed keys.
123
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
124
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/RESTAuthentication.html Authentication
125
	 */
126
	public function authenticate($operation, $payload)
127
	{
128
		// Extract data from payload
129
		$querystring = null;
130
		$opt = ($payload) ? $payload : array();
131
		$method = $operation;
132
		$path = isset($opt['path']) ? $opt['path'] : null;
133
		$xml = isset($opt['xml']) ? $opt['xml'] : null;
134
		$etag = isset($opt['etag']) ? $opt['etag'] : null;
135
 
136
		$method_arguments = func_get_args();
137
 
138
		// Use the caching flow to determine if we need to do a round-trip to the server.
139
		if ($this->use_cache_flow)
140
		{
141
			// Generate an identifier specific to this particular set of arguments.
142
			$cache_id = $this->key . '_' . get_class($this) . '_' . $method . sha1($path) . '_' . sha1(serialize($method_arguments));
143
 
144
			// Instantiate the appropriate caching object.
145
			$this->cache_object = new $this->cache_class($cache_id, $this->cache_location, $this->cache_expires, $this->cache_compress);
146
 
147
			if ($this->delete_cache)
148
			{
149
				$this->use_cache_flow = false;
150
				$this->delete_cache = false;
151
				return $this->cache_object->delete();
152
			}
153
 
154
			// Invoke the cache callback function to determine whether to pull data from the cache or make a fresh request.
155
			$data = $this->cache_object->response_manager(array($this, 'cache_callback'), $method_arguments);
156
 
157
			// Parse the XML body
158
			$data = $this->parse_callback($data);
159
 
160
			// End!
161
			return $data;
162
		}
163
 
164
		// Generate query string
165
		if (isset($opt['query_string']) && count($opt['query_string']))
166
		{
167
			$querystring = '?' . $this->util->to_query_string($opt['query_string']);
168
		}
169
 
170
		// Gather information to pass along to other classes.
171
		$helpers = array(
172
			'utilities' => $this->utilities_class,
173
			'request' => $this->request_class,
174
			'response' => $this->response_class,
175
		);
176
 
177
		// Compose the endpoint URL.
178
		$request_url = 'https://' . $this->hostname . '/' . $this->api_version;
179
		$request_url .= ($path) ? $path : '';
180
		$request_url .= ($querystring) ? $querystring : '';
181
 
182
		// Compose the request.
183
		$request = new $this->request_class($request_url, $this->proxy, $helpers, $this->credentials);
184
 
185
		// Update RequestCore settings
186
		$request->request_class = $this->request_class;
187
		$request->response_class = $this->response_class;
188
		$request->ssl_verification = $this->ssl_verification;
189
 
190
		// Pass along registered stream callbacks
191
		if ($this->registered_streaming_read_callback)
192
		{
193
			$request->register_streaming_read_callback($this->registered_streaming_read_callback);
194
		}
195
 
196
		if ($this->registered_streaming_write_callback)
197
		{
198
			$request->register_streaming_write_callback($this->registered_streaming_write_callback);
199
		}
200
 
201
		// Generate required headers.
202
		$request->set_method($method);
203
		$canonical_date = gmdate($this->util->konst($this->util, 'DATE_FORMAT_RFC2616'));
204
		$request->add_header('x-amz-date', $canonical_date);
205
		$signature = base64_encode(hash_hmac('sha1', $canonical_date, $this->secret_key, true));
206
		$request->add_header('Authorization', 'AWS ' . $this->key . ':' . $signature);
207
 
208
		// Add configuration XML if we have it.
209
		if ($xml)
210
		{
211
			$request->add_header('Content-Length', strlen($xml));
212
			$request->add_header('Content-Type', 'application/xml');
213
			$request->set_body($xml);
214
		}
215
 
216
		// Set If-Match: ETag header if we have one.
217
		if ($etag)
218
		{
219
			$request->add_header('If-Match', $etag);
220
		}
221
 
222
		$curlopts = array();
223
 
224
		// Set custom CURLOPT settings
225
		if (isset($opt['curlopts']))
226
		{
227
			$curlopts = $opt['curlopts'];
228
		}
229
 
230
		// Debug mode
231
		if ($this->debug_mode)
232
		{
233
			$curlopts[CURLOPT_VERBOSE] = true;
234
		}
235
 
236
		if (count($curlopts))
237
		{
238
			$request->set_curlopts($curlopts);
239
		}
240
 
241
		// Manage the (newer) batch request API or the (older) returnCurlHandle setting.
242
		if ($this->use_batch_flow)
243
		{
244
			$handle = $request->prep_request();
245
			$this->batch_object->add($handle);
246
			$this->use_batch_flow = false;
247
 
248
			return $handle;
249
		}
250
		elseif (isset($opt['returnCurlHandle']) && $opt['returnCurlHandle'] == (bool) true)
251
		{
252
			return $request->prep_request();
253
		}
254
 
255
		// Send!
256
		$request->send_request();
257
 
258
		// Prepare the response.
259
		$headers = $request->get_response_header();
260
		if ($xml) $headers['x-aws-body'] = $xml;
261
 
262
		$data =  new $this->response_class($headers, $this->parse_callback($request->get_response_body()), $request->get_response_code());
263
 
264
		// Was it Amazon's fault the request failed? Retry the request until we reach $max_retries.
265
		if ((integer) $request->get_response_code() === 500 || (integer) $request->get_response_code() === 503)
266
		{
267
			if ($this->redirects <= $this->max_retries)
268
			{
269
				// Exponential backoff
270
				$delay = (integer) (pow(4, $this->redirects) * 100000);
271
				usleep($delay);
272
				$this->redirects++;
273
				$data = $this->authenticate($method, $opt);
274
			}
275
		}
276
 
277
		$this->redirects = 0;
278
		return $data;
279
	}
280
 
281
 
282
	/*%******************************************************************************************%*/
283
	// SETTERS
284
 
285
	/**
286
	 * Set the key ID of the RSA key pair being used.
287
	 *
288
	 * @param string $key_pair_id (Required) The ID of the RSA key pair being used.
289
	 * @return $this A reference to the current instance.
290
	 */
291
	public function set_keypair_id($key_pair_id)
292
	{
293
		$this->key_pair_id = $key_pair_id;
294
		return $this;
295
	}
296
 
297
	/**
298
	 * Set the private key resource locator being used.
299
	 *
300
	 * @param string $private_key (Optional) The contents of the RSA private key used to sign requests.
301
	 * @return $this A reference to the current instance.
302
	 */
303
	public function set_private_key($private_key)
304
	{
305
		$this->private_key = $private_key;
306
		return $this;
307
	}
308
 
309
	/**
310
	 * Overrides the <CFRuntime::disable_ssl()> method from the base class. SSL is required for CloudFront.
311
	 *
312
	 * @return void
313
	 */
314
	public function disable_ssl()
315
	{
316
		throw new CloudFront_Exception('SSL/HTTPS is REQUIRED for Amazon CloudFront and cannot be disabled.');
317
	}
318
 
319
 
320
	/*%******************************************************************************************%*/
321
	// GENERATE CONFIG XML
322
 
323
	/**
324
	 * Generates the distribution configuration XML used with <create_distribution()> and
325
	 * <set_distribution_config()>.
326
	 *
327
	 * @param string $origin (Required) The source to use for the Amazon CloudFront distribution. Use an Amazon S3 bucket name, or a fully-qualified non-S3 domain name prefixed with <code>http://</code> or <code>https://</code>.
328
	 * @param string $caller_reference (Required) A unique identifier for the request. A timestamp-appended string is recommended.
329
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
330
	 * 	<li><code>CNAME</code> - <code>string|array</code> - Optional - A DNS CNAME to use to map to the Amazon CloudFront distribution. If setting more than one, use an indexed array. Supports 1-10 CNAMEs.</li>
331
	 * 	<li><code>Comment</code> - <code>string</code> - Optional - A comment to apply to the distribution. Cannot exceed 128 characters.</li>
332
	 * 	<li><code>DefaultRootObject</code> - <code>string</code> - Optional - The file to load when someone accesses the root of your Amazon CloudFront domain (e.g., <code>index.html</code>).</li>
333
	 * 	<li><code>Enabled</code> - <code>string</code> - Optional - A value of <code>true</code> enables the distribution. A value of <code>false</code> disables it. The default value is <code>true</code>.</li>
334
	 * 	<li><code>Logging</code> - <code>array</code> - Optional - An array that contains two keys: <code>Bucket</code>, specifying where logs are written to, and <code>Prefix</code>, specifying a prefix to append to log file names.</li>
335
	 * 	<li><code>OriginAccessIdentity</code> - <code>string</code> - Optional - The origin access identity (OAI) associated with this distribution. Use the Identity ID from the OAI, not the <code>CanonicalId</code>. Requires an S3 origin.</li>
336
	 * 	<li><code>OriginProtocolPolicy</code> - <code>string</code> - Optional - The origin protocol policy to apply to your origin. If you specify <code>http-only</code>, CloudFront will use HTTP only to access the origin. If you specify <code>match-viewer</code>, CloudFront will fetch from your origin using HTTP or HTTPS, based on the protocol of the viewer request. It has a default value of <code>match-viewer</code>. [Allowed values: <code>http-only</code>, <code>match-viewer</code>]</li>
337
	 * 	<li><code>Streaming</code> - <code>boolean</code> - Optional - Whether or not this should be for a streaming distribution. A value of <code>true</code> will create a streaming distribution. A value of <code>false</code> will create a standard distribution. The default value is <code>false</code>.</li>
338
	 * 	<li><code>TrustedSigners</code> - <code>array</code> - Optional - An array of AWS account numbers for users who are trusted signers. Explicity add the value <code>Self</code> to the array to add your own account as a trusted signer.</li></ul>
339
	 * @return string An XML document to be used as the distribution configuration.
340
	 */
341
	public function generate_config_xml($origin, $caller_reference, $opt = null)
342
	{
343
		// Default, empty XML
344
		$xml = simplexml_load_string(sprintf($this->base_xml, (
345
			(isset($opt['Streaming']) && $opt['Streaming'] == (bool) true) ? 'StreamingDistributionConfig' : 'DistributionConfig')
346
		));
347
 
348
		if (substr($origin, 0, 7) === 'http://' || substr($origin, 0, 8) === 'https://')
349
		{
350
			// Custom Origin
351
			$custom_origin = $xml->addChild('CustomOrigin');
352
			$custom_origin->addChild('DNSName', str_replace(array('http://', 'https://'), '', $origin));
353
 
354
			if (isset($opt['OriginProtocolPolicy']))
355
			{
356
				$custom_origin->addChild('OriginProtocolPolicy', $opt['OriginProtocolPolicy']);
357
			}
358
			else
359
			{
360
				$custom_origin->addChild('OriginProtocolPolicy', 'match-viewer');
361
			}
362
		}
363
		else
364
		{
365
			// S3 Origin
366
			$s3_origin = $xml->addChild('S3Origin');
367
			$s3_origin->addChild('DNSName', $origin . ((stripos($origin, '.s3.amazonaws.com') === false) ? '.s3.amazonaws.com' : ''));
368
 
369
			// Origin Access Identity
370
			if (isset($opt['OriginAccessIdentity']))
371
			{
372
				$s3_origin->addChild('OriginAccessIdentity', 'origin-access-identity/cloudfront/' . $opt['OriginAccessIdentity']);
373
			}
374
		}
375
 
376
		// CallerReference
377
		$xml->addChild('CallerReference', $caller_reference);
378
 
379
		// CNAME
380
		if (isset($opt['CNAME']))
381
		{
382
			if (is_array($opt['CNAME']))
383
			{
384
				foreach ($opt['CNAME'] as $cname)
385
				{
386
					$xml->addChild('CNAME', $cname);
387
				}
388
			}
389
			else
390
			{
391
				$xml->addChild('CNAME', $opt['CNAME']);
392
			}
393
		}
394
 
395
		// Comment
396
		if (isset($opt['Comment']))
397
		{
398
			$xml->addChild('Comment', $opt['Comment']);
399
		}
400
 
401
		// Enabled
402
		if (isset($opt['Enabled']))
403
		{
404
			$xml->addChild('Enabled', $opt['Enabled'] ? 'true' : 'false');
405
		}
406
		else
407
		{
408
			$xml->addChild('Enabled', 'true');
409
		}
410
 
411
		// Logging
412
		if (isset($opt['Logging']))
413
		{
414
			if (is_array($opt['Logging']))
415
			{
416
				$logging = $xml->addChild('Logging');
417
				$bucket_name = $opt['Logging']['Bucket'];
418
 
419
				// Origin
420
				$logging->addChild('Bucket', $bucket_name . (
421
					(stripos($bucket_name, '.s3.amazonaws.com') === false) ? '.s3.amazonaws.com' : ''
422
				));
423
 
424
				$logging->addChild('Prefix', $opt['Logging']['Prefix']);
425
			}
426
		}
427
 
428
		// Required Protocols
429
		if (isset($opt['RequiredProtocols']))
430
		{
431
			$required_protocols = $xml->addChild('RequiredProtocols');
432
			$required_protocols->addChild('Protocol', $opt['RequiredProtocols']);
433
		}
434
 
435
		// Trusted Signers
436
		if (isset($opt['TrustedSigners']))
437
		{
438
			$trusted_signers = $xml->addChild('TrustedSigners');
439
 
440
			// Not an array? Convert to one.
441
			if (!is_array($opt['TrustedSigners']))
442
			{
443
				$opt['TrustedSigners'] = array($opt['TrustedSigners']);
444
			}
445
 
446
			// Handle 'Self' vs. everything else
447
			foreach ($opt['TrustedSigners'] as $signer)
448
			{
449
				if (strtolower($signer) === 'self')
450
				{
451
					$trusted_signers->addChild('Self');
452
				}
453
				else
454
				{
455
					$trusted_signers->addChild('AwsAccountNumber', $signer);
456
				}
457
			}
458
		}
459
 
460
		// DefaultRootObject
461
		if (isset($opt['DefaultRootObject']))
462
		{
463
			$xml->addChild('DefaultRootObject', $opt['DefaultRootObject']);
464
		}
465
 
466
		return $xml->asXML();
467
	}
468
 
469
	/**
470
	 * Updates an existing configuration XML document.
471
	 *
472
	 * @param CFSimpleXML|CFResponse|string $xml (Required) The source configuration XML to make updates to. Can be the <CFSimpleXML> body of a <get_distribution_config()> response, the entire <CFResponse> of a <get_distribution_config()> response, or a string of XML generated by <generate_config_xml()> or <update_config_xml()>.
473
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
474
	 * 	<li><code>CNAME</code> - <code>string|array</code> - Optional - The value or values to add to the existing list of CNAME values. If setting more than one, use an indexed array. Supports up to 10 CNAMEs.</li>
475
	 * 	<li><code>Comment</code> - <code>string</code> - Optional - A comment to apply to the distribution. Cannot exceed 128 characters.</li>
476
	 * 	<li><code>DefaultRootObject</code> - <code>string</code> - Optional - The file to load when someone accesses the root of your Amazon CloudFront domain (e.g., <code>index.html</code>).</li>
477
	 * 	<li><code>Enabled</code> - <code>string</code> - Optional - A value of <code>true</code> enables the distribution. A value of <code>false</code> disables it. The default value is <code>true</code>.</li>
478
	 * 	<li><code>Logging</code> - <code>array</code> - Optional - An array that contains two keys: <code>Bucket</code>, specifying where logs are written to, and <code>Prefix</code>, specifying a prefix to append to log file names.</li>
479
	 * 	<li><code>OriginAccessIdentity</code> - <code>string</code> - Optional - The origin access identity (OAI) associated with this distribution. Use the Identity ID from the OAI, not the <code>CanonicalId</code>.</li>
480
	 * 	<li><code>TrustedSigners</code> - <code>array</code> - Optional - An array of AWS account numbers for users who are trusted signers. Explicity add the value <code>Self</code> to the array to add your own account as a trusted signer.</li></ul>
481
	 * @return string XML document.
482
	 */
483
	public function update_config_xml($xml, $opt = null)
484
	{
485
		// If we receive a full CFResponse object, only use the body.
486
		if ($xml instanceof CFResponse)
487
		{
488
			$xml = $xml->body;
489
		}
490
 
491
		// If we received a string of XML, convert it into a CFSimpleXML object.
492
		if (is_string($xml))
493
		{
494
			$xml = simplexml_load_string($xml, $this->parser_class);
495
		}
496
 
497
		// Default, empty XML
498
		$update = simplexml_load_string(sprintf($this->base_xml, (
499
			(isset($opt['Streaming']) && $opt['Streaming'] == (bool) true) ? 'StreamingDistributionConfig' : 'DistributionConfig')
500
		), $this->parser_class);
501
 
502
		// These can't change.
503
		if (isset($xml->S3Origin))
504
		{
505
			$origin = $update->addChild('S3Origin');
506
			$origin->addChild('DNSName', $xml->S3Origin->DNSName);
507
 
508
			// origin access identity
509
			if (isset($opt['OriginAccessIdentity']))
510
			{
511
				$origin->addChild('OriginAccessIdentity', 'origin-access-identity/cloudfront/' . $opt['OriginAccessIdentity']);
512
			}
513
			elseif (isset($xml->S3Origin->OriginAccessIdentity))
514
			{
515
				$origin->addChild('OriginAccessIdentity', $xml->S3Origin->OriginAccessIdentity);
516
			}
517
		}
518
		elseif (isset($xml->CustomOrigin))
519
		{
520
			$origin = $update->addChild('CustomOrigin');
521
			$origin->addChild('DNSName', $xml->CustomOrigin->DNSName);
522
 
523
			// Copy OriginProtocolPolicy for update
524
			if ( isset($xml->CustomOrigin->OriginProtocolPolicy) )
525
			{
526
				$origin->addChild('OriginProtocolPolicy', $xml->CustomOrigin->OriginProtocolPolicy);
527
			}
528
 
529
			// origin access identity
530
			if (isset($opt['OriginAccessIdentity']))
531
			{
532
				$origin->addChild('OriginAccessIdentity', 'origin-access-identity/cloudfront/' . $opt['OriginAccessIdentity']);
533
			}
534
			elseif (isset($xml->CustomOrigin->OriginAccessIdentity))
535
			{
536
				$origin->addChild('OriginAccessIdentity', $xml->CustomOrigin->OriginAccessIdentity);
537
			}
538
		}
539
 
540
		$update->addChild('CallerReference', $xml->CallerReference);
541
 
542
		// Add existing CNAME values
543
		if ($xml->CNAME)
544
		{
545
			$update->addChild('CNAME', $xml->CNAME);
546
		}
547
 
548
		// Add new CNAME values
549
		if (isset($opt['CNAME']))
550
		{
551
			if (is_array($opt['CNAME']))
552
			{
553
				foreach ($opt['CNAME'] as $cname)
554
				{
555
					$update->addChild('CNAME', $cname);
556
				}
557
			}
558
			else
559
			{
560
				$update->addChild('CNAME', $opt['CNAME']);
561
			}
562
		}
563
 
564
		// Comment
565
		if (isset($opt['Comment']))
566
		{
567
			$update->addChild('Comment', $opt['Comment']);
568
		}
569
		elseif (isset($xml->Comment))
570
		{
571
			$update->addChild('Comment', $xml->Comment);
572
		}
573
 
574
		// DefaultRootObject
575
		if (isset($opt['DefaultRootObject']))
576
		{
577
			$update->addChild('DefaultRootObject', $opt['DefaultRootObject']);
578
		}
579
		elseif (isset($xml->DefaultRootObject))
580
		{
581
			$update->addChild('DefaultRootObject', $xml->DefaultRootObject);
582
		}
583
 
584
		// Enabled
585
		if (isset($opt['Enabled']))
586
		{
587
			$update->addChild('Enabled', $opt['Enabled'] ? 'true' : 'false');
588
		}
589
		elseif (isset($xml->Enabled))
590
		{
591
			$update->addChild('Enabled', $xml->Enabled);
592
		}
593
 
594
		// Logging
595
		if (isset($opt['Logging']))
596
		{
597
			if (is_array($opt['Logging']))
598
			{
599
				$logging = $update->addChild('Logging');
600
				$bucket_name = $opt['Logging']['Bucket'];
601
 
602
				// Origin
603
				$logging->addChild('Bucket', $bucket_name . ((stripos($bucket_name, '.s3.amazonaws.com') === false) ? '.s3.amazonaws.com' : ''));
604
 
605
				$logging->addChild('Prefix', $opt['Logging']['Prefix']);
606
			}
607
		}
608
		elseif (isset($xml->Logging))
609
		{
610
			$logging = $update->addChild('Logging');
611
			$logging->addChild('Bucket', $xml->Logging->Bucket);
612
			$logging->addChild('Prefix', $xml->Logging->Prefix);
613
		}
614
 
615
		// Trusted Signers
616
		if (isset($opt['TrustedSigners']))
617
		{
618
			$trusted_signers = $update->addChild('TrustedSigners');
619
 
620
			// Not an array? Convert to one.
621
			if (!is_array($opt['TrustedSigners']))
622
			{
623
				$opt['TrustedSigners'] = array($opt['TrustedSigners']);
624
			}
625
 
626
			// Handle 'Self' vs. everything else
627
			foreach ($opt['TrustedSigners'] as $signer)
628
			{
629
				if (strtolower($signer) === 'self')
630
				{
631
					$trusted_signers->addChild('Self');
632
				}
633
				else
634
				{
635
					$trusted_signers->addChild('AwsAccountNumber', $signer);
636
				}
637
			}
638
		}
639
		elseif (isset($xml->TrustedSigners) && $xml->TrustedSigners->count())
640
		{
641
			$trusted_signers = $update->addChild('TrustedSigners');
642
 
643
			// Handle 'Self' vs. everything else
644
			foreach ($xml->TrustedSigners->children() as $signer_key => $signer_value)
645
			{
646
				if (strtolower((string) $signer_key) === 'self')
647
				{
648
					$trusted_signers->addChild('Self');
649
				}
650
				else
651
				{
652
					$trusted_signers->addChild('AwsAccountNumber', (string) $signer_value);
653
				}
654
			}
655
		}
656
 
657
		// Output
658
		return $update->asXML();
659
	}
660
 
661
	/**
662
	 * Removes one or more CNAMEs from a <code>DistibutionConfig</code> XML document.
663
	 *
664
	 * @param CFSimpleXML|CFResponse|string $xml (Required) The source DistributionConfig XML to make updates to. Can be the <CFSimpleXML> body of a <get_distribution_config()> response, the entire <CFResponse> of a <get_distribution_config()> response, or a string of XML generated by <generate_config_xml()> or <update_config_xml()>.
665
	 * @param string|array $cname (Optional) The value or values to remove from the existing list of CNAME values. To add a CNAME value, see <update_config_xml()>.
666
	 * @return string XML document.
667
	 */
668
	public function remove_cname($xml, $cname)
669
	{
670
		// If we receive a full CFResponse object, only use the body.
671
		if ($xml instanceof CFResponse)
672
		{
673
			$xml = $xml->body;
674
		}
675
 
676
		// If we received a string of XML, convert it into a CFSimpleXML object.
677
		if (is_string($xml))
678
		{
679
			$xml = simplexml_load_string($xml);
680
		}
681
 
682
		// Let's make sure that we have CNAMEs to remove in the first place.
683
		if (isset($xml->CNAME))
684
		{
685
			// If we have an array of CNAME values...
686
			if (is_array($cname))
687
			{
688
				foreach ($cname as $cn)
689
				{
690
					for ($i = 0, $length = sizeof($xml->CNAME); $i < $length; $i++)
691
					{
692
						if ((string) $xml->CNAME[$i] == $cn)
693
						{
694
							unset($xml->CNAME[$i]);
695
							break;
696
						}
697
					}
698
				}
699
			}
700
 
701
			// If we only have one CNAME value...
702
			else
703
			{
704
				for ($i = 0, $length = sizeof($xml->CNAME); $i < $length; $i++)
705
				{
706
					if ((string) $xml->CNAME[$i] == $cname)
707
					{
708
						unset($xml->CNAME[$i]);
709
						break;
710
					}
711
				}
712
			}
713
		}
714
 
715
		return $xml->asXML();
716
	}
717
 
718
	/**
719
	 * Used to generate the origin access identity (OAI) Config XML used in <create_oai()>.
720
	 *
721
	 * @param string $caller_reference (Required) A unique identifier for the request. A timestamp-appended string is recommended.
722
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
723
	 * 	<li><code>Comment</code> - <code>string</code> - Optional - Replaces the existing value for "Comment". Cannot exceed 128 characters.</li></ul>
724
	 * @return string An XML document to be used as the OAI configuration.
725
	 */
726
	public function generate_oai_xml($caller_reference, $opt = null)
727
	{
728
		// Default, empty XML
729
		$xml = simplexml_load_string(sprintf($this->base_xml, 'CloudFrontOriginAccessIdentityConfig'));
730
 
731
		// CallerReference
732
		$xml->addChild('CallerReference', $caller_reference);
733
 
734
		// Comment
735
		if (isset($opt['Comment']))
736
		{
737
			$xml->addChild('Comment', $opt['Comment']);
738
		}
739
 
740
		return $xml->asXML();
741
	}
742
 
743
	/**
744
	 * Updates the origin access identity (OAI) configureation XML used in <create_oai()>.
745
	 *
746
	 * @param CFSimpleXML|CFResponse|string $xml (Required) The source configuration XML to make updates to. Can be the <CFSimpleXML> body of a <get_oai_config()> response, the entire <CFResponse> of a <get_oai_config()> response, or a string of XML generated by <generate_oai_xml()> or <update_oai_xml()>.
747
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
748
	 * 	<li><code>Comment</code> - <code>string</code> - Optional - Replaces the existing value for "Comment". Cannot exceed 128 characters.</li></ul>
749
	 * @return string XML document.
750
	 */
751
	public function update_oai_xml($xml, $opt = null)
752
	{
753
		// If we receive a full CFResponse object, only use the body.
754
		if ($xml instanceof CFResponse)
755
		{
756
			$xml = $xml->body;
757
		}
758
 
759
		// If we received a string of XML, convert it into a CFSimpleXML object.
760
		if (is_string($xml))
761
		{
762
			$xml = simplexml_load_string($xml, $this->parser_class);
763
		}
764
 
765
		// Update the comment, if we have one.
766
		if (isset($opt['Comment']) && isset($xml->Comment))
767
		{
768
			$xml->Comment = $opt['Comment'];
769
		}
770
		elseif (isset($opt['Comment']))
771
		{
772
			$xml->addChild('Comment', $opt['Comment']);
773
		}
774
 
775
		return $xml->asXML();
776
	}
777
 
778
	/**
779
	 * Generates the Invalidation Config XML used in <create_invalidation()>.
780
	 *
781
	 * @param string $caller_reference (Required) A unique identifier for the request. A timestamp-appended string is recommended.
782
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
783
	 * 	<li><code>Paths</code> - <code>string|array</code> - Optional - One or more paths to set for invalidation. Pass a string for a single value, or an indexed array for multiple values.</li></ul>
784
	 * @return string An XML document to be used as the Invalidation configuration.
785
	 */
786
	public function generate_invalidation_xml($caller_reference, $opt = null)
787
	{
788
		// Default, empty XML
789
		$xml = simplexml_load_string(sprintf($this->base_xml, 'InvalidationBatch'));
790
 
791
		// CallerReference
792
		$xml->addChild('CallerReference', $caller_reference);
793
 
794
		// Paths
795
		if (isset($opt['Paths']))
796
		{
797
			$paths = is_array($opt['Paths']) ? $opt['Paths'] : array($opt['Paths']);
798
 
799
			foreach ($paths as $path)
800
			{
801
				$path = str_replace('%2F', '/', rawurlencode($path));
802
				$path = (substr($path, 0, 1) === '/') ? $path : ('/' . $path);
803
				$xml->addChild('Path', $path);
804
			}
805
		}
806
 
807
		return $xml->asXML();
808
	}
809
 
810
 
811
	/*%******************************************************************************************%*/
812
	// DISTRIBUTIONS
813
 
814
	/**
815
	 * Creates an Amazon CloudFront distribution. You can have up to 100 distributions in the Amazon
816
	 * CloudFront system.
817
	 *
818
	 * For an Adobe Real-Time Messaging Protocol (RTMP) streaming distribution, set the <code>Streaming</code> option
819
	 * to true.
820
	 *
821
	 * @param string $origin (Required) The source to use for the Amazon CloudFront distribution. Use an Amazon S3 bucket name, or a fully-qualified non-S3 domain name prefixed with <code>http://</code> or <code>https://</code>.
822
	 * @param string $caller_reference (Required) A unique identifier for the request. A timestamp-appended string is recommended.
823
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
824
	 * 	<li><code>CNAME</code> - <code>string|array</code> - Optional - A DNS CNAME to use to map to the Amazon CloudFront distribution. If setting more than one, use an indexed array. Supports 1-10 CNAMEs.</li>
825
	 * 	<li><code>Comment</code> - <code>string</code> - Optional - A comment to apply to the distribution. Cannot exceed 128 characters.</li>
826
	 * 	<li><code>DefaultRootObject</code> - <code>string</code> - Optional - The file to load when someone accesses the root of the Amazon CloudFront domain (e.g., <code>index.html</code>).</li>
827
	 * 	<li><code>Enabled</code> - <code>string</code> - Optional - A value of <code>true</code> will enable the distribution. A value of <code>false</code> will disable it. The default value is <code>true</code>.</li>
828
	 * 	<li><code>OriginAccessIdentity</code> - <code>string</code> - Optional - The origin access identity (OAI) associated with this distribution. Use the Identity ID from the OAI, not the <code>CanonicalId</code>. Requires an S3 origin.</li>
829
	 * 	<li><code>OriginProtocolPolicy</code> - <code>string</code> - Optional - The origin protocol policy to apply to your origin. If you specify <code>http-only</code>, CloudFront will use HTTP only to access the origin. If you specify <code>match-viewer</code>, CloudFront will fetch from your origin using HTTP or HTTPS, based on the protocol of the viewer request. [Allowed values: <code>http-only</code>, <code>match-viewer</code>]. The default value is <code>match-viewer</code>. Requires a non-S3 origin.</li>
830
	 * 	<li><code>Streaming</code> - <code>boolean</code> - Optional - Whether or not this should be for a streaming distribution. A value of <code>true</code> creates a streaming distribution. A value of <code>false</code> creates a standard distribution. The default value is <code>false</code>.</li>
831
	 * 	<li><code>TrustedSigners</code> - <code>array</code> - Optional - An array of AWS account numbers for users who are trusted signers. Explicity add the value <code>Self</code> to the array to add your own account as a trusted signer.</li>
832
	 * 	<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>
833
	 * 	<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>
834
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
835
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/CreateDistribution.html POST Distribution
836
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/CreateStreamingDistribution.html POST Streaming Distribution
837
	 */
838
	public function create_distribution($origin, $caller_reference, $opt = null)
839
	{
840
		if (!$opt) $opt = array();
841
 
842
		$xml = $this->generate_config_xml($origin, $caller_reference, $opt);
843
		$path = '/' . ((isset($opt['Streaming']) && $opt['Streaming'] == (bool) true) ? 'streaming-distribution' : 'distribution');
844
 
845
		$opt = array_merge($opt, array('path' => $path, 'xml' => $xml));
846
 
847
		return $this->authenticate('POST', $opt);
848
	}
849
 
850
	/**
851
	 * Gets a list of distributions. By default, the list is returned as one result. If needed, paginate the
852
	 * list by specifying values for the <code>MaxItems</code> and <code>Marker</code> parameters.
853
	 *
854
	 * Standard distributions are listed separately from streaming distributions. For streaming distributions,
855
	 * set the <code>Streaming</code> option to true.
856
	 *
857
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
858
	 * 	<li><code>Marker</code> - <code>string</code> - Optional - Use this setting when paginating results to indicate where in your list of distributions to begin. The results include distributions in the list that occur after the marker. To get the next page of results, set the <code>Marker</code> to the value of the <code>NextMarker</code> from the current page's response (which is also the ID of the last distribution on that page).</li>
859
	 * 	<li><code>MaxItems</code> - <code>integer</code> - Optional - The maximum number of distributions you want in the response body. Maximum of 100.</li>
860
	 * 	<li><code>Streaming</code> - <code>boolean</code> - Optional - Whether or not this should be for a streaming distribution. A value of <code>true</code> will create a streaming distribution. A value of <code>false</code> will create a standard distribution. The default value is <code>false</code>.</li>
861
	 * 	<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>
862
	 * 	<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>
863
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
864
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/ListDistributions.html GET Distribution List
865
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/ListStreamingDistributions.html GET Streaming Distribution List
866
	 */
867
	public function list_distributions($opt = null)
868
	{
869
		if (!$opt) $opt = array();
870
		$opt['query_string'] = array();
871
 
872
		// Pass these to the query string
873
		foreach (array('Marker', 'MaxItems') as $option)
874
		{
875
			if (isset($opt[$option]))
876
			{
877
				$opt['query_string'][$option] = $opt[$option];
878
			}
879
		}
880
 
881
		$path = '/' . ((isset($opt['Streaming']) && $opt['Streaming'] == (bool) true) ? 'streaming-distribution' : 'distribution');
882
 
883
		$opt = array_merge($opt, array('path' => $path));
884
 
885
		return $this->authenticate('GET', $opt);
886
	}
887
 
888
	/**
889
	 * Gets distribution information for the specified distribution ID.
890
	 *
891
	 * Standard distributions are handled separately from streaming distributions. For streaming
892
	 * distributions, set the <code>Streaming</code> option to true.
893
	 *
894
	 * @param string $distribution_id (Required) The distribution ID returned from <create_distribution()> or <list_distributions()>.
895
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
896
	 * 	<li><code>Streaming</code> - <code>boolean</code> - Optional - Whether or not this should be for a streaming distribution. A value of <code>true</code> will create a streaming distribution. A value of <code>false</code> will create a standard distribution. The default value is <code>false</code>.</li>
897
	 * 	<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>
898
	 * 	<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>
899
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
900
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/GetDistribution.html GET Distribution
901
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/GetStreamingDistribution.html GET Streaming Distribution
902
	 */
903
	public function get_distribution_info($distribution_id, $opt = null)
904
	{
905
		if (!$opt) $opt = array();
906
 
907
		$path = '/' . ((isset($opt['Streaming']) && $opt['Streaming'] == (bool) true) ? 'streaming-distribution' : 'distribution');
908
		$path .= '/' . $distribution_id;
909
 
910
		$opt = array_merge($opt, array('path' => $path));
911
 
912
		return $this->authenticate('GET', $opt);
913
	}
914
 
915
	/**
916
	 * Deletes a disabled distribution. If distribution hasn't been disabled, Amazon CloudFront returns a
917
	 * <code>DistributionNotDisabled</code> error. Use <set_distribution_config()> to disable a distribution before
918
	 * attempting to delete.
919
	 *
920
	 * For an Adobe Real-Time Messaging Protocol (RTMP) streaming distribution, set the <code>Streaming</code> option
921
	 * to be <code>true</code>.
922
	 *
923
	 * @param string $distribution_id (Required) The distribution ID returned from <create_distribution()> or <list_distributions()>.
924
	 * @param string $etag (Required) The <code>ETag</code> header value retrieved from <get_distribution_config()>.
925
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
926
	 * 	<li><code>Streaming</code> - <code>boolean</code> - Optional - Whether or not this should be for a streaming distribution. A value of <code>true</code> will create a streaming distribution. A value of <code>false</code> will create a standard distribution. The default value is <code>false</code>.</li>
927
	 * 	<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>
928
	 * 	<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>
929
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
930
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/DeleteDistribution.html DELETE Distribution
931
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/DeleteStreamingDistribution.html DELETE Streaming Distribution
932
	 */
933
	public function delete_distribution($distribution_id, $etag, $opt = null)
934
	{
935
		if (!$opt) $opt = array();
936
 
937
		$path = '/' . ((isset($opt['Streaming']) && $opt['Streaming'] == (bool) true) ? 'streaming-distribution' : 'distribution');
938
		$path .= '/' . $distribution_id;
939
 
940
		$opt = array_merge($opt, array('path' => $path, 'etag' => $etag));
941
 
942
		return $this->authenticate('DELETE', $opt);
943
	}
944
 
945
	/**
946
	 * Gets the current distribution configuration for the specified distribution ID.
947
	 *
948
	 * Standard distributions are handled separately from streaming distributions. For streaming
949
	 * distributions, set the <code>Streaming</code> option to true.
950
	 *
951
	 * @param string $distribution_id (Required) The distribution ID returned from <create_distribution()> or <list_distributions()>.
952
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
953
	 * 	<li><code>Streaming</code> - <code>boolean</code> - Optional - Whether or not this should be for a streaming distribution. A value of <code>true</code> will create a streaming distribution. A value of <code>false</code> will create a standard distribution. The default value is <code>false</code>.</li>
954
	 * 	<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>
955
	 * 	<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>
956
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
957
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/GetConfig.html GET Distribution Config
958
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/GetStreamingDistConfig.html GET Streaming Distribution Config
959
	 */
960
	public function get_distribution_config($distribution_id, $opt = null)
961
	{
962
		if (!$opt) $opt = array();
963
 
964
		$path = '/' . ((isset($opt['Streaming']) && $opt['Streaming'] == (bool) true) ? 'streaming-distribution' : 'distribution');
965
		$path .= '/' . $distribution_id . '/config';
966
 
967
		$opt = array_merge($opt, array('path' => $path));
968
 
969
		return $this->authenticate('GET', $opt);
970
	}
971
 
972
	/**
973
	 * Sets a new distribution configuration for the specified distribution ID.
974
	 *
975
	 * Standard distributions are handled separately from streaming distributions. For streaming
976
	 * distributions, set the <code>Streaming</code> option to true.
977
	 *
978
	 * @param string $distribution_id (Required) The distribution ID returned from <create_distribution()> or <list_distributions()>.
979
	 * @param string $xml (Required) The DistributionConfig XML generated by <generate_config_xml()> or <update_config_xml()>.
980
	 * @param string $etag (Required) The ETag header value retrieved from <get_distribution_config()>.
981
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
982
	 * 	<li><code>Streaming</code> - <code>boolean</code> - Optional - Whether or not this should be for a streaming distribution. A value of <code>true</code> will create a streaming distribution. A value of <code>false</code> will create a standard distribution. The default value is <code>false</code>.</li>
983
	 * 	<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>
984
	 * 	<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>
985
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
986
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/PutConfig.html PUT Distribution Config
987
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/PutStreamingDistConfig.html PUT Streaming Distribution Config
988
	 */
989
	public function set_distribution_config($distribution_id, $xml, $etag, $opt = null)
990
	{
991
		if (!$opt) $opt = array();
992
 
993
		$path = '/' . ((isset($opt['Streaming']) && $opt['Streaming'] == (bool) true) ? 'streaming-distribution' : 'distribution');
994
		$path .= '/' . $distribution_id . '/config';
995
 
996
		$opt = array_merge($opt, array('path' => $path, 'xml' => $xml, 'etag' => $etag));
997
 
998
		return $this->authenticate('PUT', $opt);
999
	}
1000
 
1001
 
1002
	/*%******************************************************************************************%*/
1003
	// Origin Access Identity
1004
 
1005
	/**
1006
	 * Creates a new Amazon CloudFront origin access identity (OAI). You can create up to 100 OAIs per AWS
1007
	 * account. For more information, see the Amazon CloudFront Developer Guide.
1008
	 *
1009
	 * @param string $caller_reference (Required) A unique identifier for the request. A timestamp-appended string is recommended.
1010
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
1011
	 * 	<li><code>Comment</code> - <code>string</code> - Optional - A comment about the OAI.</li>
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 CFResponse A <CFResponse> object containing a parsed HTTP response.
1015
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/CreateOAI.html POST Origin Access Identity
1016
	 */
1017
	public function create_oai($caller_reference, $opt = null)
1018
	{
1019
		if (!$opt) $opt = array();
1020
 
1021
		$path = '/origin-access-identity/cloudfront';
1022
		$xml = $this->generate_oai_xml($caller_reference, $opt);
1023
 
1024
		$opt = array_merge($opt, array('path' => $path, 'xml' => $xml));
1025
 
1026
		return $this->authenticate('POST', $opt);
1027
	}
1028
 
1029
	/**
1030
	 * Gets a list of origin access identity (OAI) summaries. By default, the list is returned as one result.
1031
	 * If needed, paginate the list by specifying values for the <code>MaxItems</code> and <code>Marker</code>
1032
	 * parameters.
1033
	 *
1034
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
1035
	 * 	<li><code>Marker</code> - <code>string</code> - Optional - Use this when paginating results to indicate where in your list of distributions to begin. The results include distributions in the list that occur after the marker. To get the next page of results, set the Marker to the value of the NextMarker from the current page's response (which is also the ID of the last distribution on that page).</li>
1036
	 * 	<li><code>MaxItems</code> - <code>integer</code> - Optional - The maximum number of distributions you want in the response body. Maximum of 100.</li>
1037
	 * 	<li><code>curlopts</code> - <code>array</code> - Optional - A set of values to pass directly into <code>curl_setopt()</code>, where the key is a pre-defined <code>CURLOPT_*</code> constant.</li>
1038
	 * 	<li><code>returnCurlHandle</code> - <code>boolean</code> - Optional - A private toggle specifying that the cURL handle be returned rather than actually completing the request. This toggle is useful for manually managed batch requests.</li></ul>
1039
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
1040
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/ListOAIs.html GET Origin Access Identity List
1041
	 */
1042
	public function list_oais($opt = null)
1043
	{
1044
		if (!$opt) $opt = array();
1045
		$opt['query_string'] = array();
1046
 
1047
		// Pass these to the query string
1048
		foreach (array('Marker', 'MaxItems') as $option)
1049
		{
1050
			if (isset($opt[$option]))
1051
			{
1052
				$opt['query_string'][$option] = $opt[$option];
1053
			}
1054
		}
1055
 
1056
		$path = '/origin-access-identity/cloudfront';
1057
 
1058
		$opt = array_merge($opt, array('path' => $path));
1059
 
1060
		return $this->authenticate('GET', $opt);
1061
	}
1062
 
1063
	/**
1064
	 * Gets information about an origin access identity (OAI).
1065
	 *
1066
	 * @param string $identity_id (Required) The Identity ID for an existing OAI.
1067
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
1068
	 * 	<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>
1069
	 * 	<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>
1070
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
1071
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/GetOAI.html GET Origin Access Identity
1072
	 */
1073
	public function get_oai($identity_id, $opt = null)
1074
	{
1075
		if (!$opt) $opt = array();
1076
 
1077
		$path = '/origin-access-identity/cloudfront/' . $identity_id;
1078
 
1079
		$opt = array_merge($opt, array('path' => $path));
1080
 
1081
		return $this->authenticate('GET', $opt);
1082
	}
1083
 
1084
	/**
1085
	 * Deletes an Amazon CloudFront origin access identity (OAI). To delete an OAI, the identity must first
1086
	 * be disassociated from all distributions (by updating each distribution's configuration to omit the
1087
	 * <code>OriginAccessIdentity</code> element). Wait until each distribution's state is <code>Deployed</code>
1088
	 * before deleting the OAI.
1089
	 *
1090
	 * @param string $identity_id (Required) An Identity ID for an existing OAI.
1091
	 * @param string $etag (Required) The <code>ETag</code> header value retrieved from a call to <get_oai()>.
1092
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
1093
	 * 	<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>
1094
	 * 	<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>
1095
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
1096
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/DeleteOAI.html DELETE Origin Access Identity
1097
	 */
1098
	public function delete_oai($identity_id, $etag, $opt = null)
1099
	{
1100
		if (!$opt) $opt = array();
1101
 
1102
		$path = '/origin-access-identity/cloudfront/' . $identity_id;
1103
 
1104
		$opt = array_merge($opt, array('path' => $path, 'etag' => $etag));
1105
 
1106
		return $this->authenticate('DELETE', $opt);
1107
	}
1108
 
1109
	/**
1110
	 * Gets the configuration of the origin access identity (OAI) for the specified identity ID.
1111
	 *
1112
	 * @param string $identity_id (Required) An Identity ID for an existing OAI.
1113
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
1114
	 * 	<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>
1115
	 * 	<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>
1116
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
1117
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/GetOAIConfig.html GET Origin Access Identity Config
1118
	 */
1119
	public function get_oai_config($identity_id, $opt = null)
1120
	{
1121
		if (!$opt) $opt = array();
1122
 
1123
		$path = '/origin-access-identity/cloudfront/' . $identity_id . '/config';
1124
 
1125
		$opt = array_merge($opt, array('path' => $path));
1126
 
1127
		return $this->authenticate('GET', $opt);
1128
	}
1129
 
1130
	/**
1131
	 * Sets the configuration for an Amazon CloudFront origin access identity (OAI). Use this when updating
1132
	 * the configuration. Currently, only comments may be updated.  Follow the same process as when updating
1133
	 * an identity's configuration as you do when updating a distribution's configuration. For more
1134
	 * information, go to Updating a Distribution's Configuration in the Amazon CloudFront Developer Guide.
1135
	 *
1136
	 * When attempting to change configuration items that are not allowed to be updated, Amazon CloudFront
1137
	 * returns an <code>IllegalUpdate</code> error.
1138
	 *
1139
	 * @param string $identity_id (Required) An Identity ID for an existing OAI.
1140
	 * @param string $xml (Required) The configuration XML generated by <generate_oai_xml()>.
1141
	 * @param string $etag (Required) The ETag header value retrieved from a call to <get_distribution_config()>.
1142
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
1143
	 * 	<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>
1144
	 * 	<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>
1145
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
1146
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/PutOAIConfig.html PUT Origin Access Identity Config
1147
	 */
1148
	public function set_oai_config($identity_id, $xml, $etag, $opt = null)
1149
	{
1150
		if (!$opt) $opt = array();
1151
 
1152
		$path = '/origin-access-identity/cloudfront/' . $identity_id . '/config';
1153
 
1154
		$opt = array_merge($opt, array('path' => $path, 'xml' => $xml, 'etag' => $etag));
1155
 
1156
		return $this->authenticate('PUT', $opt);
1157
	}
1158
 
1159
 
1160
	/*%******************************************************************************************%*/
1161
	// INVALIDATION
1162
 
1163
	/**
1164
	 * Creates a new invalidation request.
1165
	 *
1166
	 * @param string $distribution_id (Required) The distribution ID returned from <create_distribution()> or <list_distributions()>.
1167
	 * @param string $caller_reference (Required) A unique identifier for the request. A timestamp-appended string is recommended.
1168
	 * @param string|array $paths (Required) One or more paths to set for invalidation. Pass a string for a single value, or an indexed array for multiple values. values.
1169
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
1170
	 * 	<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>
1171
	 * 	<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>
1172
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
1173
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/CreateInvalidation.html POST Invalidation
1174
	 */
1175
	public function create_invalidation($distribution_id, $caller_reference, $paths, $opt = null)
1176
	{
1177
		if (!$opt) $opt = array();
1178
		$opt['Paths'] = $paths;
1179
 
1180
		$path = '/distribution/' . $distribution_id . '/invalidation';
1181
		$xml = $this->generate_invalidation_xml($caller_reference, $opt);
1182
 
1183
		$opt = array_merge($opt, array('path' => $path, 'xml' => $xml));
1184
 
1185
		return $this->authenticate('POST', $opt);
1186
	}
1187
 
1188
	/**
1189
	 * Gets a list of invalidations. By default, the list is returned as one result. If needed, paginate the
1190
	 * list by specifying values for the <code>MaxItems</code> and <code>Marker</code> parameters.
1191
	 *
1192
	 * @param string $distribution_id (Required) The distribution ID returned from <create_distribution()> or <list_distributions()>.
1193
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
1194
	 * 	<li><code>Marker</code> - <code>string</code> - Optional - Use this when paginating results to indicate where in the list of invalidations to begin. The results include invalidations in the list that occur after the marker. To get the next page of results, set the <code>Marker</code> parameter to the value of the <code>NextMarker</code> parameter from the current page's response, which is also the ID of the last invalidation on that page.</li>
1195
	 * 	<li><code>MaxItems</code> - <code>integer</code> - Optional - The maximum number of invalidations you want in the response body. A maximum value of 100 can be used.</li>
1196
	 * 	<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>
1197
	 * 	<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>
1198
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
1199
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/ListInvalidation.html GET Invalidation List
1200
	 */
1201
	public function list_invalidations($distribution_id, $opt = null)
1202
	{
1203
		if (!$opt) $opt = array();
1204
		$opt['query_string'] = array();
1205
 
1206
		// Pass these to the query string
1207
		foreach (array('Marker', 'MaxItems') as $option)
1208
		{
1209
			if (isset($opt[$option]))
1210
			{
1211
				$opt['query_string'][$option] = $opt[$option];
1212
			}
1213
		}
1214
 
1215
		$path = '/distribution/' . $distribution_id . '/invalidation';
1216
 
1217
		$opt = array_merge($opt, array('path' => $path));
1218
 
1219
		return $this->authenticate('GET', $opt);
1220
	}
1221
 
1222
	/**
1223
	 * Gets information about an invalidation.
1224
	 *
1225
	 * @param string $distribution_id (Required) The distribution ID returned from <create_distribution()> or <list_distributions()>.
1226
	 * @param string $invalidation_id (Required) The invalidation ID returned from <create_invalidation()> or <list_invalidations()>.
1227
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
1228
	 * 	<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>
1229
	 * 	<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>
1230
	 * @return CFResponse A <CFResponse> object containing a parsed HTTP response.
1231
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/APIReference/GetInvalidation.html GET Invalidation
1232
	 */
1233
	public function get_invalidation($distribution_id, $invalidation_id, $opt = null)
1234
	{
1235
		if (!$opt) $opt = array();
1236
 
1237
		$path = '/distribution/' . $distribution_id . '/invalidation/' . $invalidation_id;
1238
 
1239
		$opt = array_merge($opt, array('path' => $path));
1240
 
1241
		return $this->authenticate('GET', $opt);
1242
	}
1243
 
1244
 
1245
	/*%******************************************************************************************%*/
1246
	// CONVENIENCE METHODS
1247
 
1248
	/**
1249
	 * Gets a simplified list of standard distribution IDs.
1250
	 *
1251
	 * @param string $pcre (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the distribution caller references against.
1252
	 * @return array A list of standard distribution IDs.
1253
	 */
1254
	public function get_distribution_list($pcre = null)
1255
	{
1256
		if ($this->use_batch_flow)
1257
		{
1258
			throw new CloudFront_Exception(__FUNCTION__ . '() cannot be batch requested');
1259
		}
1260
 
1261
		$list = $this->list_distributions();
1262
		if ($list = $list->body->Id())
1263
		{
1264
			$list = $list->map_string($pcre);
1265
			return $list;
1266
		}
1267
 
1268
		return array();
1269
	}
1270
 
1271
	/**
1272
	 * Gets a simplified list of streaming distribution IDs.
1273
	 *
1274
	 * @param string $pcre (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the distribution caller references against.
1275
	 * @return array A list of streaming distribution IDs.
1276
	 */
1277
	public function get_streaming_distribution_list($pcre = null)
1278
	{
1279
		if ($this->use_batch_flow)
1280
		{
1281
			throw new CloudFront_Exception(__FUNCTION__ . '() cannot be batch requested');
1282
		}
1283
 
1284
		$list = $this->list_distributions(array(
1285
			'Streaming' => true
1286
		));
1287
		if ($list = $list->body->Id())
1288
		{
1289
			$list = $list->map_string($pcre);
1290
			return $list;
1291
		}
1292
 
1293
		return array();
1294
	}
1295
 
1296
	/**
1297
	 * Gets a simplified list of origin access identity (OAI) IDs.
1298
	 *
1299
	 * @param string $pcre (Optional) A Perl-Compatible Regular Expression (PCRE) to filter the OAI caller references against.
1300
	 * @return array A list of OAI IDs.
1301
	 */
1302
	public function get_oai_list($pcre = null)
1303
	{
1304
		if ($this->use_batch_flow)
1305
		{
1306
			throw new CloudFront_Exception(__FUNCTION__ . '() cannot be batch requested');
1307
		}
1308
 
1309
		$list = $this->list_oais();
1310
		if ($list = $list->body->Id())
1311
		{
1312
			$list = $list->map_string($pcre);
1313
			return $list;
1314
		}
1315
 
1316
		return array();
1317
	}
1318
 
1319
 
1320
	/*%******************************************************************************************%*/
1321
	// URLS
1322
 
1323
	/**
1324
	 * Generates a time-limited and/or query signed request for a private file with additional optional
1325
	 * restrictions.
1326
	 *
1327
	 * @param string $distribution_hostname (Required) The hostname of the distribution. Obtained from <create_distribution()> or <get_distribution_info()>.
1328
	 * @param string $filename (Required) The file name of the object. Query parameters can be included. You can use multicharacter match wild cards () or a single-character match wild card (?) anywhere in the string.
1329
	 * @param integer|string $expires (Required) The expiration time expressed either as a number of seconds since UNIX Epoch, or any string that <php:strtotime()> can understand.
1330
	 * @param array $opt (Optional) An associative array of parameters that can have the following keys: <ul>
1331
	 *	<li><code>BecomeAvailable</code> - <code>integer|string</code> - Optional - The time when the private URL becomes active. Can be expressed either as a number of seconds since UNIX Epoch, or any string that <code>strtotime()</code> can understand.</li>
1332
	 *	<li><code>IPAddress</code> - <code>string</code> - Optional - A single IP address to restrict the access to.</li>
1333
	 * 	<li><code>Secure</code> - <code>boolean</code> - Optional - Whether or not to use HTTPS as the protocol scheme. A value of <code>true</code> uses <code>https</code>. A value of <code>false</code> uses <code>http</code>. The default value is <code>false</code>.</li></ul>
1334
	 * @return string The file URL with authentication parameters.
1335
	 * @link http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html Serving Private Content
1336
	 */
1337
	public function get_private_object_url($distribution_hostname, $filename, $expires, $opt = null)
1338
	{
1339
		if (!$this->key_pair_id || !$this->private_key)
1340
		{
1341
			throw new CloudFront_Exception('You must set both a Amazon CloudFront keypair ID and an RSA private key for that keypair before using ' . __FUNCTION__ . '()');
1342
		}
1343
		if (!function_exists('openssl_sign'))
1344
		{
1345
			throw new CloudFront_Exception(__FUNCTION__ . '() uses functions from the OpenSSL PHP Extension <http://php.net/openssl>, which is not installed in this PHP installation');
1346
		}
1347
 
1348
		if (!$opt) $opt = array();
1349
 
1350
		$resource = '';
1351
		$expiration_key = 'Expires';
1352
		if (is_string($expires))
1353
		{
1354
			$expires = strtotime($expires);
1355
		}
1356
		$conjunction = (strpos($filename, '?') === false ? '?' : '&');
1357
 
1358
		// Determine the protocol scheme
1359
		switch (substr($distribution_hostname, 0, 1) === 's')
1360
		{
1361
			// Streaming
1362
			case 's':
1363
				$scheme = 'rtmp';
1364
				$resource = str_replace(array('%3F', '%3D', '%26', '%2F'), array('?', '=', '&', '/'), rawurlencode($filename));
1365
				break;
1366
 
1367
			// Default
1368
			case 'd':
1369
			default:
1370
				$scheme = 'http';
1371
				$scheme .= (isset($opt['Secure']) && $opt['Secure'] === true ? 's' : '');
1372
				$resource = $scheme . '://' . $distribution_hostname . '/' . str_replace(array('%3F', '%3D', '%26', '%2F'), array('?', '=', '&', '/'), rawurlencode($filename));
1373
				break;
1374
		}
1375
 
1376
		// Generate default policy
1377
		$raw_policy = array(
1378
			'Statement' => array(
1379
				array(
1380
					'Resource' => $resource,
1381
					'Condition' => array(
1382
						'DateLessThan' => array(
1383
							'AWS:EpochTime' => $expires
1384
						)
1385
					)
1386
				)
1387
			)
1388
		);
1389
 
1390
		// Become Available
1391
		if (isset($opt['BecomeAvailable']))
1392
		{
1393
			// Switch to 'Policy' instead
1394
			$expiration_key = 'Policy';
1395
 
1396
			// Update the policy
1397
			$raw_policy['Statement'][0]['Condition']['DateGreaterThan'] = array(
1398
				'AWS:EpochTime' => strtotime($opt['BecomeAvailable'])
1399
			);
1400
		}
1401
 
1402
		// IP Address
1403
		if (isset($opt['IPAddress']))
1404
		{
1405
			// Switch to 'Policy' instead
1406
			$expiration_key = 'Policy';
1407
 
1408
			// Update the policy
1409
			$raw_policy['Statement'][0]['Condition']['IpAddress'] = array(
1410
				'AWS:SourceIp' => $opt['IPAddress']
1411
			);
1412
		}
1413
 
1414
		// Munge the policy
1415
		$json_policy = str_replace('\/', '/', json_encode($raw_policy));
1416
		$json_policy = $this->util->decode_uhex($json_policy);
1417
		$encoded_policy = strtr(base64_encode($json_policy), '+=/', '-_~');
1418
 
1419
		// Generate the signature
1420
		openssl_sign($json_policy, $signature, $this->private_key);
1421
		$signature = strtr(base64_encode($signature), '+=/', '-_~');
1422
 
1423
		return $scheme . '://' . $distribution_hostname . '/'
1424
			. str_replace(array('%3F', '%3D', '%26', '%2F'), array('?', '=', '&', '/'), rawurlencode($filename))
1425
			. $conjunction
1426
			. ($expiration_key === 'Expires' ? ($expiration_key . '=' . $expires) : ($expiration_key . '=' . $encoded_policy))
1427
			. '&Key-Pair-Id=' . $this->key_pair_id
1428
			. '&Signature=' . $signature;
1429
	}
1430
}