Microsoft_WindowsAzure
[ class tree: Microsoft_WindowsAzure ] [ index: Microsoft_WindowsAzure ] [ all elements ]

Source for file Storage.php

Documentation is available at Storage.php

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

Documentation generated on Wed, 18 May 2011 12:06:53 +0200 by phpDocumentor 1.4.3