~clint-fewbar/charms/oneiric/omgubuntu-wp/trunk

« back to all changes in this revision

Viewing changes to files/wordpress/wp-content/plugins/w3-total-cache/lib/Microsoft/WindowsAzure/Storage.php

  • Committer: Marco Ceppi
  • Date: 2012-03-19 14:27:51 UTC
  • Revision ID: marco@ceppi.net-20120319142751-xvn4zfl0rq99r00p
First revision of OMG charm

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * Copyright (c) 2009 - 2010, RealDolmen
 
4
 * All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions are met:
 
8
 *     * Redistributions of source code must retain the above copyright
 
9
 *       notice, this list of conditions and the following disclaimer.
 
10
 *     * Redistributions in binary form must reproduce the above copyright
 
11
 *       notice, this list of conditions and the following disclaimer in the
 
12
 *       documentation and/or other materials provided with the distribution.
 
13
 *     * Neither the name of RealDolmen nor the
 
14
 *       names of its contributors may be used to endorse or promote products
 
15
 *       derived from this software without specific prior written permission.
 
16
 *
 
17
 * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
 
18
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
19
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
20
 * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
 
21
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
22
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
23
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
24
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
26
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
27
 *
 
28
 * @category   Microsoft
 
29
 * @package    Microsoft_WindowsAzure
 
30
 * @subpackage Storage
 
31
 * @copyright  Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
 
32
 * @license    http://phpazure.codeplex.com/license
 
33
 * @version    $Id: Storage.php 51671 2010-09-30 08:33:45Z unknown $
 
34
 */
 
35
if (!defined('W3TC')) {
 
36
    die();
 
37
}
 
38
 
 
39
/**
 
40
 * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract
 
41
 */
 
42
require_once 'Microsoft/WindowsAzure/Credentials/CredentialsAbstract.php';
 
43
 
 
44
/**
 
45
 * @see Microsoft_WindowsAzure_Credentials_SharedKey
 
46
 */
 
47
require_once 'Microsoft/WindowsAzure/Credentials/SharedKey.php';
 
48
 
 
49
/**
 
50
 * @see Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
 
51
 */
 
52
require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
 
53
 
 
54
/**
 
55
 * @see Microsoft_WindowsAzure_Exception
 
56
 */
 
57
require_once 'Microsoft/WindowsAzure/Exception.php';
 
58
 
 
59
/**
 
60
 * @see Microsoft_Http_Client
 
61
 */
 
62
require_once 'Microsoft/Http/Client.php';
 
63
 
 
64
/**
 
65
 * @see Microsoft_Http_Response
 
66
 */
 
67
require_once 'Microsoft/Http/Response.php';
 
68
 
 
69
/**
 
70
 * @category   Microsoft
 
71
 * @package    Microsoft_WindowsAzure
 
72
 * @subpackage Storage
 
73
 * @copyright  Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
 
74
 * @license    http://phpazure.codeplex.com/license
 
75
 */
 
76
class Microsoft_WindowsAzure_Storage
 
77
{
 
78
        /**
 
79
         * Development storage URLS
 
80
         */
 
81
        const URL_DEV_BLOB      = "127.0.0.1:10000";
 
82
        const URL_DEV_QUEUE     = "127.0.0.1:10001";
 
83
        const URL_DEV_TABLE     = "127.0.0.1:10002";
 
84
 
 
85
        /**
 
86
         * Live storage URLS
 
87
         */
 
88
        const URL_CLOUD_BLOB    = "blob.core.windows.net";
 
89
        const URL_CLOUD_QUEUE   = "queue.core.windows.net";
 
90
        const URL_CLOUD_TABLE   = "table.core.windows.net";
 
91
 
 
92
        /**
 
93
         * Resource types
 
94
         */
 
95
        const RESOURCE_UNKNOWN     = "unknown";
 
96
        const RESOURCE_CONTAINER   = "c";
 
97
        const RESOURCE_BLOB        = "b";
 
98
        const RESOURCE_TABLE       = "t";
 
99
        const RESOURCE_ENTITY      = "e";
 
100
        const RESOURCE_QUEUE       = "q";
 
101
 
 
102
        /**
 
103
         * HTTP header prefixes
 
104
         */
 
105
        const PREFIX_PROPERTIES      = "x-ms-prop-";
 
106
        const PREFIX_METADATA        = "x-ms-meta-";
 
107
        const PREFIX_STORAGE_HEADER  = "x-ms-";
 
108
 
 
109
        /**
 
110
         * Current API version
 
111
         *
 
112
         * @var string
 
113
         */
 
114
        protected $_apiVersion = '2009-09-19';
 
115
 
 
116
        /**
 
117
         * Storage host name
 
118
         *
 
119
         * @var string
 
120
         */
 
121
        protected $_host = '';
 
122
 
 
123
        /**
 
124
         * Account name for Windows Azure
 
125
         *
 
126
         * @var string
 
127
         */
 
128
        protected $_accountName = '';
 
129
 
 
130
        /**
 
131
         * Account key for Windows Azure
 
132
         *
 
133
         * @var string
 
134
         */
 
135
        protected $_accountKey = '';
 
136
 
 
137
        /**
 
138
         * Use path-style URI's
 
139
         *
 
140
         * @var boolean
 
141
         */
 
142
        protected $_usePathStyleUri = false;
 
143
 
 
144
        /**
 
145
         * Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance
 
146
         *
 
147
         * @var Microsoft_WindowsAzure_Credentials_CredentialsAbstract
 
148
         */
 
149
        protected $_credentials = null;
 
150
 
 
151
        /**
 
152
         * Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract instance
 
153
         *
 
154
         * @var Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
 
155
         */
 
156
        protected $_retryPolicy = null;
 
157
 
 
158
        /**
 
159
         * Microsoft_Http_Client channel used for communication with REST services
 
160
         *
 
161
         * @var Microsoft_Http_Client
 
162
         */
 
163
        protected $_httpClientChannel = null;
 
164
 
 
165
        /**
 
166
         * Use proxy?
 
167
         *
 
168
         * @var boolean
 
169
         */
 
170
        protected $_useProxy = false;
 
171
 
 
172
        /**
 
173
         * Proxy url
 
174
         *
 
175
         * @var string
 
176
         */
 
177
        protected $_proxyUrl = '';
 
178
 
 
179
        /**
 
180
         * Proxy port
 
181
         *
 
182
         * @var int
 
183
         */
 
184
        protected $_proxyPort = 80;
 
185
 
 
186
        /**
 
187
         * Proxy credentials
 
188
         *
 
189
         * @var string
 
190
         */
 
191
        protected $_proxyCredentials = '';
 
192
 
 
193
        /**
 
194
         * Creates a new Microsoft_WindowsAzure_Storage instance
 
195
         *
 
196
         * @param string $host Storage host name
 
197
         * @param string $accountName Account name for Windows Azure
 
198
         * @param string $accountKey Account key for Windows Azure
 
199
         * @param boolean $usePathStyleUri Use path-style URI's
 
200
         * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
 
201
         */
 
202
        public function __construct(
 
203
                $host = self::URL_DEV_BLOB,
 
204
                $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT,
 
205
                $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY,
 
206
                $usePathStyleUri = false,
 
207
                Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null
 
208
        ) {
 
209
                $this->_host = $host;
 
210
                $this->_accountName = $accountName;
 
211
                $this->_accountKey = $accountKey;
 
212
                $this->_usePathStyleUri = $usePathStyleUri;
 
213
 
 
214
                // Using local storage?
 
215
                if (!$this->_usePathStyleUri
 
216
                        && ($this->_host == self::URL_DEV_BLOB
 
217
                                || $this->_host == self::URL_DEV_QUEUE
 
218
                                || $this->_host == self::URL_DEV_TABLE)
 
219
                ) {
 
220
                        // Local storage
 
221
                        $this->_usePathStyleUri = true;
 
222
                }
 
223
 
 
224
                if (is_null($this->_credentials)) {
 
225
                    $this->_credentials = new Microsoft_WindowsAzure_Credentials_SharedKey(
 
226
                        $this->_accountName, $this->_accountKey, $this->_usePathStyleUri);
 
227
                }
 
228
 
 
229
                $this->_retryPolicy = $retryPolicy;
 
230
                if (is_null($this->_retryPolicy)) {
 
231
                    $this->_retryPolicy = Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract::noRetry();
 
232
                }
 
233
 
 
234
                // Setup default Microsoft_Http_Client channel
 
235
                $options = array(
 
236
                        'adapter' => 'Microsoft_Http_Client_Adapter_Proxy'
 
237
                );
 
238
                if (function_exists('curl_init')) {
 
239
                        // Set cURL options if cURL is used afterwards
 
240
                        $options['curloptions'] = array(
 
241
                                        CURLOPT_FOLLOWLOCATION => true,
 
242
                                        CURLOPT_TIMEOUT => 120,
 
243
                        );
 
244
                }
 
245
                $this->_httpClientChannel = new Microsoft_Http_Client(null, $options);
 
246
        }
 
247
 
 
248
        /**
 
249
         * Set the HTTP client channel to use
 
250
         *
 
251
         * @param Microsoft_Http_Client_Adapter_Interface|string $adapterInstance Adapter instance or adapter class name.
 
252
         */
 
253
        public function setHttpClientChannel($adapterInstance = 'Microsoft_Http_Client_Adapter_Proxy')
 
254
        {
 
255
                $this->_httpClientChannel->setAdapter($adapterInstance);
 
256
        }
 
257
 
 
258
    /**
 
259
     * Retrieve HTTP client channel
 
260
     *
 
261
     * @return Microsoft_Http_Client_Adapter_Interface
 
262
     */
 
263
    public function getHttpClientChannel()
 
264
    {
 
265
        return $this->_httpClientChannel;
 
266
    }
 
267
 
 
268
        /**
 
269
         * Set retry policy to use when making requests
 
270
         *
 
271
         * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
 
272
         */
 
273
        public function setRetryPolicy(Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
 
274
        {
 
275
                $this->_retryPolicy = $retryPolicy;
 
276
                if (is_null($this->_retryPolicy)) {
 
277
                    $this->_retryPolicy = Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract::noRetry();
 
278
                }
 
279
        }
 
280
 
 
281
        /**
 
282
         * Set proxy
 
283
         *
 
284
         * @param boolean $useProxy         Use proxy?
 
285
         * @param string  $proxyUrl         Proxy URL
 
286
         * @param int     $proxyPort        Proxy port
 
287
         * @param string  $proxyCredentials Proxy credentials
 
288
         */
 
289
        public function setProxy($useProxy = false, $proxyUrl = '', $proxyPort = 80, $proxyCredentials = '')
 
290
        {
 
291
            $this->_useProxy         = $useProxy;
 
292
            $this->_proxyUrl         = $proxyUrl;
 
293
            $this->_proxyPort        = $proxyPort;
 
294
            $this->_proxyCredentials = $proxyCredentials;
 
295
 
 
296
            if ($this->_useProxy) {
 
297
                $credentials = explode(':', $this->_proxyCredentials);
 
298
 
 
299
                $this->_httpClientChannel->setConfig(array(
 
300
                                'proxy_host' => $this->_proxyUrl,
 
301
                        'proxy_port' => $this->_proxyPort,
 
302
                        'proxy_user' => $credentials[0],
 
303
                        'proxy_pass' => $credentials[1],
 
304
                ));
 
305
            } else {
 
306
                        $this->_httpClientChannel->setConfig(array(
 
307
                                'proxy_host' => '',
 
308
                        'proxy_port' => 8080,
 
309
                        'proxy_user' => '',
 
310
                        'proxy_pass' => '',
 
311
                ));
 
312
            }
 
313
        }
 
314
 
 
315
        /**
 
316
         * Returns the Windows Azure account name
 
317
         *
 
318
         * @return string
 
319
         */
 
320
        public function getAccountName()
 
321
        {
 
322
                return $this->_accountName;
 
323
        }
 
324
 
 
325
        /**
 
326
         * Get base URL for creating requests
 
327
         *
 
328
         * @return string
 
329
         */
 
330
        public function getBaseUrl()
 
331
        {
 
332
                if ($this->_usePathStyleUri) {
 
333
                        return 'http://' . $this->_host . '/' . $this->_accountName;
 
334
                } else {
 
335
                        return 'http://' . $this->_accountName . '.' . $this->_host;
 
336
                }
 
337
        }
 
338
 
 
339
        /**
 
340
         * Set Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance
 
341
         *
 
342
         * @param Microsoft_WindowsAzure_Credentials_CredentialsAbstract $credentials Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance to use for request signing.
 
343
         */
 
344
        public function setCredentials(Microsoft_WindowsAzure_Credentials_CredentialsAbstract $credentials)
 
345
        {
 
346
            $this->_credentials = $credentials;
 
347
            $this->_credentials->setAccountName($this->_accountName);
 
348
            $this->_credentials->setAccountkey($this->_accountKey);
 
349
            $this->_credentials->setUsePathStyleUri($this->_usePathStyleUri);
 
350
        }
 
351
 
 
352
        /**
 
353
         * Get Microsoft_WindowsAzure_Credentials_CredentialsAbstract instance
 
354
         *
 
355
         * @return Microsoft_WindowsAzure_Credentials_CredentialsAbstract
 
356
         */
 
357
        public function getCredentials()
 
358
        {
 
359
            return $this->_credentials;
 
360
        }
 
361
 
 
362
        /**
 
363
         * Perform request using Microsoft_Http_Client channel
 
364
         *
 
365
         * @param string $path Path
 
366
         * @param string $queryString Query string
 
367
         * @param string $httpVerb HTTP verb the request will use
 
368
         * @param array $headers x-ms headers to add
 
369
         * @param boolean $forTableStorage Is the request for table storage?
 
370
         * @param mixed $rawData Optional RAW HTTP data to be sent over the wire
 
371
         * @param string $resourceType Resource type
 
372
         * @param string $requiredPermission Required permission
 
373
         * @return Microsoft_Http_Response
 
374
         */
 
375
        protected function _performRequest(
 
376
                $path = '/',
 
377
                $queryString = '',
 
378
                $httpVerb = Microsoft_Http_Client::GET,
 
379
                $headers = array(),
 
380
                $forTableStorage = false,
 
381
                $rawData = null,
 
382
                $resourceType = Microsoft_WindowsAzure_Storage::RESOURCE_UNKNOWN,
 
383
                $requiredPermission = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ
 
384
        ) {
 
385
            // Clean path
 
386
                if (strpos($path, '/') !== 0) {
 
387
                        $path = '/' . $path;
 
388
                }
 
389
 
 
390
                // Clean headers
 
391
                if (is_null($headers)) {
 
392
                    $headers = array();
 
393
                }
 
394
 
 
395
                // Ensure cUrl will also work correctly:
 
396
                //  - disable Content-Type if required
 
397
                //  - disable Expect: 100 Continue
 
398
                if (!isset($headers["Content-Type"])) {
 
399
                        $headers["Content-Type"] = '';
 
400
                }
 
401
                $headers["Expect"]= '';
 
402
 
 
403
                // Add version header
 
404
                $headers['x-ms-version'] = $this->_apiVersion;
 
405
 
 
406
                // URL encoding
 
407
                $path           = self::urlencode($path);
 
408
                $queryString    = self::urlencode($queryString);
 
409
 
 
410
                // Generate URL and sign request
 
411
                $requestUrl     = $this->_credentials
 
412
                                                  ->signRequestUrl($this->getBaseUrl() . $path . $queryString, $resourceType, $requiredPermission);
 
413
                $requestHeaders = $this->_credentials
 
414
                                                  ->signRequestHeaders($httpVerb, $path, $queryString, $headers, $forTableStorage, $resourceType, $requiredPermission, $rawData);
 
415
 
 
416
                // Prepare request
 
417
                $this->_httpClientChannel->resetParameters(true);
 
418
                $this->_httpClientChannel->setUri($requestUrl);
 
419
                $this->_httpClientChannel->setHeaders($requestHeaders);
 
420
                $this->_httpClientChannel->setRawData($rawData);
 
421
 
 
422
                // Execute request
 
423
                $response = $this->_retryPolicy->execute(
 
424
                    array($this->_httpClientChannel, 'request'),
 
425
                    array($httpVerb)
 
426
                );
 
427
 
 
428
                return $response;
 
429
        }
 
430
 
 
431
        /**
 
432
         * Parse result from Microsoft_Http_Response
 
433
         *
 
434
         * @param Microsoft_Http_Response $response Response from HTTP call
 
435
         * @return object
 
436
         * @throws Microsoft_WindowsAzure_Exception
 
437
         */
 
438
        protected function _parseResponse(Microsoft_Http_Response $response = null)
 
439
        {
 
440
                if (is_null($response)) {
 
441
                        throw new Microsoft_WindowsAzure_Exception('Response should not be null.');
 
442
                }
 
443
 
 
444
        $xml = @simplexml_load_string($response->getBody());
 
445
 
 
446
        if ($xml !== false) {
 
447
            // Fetch all namespaces
 
448
            $namespaces = array_merge($xml->getNamespaces(true), $xml->getDocNamespaces(true));
 
449
 
 
450
            // Register all namespace prefixes
 
451
            foreach ($namespaces as $prefix => $ns) {
 
452
                if ($prefix != '') {
 
453
                    $xml->registerXPathNamespace($prefix, $ns);
 
454
                }
 
455
            }
 
456
        }
 
457
 
 
458
        return $xml;
 
459
        }
 
460
 
 
461
        /**
 
462
         * Generate metadata headers
 
463
         *
 
464
         * @param array $metadata
 
465
         * @return HTTP headers containing metadata
 
466
         */
 
467
        protected function _generateMetadataHeaders($metadata = array())
 
468
        {
 
469
                // Validate
 
470
                if (!is_array($metadata)) {
 
471
                        return array();
 
472
                }
 
473
 
 
474
                // Return headers
 
475
                $headers = array();
 
476
                foreach ($metadata as $key => $value) {
 
477
                        if (strpos($value, "\r") !== false || strpos($value, "\n") !== false) {
 
478
                                throw new Microsoft_WindowsAzure_Exception('Metadata cannot contain newline characters.');
 
479
                        }
 
480
 
 
481
                        if (!self::isValidMetadataName($key)) {
 
482
                        throw new Microsoft_WindowsAzure_Exception('Metadata name does not adhere to metadata naming conventions. See http://msdn.microsoft.com/en-us/library/aa664670(VS.71).aspx for more information.');
 
483
                        }
 
484
 
 
485
                    $headers["x-ms-meta-" . strtolower($key)] = $value;
 
486
                }
 
487
                return $headers;
 
488
        }
 
489
 
 
490
        /**
 
491
         * Parse metadata headers
 
492
         *
 
493
         * @param array $headers HTTP headers containing metadata
 
494
         * @return array
 
495
         */
 
496
        protected function _parseMetadataHeaders($headers = array())
 
497
        {
 
498
                // Validate
 
499
                if (!is_array($headers)) {
 
500
                        return array();
 
501
                }
 
502
 
 
503
                // Return metadata
 
504
                $metadata = array();
 
505
                foreach ($headers as $key => $value) {
 
506
                    if (substr(strtolower($key), 0, 10) == "x-ms-meta-") {
 
507
                        $metadata[str_replace("x-ms-meta-", '', strtolower($key))] = $value;
 
508
                    }
 
509
                }
 
510
                return $metadata;
 
511
        }
 
512
 
 
513
        /**
 
514
         * Parse metadata XML
 
515
         *
 
516
         * @param SimpleXMLElement $parentElement Element containing the Metadata element.
 
517
         * @return array
 
518
         */
 
519
        protected function _parseMetadataElement($element = null)
 
520
        {
 
521
                // Metadata present?
 
522
                if (!is_null($element) && isset($element->Metadata) && !is_null($element->Metadata)) {
 
523
                        return get_object_vars($element->Metadata);
 
524
                }
 
525
 
 
526
                return array();
 
527
        }
 
528
 
 
529
        /**
 
530
         * Generate ISO 8601 compliant date string in UTC time zone
 
531
         *
 
532
         * @param int $timestamp
 
533
         * @return string
 
534
         */
 
535
        public function isoDate($timestamp = null)
 
536
        {
 
537
            $tz = @date_default_timezone_get();
 
538
            @date_default_timezone_set('UTC');
 
539
 
 
540
            if (is_null($timestamp)) {
 
541
                $timestamp = time();
 
542
            }
 
543
 
 
544
            $returnValue = str_replace('+00:00', '.0000000Z', @date('c', $timestamp));
 
545
            @date_default_timezone_set($tz);
 
546
            return $returnValue;
 
547
        }
 
548
 
 
549
        /**
 
550
         * URL encode function
 
551
         *
 
552
         * @param  string $value Value to encode
 
553
         * @return string        Encoded value
 
554
         */
 
555
        public static function urlencode($value)
 
556
        {
 
557
            return str_replace(' ', '%20', $value);
 
558
        }
 
559
 
 
560
        /**
 
561
         * Is valid metadata name?
 
562
         *
 
563
         * @param string $metadataName Metadata name
 
564
         * @return boolean
 
565
         */
 
566
    public static function isValidMetadataName($metadataName = '')
 
567
    {
 
568
        if (preg_match("/^[a-zA-Z0-9_@][a-zA-Z0-9_]*$/", $metadataName) === 0) {
 
569
            return false;
 
570
        }
 
571
 
 
572
        if ($metadataName == '') {
 
573
            return false;
 
574
        }
 
575
 
 
576
        return true;
 
577
    }
 
578
 
 
579
    /**
 
580
     * Builds a query string from an array of elements
 
581
     *
 
582
     * @param array     Array of elements
 
583
     * @return string   Assembled query string
 
584
     */
 
585
    public static function createQueryStringFromArray($queryString)
 
586
    {
 
587
        return count($queryString) > 0 ? '?' . implode('&', $queryString) : '';
 
588
    }
 
589
}