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

Source for file Blob.php

Documentation is available at Blob.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://todo     name_todo
  33.  * @version    $Id: Blob.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. /**
  43.  * @category   Microsoft
  44.  * @package    Microsoft_WindowsAzure
  45.  * @subpackage Storage
  46.  * @copyright  Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
  47.  * @license    http://phpazure.codeplex.com/license
  48.  */
  49. {
  50.     /**
  51.      * ACL - Private access
  52.      */
  53.     const ACL_PRIVATE = null;
  54.  
  55.     /**
  56.      * ACL - Public access (read all blobs)
  57.      *
  58.      * @deprecated Use ACL_PUBLIC_CONTAINER or ACL_PUBLIC_BLOB instead.
  59.      */
  60.     const ACL_PUBLIC = 'container';
  61.     
  62.     /**
  63.      * ACL - Blob Public access (read all blobs)
  64.      */
  65.     const ACL_PUBLIC_BLOB = 'blob';
  66.  
  67.     /**
  68.      * ACL - Container Public access (enumerate and read all blobs)
  69.      */
  70.     const ACL_PUBLIC_CONTAINER = 'container';
  71.  
  72.     /**
  73.      * Blob lease constants
  74.      */
  75.     const LEASE_ACQUIRE = 'acquire';
  76.     const LEASE_RENEW   = 'renew';
  77.     const LEASE_RELEASE = 'release';
  78.     const LEASE_BREAK   = 'break';
  79.  
  80.     /**
  81.      * Maximal blob size (in bytes)
  82.      */
  83.     const MAX_BLOB_SIZE = 67108864;
  84.  
  85.     /**
  86.      * Maximal blob transfer size (in bytes)
  87.      */
  88.     const MAX_BLOB_TRANSFER_SIZE = 4194304;
  89.  
  90.     /**
  91.      * Blob types
  92.      */
  93.     const BLOBTYPE_BLOCK = 'BlockBlob';
  94.     const BLOBTYPE_PAGE  = 'PageBlob';
  95.  
  96.     /**
  97.      * Put page write options
  98.      */
  99.     const PAGE_WRITE_UPDATE = 'update';
  100.     const PAGE_WRITE_CLEAR  = 'clear';
  101.  
  102.     /**
  103.      * Stream wrapper clients
  104.      *
  105.      * @var array 
  106.      */
  107.     protected static $_wrapperClients array();
  108.  
  109.     /**
  110.      * SharedAccessSignature credentials
  111.      *
  112.      * @var Microsoft_WindowsAzure_Credentials_SharedAccessSignature 
  113.      */
  114.     protected $_sharedAccessSignatureCredentials = null;
  115.  
  116.     /**
  117.      * Creates a new Microsoft_WindowsAzure_Storage_Blob instance
  118.      *
  119.      * @param string $host Storage host name
  120.      * @param string $accountName Account name for Windows Azure
  121.      * @param string $accountKey Account key for Windows Azure
  122.      * @param boolean $usePathStyleUri Use path-style URI's
  123.      * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
  124.      */
  125.     public function __construct($host Microsoft_WindowsAzure_Storage::URL_DEV_BLOB$accountName Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT$accountKey Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY$usePathStyleUri falseMicrosoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy null)
  126.     {
  127.         parent::__construct($host$accountName$accountKey$usePathStyleUri$retryPolicy);
  128.  
  129.         // API version
  130.         $this->_apiVersion = '2009-09-19';
  131.  
  132.         // SharedAccessSignature credentials
  133.         $this->_sharedAccessSignatureCredentials = new Microsoft_WindowsAzure_Credentials_SharedAccessSignature($accountName$accountKey$usePathStyleUri);
  134.     }
  135.  
  136.     /**
  137.      * Check if a blob exists
  138.      *
  139.      * @param string $containerName Container name
  140.      * @param string $blobName      Blob name
  141.      * @param string $snapshotId    Snapshot identifier
  142.      * @return boolean 
  143.      */
  144.     public function blobExists($containerName ''$blobName ''$snapshotId null)
  145.     {
  146.         if ($containerName === ''{
  147.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  148.         }
  149.         if (!self::isValidContainerName($containerName)) {
  150.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  151.         }
  152.         if ($blobName === ''{
  153.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  154.         }
  155.  
  156.         // Get blob instance
  157.         try {
  158.             $this->getBlobInstance($containerName$blobName$snapshotId);
  159.         catch (Microsoft_WindowsAzure_Exception $e{
  160.             return false;
  161.         }
  162.  
  163.         return true;
  164.     }
  165.  
  166.     /**
  167.      * Check if a container exists
  168.      *
  169.      * @param string $containerName Container name
  170.      * @return boolean 
  171.      */
  172.     public function containerExists($containerName '')
  173.     {
  174.         if ($containerName === ''{
  175.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  176.         }
  177.         if (!self::isValidContainerName($containerName)) {
  178.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  179.         }
  180.             
  181.         // List containers
  182.         $containers $this->listContainers($containerName1);
  183.         foreach ($containers as $container{
  184.             if ($container->Name == $containerName{
  185.                 return true;
  186.             }
  187.         }
  188.  
  189.         return false;
  190.     }
  191.  
  192.     /**
  193.      * Create container
  194.      *
  195.      * @param string $containerName Container name
  196.      * @param array  $metadata      Key/value pairs of meta data
  197.      * @return object Container properties
  198.      * @throws Microsoft_WindowsAzure_Exception
  199.      */
  200.     public function createContainer($containerName ''$metadata array())
  201.     {
  202.         if ($containerName === ''{
  203.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  204.         }
  205.         if (!self::isValidContainerName($containerName)) {
  206.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  207.         }
  208.         if (!is_array($metadata)) {
  209.             throw new Microsoft_WindowsAzure_Exception('Meta data should be an array of key and value pairs.');
  210.         }
  211.             
  212.         // Create metadata headers
  213.         $headers array();
  214.         $headers array_merge($headers$this->_generateMetadataHeaders($metadata));
  215.  
  216.         // Perform request
  217.         $response $this->_performRequest($containerName'?restype=container'Microsoft_Http_Client::PUT$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  218.         if ($response->isSuccessful()) {
  219.             return new Microsoft_WindowsAzure_Storage_BlobContainer(
  220.             $containerName,
  221.             $response->getHeader('Etag'),
  222.             $response->getHeader('Last-modified'),
  223.             $metadata
  224.             );
  225.         else {
  226.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  227.         }
  228.     }
  229.     
  230.     /**
  231.      * Create container if it does not exist
  232.      *
  233.      * @param string $containerName Container name
  234.      * @param array  $metadata      Key/value pairs of meta data
  235.      * @throws Microsoft_WindowsAzure_Exception
  236.      */
  237.     public function createContainerIfNotExists($containerName ''$metadata array())
  238.     {
  239.         if (!$this->containerExists($containerName)) {
  240.             $this->createContainer($containerName$metadata);
  241.         }
  242.     }
  243.  
  244.     /**
  245.      * Get container ACL
  246.      *
  247.      * @param string $containerName Container name
  248.      * @param bool   $signedIdentifiers Display only private/blob/container or display signed identifiers?
  249.      * @return string Acl, to be compared with Microsoft_WindowsAzure_Storage_Blob::ACL_*
  250.      * @throws Microsoft_WindowsAzure_Exception
  251.      */
  252.     public function getContainerAcl($containerName ''$signedIdentifiers false)
  253.     {
  254.         if ($containerName === ''{
  255.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  256.         }
  257.         if (!self::isValidContainerName($containerName)) {
  258.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  259.         }
  260.  
  261.         // Perform request
  262.         $response $this->_performRequest($containerName'?restype=container&comp=acl'Microsoft_Http_Client::GETarray()falsenullMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
  263.         if ($response->isSuccessful()) {
  264.             if ($signedIdentifiers == false)  {
  265.                 // Only private/blob/container
  266.                 $accessType $response->getHeader(Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER 'blob-public-access');
  267.                 if (strtolower($accessType== 'true'{
  268.                     $accessType self::ACL_PUBLIC_CONTAINER;
  269.                 }
  270.                 return $accessType;
  271.             else {
  272.                 // Parse result
  273.                 $result $this->_parseResponse($response);
  274.                 if (!$result{
  275.                     return array();
  276.                 }
  277.  
  278.                 $entries null;
  279.                 if ($result->SignedIdentifier{
  280.                     if (count($result->SignedIdentifier1{
  281.                         $entries $result->SignedIdentifier;
  282.                     else {
  283.                         $entries array($result->SignedIdentifier);
  284.                     }
  285.                 }
  286.  
  287.                 // Return value
  288.                 $returnValue array();
  289.                 foreach ($entries as $entry{
  290.                     $returnValue[new Microsoft_WindowsAzure_Storage_SignedIdentifier(
  291.                     $entry->Id,
  292.                     $entry->AccessPolicy $entry->AccessPolicy->Start $entry->AccessPolicy->Start '' '',
  293.                     $entry->AccessPolicy $entry->AccessPolicy->Expiry $entry->AccessPolicy->Expiry '' '',
  294.                     $entry->AccessPolicy $entry->AccessPolicy->Permission $entry->AccessPolicy->Permission '' ''
  295.                     );
  296.                 }
  297.  
  298.                 // Return
  299.                 return $returnValue;
  300.             }
  301.         else {
  302.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  303.         }
  304.     }
  305.  
  306.     /**
  307.      * Set container ACL
  308.      *
  309.      * @param string $containerName Container name
  310.      * @param bool $acl Microsoft_WindowsAzure_Storage_Blob::ACL_*
  311.      * @param array $signedIdentifiers Signed identifiers
  312.      * @throws Microsoft_WindowsAzure_Exception
  313.      */
  314.     public function setContainerAcl($containerName ''$acl self::ACL_PRIVATE$signedIdentifiers array())
  315.     {
  316.         if ($containerName === ''{
  317.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  318.         }
  319.         if (!self::isValidContainerName($containerName)) {
  320.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  321.         }
  322.  
  323.         // Headers
  324.         $headers array();
  325.  
  326.         // Acl specified?
  327.         if ($acl != self::ACL_PRIVATE && !is_null($acl&& $acl != ''{
  328.             $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER 'blob-public-access'$acl;
  329.         }
  330.  
  331.         // Policies
  332.         $policies null;
  333.         if (is_array($signedIdentifiers&& count($signedIdentifiers0{
  334.             $policies  '';
  335.             $policies .= '<?xml version="1.0" encoding="utf-8"?>' "\r\n";
  336.             $policies .= '<SignedIdentifiers>' "\r\n";
  337.             foreach ($signedIdentifiers as $signedIdentifier{
  338.                 $policies .= '  <SignedIdentifier>' "\r\n";
  339.                 $policies .= '    <Id>' $signedIdentifier->Id '</Id>' "\r\n";
  340.                 $policies .= '    <AccessPolicy>' "\r\n";
  341.                 if ($signedIdentifier->Start != '')
  342.                 $policies .= '      <Start>' $signedIdentifier->Start '</Start>' "\r\n";
  343.                 if ($signedIdentifier->Expiry != '')
  344.                 $policies .= '      <Expiry>' $signedIdentifier->Expiry '</Expiry>' "\r\n";
  345.                 if ($signedIdentifier->Permissions != '')
  346.                 $policies .= '      <Permission>' $signedIdentifier->Permissions '</Permission>' "\r\n";
  347.                 $policies .= '    </AccessPolicy>' "\r\n";
  348.                 $policies .= '  </SignedIdentifier>' "\r\n";
  349.             }
  350.             $policies .= '</SignedIdentifiers>' "\r\n";
  351.         }
  352.  
  353.         // Perform request
  354.         $response $this->_performRequest($containerName'?restype=container&comp=acl'Microsoft_Http_Client::PUT$headersfalse$policiesMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  355.         if (!$response->isSuccessful()) {
  356.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  357.         }
  358.     }
  359.  
  360.     /**
  361.      * Get container
  362.      *
  363.      * @param string $containerName  Container name
  364.      * @return Microsoft_WindowsAzure_Storage_BlobContainer 
  365.      * @throws Microsoft_WindowsAzure_Exception
  366.      */
  367.     public function getContainer($containerName '')
  368.     {
  369.         if ($containerName === ''{
  370.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  371.         }
  372.         if (!self::isValidContainerName($containerName)) {
  373.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  374.         }
  375.  
  376.         // Perform request
  377.         $response $this->_performRequest($containerName'?restype=container'Microsoft_Http_Client::GETarray()falsenullMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
  378.         if ($response->isSuccessful()) {
  379.             // Parse metadata
  380.             $metadata $this->_parseMetadataHeaders($response->getHeaders());
  381.  
  382.             // Return container
  383.             return new Microsoft_WindowsAzure_Storage_BlobContainer(
  384.             $containerName,
  385.             $response->getHeader('Etag'),
  386.             $response->getHeader('Last-modified'),
  387.             $metadata
  388.             );
  389.         else {
  390.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  391.         }
  392.     }
  393.  
  394.     /**
  395.      * Get container metadata
  396.      *
  397.      * @param string $containerName  Container name
  398.      * @return array Key/value pairs of meta data
  399.      * @throws Microsoft_WindowsAzure_Exception
  400.      */
  401.     public function getContainerMetadata($containerName '')
  402.     {
  403.         if ($containerName === ''{
  404.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  405.         }
  406.         if (!self::isValidContainerName($containerName)) {
  407.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  408.         }
  409.  
  410.         return $this->getContainer($containerName)->Metadata;
  411.     }
  412.  
  413.     /**
  414.      * Set container metadata
  415.      *
  416.      * Calling the Set Container Metadata operation overwrites all existing metadata that is associated with the container. It's not possible to modify an individual name/value pair.
  417.      *
  418.      * @param string $containerName      Container name
  419.      * @param array  $metadata           Key/value pairs of meta data
  420.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  421.      * @throws Microsoft_WindowsAzure_Exception
  422.      */
  423.     public function setContainerMetadata($containerName ''$metadata array()$additionalHeaders array())
  424.     {
  425.         if ($containerName === ''{
  426.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  427.         }
  428.         if (!self::isValidContainerName($containerName)) {
  429.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  430.         }
  431.         if (!is_array($metadata)) {
  432.             throw new Microsoft_WindowsAzure_Exception('Meta data should be an array of key and value pairs.');
  433.         }
  434.         if (count($metadata== 0{
  435.             return;
  436.         }
  437.  
  438.         // Create metadata headers
  439.         $headers array();
  440.         $headers array_merge($headers$this->_generateMetadataHeaders($metadata));
  441.  
  442.         // Additional headers?
  443.         foreach ($additionalHeaders as $key => $value{
  444.             $headers[$key$value;
  445.         }
  446.  
  447.         // Perform request
  448.         $response $this->_performRequest($containerName'?restype=container&comp=metadata'Microsoft_Http_Client::PUT$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  449.         if (!$response->isSuccessful()) {
  450.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  451.         }
  452.     }
  453.  
  454.     /**
  455.      * Delete container
  456.      *
  457.      * @param string $containerName      Container name
  458.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  459.      * @throws Microsoft_WindowsAzure_Exception
  460.      */
  461.     public function deleteContainer($containerName ''$additionalHeaders array())
  462.     {
  463.         if ($containerName === ''{
  464.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  465.         }
  466.         if (!self::isValidContainerName($containerName)) {
  467.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  468.         }
  469.             
  470.         // Additional headers?
  471.         $headers array();
  472.         foreach ($additionalHeaders as $key => $value{
  473.             $headers[$key$value;
  474.         }
  475.  
  476.         // Perform request
  477.         $response $this->_performRequest($containerName'?restype=container'Microsoft_Http_Client::DELETE$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  478.         if (!$response->isSuccessful()) {
  479.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  480.         }
  481.     }
  482.  
  483.     /**
  484.      * List containers
  485.      *
  486.      * @param string $prefix     Optional. Filters the results to return only containers whose name begins with the specified prefix.
  487.      * @param int    $maxResults Optional. Specifies the maximum number of containers to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000)
  488.      * @param string $marker     Optional string value that identifies the portion of the list to be returned with the next list operation.
  489.      * @param string $include    Optional. Include this parameter to specify that the container's metadata be returned as part of the response body. (allowed values: '', 'metadata')
  490.      * @param int    $currentResultCount Current result count (internal use)
  491.      * @return array 
  492.      * @throws Microsoft_WindowsAzure_Exception
  493.      */
  494.     public function listContainers($prefix null$maxResults null$marker null$include null$currentResultCount 0)
  495.     {
  496.         // Build query string
  497.         $queryString array('comp=list');
  498.         if (!is_null($prefix)) {
  499.             $queryString['prefix=' $prefix;
  500.         }
  501.         if (!is_null($maxResults)) {
  502.             $queryString['maxresults=' $maxResults;
  503.         }
  504.         if (!is_null($marker)) {
  505.             $queryString['marker=' $marker;
  506.         }
  507.         if (!is_null($include)) {
  508.             $queryString['include=' $include;
  509.         }
  510.         $queryString self::createQueryStringFromArray($queryString);
  511.          
  512.         // Perform request
  513.         $response $this->_performRequest(''$queryStringMicrosoft_Http_Client::GETarray()falsenullMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_LIST);
  514.         if ($response->isSuccessful()) {
  515.             $xmlContainers $this->_parseResponse($response)->Containers->Container;
  516.             $xmlMarker = (string)$this->_parseResponse($response)->NextMarker;
  517.  
  518.             $containers array();
  519.             if (!is_null($xmlContainers)) {
  520.                 for ($i 0$i count($xmlContainers)$i++{
  521.                     $containers[new Microsoft_WindowsAzure_Storage_BlobContainer(
  522.                     (string)$xmlContainers[$i]->Name,
  523.                     (string)$xmlContainers[$i]->Etag,
  524.                     (string)$xmlContainers[$i]->LastModified,
  525.                     $this->_parseMetadataElement($xmlContainers[$i])
  526.                     );
  527.                 }
  528.             }
  529.             $currentResultCount $currentResultCount count($containers);
  530.             if (!is_null($maxResults&& $currentResultCount $maxResults{
  531.                 if (!is_null($xmlMarker&& $xmlMarker != ''{
  532.                     $containers array_merge($containers$this->listContainers($prefix$maxResults$xmlMarker$include$currentResultCount));
  533.                 }
  534.             }
  535.             if (!is_null($maxResults&& count($containers$maxResults{
  536.                 $containers array_slice($containers0$maxResults);
  537.             }
  538.              
  539.             return $containers;
  540.         else {
  541.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  542.         }
  543.     }
  544.  
  545.     /**
  546.      * Put blob
  547.      *
  548.      * @param string $containerName      Container name
  549.      * @param string $blobName           Blob name
  550.      * @param string $localFileName      Local file name to be uploaded
  551.      * @param array  $metadata           Key/value pairs of meta data
  552.      * @param string $leaseId            Lease identifier
  553.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  554.      * @return object Partial blob properties
  555.      * @throws Microsoft_WindowsAzure_Exception
  556.      */
  557.     public function putBlob($containerName ''$blobName ''$localFileName ''$metadata array()$leaseId null$additionalHeaders array())
  558.     {
  559.         if ($containerName === ''{
  560.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  561.         }
  562.         if (!self::isValidContainerName($containerName)) {
  563.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  564.         }
  565.         if ($blobName === ''{
  566.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  567.         }
  568.         if ($localFileName === ''{
  569.             throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
  570.         }
  571.         if (!file_exists($localFileName)) {
  572.             throw new Microsoft_WindowsAzure_Exception('Local file not found.');
  573.         }
  574.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  575.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  576.         }
  577.             
  578.         // Check file size
  579.         if (filesize($localFileName>= self::MAX_BLOB_SIZE{
  580.             return $this->putLargeBlob($containerName$blobName$localFileName$metadata$leaseId$additionalHeaders);
  581.         }
  582.  
  583.         // Put the data to Windows Azure Storage
  584.         return $this->putBlobData($containerName$blobNamefile_get_contents($localFileName)$metadata$leaseId$additionalHeaders);
  585.     }
  586.  
  587.     /**
  588.      * Put blob data
  589.      *
  590.      * @param string $containerName      Container name
  591.      * @param string $blobName           Blob name
  592.      * @param mixed  $data               Data to store
  593.      * @param array  $metadata           Key/value pairs of meta data
  594.      * @param string $leaseId            Lease identifier
  595.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  596.      * @return object Partial blob properties
  597.      * @throws Microsoft_WindowsAzure_Exception
  598.      */
  599.     public function putBlobData($containerName ''$blobName ''$data ''$metadata array()$leaseId null$additionalHeaders array())
  600.     {
  601.         if ($containerName === ''{
  602.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  603.         }
  604.         if (!self::isValidContainerName($containerName)) {
  605.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  606.         }
  607.         if ($blobName === ''{
  608.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  609.         }
  610.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  611.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  612.         }
  613.  
  614.         // Create metadata headers
  615.         $headers array();
  616.         if (!is_null($leaseId)) {
  617.             $headers['x-ms-lease-id'$leaseId;
  618.         }
  619.         $headers array_merge($headers$this->_generateMetadataHeaders($metadata));
  620.  
  621.         // Additional headers?
  622.         foreach ($additionalHeaders as $key => $value{
  623.             $headers[$key$value;
  624.         }
  625.  
  626.         // Specify blob type
  627.         $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER 'blob-type'self::BLOBTYPE_BLOCK;
  628.  
  629.         // Resource name
  630.         $resourceName self::createResourceName($containerName $blobName);
  631.  
  632.         // Perform request
  633.         $response $this->_performRequest($resourceName''Microsoft_Http_Client::PUT$headersfalse$dataMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  634.         if ($response->isSuccessful()) {
  635.             return new Microsoft_WindowsAzure_Storage_BlobInstance(
  636.             $containerName,
  637.             $blobName,
  638.             null,
  639.             $response->getHeader('Etag'),
  640.             $response->getHeader('Last-modified'),
  641.             $this->getBaseUrl('/' $containerName '/' $blobName,
  642.             strlen($data),
  643.                 '',
  644.                 '',
  645.                 '',
  646.             false,
  647.             $metadata
  648.             );
  649.         else {
  650.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  651.         }
  652.     }
  653.  
  654.     /**
  655.      * Put large blob (> 64 MB)
  656.      *
  657.      * @param string $containerName Container name
  658.      * @param string $blobName Blob name
  659.      * @param string $localFileName Local file name to be uploaded
  660.      * @param array  $metadata      Key/value pairs of meta data
  661.      * @param string $leaseId       Lease identifier
  662.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  663.      * @return object Partial blob properties
  664.      * @throws Microsoft_WindowsAzure_Exception
  665.      */
  666.     public function putLargeBlob($containerName ''$blobName ''$localFileName ''$metadata array()$leaseId null$additionalHeaders array())
  667.     {
  668.         if ($containerName === ''{
  669.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  670.         }
  671.         if (!self::isValidContainerName($containerName)) {
  672.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  673.         }
  674.         if ($blobName === ''{
  675.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  676.         }
  677.         if ($localFileName === ''{
  678.             throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
  679.         }
  680.         if (!file_exists($localFileName)) {
  681.             throw new Microsoft_WindowsAzure_Exception('Local file not found.');
  682.         }
  683.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  684.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  685.         }
  686.             
  687.         // Check file size
  688.         if (filesize($localFileNameself::MAX_BLOB_SIZE{
  689.             return $this->putBlob($containerName$blobName$localFileName$metadata$leaseId$additionalHeaders);
  690.         }
  691.             
  692.         // Determine number of parts
  693.         $numberOfParts ceilfilesize($localFileNameself::MAX_BLOB_TRANSFER_SIZE );
  694.  
  695.         // Generate block id's
  696.         $blockIdentifiers array();
  697.         for ($i 0$i $numberOfParts$i++{
  698.             $blockIdentifiers[$this->_generateBlockId($i);
  699.         }
  700.  
  701.         // Open file
  702.         $fp fopen($localFileName'r');
  703.         if ($fp === false{
  704.             throw new Microsoft_WindowsAzure_Exception('Could not open local file.');
  705.         }
  706.             
  707.         // Upload parts
  708.         for ($i 0$i $numberOfParts$i++{
  709.             // Seek position in file
  710.             fseek($fp$i self::MAX_BLOB_TRANSFER_SIZE);
  711.                 
  712.             // Read contents
  713.             $fileContents fread($fpself::MAX_BLOB_TRANSFER_SIZE);
  714.                 
  715.             // Put block
  716.             $this->putBlock($containerName$blobName$blockIdentifiers[$i]$fileContents$leaseId);
  717.                 
  718.             // Dispose file contents
  719.             $fileContents null;
  720.             unset($fileContents);
  721.         }
  722.  
  723.         // Close file
  724.         fclose($fp);
  725.  
  726.         // Put block list
  727.         $this->putBlockList($containerName$blobName$blockIdentifiers$metadata$leaseId$additionalHeaders);
  728.  
  729.         // Return information of the blob
  730.         return $this->getBlobInstance($containerName$blobNamenull$leaseId);
  731.     }
  732.         
  733.     /**
  734.      * Put large blob block
  735.      *
  736.      * @param string $containerName Container name
  737.      * @param string $blobName      Blob name
  738.      * @param string $identifier    Block ID
  739.      * @param array  $contents      Contents of the block
  740.      * @param string $leaseId       Lease identifier
  741.      * @throws Microsoft_WindowsAzure_Exception
  742.      */
  743.     public function putBlock($containerName ''$blobName ''$identifier ''$contents ''$leaseId null)
  744.     {
  745.         if ($containerName === ''{
  746.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  747.         }
  748.         if (!self::isValidContainerName($containerName)) {
  749.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  750.         }
  751.         if ($identifier === ''{
  752.             throw new Microsoft_WindowsAzure_Exception('Block identifier is not specified.');
  753.         }
  754.         if (strlen($contentsself::MAX_BLOB_TRANSFER_SIZE{
  755.             throw new Microsoft_WindowsAzure_Exception('Block size is too big.');
  756.         }
  757.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  758.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  759.         }
  760.  
  761.         // Headers
  762.         $headers array();
  763.         if (!is_null($leaseId)) {
  764.             $headers['x-ms-lease-id'$leaseId;
  765.         }
  766.             
  767.         // Resource name
  768.         $resourceName self::createResourceName($containerName $blobName);
  769.  
  770.         // Upload
  771.         $response $this->_performRequest($resourceName'?comp=block&blockid=' base64_encode($identifier)Microsoft_Http_Client::PUT$headersfalse$contentsMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  772.         if (!$response->isSuccessful()) {
  773.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  774.         }
  775.     }
  776.  
  777.     /**
  778.      * Put block list
  779.      *
  780.      * @param string $containerName      Container name
  781.      * @param string $blobName           Blob name
  782.      * @param array $blockList           Array of block identifiers
  783.      * @param array  $metadata           Key/value pairs of meta data
  784.      * @param string $leaseId            Lease identifier
  785.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  786.      * @throws Microsoft_WindowsAzure_Exception
  787.      */
  788.     public function putBlockList($containerName ''$blobName ''$blockList array()$metadata array()$leaseId null$additionalHeaders array())
  789.     {
  790.         if ($containerName === ''{
  791.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  792.         }
  793.         if (!self::isValidContainerName($containerName)) {
  794.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  795.         }
  796.         if ($blobName === ''{
  797.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  798.         }
  799.         if (count($blockList== 0{
  800.             throw new Microsoft_WindowsAzure_Exception('Block list does not contain any elements.');
  801.         }
  802.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  803.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  804.         }
  805.  
  806.         // Generate block list
  807.         $blocks '';
  808.         foreach ($blockList as $block{
  809.             $blocks .= '  <Latest>' base64_encode($block'</Latest>' "\n";
  810.         }
  811.  
  812.         // Generate block list request
  813.         $fileContents utf8_encode(implode("\n"array(
  814.                 '<?xml version="1.0" encoding="utf-8"?>',
  815.                 '<BlockList>',
  816.                 $blocks,
  817.                 '</BlockList>'
  818.             )));
  819.  
  820.             // Create metadata headers
  821.             $headers array();
  822.             if (!is_null($leaseId)) {
  823.                 $headers['x-ms-lease-id'$leaseId;
  824.             }
  825.             $headers array_merge($headers$this->_generateMetadataHeaders($metadata));
  826.  
  827.             // Additional headers?
  828.             foreach ($additionalHeaders as $key => $value{
  829.                 $headers[$key$value;
  830.             }
  831.  
  832.             // Resource name
  833.             $resourceName self::createResourceName($containerName $blobName);
  834.  
  835.             // Perform request
  836.             $response $this->_performRequest($resourceName'?comp=blocklist'Microsoft_Http_Client::PUT$headersfalse$fileContentsMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  837.             if (!$response->isSuccessful()) {
  838.                 throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  839.             }
  840.     }
  841.  
  842.     /**
  843.      * Get block list
  844.      *
  845.      * @param string $containerName Container name
  846.      * @param string $blobName      Blob name
  847.      * @param string $snapshotId    Snapshot identifier
  848.      * @param string $leaseId       Lease identifier
  849.      * @param integer $type         Type of block list to retrieve. 0 = all, 1 = committed, 2 = uncommitted
  850.      * @return array 
  851.      * @throws Microsoft_WindowsAzure_Exception
  852.      */
  853.     public function getBlockList($containerName ''$blobName ''$snapshotId null$leaseId null$type 0)
  854.     {
  855.         if ($containerName === ''{
  856.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  857.         }
  858.         if (!self::isValidContainerName($containerName)) {
  859.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  860.         }
  861.         if ($blobName === ''{
  862.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  863.         }
  864.         if ($type || $type 2{
  865.             throw new Microsoft_WindowsAzure_Exception('Invalid type of block list to retrieve.');
  866.         }
  867.  
  868.         // Set $blockListType
  869.         $blockListType 'all';
  870.         if ($type == 1{
  871.             $blockListType 'committed';
  872.         }
  873.         if ($type == 2{
  874.             $blockListType 'uncommitted';
  875.         }
  876.  
  877.         // Headers
  878.         $headers array();
  879.         if (!is_null($leaseId)) {
  880.             $headers['x-ms-lease-id'$leaseId;
  881.         }
  882.  
  883.         // Build query string
  884.         $queryString array('comp=blocklist''blocklisttype=' $blockListType);
  885.         if (!is_null($snapshotId)) {
  886.             $queryString['snapshot=' $snapshotId;
  887.         }
  888.         $queryString self::createQueryStringFromArray($queryString);
  889.  
  890.         // Resource name
  891.         $resourceName self::createResourceName($containerName $blobName);
  892.             
  893.         // Perform request
  894.         $response $this->_performRequest($resourceName$queryStringMicrosoft_Http_Client::GET$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
  895.         if ($response->isSuccessful()) {
  896.             // Parse response
  897.             $blockList $this->_parseResponse($response);
  898.  
  899.             // Create return value
  900.             $returnValue array();
  901.             if ($blockList->CommittedBlocks{
  902.                 foreach ($blockList->CommittedBlocks->Block as $block{
  903.                     $returnValue['CommittedBlocks'][= (object)array(
  904.                         'Name' => (string)$block->Name,
  905.                         'Size' => (string)$block->Size
  906.                     );
  907.                 }
  908.             }
  909.             if ($blockList->UncommittedBlocks)  {
  910.                 foreach ($blockList->UncommittedBlocks->Block as $block{
  911.                     $returnValue['UncommittedBlocks'][= (object)array(
  912.                         'Name' => (string)$block->Name,
  913.                         'Size' => (string)$block->Size
  914.                     );
  915.                 }
  916.             }
  917.  
  918.             return $returnValue;
  919.         else {
  920.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  921.         }
  922.     }
  923.  
  924.     /**
  925.      * Create page blob
  926.      *
  927.      * @param string $containerName      Container name
  928.      * @param string $blobName           Blob name
  929.      * @param int    $size               Size of the page blob in bytes
  930.      * @param array  $metadata           Key/value pairs of meta data
  931.      * @param string $leaseId            Lease identifier
  932.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  933.      * @return object Partial blob properties
  934.      * @throws Microsoft_WindowsAzure_Exception
  935.      */
  936.     public function createPageBlob($containerName ''$blobName ''$size 0$metadata array()$leaseId null$additionalHeaders array())
  937.     {
  938.         if ($containerName === ''{
  939.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  940.         }
  941.         if (!self::isValidContainerName($containerName)) {
  942.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  943.         }
  944.         if ($blobName === ''{
  945.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  946.         }
  947.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  948.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  949.         }
  950.         if ($size <= 0{
  951.             throw new Microsoft_WindowsAzure_Exception('Page blob size must be specified.');
  952.         }
  953.  
  954.         // Create metadata headers
  955.         $headers array();
  956.         if (!is_null($leaseId)) {
  957.             $headers['x-ms-lease-id'$leaseId;
  958.         }
  959.         $headers array_merge($headers$this->_generateMetadataHeaders($metadata));
  960.  
  961.         // Additional headers?
  962.         foreach ($additionalHeaders as $key => $value{
  963.             $headers[$key$value;
  964.         }
  965.  
  966.         // Specify blob type & blob length
  967.         $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER 'blob-type'self::BLOBTYPE_PAGE;
  968.         $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER 'blob-content-length'$size;
  969.         $headers['Content-Length'0;
  970.  
  971.         // Resource name
  972.         $resourceName self::createResourceName($containerName $blobName);
  973.  
  974.         // Perform request
  975.         $response $this->_performRequest($resourceName''Microsoft_Http_Client::PUT$headersfalse''Microsoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  976.         if ($response->isSuccessful()) {
  977.             return new Microsoft_WindowsAzure_Storage_BlobInstance(
  978.             $containerName,
  979.             $blobName,
  980.             null,
  981.             $response->getHeader('Etag'),
  982.             $response->getHeader('Last-modified'),
  983.             $this->getBaseUrl('/' $containerName '/' $blobName,
  984.             $size,
  985.                 '',
  986.                 '',
  987.                 '',
  988.             false,
  989.             $metadata
  990.             );
  991.         else {
  992.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  993.         }
  994.     }
  995.  
  996.     /**
  997.      * Put page in page blob
  998.      *
  999.      * @param string $containerName      Container name
  1000.      * @param string $blobName           Blob name
  1001.      * @param int    $startByteOffset    Start byte offset
  1002.      * @param int    $endByteOffset      End byte offset
  1003.      * @param mixed  $contents             Page contents
  1004.      * @param string $writeMethod        Write method (Microsoft_WindowsAzure_Storage_Blob::PAGE_WRITE_*)
  1005.      * @param string $leaseId            Lease identifier
  1006.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  1007.      * @throws Microsoft_WindowsAzure_Exception
  1008.      */
  1009.     public function putPage($containerName ''$blobName ''$startByteOffset 0$endByteOffset 0$contents ''$writeMethod self::PAGE_WRITE_UPDATE$leaseId null$additionalHeaders array())
  1010.     {
  1011.         if ($containerName === ''{
  1012.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1013.         }
  1014.         if (!self::isValidContainerName($containerName)) {
  1015.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1016.         }
  1017.         if ($blobName === ''{
  1018.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1019.         }
  1020.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  1021.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1022.         }
  1023.         if ($startByteOffset 512 != 0{
  1024.             throw new Microsoft_WindowsAzure_Exception('Start byte offset must be a modulus of 512.');
  1025.         }
  1026.         if (($endByteOffset 1512 != 0{
  1027.             throw new Microsoft_WindowsAzure_Exception('End byte offset must be a modulus of 512 minus 1.');
  1028.         }
  1029.  
  1030.         // Determine size
  1031.         $size strlen($contents);
  1032.         if ($size >= self::MAX_BLOB_TRANSFER_SIZE{
  1033.             throw new Microsoft_WindowsAzure_Exception('Page blob size must not be larger than ' self::MAX_BLOB_TRANSFER_SIZE ' bytes.');
  1034.         }
  1035.  
  1036.         // Create metadata headers
  1037.         $headers array();
  1038.         if (!is_null($leaseId)) {
  1039.             $headers['x-ms-lease-id'$leaseId;
  1040.         }
  1041.  
  1042.         // Additional headers?
  1043.         foreach ($additionalHeaders as $key => $value{
  1044.             $headers[$key$value;
  1045.         }
  1046.  
  1047.         // Specify range
  1048.         $headers['Range''bytes=' $startByteOffset '-' $endByteOffset;
  1049.  
  1050.         // Write method
  1051.         $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER 'page-write'$writeMethod;
  1052.  
  1053.         // Resource name
  1054.         $resourceName self::createResourceName($containerName $blobName);
  1055.  
  1056.         // Perform request
  1057.         $response $this->_performRequest($resourceName'?comp=page'Microsoft_Http_Client::PUT$headersfalse$contentsMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  1058.         if (!$response->isSuccessful()) {
  1059.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  1060.         }
  1061.     }
  1062.  
  1063.     /**
  1064.      * Put page in page blob
  1065.      *
  1066.      * @param string $containerName      Container name
  1067.      * @param string $blobName           Blob name
  1068.      * @param int    $startByteOffset    Start byte offset
  1069.      * @param int    $endByteOffset      End byte offset
  1070.      * @param string $leaseId            Lease identifier
  1071.      * @return array Array of page ranges
  1072.      * @throws Microsoft_WindowsAzure_Exception
  1073.      */
  1074.     public function getPageRegions($containerName ''$blobName ''$startByteOffset 0$endByteOffset 0$leaseId null)
  1075.     {
  1076.         if ($containerName === ''{
  1077.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1078.         }
  1079.         if (!self::isValidContainerName($containerName)) {
  1080.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1081.         }
  1082.         if ($blobName === ''{
  1083.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1084.         }
  1085.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  1086.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1087.         }
  1088.         if ($startByteOffset 512 != 0{
  1089.             throw new Microsoft_WindowsAzure_Exception('Start byte offset must be a modulus of 512.');
  1090.         }
  1091.         if ($endByteOffset && ($endByteOffset 1512 != 0{
  1092.             throw new Microsoft_WindowsAzure_Exception('End byte offset must be a modulus of 512 minus 1.');
  1093.         }
  1094.  
  1095.         // Create metadata headers
  1096.         $headers array();
  1097.         if (!is_null($leaseId)) {
  1098.             $headers['x-ms-lease-id'$leaseId;
  1099.         }
  1100.  
  1101.         // Specify range?
  1102.         if ($endByteOffset 0{
  1103.             $headers['Range''bytes=' $startByteOffset '-' $endByteOffset;
  1104.         }
  1105.  
  1106.         // Resource name
  1107.         $resourceName self::createResourceName($containerName $blobName);
  1108.  
  1109.         // Perform request
  1110.         $response $this->_performRequest($resourceName'?comp=pagelist'Microsoft_Http_Client::GET$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  1111.         if ($response->isSuccessful()) {
  1112.             $result $this->_parseResponse($response);
  1113.             $xmlRanges null;
  1114.             if (count($result->PageRange1{
  1115.                 $xmlRanges $result->PageRange;
  1116.             else {
  1117.                 $xmlRanges array($result->PageRange);
  1118.             }
  1119.  
  1120.             $ranges array();
  1121.             for ($i 0$i count($xmlRanges)$i++{
  1122.                 $ranges[new Microsoft_WindowsAzure_Storage_PageRegionInstance(
  1123.                 (int)$xmlRanges[$i]->Start,
  1124.                 (int)$xmlRanges[$i]->End
  1125.                 );
  1126.             }
  1127.              
  1128.             return $ranges;
  1129.         else {
  1130.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  1131.         }
  1132.     }
  1133.         
  1134.     /**
  1135.      * Copy blob
  1136.      *
  1137.      * @param string $sourceContainerName       Source container name
  1138.      * @param string $sourceBlobName            Source blob name
  1139.      * @param string $destinationContainerName  Destination container name
  1140.      * @param string $destinationBlobName       Destination blob name
  1141.      * @param array  $metadata                  Key/value pairs of meta data
  1142.      * @param string $sourceSnapshotId          Source snapshot identifier
  1143.      * @param string $destinationLeaseId        Destination lease identifier
  1144.      * @param array  $additionalHeaders         Additional headers. See http://msdn.microsoft.com/en-us/library/dd894037.aspx for more information.
  1145.      * @return object Partial blob properties
  1146.      * @throws Microsoft_WindowsAzure_Exception
  1147.      */
  1148.     public function copyBlob($sourceContainerName ''$sourceBlobName ''$destinationContainerName ''$destinationBlobName ''$metadata array()$sourceSnapshotId null$destinationLeaseId null$additionalHeaders array())
  1149.     {
  1150.         if ($sourceContainerName === ''{
  1151.             throw new Microsoft_WindowsAzure_Exception('Source container name is not specified.');
  1152.         }
  1153.         if (!self::isValidContainerName($sourceContainerName)) {
  1154.             throw new Microsoft_WindowsAzure_Exception('Source container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1155.         }
  1156.         if ($sourceBlobName === ''{
  1157.             throw new Microsoft_WindowsAzure_Exception('Source blob name is not specified.');
  1158.         }
  1159.         if ($destinationContainerName === ''{
  1160.             throw new Microsoft_WindowsAzure_Exception('Destination container name is not specified.');
  1161.         }
  1162.         if (!self::isValidContainerName($destinationContainerName)) {
  1163.             throw new Microsoft_WindowsAzure_Exception('Destination container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1164.         }
  1165.         if ($destinationBlobName === ''{
  1166.             throw new Microsoft_WindowsAzure_Exception('Destination blob name is not specified.');
  1167.         }
  1168.         if ($sourceContainerName === '$root' && strpos($sourceBlobName'/'!== false{
  1169.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1170.         }
  1171.         if ($destinationContainerName === '$root' && strpos($destinationBlobName'/'!== false{
  1172.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1173.         }
  1174.  
  1175.         // Create metadata headers
  1176.         $headers array();
  1177.         if (!is_null($destinationLeaseId)) {
  1178.             $headers['x-ms-lease-id'$destinationLeaseId;
  1179.         }
  1180.         $headers array_merge($headers$this->_generateMetadataHeaders($metadata));
  1181.  
  1182.         // Additional headers?
  1183.         foreach ($additionalHeaders as $key => $value{
  1184.             $headers[$key$value;
  1185.         }
  1186.  
  1187.         // Resource names
  1188.         $sourceResourceName self::createResourceName($sourceContainerName$sourceBlobName);
  1189.         if (!is_null($sourceSnapshotId)) {
  1190.             $sourceResourceName .= '?snapshot=' $sourceSnapshotId;
  1191.         }
  1192.         $destinationResourceName self::createResourceName($destinationContainerName$destinationBlobName);
  1193.  
  1194.         // Set source blob
  1195.         $headers["x-ms-copy-source"'/' $this->_accountName . '/' $sourceResourceName;
  1196.  
  1197.         // Perform request
  1198.         $response $this->_performRequest($destinationResourceName''Microsoft_Http_Client::PUT$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  1199.         if ($response->isSuccessful()) {
  1200.             return new Microsoft_WindowsAzure_Storage_BlobInstance(
  1201.             $destinationContainerName,
  1202.             $destinationBlobName,
  1203.             null,
  1204.             $response->getHeader('Etag'),
  1205.             $response->getHeader('Last-modified'),
  1206.             $this->getBaseUrl('/' $destinationContainerName '/' $destinationBlobName,
  1207.             0,
  1208.                 '',
  1209.                 '',
  1210.                 '',
  1211.             false,
  1212.             $metadata
  1213.             );
  1214.         else {
  1215.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  1216.         }
  1217.     }
  1218.  
  1219.     /**
  1220.      * Get blob
  1221.      *
  1222.      * @param string $containerName      Container name
  1223.      * @param string $blobName           Blob name
  1224.      * @param string $localFileName      Local file name to store downloaded blob
  1225.      * @param string $snapshotId         Snapshot identifier
  1226.      * @param string $leaseId            Lease identifier
  1227.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  1228.      * @throws Microsoft_WindowsAzure_Exception
  1229.      */
  1230.     public function getBlob($containerName ''$blobName ''$localFileName ''$snapshotId null$leaseId null$additionalHeaders array())
  1231.     {
  1232.         if ($containerName === ''{
  1233.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1234.         }
  1235.         if (!self::isValidContainerName($containerName)) {
  1236.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1237.         }
  1238.         if ($blobName === ''{
  1239.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1240.         }
  1241.         if ($localFileName === ''{
  1242.             throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
  1243.         }
  1244.  
  1245.         // Fetch data
  1246.         file_put_contents($localFileName$this->getBlobData($containerName$blobName$snapshotId$leaseId$additionalHeaders));
  1247.     }
  1248.  
  1249.     /**
  1250.      * Get blob data
  1251.      *
  1252.      * @param string $containerName      Container name
  1253.      * @param string $blobName           Blob name
  1254.      * @param string $snapshotId         Snapshot identifier
  1255.      * @param string $leaseId            Lease identifier
  1256.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  1257.      * @return mixed Blob contents
  1258.      * @throws Microsoft_WindowsAzure_Exception
  1259.      */
  1260.     public function getBlobData($containerName ''$blobName ''$snapshotId null$leaseId null$additionalHeaders array())
  1261.     {
  1262.         if ($containerName === ''{
  1263.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1264.         }
  1265.         if (!self::isValidContainerName($containerName)) {
  1266.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1267.         }
  1268.         if ($blobName === ''{
  1269.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1270.         }
  1271.  
  1272.         // Build query string
  1273.         $queryString array();
  1274.         if (!is_null($snapshotId)) {
  1275.             $queryString['snapshot=' $snapshotId;
  1276.         }
  1277.         $queryString self::createQueryStringFromArray($queryString);
  1278.  
  1279.         // Additional headers?
  1280.         $headers array();
  1281.         if (!is_null($leaseId)) {
  1282.             $headers['x-ms-lease-id'$leaseId;
  1283.         }
  1284.         foreach ($additionalHeaders as $key => $value{
  1285.             $headers[$key$value;
  1286.         }
  1287.  
  1288.         // Resource name
  1289.         $resourceName self::createResourceName($containerName $blobName);
  1290.  
  1291.         // Perform request
  1292.         $response $this->_performRequest($resourceName$queryStringMicrosoft_Http_Client::GET$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
  1293.         if ($response->isSuccessful()) {
  1294.             return $response->getBody();
  1295.         else {
  1296.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  1297.         }
  1298.     }
  1299.  
  1300.     /**
  1301.      * Get blob instance
  1302.      *
  1303.      * @param string $containerName      Container name
  1304.      * @param string $blobName           Blob name
  1305.      * @param string $snapshotId         Snapshot identifier
  1306.      * @param string $leaseId            Lease identifier
  1307.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  1308.      * @return Microsoft_WindowsAzure_Storage_BlobInstance 
  1309.      * @throws Microsoft_WindowsAzure_Exception
  1310.      */
  1311.     public function getBlobInstance($containerName ''$blobName ''$snapshotId null$leaseId null$additionalHeaders array())
  1312.     {
  1313.         if ($containerName === ''{
  1314.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1315.         }
  1316.         if (!self::isValidContainerName($containerName)) {
  1317.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1318.         }
  1319.         if ($blobName === ''{
  1320.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1321.         }
  1322.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  1323.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1324.         }
  1325.  
  1326.         // Build query string
  1327.         $queryString array();
  1328.         if (!is_null($snapshotId)) {
  1329.             $queryString['snapshot=' $snapshotId;
  1330.         }
  1331.         $queryString self::createQueryStringFromArray($queryString);
  1332.          
  1333.         // Additional headers?
  1334.         $headers array();
  1335.         if (!is_null($leaseId)) {
  1336.             $headers['x-ms-lease-id'$leaseId;
  1337.         }
  1338.         foreach ($additionalHeaders as $key => $value{
  1339.             $headers[$key$value;
  1340.         }
  1341.  
  1342.         // Resource name
  1343.         $resourceName self::createResourceName($containerName $blobName);
  1344.  
  1345.         // Perform request
  1346.         $response $this->_performRequest($resourceName$queryStringMicrosoft_Http_Client::HEAD$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
  1347.         if ($response->isSuccessful()) {
  1348.             // Parse metadata
  1349.             $metadata $this->_parseMetadataHeaders($response->getHeaders());
  1350.  
  1351.             // Return blob
  1352.             return new Microsoft_WindowsAzure_Storage_BlobInstance(
  1353.                 $containerName,
  1354.                 $blobName,
  1355.                 $snapshotId,
  1356.                 $response->getHeader('Etag'),
  1357.                 $response->getHeader('Last-modified'),
  1358.                 $this->getBaseUrl('/' $containerName '/' $blobName,
  1359.                 $response->getHeader('Content-Length'),
  1360.                 $response->getHeader('Content-Type'),
  1361.                 $response->getHeader('Content-Encoding'),
  1362.                 $response->getHeader('Content-Language'),
  1363.                 $response->getHeader('Cache-Control'),
  1364.                 $response->getHeader('x-ms-blob-type'),
  1365.                 $response->getHeader('x-ms-lease-status'),
  1366.                 false,
  1367.                 $metadata
  1368.             );
  1369.         else {
  1370.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  1371.         }
  1372.     }
  1373.  
  1374.     /**
  1375.      * Get blob metadata
  1376.      *
  1377.      * @param string $containerName  Container name
  1378.      * @param string $blobName       Blob name
  1379.      * @param string $snapshotId     Snapshot identifier
  1380.      * @param string $leaseId        Lease identifier
  1381.      * @return array Key/value pairs of meta data
  1382.      * @throws Microsoft_WindowsAzure_Exception
  1383.      */
  1384.     public function getBlobMetadata($containerName ''$blobName ''$snapshotId null$leaseId null)
  1385.     {
  1386.         if ($containerName === ''{
  1387.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1388.         }
  1389.         if (!self::isValidContainerName($containerName)) {
  1390.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1391.         }
  1392.         if ($blobName === ''{
  1393.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1394.         }
  1395.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  1396.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1397.         }
  1398.  
  1399.         return $this->getBlobInstance($containerName$blobName$snapshotId$leaseId)->Metadata;
  1400.     }
  1401.  
  1402.     /**
  1403.      * Set blob metadata
  1404.      *
  1405.      * Calling the Set Blob Metadata operation overwrites all existing metadata that is associated with the blob. It's not possible to modify an individual name/value pair.
  1406.      *
  1407.      * @param string $containerName      Container name
  1408.      * @param string $blobName           Blob name
  1409.      * @param array  $metadata           Key/value pairs of meta data
  1410.      * @param string $leaseId            Lease identifier
  1411.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  1412.      * @throws Microsoft_WindowsAzure_Exception
  1413.      */
  1414.     public function setBlobMetadata($containerName ''$blobName ''$metadata array()$leaseId null$additionalHeaders array())
  1415.     {
  1416.         if ($containerName === ''{
  1417.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1418.         }
  1419.         if (!self::isValidContainerName($containerName)) {
  1420.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1421.         }
  1422.         if ($blobName === ''{
  1423.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1424.         }
  1425.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  1426.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1427.         }
  1428.         if (count($metadata== 0{
  1429.             return;
  1430.         }
  1431.  
  1432.         // Create metadata headers
  1433.         $headers array();
  1434.         if (!is_null($leaseId)) {
  1435.             $headers['x-ms-lease-id'$leaseId;
  1436.         }
  1437.         $headers array_merge($headers$this->_generateMetadataHeaders($metadata));
  1438.  
  1439.         // Additional headers?
  1440.         foreach ($additionalHeaders as $key => $value{
  1441.             $headers[$key$value;
  1442.         }
  1443.  
  1444.         // Perform request
  1445.         $response $this->_performRequest($containerName '/' $blobName'?comp=metadata'Microsoft_Http_Client::PUT$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  1446.         if (!$response->isSuccessful()) {
  1447.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  1448.         }
  1449.     }
  1450.  
  1451.     /**
  1452.      * Set blob properties
  1453.      *
  1454.      * All available properties are listed at http://msdn.microsoft.com/en-us/library/ee691966.aspx and should be provided in the $additionalHeaders parameter.
  1455.      *
  1456.      * @param string $containerName      Container name
  1457.      * @param string $blobName           Blob name
  1458.      * @param string $leaseId            Lease identifier
  1459.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  1460.      * @throws Microsoft_WindowsAzure_Exception
  1461.      */
  1462.     public function setBlobProperties($containerName ''$blobName ''$leaseId null$additionalHeaders array())
  1463.     {
  1464.         if ($containerName === ''{
  1465.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1466.         }
  1467.         if (!self::isValidContainerName($containerName)) {
  1468.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1469.         }
  1470.         if ($blobName === ''{
  1471.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1472.         }
  1473.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  1474.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1475.         }
  1476.         if (count($additionalHeaders== 0{
  1477.             throw new Microsoft_WindowsAzure_Exception('No additional headers are specified.');
  1478.         }
  1479.  
  1480.         // Create headers
  1481.         $headers array();
  1482.  
  1483.         // Lease set?
  1484.         if (!is_null($leaseId)) {
  1485.             $headers['x-ms-lease-id'$leaseId;
  1486.         }
  1487.  
  1488.         // Additional headers?
  1489.         foreach ($additionalHeaders as $key => $value{
  1490.             $headers[$key$value;
  1491.         }
  1492.  
  1493.         // Perform request
  1494.         $response $this->_performRequest($containerName '/' $blobName'?comp=properties'Microsoft_Http_Client::PUT$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  1495.         if (!$response->isSuccessful()) {
  1496.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  1497.         }
  1498.     }
  1499.  
  1500.     /**
  1501.      * Get blob properties
  1502.      *
  1503.      * @param string $containerName      Container name
  1504.      * @param string $blobName           Blob name
  1505.      * @param string $snapshotId         Snapshot identifier
  1506.      * @param string $leaseId            Lease identifier
  1507.      * @return Microsoft_WindowsAzure_Storage_BlobInstance 
  1508.      * @throws Microsoft_WindowsAzure_Exception
  1509.      */
  1510.     public function getBlobProperties($containerName ''$blobName ''$snapshotId null$leaseId null)
  1511.     {
  1512.         if ($containerName === ''{
  1513.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1514.         }
  1515.         if (!self::isValidContainerName($containerName)) {
  1516.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1517.         }
  1518.         if ($blobName === ''{
  1519.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1520.         }
  1521.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  1522.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1523.         }
  1524.  
  1525.         return $this->getBlobInstance($containerName$blobName$snapshotId$leaseId);
  1526.     }
  1527.  
  1528.     /**
  1529.      * Delete blob
  1530.      *
  1531.      * @param string $containerName      Container name
  1532.      * @param string $blobName           Blob name
  1533.      * @param string $snapshotId         Snapshot identifier
  1534.      * @param string $leaseId            Lease identifier
  1535.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  1536.      * @throws Microsoft_WindowsAzure_Exception
  1537.      */
  1538.     public function deleteBlob($containerName ''$blobName ''$snapshotId null$leaseId null$additionalHeaders array())
  1539.     {
  1540.         if ($containerName === ''{
  1541.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1542.         }
  1543.         if (!self::isValidContainerName($containerName)) {
  1544.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1545.         }
  1546.         if ($blobName === ''{
  1547.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1548.         }
  1549.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  1550.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1551.         }
  1552.  
  1553.         // Build query string
  1554.         $queryString array();
  1555.         if (!is_null($snapshotId)) {
  1556.             $queryString['snapshot=' $snapshotId;
  1557.         }
  1558.         $queryString self::createQueryStringFromArray($queryString);
  1559.             
  1560.         // Additional headers?
  1561.         $headers array();
  1562.         if (!is_null($leaseId)) {
  1563.             $headers['x-ms-lease-id'$leaseId;
  1564.         }
  1565.         foreach ($additionalHeaders as $key => $value{
  1566.             $headers[$key$value;
  1567.         }
  1568.  
  1569.         // Resource name
  1570.         $resourceName self::createResourceName($containerName $blobName);
  1571.  
  1572.         // Perform request
  1573.         $response $this->_performRequest($resourceName$queryStringMicrosoft_Http_Client::DELETE$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  1574.         if (!$response->isSuccessful()) {
  1575.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  1576.         }
  1577.     }
  1578.  
  1579.     /**
  1580.      * Snapshot blob
  1581.      *
  1582.      * @param string $containerName      Container name
  1583.      * @param string $blobName           Blob name
  1584.      * @param array  $metadata           Key/value pairs of meta data
  1585.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  1586.      * @return string Date/Time value representing the snapshot identifier.
  1587.      * @throws Microsoft_WindowsAzure_Exception
  1588.      */
  1589.     public function snapshotBlob($containerName ''$blobName ''$metadata array()$additionalHeaders array())
  1590.     {
  1591.         if ($containerName === ''{
  1592.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1593.         }
  1594.         if (!self::isValidContainerName($containerName)) {
  1595.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1596.         }
  1597.         if ($blobName === ''{
  1598.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1599.         }
  1600.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  1601.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1602.         }
  1603.  
  1604.         // Additional headers?
  1605.         $headers array();
  1606.         foreach ($additionalHeaders as $key => $value{
  1607.             $headers[$key$value;
  1608.         }
  1609.  
  1610.         // Resource name
  1611.         $resourceName self::createResourceName($containerName $blobName);
  1612.  
  1613.         // Perform request
  1614.         $response $this->_performRequest($resourceName'?comp=snapshot'Microsoft_Http_Client::PUT$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  1615.         if ($response->isSuccessful()) {
  1616.             return $response->getHeader('x-ms-snapshot');
  1617.         else {
  1618.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  1619.         }
  1620.     }
  1621.  
  1622.     /**
  1623.      * Lease blob - See (http://msdn.microsoft.com/en-us/library/ee691972.aspx)
  1624.      *
  1625.      * @param string $containerName      Container name
  1626.      * @param string $blobName           Blob name
  1627.      * @param string $leaseAction        Lease action (Microsoft_WindowsAzure_Storage_Blob::LEASE_*)
  1628.      * @param string $leaseId            Lease identifier, required to renew the lease or to release the lease.
  1629.      * @return Microsoft_WindowsAzure_Storage_LeaseInstance Lease instance
  1630.      * @throws Microsoft_WindowsAzure_Exception
  1631.      */
  1632.     public function leaseBlob($containerName ''$blobName ''$leaseAction self::LEASE_ACQUIRE$leaseId null)
  1633.     {
  1634.         if ($containerName === ''{
  1635.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1636.         }
  1637.         if (!self::isValidContainerName($containerName)) {
  1638.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1639.         }
  1640.         if ($blobName === ''{
  1641.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1642.         }
  1643.         if ($containerName === '$root' && strpos($blobName'/'!== false{
  1644.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1645.         }
  1646.  
  1647.         // Additional headers?
  1648.         $headers array();
  1649.         $headers['x-ms-lease-action'strtolower($leaseAction);
  1650.         if (!is_null($leaseId)) {
  1651.             $headers['x-ms-lease-id'$leaseId;
  1652.         }
  1653.  
  1654.         // Resource name
  1655.         $resourceName self::createResourceName($containerName $blobName);
  1656.  
  1657.         // Perform request
  1658.         $response $this->_performRequest($resourceName'?comp=lease'Microsoft_Http_Client::PUT$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  1659.         if ($response->isSuccessful()) {
  1660.             return new Microsoft_WindowsAzure_Storage_LeaseInstance(
  1661.             $containerName,
  1662.             $blobName,
  1663.             $response->getHeader('x-ms-lease-id'),
  1664.             $response->getHeader('x-ms-lease-time'));
  1665.         else {
  1666.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  1667.         }
  1668.     }
  1669.  
  1670.     /**
  1671.      * List blobs
  1672.      *
  1673.      * @param string $containerName Container name
  1674.      * @param string $prefix     Optional. Filters the results to return only blobs whose name begins with the specified prefix.
  1675.      * @param string $delimiter  Optional. Delimiter, i.e. '/', for specifying folder hierarchy
  1676.      * @param int    $maxResults Optional. Specifies the maximum number of blobs to return per call to Azure storage. This does NOT affect list size returned by this function. (maximum: 5000)
  1677.      * @param string $marker     Optional string value that identifies the portion of the list to be returned with the next list operation.
  1678.      * @param string $include    Optional. Specifies that the response should include one or more of the following subsets: '', 'metadata', 'snapshots', 'uncommittedblobs'). Multiple values can be added separated with a comma (,)
  1679.      * @param int    $currentResultCount Current result count (internal use)
  1680.      * @return array 
  1681.      * @throws Microsoft_WindowsAzure_Exception
  1682.      */
  1683.     public function listBlobs($containerName ''$prefix ''$delimiter ''$maxResults null$marker null$include null$currentResultCount 0)
  1684.     {
  1685.         if ($containerName === ''{
  1686.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1687.         }
  1688.         if (!self::isValidContainerName($containerName)) {
  1689.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1690.         }
  1691.             
  1692.         // Build query string
  1693.         $queryString array('restype=container''comp=list');
  1694.         if (!is_null($prefix)) {
  1695.             $queryString['prefix=' $prefix;
  1696.         }
  1697.         if ($delimiter !== ''{
  1698.             $queryString['delimiter=' $delimiter;
  1699.         }
  1700.         if (!is_null($maxResults)) {
  1701.             $queryString['maxresults=' $maxResults;
  1702.         }
  1703.         if (!is_null($marker)) {
  1704.             $queryString['marker=' $marker;
  1705.         }
  1706.         if (!is_null($include)) {
  1707.             $queryString['include=' $include;
  1708.         }
  1709.         $queryString self::createQueryStringFromArray($queryString);
  1710.  
  1711.         // Perform request
  1712.         $response $this->_performRequest($containerName$queryStringMicrosoft_Http_Client::GETarray()falsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_LIST);
  1713.         if ($response->isSuccessful()) {
  1714.             // Return value
  1715.             $blobs array();
  1716.  
  1717.             // Blobs
  1718.             $xmlBlobs $this->_parseResponse($response)->Blobs->Blob;
  1719.             if (!is_null($xmlBlobs)) {
  1720.                 for ($i 0$i count($xmlBlobs)$i++{
  1721.                     $properties = (array)$xmlBlobs[$i]->Properties;
  1722.                         
  1723.                     $blobs[new Microsoft_WindowsAzure_Storage_BlobInstance(
  1724.                     $containerName,
  1725.                     (string)$xmlBlobs[$i]->Name,
  1726.                     (string)$xmlBlobs[$i]->Snapshot,
  1727.                     (string)$properties['Etag'],
  1728.                     (string)$properties['Last-Modified'],
  1729.                     (string)$xmlBlobs[$i]->Url,
  1730.                     (string)$properties['Content-Length'],
  1731.                     (string)$properties['Content-Type'],
  1732.                     (string)$properties['Content-Encoding'],
  1733.                     (string)$properties['Content-Language'],
  1734.                     (string)$properties['Cache-Control'],
  1735.                     (string)$properties['BlobType'],
  1736.                     (string)$properties['LeaseStatus'],
  1737.                     false,
  1738.                     $this->_parseMetadataElement($xmlBlobs[$i])
  1739.                     );
  1740.                 }
  1741.             }
  1742.                 
  1743.             // Blob prefixes (folders)
  1744.             $xmlBlobs $this->_parseResponse($response)->Blobs->BlobPrefix;
  1745.                 
  1746.             if (!is_null($xmlBlobs)) {
  1747.                 for ($i 0$i count($xmlBlobs)$i++{
  1748.                     $blobs[new Microsoft_WindowsAzure_Storage_BlobInstance(
  1749.                     $containerName,
  1750.                     (string)$xmlBlobs[$i]->Name,
  1751.                     null,
  1752.                         '',
  1753.                         '',
  1754.                         '',
  1755.                     0,
  1756.                         '',
  1757.                         '',
  1758.                         '',
  1759.                         '',
  1760.                         '',
  1761.                         '',
  1762.                     true,
  1763.                     $this->_parseMetadataElement($xmlBlobs[$i])
  1764.                     );
  1765.                 }
  1766.             }
  1767.                 
  1768.             // More blobs?
  1769.             $xmlMarker = (string)$this->_parseResponse($response)->NextMarker;
  1770.             $currentResultCount $currentResultCount count($blobs);
  1771.             if (!is_null($maxResults&& $currentResultCount $maxResults{
  1772.                 if (!is_null($xmlMarker&& $xmlMarker != ''{
  1773.                     $blobs array_merge($blobs$this->listBlobs($containerName$prefix$delimiter$maxResults$marker$include$currentResultCount));
  1774.                 }
  1775.             }
  1776.             if (!is_null($maxResults&& count($blobs$maxResults{
  1777.                 $blobs array_slice($blobs0$maxResults);
  1778.             }
  1779.                 
  1780.             return $blobs;
  1781.         else {
  1782.             throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response'Resource could not be accessed.'));
  1783.         }
  1784.     }
  1785.  
  1786.     /**
  1787.      * Generate shared access URL
  1788.      *
  1789.      * @param string $containerName  Container name
  1790.      * @param string $blobName       Blob name
  1791.      * @param string $resource       Signed resource - container (c) - blob (b)
  1792.      * @param string $permissions    Signed permissions - read (r), write (w), delete (d) and list (l)
  1793.      * @param string $start          The time at which the Shared Access Signature becomes valid.
  1794.      * @param string $expiry         The time at which the Shared Access Signature becomes invalid.
  1795.      * @param string $identifier     Signed identifier
  1796.      * @return string 
  1797.      */
  1798.     public function generateSharedAccessUrl($containerName ''$blobName ''$resource 'b'$permissions 'r'$start ''$expiry ''$identifier '')
  1799.     {
  1800.         if ($containerName === ''{
  1801.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1802.         }
  1803.         if (!self::isValidContainerName($containerName)) {
  1804.             throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1805.         }
  1806.  
  1807.         // Resource name
  1808.         $resourceName self::createResourceName($containerName $blobName);
  1809.  
  1810.         // Generate URL
  1811.         return $this->getBaseUrl('/' $resourceName '?' .
  1812.         $resourceName,
  1813.                 '',
  1814.         $resource,
  1815.         $permissions,
  1816.         $start,
  1817.         $expiry,
  1818.         $identifier);
  1819.     }
  1820.  
  1821.     /**
  1822.      * Register this object as stream wrapper client
  1823.      *
  1824.      * @param  string $name Protocol name
  1825.      * @return Microsoft_WindowsAzure_Storage_Blob 
  1826.      */
  1827.     public function registerAsClient($name)
  1828.     {
  1829.         self::$_wrapperClients[$name$this;
  1830.         return $this;
  1831.     }
  1832.  
  1833.     /**
  1834.      * Unregister this object as stream wrapper client
  1835.      *
  1836.      * @param  string $name Protocol name
  1837.      * @return Microsoft_WindowsAzure_Storage_Blob 
  1838.      */
  1839.     public function unregisterAsClient($name)
  1840.     {
  1841.         unset(self::$_wrapperClients[$name]);
  1842.         return $this;
  1843.     }
  1844.  
  1845.     /**
  1846.      * Get wrapper client for stream type
  1847.      *
  1848.      * @param  string $name Protocol name
  1849.      * @return Microsoft_WindowsAzure_Storage_Blob 
  1850.      */
  1851.     public static function getWrapperClient($name)
  1852.     {
  1853.         return self::$_wrapperClients[$name];
  1854.     }
  1855.  
  1856.     /**
  1857.      * Register this object as stream wrapper
  1858.      *
  1859.      * @param  string $name Protocol name
  1860.      */
  1861.     public function registerStreamWrapper($name 'azure')
  1862.     {
  1863.         /**
  1864.          * @see Microsoft_WindowsAzure_Storage_Blob_Stream
  1865.          */
  1866.         require_once 'Microsoft/WindowsAzure/Storage/Blob/Stream.php';
  1867.  
  1868.         stream_register_wrapper($name'Microsoft_WindowsAzure_Storage_Blob_Stream');
  1869.         $this->registerAsClient($name);
  1870.     }
  1871.  
  1872.     /**
  1873.      * Unregister this object as stream wrapper
  1874.      *
  1875.      * @param  string $name Protocol name
  1876.      * @return Microsoft_WindowsAzure_Storage_Blob 
  1877.      */
  1878.     public function unregisterStreamWrapper($name 'azure')
  1879.     {
  1880.         stream_wrapper_unregister($name);
  1881.         $this->unregisterAsClient($name);
  1882.     }
  1883.  
  1884.     /**
  1885.      * Create resource name
  1886.      *
  1887.      * @param string $containerName  Container name
  1888.      * @param string $blobName Blob name
  1889.      * @return string 
  1890.      */
  1891.     public static function createResourceName($containerName ''$blobName '')
  1892.     {
  1893.         // Resource name
  1894.         $resourceName $containerName '/' $blobName;
  1895.         if ($containerName === '' || $containerName === '$root'{
  1896.             $resourceName $blobName;
  1897.         }
  1898.         if ($blobName === ''{
  1899.             $resourceName $containerName;
  1900.         }
  1901.  
  1902.         return $resourceName;
  1903.     }
  1904.  
  1905.     /**
  1906.      * Is valid container name?
  1907.      *
  1908.      * @param string $containerName Container name
  1909.      * @return boolean 
  1910.      */
  1911.     public static function isValidContainerName($containerName '')
  1912.     {
  1913.         if ($containerName == '$root'{
  1914.             return true;
  1915.         }
  1916.  
  1917.         if (preg_match("/^[a-z0-9][a-z0-9-]*$/"$containerName=== 0{
  1918.             return false;
  1919.         }
  1920.  
  1921.         if (strpos($containerName'--'!== false{
  1922.             return false;
  1923.         }
  1924.  
  1925.         if (strtolower($containerName!= $containerName{
  1926.             return false;
  1927.         }
  1928.  
  1929.         if (strlen($containerName|| strlen($containerName63{
  1930.             return false;
  1931.         }
  1932.  
  1933.         if (substr($containerName-1== '-'{
  1934.             return false;
  1935.         }
  1936.  
  1937.         return true;
  1938.     }
  1939.  
  1940.     /**
  1941.      * Get error message from Microsoft_Http_Response
  1942.      *
  1943.      * @param Microsoft_Http_Response $response Repsonse
  1944.      * @param string $alternativeError Alternative error message
  1945.      * @return string 
  1946.      */
  1947.     protected function _getErrorMessage(Microsoft_Http_Response $response$alternativeError 'Unknown error.')
  1948.     {
  1949.         $response $this->_parseResponse($response);
  1950.         if ($response && $response->Message{
  1951.             return (string)$response->Message;
  1952.         else {
  1953.             return $alternativeError;
  1954.         }
  1955.     }
  1956.  
  1957.     /**
  1958.      * Generate block id
  1959.      *
  1960.      * @param int $part Block number
  1961.      * @return string Windows Azure Blob Storage block number
  1962.      */
  1963.     protected function _generateBlockId($part 0)
  1964.     {
  1965.         $returnValue $part;
  1966.         while (strlen($returnValue64{
  1967.             $returnValue '0' $returnValue;
  1968.         }
  1969.  
  1970.         return $returnValue;
  1971.     }
  1972. }

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