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, 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, RealDolmen (http://www.realdolmen.com)
  32.  * @license    http://todo     name_todo
  33.  * @version    $Id: Blob.php 33934 2009-11-03 07:21:49Z unknown $
  34.  */
  35.  
  36. /**
  37.  * @see Microsoft_WindowsAzure_SharedKeyCredentials
  38.  */
  39. require_once 'Microsoft/WindowsAzure/SharedKeyCredentials.php';
  40.  
  41. /**
  42.  * @see Microsoft_WindowsAzure_SharedAccessSignatureCredentials
  43.  */
  44. require_once 'Microsoft/WindowsAzure/SharedAccessSignatureCredentials.php';
  45.  
  46. /**
  47.  * @see Microsoft_WindowsAzure_RetryPolicy
  48.  */
  49. require_once 'Microsoft/WindowsAzure/RetryPolicy.php';
  50.  
  51. /**
  52.  * @see Microsoft_Http_Transport
  53.  */
  54. require_once 'Microsoft/Http/Transport.php';
  55.  
  56. /**
  57.  * @see Microsoft_Http_Response
  58.  */
  59. require_once 'Microsoft/Http/Response.php';
  60.  
  61. /**
  62.  * @see Microsoft_WindowsAzure_Storage
  63.  */
  64. require_once 'Microsoft/WindowsAzure/Storage.php';
  65.  
  66. /**
  67.  * @see Microsoft_WindowsAzure_Storage_BlobContainer
  68.  */
  69. require_once 'Microsoft/WindowsAzure/Storage/BlobContainer.php';
  70.  
  71. /**
  72.  * @see Microsoft_WindowsAzure_Storage_BlobInstance
  73.  */
  74. require_once 'Microsoft/WindowsAzure/Storage/BlobInstance.php';
  75.  
  76. /**
  77.  * @see Microsoft_WindowsAzure_Storage_SignedIdentifier
  78.  */
  79. require_once 'Microsoft/WindowsAzure/Storage/SignedIdentifier.php';
  80.  
  81. /**
  82.  * @see Microsoft_WindowsAzure_Exception
  83.  */
  84. require_once 'Microsoft/WindowsAzure/Exception.php';
  85.  
  86.  
  87. /**
  88.  * @category   Microsoft
  89.  * @package    Microsoft_WindowsAzure
  90.  * @subpackage Storage
  91.  * @copyright  Copyright (c) 2009, RealDolmen (http://www.realdolmen.com)
  92.  * @license    http://phpazure.codeplex.com/license
  93.  */
  94. {
  95.     /**
  96.      * ACL - Private access
  97.      */
  98.     const ACL_PRIVATE = false;
  99.     
  100.     /**
  101.      * ACL - Public access
  102.      */
  103.     const ACL_PUBLIC = true;
  104.     
  105.     /**
  106.      * Maximal blob size (in bytes)
  107.      */
  108.     const MAX_BLOB_SIZE = 67108864;
  109.  
  110.     /**
  111.      * Maximal blob transfer size (in bytes)
  112.      */
  113.     const MAX_BLOB_TRANSFER_SIZE = 4194304;
  114.     
  115.     /**
  116.      * Stream wrapper clients
  117.      *
  118.      * @var array 
  119.      */
  120.     protected static $_wrapperClients array();
  121.     
  122.     /**
  123.      * SharedAccessSignature credentials
  124.      * 
  125.      * @var Microsoft_WindowsAzure_SharedAccessSignatureCredentials 
  126.      */
  127.     private $_sharedAccessSignatureCredentials null;
  128.     
  129.     /**
  130.      * Creates a new Microsoft_WindowsAzure_Storage_Blob instance
  131.      *
  132.      * @param string $host Storage host name
  133.      * @param string $accountName Account name for Windows Azure
  134.      * @param string $accountKey Account key for Windows Azure
  135.      * @param boolean $usePathStyleUri Use path-style URI's
  136.      * @param Microsoft_WindowsAzure_RetryPolicy $retryPolicy Retry policy to use when making requests
  137.      */
  138.     public function __construct($host Microsoft_WindowsAzure_Storage::URL_DEV_BLOB$accountName Microsoft_WindowsAzure_SharedKeyCredentials::DEVSTORE_ACCOUNT$accountKey Microsoft_WindowsAzure_SharedKeyCredentials::DEVSTORE_KEY$usePathStyleUri falseMicrosoft_WindowsAzure_RetryPolicy $retryPolicy null)
  139.     {
  140.         parent::__construct($host$accountName$accountKey$usePathStyleUri$retryPolicy);
  141.         
  142.         // API version
  143.         $this->_apiVersion = '2009-07-17';
  144.         
  145.         // SharedAccessSignature credentials
  146.         $this->_sharedAccessSignatureCredentials new Microsoft_WindowsAzure_SharedAccessSignatureCredentials($accountName$accountKey$usePathStyleUri);
  147.     }
  148.     
  149.     /**
  150.      * Check if a blob exists
  151.      * 
  152.      * @param string $containerName Container name
  153.      * @param string $blobName      Blob name
  154.      * @return boolean 
  155.      */
  156.     public function blobExists($containerName ''$blobName '')
  157.     {
  158.         if ($containerName === '')
  159.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  160.         if (!self::isValidContainerName($containerName))
  161.             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.');
  162.         if ($blobName === '')
  163.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  164.         
  165.         // List blobs
  166.         $blobs $this->listBlobs($containerName$blobName''1);
  167.         foreach ($blobs as $blob)
  168.         {
  169.             if ($blob->Name == $blobName)
  170.                 return true;
  171.         }
  172.         
  173.         return false;
  174.     }
  175.     
  176.     /**
  177.      * Check if a container exists
  178.      * 
  179.      * @param string $containerName Container name
  180.      * @return boolean 
  181.      */
  182.     public function containerExists($containerName '')
  183.     {
  184.         if ($containerName === '')
  185.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  186.         if (!self::isValidContainerName($containerName))
  187.             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.');
  188.             
  189.         // List containers
  190.         $containers $this->listContainers($containerName1);
  191.         foreach ($containers as $container)
  192.         {
  193.             if ($container->Name == $containerName)
  194.                 return true;
  195.         }
  196.         
  197.         return false;
  198.     }
  199.     
  200.     /**
  201.      * Create container
  202.      *
  203.      * @param string $containerName Container name
  204.      * @param array  $metadata      Key/value pairs of meta data
  205.      * @return object Container properties
  206.      * @throws Microsoft_WindowsAzure_Exception
  207.      */
  208.     public function createContainer($containerName ''$metadata array())
  209.     {
  210.         if ($containerName === '')
  211.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  212.         if (!self::isValidContainerName($containerName))
  213.             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.');
  214.         if (!is_array($metadata))
  215.             throw new Microsoft_WindowsAzure_Exception('Meta data should be an array of key and value pairs.');
  216.             
  217.         // Create metadata headers
  218.         $headers array();
  219.         foreach ($metadata as $key => $value)
  220.         {
  221.             $headers["x-ms-meta-" strtolower($key)$value;
  222.         }
  223.         
  224.         // Perform request
  225.         $response $this->performRequest($containerName'?restype=container'Microsoft_Http_Transport::VERB_PUT$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials::PERMISSION_WRITE);            
  226.         if ($response->isSuccessful())
  227.         {
  228.             return new Microsoft_WindowsAzure_Storage_BlobContainer(
  229.                 $containerName,
  230.                 $response->getHeader('Etag'),
  231.                 $response->getHeader('Last-modified'),
  232.                 $metadata
  233.             );
  234.         }
  235.         else
  236.         {
  237.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  238.         }
  239.     }
  240.     
  241.     /**
  242.      * Get container ACL
  243.      *
  244.      * @param string $containerName Container name
  245.      * @param bool   $signedIdentifiers Display only public/private or display signed identifiers?
  246.      * @return bool Acl, to be compared with Microsoft_WindowsAzure_Storage_Blob::ACL_*
  247.      * @throws Microsoft_WindowsAzure_Exception
  248.      */
  249.     public function getContainerAcl($containerName ''$signedIdentifiers false)
  250.     {
  251.         if ($containerName === '')
  252.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  253.         if (!self::isValidContainerName($containerName))
  254.             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.');
  255.  
  256.         // Perform request
  257.         $response $this->performRequest($containerName'?restype=container&comp=acl'Microsoft_Http_Transport::VERB_GETarray()falsenullMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials::PERMISSION_READ);
  258.         if ($response->isSuccessful())
  259.         {
  260.             if ($signedIdentifiers == false)
  261.             {
  262.                 // Only public/private
  263.                 return $response->getHeader('x-ms-prop-publicaccess'== 'True';
  264.             }
  265.             else
  266.             {
  267.                    // Parse result
  268.                 $result $this->parseResponse($response);
  269.                 if (!$result)
  270.                     return array();
  271.     
  272.                 $entries null;
  273.                 if ($result->SignedIdentifier)
  274.                 {
  275.                     if (count($result->SignedIdentifier1)
  276.                     {
  277.                         $entries $result->SignedIdentifier;
  278.                     }
  279.                     else
  280.                     {
  281.                         $entries array($result->SignedIdentifier);
  282.                     }
  283.                 }
  284.                 
  285.                 // Return value
  286.                 $returnValue array();
  287.                 foreach ($entries as $entry)
  288.                 {
  289.                     $returnValue[new Microsoft_WindowsAzure_Storage_SignedIdentifier(
  290.                         $entry->Id,
  291.                         $entry->AccessPolicy $entry->AccessPolicy->Start $entry->AccessPolicy->Start '' '',
  292.                         $entry->AccessPolicy $entry->AccessPolicy->Expiry $entry->AccessPolicy->Expiry '' '',
  293.                         $entry->AccessPolicy $entry->AccessPolicy->Permission $entry->AccessPolicy->Permission '' ''
  294.                     );
  295.                 }
  296.                 
  297.                 // Return
  298.                 return $returnValue;
  299.             }               
  300.         }
  301.         else
  302.         {
  303.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  304.         }
  305.     }
  306.     
  307.     /**
  308.      * Set container ACL
  309.      *
  310.      * @param string $containerName Container name
  311.      * @param bool $acl Microsoft_WindowsAzure_Storage_Blob::ACL_*
  312.      * @param array $signedIdentifiers Signed identifiers
  313.      * @throws Microsoft_WindowsAzure_Exception
  314.      */
  315.     public function setContainerAcl($containerName ''$acl self::ACL_PRIVATE$signedIdentifiers array())
  316.     {
  317.         if ($containerName === '')
  318.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  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.         // Policies
  323.         $policies null;
  324.         if (is_array($signedIdentifiers&& count($signedIdentifiers0)
  325.         {
  326.             $policies  '';
  327.             $policies .= '<?xml version="1.0" encoding="utf-8"?>' "\r\n";
  328.             $policies .= '<SignedIdentifiers>' "\r\n";
  329.             foreach ($signedIdentifiers as $signedIdentifier)
  330.             {
  331.                 $policies .= '  <SignedIdentifier>' "\r\n";
  332.                 $policies .= '    <Id>' $signedIdentifier->Id '</Id>' "\r\n";
  333.                 $policies .= '    <AccessPolicy>' "\r\n";
  334.                 if ($signedIdentifier->Start != '')
  335.                     $policies .= '      <Start>' $signedIdentifier->Start '</Start>' "\r\n";
  336.                 if ($signedIdentifier->Expiry != '')
  337.                     $policies .= '      <Expiry>' $signedIdentifier->Expiry '</Expiry>' "\r\n";
  338.                 if ($signedIdentifier->Permissions != '')
  339.                     $policies .= '      <Permission>' $signedIdentifier->Permissions '</Permission>' "\r\n";
  340.                 $policies .= '    </AccessPolicy>' "\r\n";
  341.                 $policies .= '  </SignedIdentifier>' "\r\n";
  342.             }
  343.             $policies .= '</SignedIdentifiers>' "\r\n";
  344.         }
  345.         
  346.         // Perform request
  347.         $response $this->performRequest($containerName'?restype=container&comp=acl'Microsoft_Http_Transport::VERB_PUTarray('x-ms-prop-publicaccess' => $acl)false$policiesMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials::PERMISSION_WRITE);
  348.         if (!$response->isSuccessful())
  349.         {
  350.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  351.         }
  352.     }
  353.     
  354.     /**
  355.      * Get container
  356.      * 
  357.      * @param string $containerName  Container name
  358.      * @return Microsoft_WindowsAzure_Storage_BlobContainer 
  359.      * @throws Microsoft_WindowsAzure_Exception
  360.      */
  361.     public function getContainer($containerName '')
  362.     {
  363.         if ($containerName === '')
  364.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  365.         if (!self::isValidContainerName($containerName))
  366.             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.');
  367.             
  368.         // Perform request
  369.         $response $this->performRequest($containerName'?restype=container'Microsoft_Http_Transport::VERB_GETarray()falsenullMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials::PERMISSION_READ);    
  370.         if ($response->isSuccessful())
  371.         {
  372.             // Parse metadata
  373.             $metadata array();
  374.             foreach ($response->getHeaders(as $key => $value)
  375.             {
  376.                 if (substr(strtolower($key)010== "x-ms-meta-")
  377.                 {
  378.                     $metadata[str_replace("x-ms-meta-"''strtolower($key))$value;
  379.                 }
  380.             }
  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.         }
  390.         else
  391.         {
  392.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  393.         }
  394.     }
  395.     
  396.     /**
  397.      * Get container metadata
  398.      * 
  399.      * @param string $containerName  Container name
  400.      * @return array Key/value pairs of meta data
  401.      * @throws Microsoft_WindowsAzure_Exception
  402.      */
  403.     public function getContainerMetadata($containerName '')
  404.     {
  405.         if ($containerName === '')
  406.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  407.         if (!self::isValidContainerName($containerName))
  408.             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.');
  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.         if (!self::isValidContainerName($containerName))
  428.             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.');
  429.         if (!is_array($metadata))
  430.             throw new Microsoft_WindowsAzure_Exception('Meta data should be an array of key and value pairs.');
  431.         if (count($metadata== 0)
  432.             return;
  433.             
  434.         // Create metadata headers
  435.         $headers array();
  436.         foreach ($metadata as $key => $value)
  437.         {
  438.             $headers["x-ms-meta-" strtolower($key)$value;
  439.         }
  440.         
  441.         // Additional headers?
  442.         foreach ($additionalHeaders as $key => $value)
  443.         {
  444.             $headers[$key$value;
  445.         }
  446.         
  447.         // Perform request
  448.         $response $this->performRequest($containerName'?restype=container&comp=metadata'Microsoft_Http_Transport::VERB_PUT$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials::PERMISSION_WRITE);
  449.         if (!$response->isSuccessful())
  450.         {
  451.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  452.         }
  453.     }
  454.     
  455.     /**
  456.      * Delete container
  457.      *
  458.      * @param string $containerName      Container name
  459.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  460.      * @throws Microsoft_WindowsAzure_Exception
  461.      */
  462.     public function deleteContainer($containerName ''$additionalHeaders array())
  463.     {
  464.         if ($containerName === '')
  465.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  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.         // Additional headers?
  470.         $headers array();
  471.         foreach ($additionalHeaders as $key => $value)
  472.         {
  473.             $headers[$key$value;
  474.         }
  475.         
  476.         // Perform request
  477.         $response $this->performRequest($containerName'?restype=container'Microsoft_Http_Transport::VERB_DELETE$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials::PERMISSION_WRITE);
  478.         if (!$response->isSuccessful())
  479.         {
  480.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  481.         }
  482.     }
  483.     
  484.     /**
  485.      * List containers
  486.      *
  487.      * @param string $prefix     Optional. Filters the results to return only containers whose name begins with the specified prefix.
  488.      * @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)
  489.      * @param string $marker     Optional string value that identifies the portion of the list to be returned with the next list operation.
  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$currentResultCount 0)
  495.     {
  496.         // Build query string
  497.         $queryString '?comp=list';
  498.         if (!is_null($prefix))
  499.             $queryString .= '&prefix=' $prefix;
  500.         if (!is_null($maxResults))
  501.             $queryString .= '&maxresults=' $maxResults;
  502.         if (!is_null($marker))
  503.             $queryString .= '&marker=' $marker;
  504.             
  505.         // Perform request
  506.         $response $this->performRequest(''$queryStringMicrosoft_Http_Transport::VERB_GETarray()falsenullMicrosoft_WindowsAzure_Storage::RESOURCE_CONTAINERMicrosoft_WindowsAzure_Credentials::PERMISSION_LIST);    
  507.         if ($response->isSuccessful())
  508.         {
  509.             $xmlContainers $this->parseResponse($response)->Containers->Container;
  510.             $xmlMarker = (string)$this->parseResponse($response)->NextMarker;
  511.  
  512.             $containers array();
  513.             if (!is_null($xmlContainers))
  514.             {
  515.                 for ($i 0$i count($xmlContainers)$i++)
  516.                 {
  517.                     $containers[new Microsoft_WindowsAzure_Storage_BlobContainer(
  518.                         (string)$xmlContainers[$i]->Name,
  519.                         (string)$xmlContainers[$i]->Etag,
  520.                         (string)$xmlContainers[$i]->LastModified
  521.                     );
  522.                 }
  523.             }
  524.             $currentResultCount $currentResultCount count($containers);
  525.             if (!is_null($maxResults&& $currentResultCount $maxResults)
  526.             {
  527.                 if (!is_null($xmlMarker&& $xmlMarker != '')
  528.                 {
  529.                     $containers array_merge($containers$this->listContainers($prefix$maxResults$xmlMarker$currentResultCount));
  530.                 }
  531.             }
  532.             if (!is_null($maxResults&& count($containers$maxResults)
  533.                 $containers array_slice($containers0$maxResults);
  534.                 
  535.             return $containers;
  536.         }
  537.         else 
  538.         {
  539.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  540.         }
  541.     }
  542.     
  543.     /**
  544.      * Put blob
  545.      *
  546.      * @param string $containerName      Container name
  547.      * @param string $blobName           Blob name
  548.      * @param string $localFileName      Local file name to be uploaded
  549.      * @param array  $metadata           Key/value pairs of meta data
  550.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  551.      * @return object Partial blob properties
  552.      * @throws Microsoft_WindowsAzure_Exception
  553.      */
  554.     public function putBlob($containerName ''$blobName ''$localFileName ''$metadata array()$additionalHeaders array())
  555.     {
  556.         if ($containerName === '')
  557.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  558.         if (!self::isValidContainerName($containerName))
  559.             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.');
  560.         if ($blobName === '')
  561.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  562.         if ($localFileName === '')
  563.             throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
  564.         if (!file_exists($localFileName))
  565.             throw new Microsoft_WindowsAzure_Exception('Local file not found.');
  566.         if ($containerName === '$root' && strpos($blobName'/'!== false)
  567.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  568.             
  569.         // Check file size
  570.         if (filesize($localFileName>= self::MAX_BLOB_SIZE)
  571.             return $this->putLargeBlob($containerName$blobName$localFileName$metadata);
  572.  
  573.         // Create metadata headers
  574.         $headers array();
  575.         foreach ($metadata as $key => $value)
  576.         {
  577.             $headers["x-ms-meta-" strtolower($key)$value;
  578.         }
  579.         
  580.         // Additional headers?
  581.         foreach ($additionalHeaders as $key => $value)
  582.         {
  583.             $headers[$key$value;
  584.         }
  585.         
  586.         // File contents
  587.         $fileContents file_get_contents($localFileName);
  588.         
  589.         // Resource name
  590.         $resourceName self::createResourceName($containerName $blobName);
  591.         
  592.         // Perform request
  593.         $response $this->performRequest($resourceName''Microsoft_Http_Transport::VERB_PUT$headersfalse$fileContentsMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials::PERMISSION_WRITE);    
  594.         if ($response->isSuccessful())
  595.         {
  596.             return new Microsoft_WindowsAzure_Storage_BlobInstance(
  597.                 $containerName,
  598.                 $blobName,
  599.                 $response->getHeader('Etag'),
  600.                 $response->getHeader('Last-modified'),
  601.                 $this->getBaseUrl('/' $containerName '/' $blobName,
  602.                 strlen($fileContents),
  603.                 '',
  604.                 '',
  605.                 '',
  606.                 false,
  607.                 $metadata
  608.             );
  609.         }
  610.         else
  611.         {
  612.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  613.         }
  614.     }
  615.     
  616.     /**
  617.      * Put large blob (> 64 MB)
  618.      *
  619.      * @param string $containerName Container name
  620.      * @param string $blobName Blob name
  621.      * @param string $localFileName Local file name to be uploaded
  622.      * @param array  $metadata      Key/value pairs of meta data
  623.      * @return object Partial blob properties
  624.      * @throws Microsoft_WindowsAzure_Exception
  625.      */
  626.     public function putLargeBlob($containerName ''$blobName ''$localFileName ''$metadata array())
  627.     {
  628.         if ($containerName === '')
  629.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  630.         if (!self::isValidContainerName($containerName))
  631.             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.');
  632.         if ($blobName === '')
  633.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  634.         if ($localFileName === '')
  635.             throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
  636.         if (!file_exists($localFileName))
  637.             throw new Microsoft_WindowsAzure_Exception('Local file not found.');
  638.         if ($containerName === '$root' && strpos($blobName'/'!== false)
  639.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  640.             
  641.         // Check file size
  642.         if (filesize($localFileNameself::MAX_BLOB_SIZE)
  643.             return $this->putBlob($containerName$blobName$localFileName$metadata);
  644.             
  645.         // Determine number of parts
  646.         $numberOfParts ceilfilesize($localFileNameself::MAX_BLOB_TRANSFER_SIZE );
  647.         
  648.         // Generate block id's
  649.         $blockIdentifiers array();
  650.         for ($i 0$i $numberOfParts$i++)
  651.         {
  652.             $blockIdentifiers[$this->generateBlockId($i);
  653.         }
  654.         
  655.         // Open file
  656.         $fp fopen($localFileName'r');
  657.         if ($fp === false)
  658.             throw new Microsoft_WindowsAzure_Exception('Could not open local file.');
  659.             
  660.         // Upload parts
  661.         for ($i 0$i $numberOfParts$i++)
  662.         {
  663.             // Seek position in file
  664.             fseek($fp$i self::MAX_BLOB_TRANSFER_SIZE);
  665.             
  666.             // Read contents
  667.             $fileContents fread($fpself::MAX_BLOB_TRANSFER_SIZE);
  668.             
  669.             // Put block
  670.             $this->putBlock($containerName$blobName$blockIdentifiers[$i]$fileContents);
  671.             
  672.             // Dispose file contents
  673.             $fileContents null;
  674.             unset($fileContents);
  675.         }
  676.         
  677.         // Close file
  678.         fclose($fp);
  679.         
  680.         // Put block list
  681.         $this->putBlockList($containerName$blobName$blockIdentifiers$metadata);
  682.         
  683.         // Return information of the blob
  684.         return $this->getBlobInstance($containerName$blobName);
  685.     }            
  686.             
  687.     /**
  688.      * Put large blob block
  689.      *
  690.      * @param string $containerName Container name
  691.      * @param string $blobName      Blob name
  692.      * @param string $identifier    Block ID
  693.      * @param array  $contents      Contents of the block
  694.      * @throws Microsoft_WindowsAzure_Exception
  695.      */
  696.     public function putBlock($containerName ''$blobName ''$identifier ''$contents '')
  697.     {
  698.         if ($containerName === '')
  699.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  700.         if (!self::isValidContainerName($containerName))
  701.             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.');
  702.         if ($identifier === '')
  703.             throw new Microsoft_WindowsAzure_Exception('Block identifier is not specified.');
  704.         if (strlen($contentsself::MAX_BLOB_TRANSFER_SIZE)
  705.             throw new Microsoft_WindowsAzure_Exception('Block size is too big.');
  706.         if ($containerName === '$root' && strpos($blobName'/'!== false)
  707.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  708.             
  709.         // Resource name
  710.         $resourceName self::createResourceName($containerName $blobName);
  711.         
  712.         // Upload
  713.         $response $this->performRequest($resourceName'?comp=block&blockid=' base64_encode($identifier)Microsoft_Http_Transport::VERB_PUTnullfalse$contentsMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials::PERMISSION_WRITE);
  714.         if (!$response->isSuccessful())
  715.         {
  716.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  717.         }
  718.     }
  719.     
  720.     /**
  721.      * Put block list
  722.      *
  723.      * @param string $containerName      Container name
  724.      * @param string $blobName           Blob name
  725.      * @param array $blockList           Array of block identifiers
  726.      * @param array  $metadata           Key/value pairs of meta data
  727.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  728.      * @throws Microsoft_WindowsAzure_Exception
  729.      */
  730.     public function putBlockList($containerName ''$blobName ''$blockList array()$metadata array()$additionalHeaders array())
  731.     {
  732.         if ($containerName === '')
  733.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  734.         if (!self::isValidContainerName($containerName))
  735.             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.');
  736.         if ($blobName === '')
  737.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  738.         if (count($blockList== 0)
  739.             throw new Microsoft_WindowsAzure_Exception('Block list does not contain any elements.');
  740.         if ($containerName === '$root' && strpos($blobName'/'!== false)
  741.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  742.         
  743.         // Generate block list
  744.         $blocks '';
  745.         foreach ($blockList as $block)
  746.         {
  747.             $blocks .= '  <Latest>' base64_encode($block'</Latest>' "\n";
  748.         }
  749.         
  750.         // Generate block list request
  751.         $fileContents utf8_encode(implode("\n"array(
  752.             '<?xml version="1.0" encoding="utf-8"?>',
  753.             '<BlockList>',
  754.             $blocks,
  755.             '</BlockList>'
  756.         )));
  757.         
  758.         // Create metadata headers
  759.         $headers array();
  760.         foreach ($metadata as $key => $value)
  761.         {
  762.             $headers["x-ms-meta-" strtolower($key)$value;
  763.         }
  764.         
  765.         // Additional headers?
  766.         foreach ($additionalHeaders as $key => $value)
  767.         {
  768.             $headers[$key$value;
  769.         }
  770.  
  771.         // Resource name
  772.         $resourceName self::createResourceName($containerName $blobName);
  773.         
  774.         // Perform request
  775.         $response $this->performRequest($resourceName'?comp=blocklist'Microsoft_Http_Transport::VERB_PUT$headersfalse$fileContentsMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials::PERMISSION_WRITE);
  776.         if (!$response->isSuccessful())
  777.         {
  778.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  779.         }
  780.     }
  781.     
  782.     /**
  783.      * Get block list
  784.      *
  785.      * @param string $containerName Container name
  786.      * @param string $blobName      Blob name
  787.      * @param integer $type         Type of block list to retrieve. 0 = all, 1 = committed, 2 = uncommitted
  788.      * @return array 
  789.      * @throws Microsoft_WindowsAzure_Exception
  790.      */
  791.     public function getBlockList($containerName ''$blobName ''$type 0)
  792.     {
  793.         if ($containerName === '')
  794.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  795.         if (!self::isValidContainerName($containerName))
  796.             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.');
  797.         if ($blobName === '')
  798.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  799.         if ($type || $type 2)
  800.             throw new Microsoft_WindowsAzure_Exception('Invalid type of block list to retrieve.');
  801.             
  802.         // Set $blockListType
  803.         $blockListType 'all';
  804.         if ($type == 1)
  805.             $blockListType 'committed';
  806.         if ($type == 2)
  807.             $blockListType 'uncommitted';
  808.             
  809.         // Resource name
  810.         $resourceName self::createResourceName($containerName $blobName);
  811.             
  812.         // Perform request
  813.         $response $this->performRequest($resourceName'?comp=blocklist&blocklisttype=' $blockListTypeMicrosoft_Http_Transport::VERB_GETarray()falsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials::PERMISSION_READ);
  814.         if ($response->isSuccessful())
  815.         {
  816.             // Parse response
  817.             $blockList $this->parseResponse($response);
  818.             
  819.             // Create return value
  820.             $returnValue array();
  821.             if ($blockList->CommittedBlocks)
  822.             {
  823.                 foreach ($blockList->CommittedBlocks->Block as $block)
  824.                 {
  825.                     $returnValue['CommittedBlocks'][= (object)array(
  826.                         'Name' => (string)$block->Name,
  827.                         'Size' => (string)$block->Size
  828.                     );
  829.                 }
  830.             }
  831.             if ($blockList->UncommittedBlocks)
  832.             {
  833.                 foreach ($blockList->UncommittedBlocks->Block as $block)
  834.                 {
  835.                     $returnValue['UncommittedBlocks'][= (object)array(
  836.                         'Name' => (string)$block->Name,
  837.                         'Size' => (string)$block->Size
  838.                     );
  839.                 }
  840.             }
  841.             
  842.             return $returnValue;
  843.         }
  844.         else
  845.         {
  846.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  847.         }
  848.     }
  849.             
  850.     /**
  851.      * Copy blob
  852.      *
  853.      * @param string $sourceContainerName       Source container name
  854.      * @param string $sourceBlobName            Source blob name
  855.      * @param string $destinationContainerName  Destination container name
  856.      * @param string $destinationBlobName       Destination blob name
  857.      * @param array  $metadata                  Key/value pairs of meta data
  858.      * @param array  $additionalHeaders         Additional headers. See http://msdn.microsoft.com/en-us/library/dd894037.aspx for more information.
  859.      * @return object Partial blob properties
  860.      * @throws Microsoft_WindowsAzure_Exception
  861.      */
  862.     public function copyBlob($sourceContainerName ''$sourceBlobName ''$destinationContainerName ''$destinationBlobName ''$metadata array()$additionalHeaders array())
  863.     {
  864.         if ($sourceContainerName === '')
  865.             throw new Microsoft_WindowsAzure_Exception('Source container name is not specified.');
  866.         if (!self::isValidContainerName($sourceContainerName))
  867.             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.');
  868.         if ($sourceBlobName === '')
  869.             throw new Microsoft_WindowsAzure_Exception('Source blob name is not specified.');
  870.         if ($destinationContainerName === '')
  871.             throw new Microsoft_WindowsAzure_Exception('Destination container name is not specified.');
  872.         if (!self::isValidContainerName($destinationContainerName))
  873.             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.');
  874.         if ($destinationBlobName === '')
  875.             throw new Microsoft_WindowsAzure_Exception('Destination blob name is not specified.');
  876.         if ($sourceContainerName === '$root' && strpos($sourceBlobName'/'!== false)
  877.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  878.         if ($destinationContainerName === '$root' && strpos($destinationBlobName'/'!== false)
  879.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  880.  
  881.         // Create metadata headers
  882.         $headers array();
  883.         foreach ($metadata as $key => $value)
  884.         {
  885.             $headers["x-ms-meta-" strtolower($key)$value;
  886.         }
  887.         
  888.         // Additional headers?
  889.         foreach ($additionalHeaders as $key => $value)
  890.         {
  891.             $headers[$key$value;
  892.         }
  893.         
  894.         // Resource names
  895.         $sourceResourceName self::createResourceName($sourceContainerName$sourceBlobName);
  896.         $destinationResourceName self::createResourceName($destinationContainerName$destinationBlobName);
  897.         
  898.         // Set source blob
  899.         $headers["x-ms-copy-source"'/' $this->_accountName . '/' $sourceResourceName;
  900.  
  901.         // Perform request
  902.         $response $this->performRequest($destinationResourceName''Microsoft_Http_Transport::VERB_PUT$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials::PERMISSION_WRITE);
  903.         if ($response->isSuccessful())
  904.         {
  905.             return new Microsoft_WindowsAzure_Storage_BlobInstance(
  906.                 $destinationContainerName,
  907.                 $destinationBlobName,
  908.                 $response->getHeader('Etag'),
  909.                 $response->getHeader('Last-modified'),
  910.                 $this->getBaseUrl('/' $destinationContainerName '/' $destinationBlobName,
  911.                 0,
  912.                 '',
  913.                 '',
  914.                 '',
  915.                 false,
  916.                 $metadata
  917.             );
  918.         }
  919.         else
  920.         {
  921.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  922.         }
  923.     }
  924.     
  925.     /**
  926.      * Get blob
  927.      *
  928.      * @param string $containerName      Container name
  929.      * @param string $blobName           Blob name
  930.      * @param string $localFileName      Local file name to store downloaded blob
  931.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  932.      * @throws Microsoft_WindowsAzure_Exception
  933.      */
  934.     public function getBlob($containerName ''$blobName ''$localFileName ''$additionalHeaders array())
  935.     {
  936.         if ($containerName === '')
  937.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  938.         if (!self::isValidContainerName($containerName))
  939.             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.');
  940.         if ($blobName === '')
  941.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  942.         if ($localFileName === '')
  943.             throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
  944.             
  945.         // Additional headers?
  946.         $headers array();
  947.         foreach ($additionalHeaders as $key => $value)
  948.         {
  949.             $headers[$key$value;
  950.         }
  951.         
  952.         // Resource name
  953.         $resourceName self::createResourceName($containerName $blobName);
  954.         
  955.         // Perform request
  956.         $response $this->performRequest($resourceName''Microsoft_Http_Transport::VERB_GET$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials::PERMISSION_READ);
  957.         if ($response->isSuccessful())
  958.             file_put_contents($localFileName$response->getBody());
  959.         else
  960.         {
  961.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  962.         }
  963.     }
  964.     
  965.     /**
  966.      * Get container
  967.      * 
  968.      * @param string $containerName      Container name
  969.      * @param string $blobName           Blob name
  970.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  971.      * @return Microsoft_WindowsAzure_Storage_BlobInstance 
  972.      * @throws Microsoft_WindowsAzure_Exception
  973.      */
  974.     public function getBlobInstance($containerName ''$blobName ''$additionalHeaders array())
  975.     {
  976.         if ($containerName === '')
  977.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  978.         if (!self::isValidContainerName($containerName))
  979.             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.');
  980.         if ($blobName === '')
  981.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  982.         if ($containerName === '$root' && strpos($blobName'/'!== false)
  983.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  984.             
  985.         // Additional headers?
  986.         $headers array();
  987.         foreach ($additionalHeaders as $key => $value)
  988.         {
  989.             $headers[$key$value;
  990.         }
  991.         
  992.         // Resource name
  993.         $resourceName self::createResourceName($containerName $blobName);
  994.             
  995.         // Perform request
  996.         $response $this->performRequest($resourceName''Microsoft_Http_Transport::VERB_HEAD$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials::PERMISSION_READ);
  997.         if ($response->isSuccessful())
  998.         {
  999.             // Parse metadata
  1000.             $metadata array();
  1001.             foreach ($response->getHeaders(as $key => $value)
  1002.             {
  1003.                 if (substr(strtolower($key)010== "x-ms-meta-")
  1004.                 {
  1005.                     $metadata[str_replace("x-ms-meta-"''strtolower($key))$value;
  1006.                 }
  1007.             }
  1008.  
  1009.             // Return blob
  1010.             return new Microsoft_WindowsAzure_Storage_BlobInstance(
  1011.                 $containerName,
  1012.                 $blobName,
  1013.                 $response->getHeader('Etag'),
  1014.                 $response->getHeader('Last-modified'),
  1015.                 $this->getBaseUrl('/' $containerName '/' $blobName,
  1016.                 $response->getHeader('Content-Length'),
  1017.                 $response->getHeader('Content-Type'),
  1018.                 $response->getHeader('Content-Encoding'),
  1019.                 $response->getHeader('Content-Language'),
  1020.                 false,
  1021.                 $metadata
  1022.             );
  1023.         }
  1024.         else
  1025.         {
  1026.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  1027.         }
  1028.     }
  1029.     
  1030.     /**
  1031.      * Get blob metadata
  1032.      * 
  1033.      * @param string $containerName  Container name
  1034.      * @param string $blobName Blob name
  1035.      * @return array Key/value pairs of meta data
  1036.      * @throws Microsoft_WindowsAzure_Exception
  1037.      */
  1038.     public function getBlobMetadata($containerName ''$blobName '')
  1039.     {
  1040.         if ($containerName === '')
  1041.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1042.         if (!self::isValidContainerName($containerName))
  1043.             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.');
  1044.         if ($blobName === '')
  1045.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1046.         if ($containerName === '$root' && strpos($blobName'/'!== false)
  1047.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1048.         
  1049.         return $this->getBlobInstance($containerName$blobName)->Metadata;
  1050.     }
  1051.     
  1052.     /**
  1053.      * Set blob metadata
  1054.      * 
  1055.      * 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.
  1056.      *
  1057.      * @param string $containerName      Container name
  1058.      * @param string $blobName           Blob name
  1059.      * @param array  $metadata           Key/value pairs of meta data
  1060.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  1061.      * @throws Microsoft_WindowsAzure_Exception
  1062.      */
  1063.     public function setBlobMetadata($containerName ''$blobName ''$metadata array()$additionalHeaders array())
  1064.     {
  1065.         if ($containerName === '')
  1066.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1067.         if (!self::isValidContainerName($containerName))
  1068.             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.');
  1069.         if ($blobName === '')
  1070.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1071.         if ($containerName === '$root' && strpos($blobName'/'!== false)
  1072.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1073.         if (count($metadata== 0)
  1074.             return;
  1075.             
  1076.         // Create metadata headers
  1077.         $headers array();
  1078.         foreach ($metadata as $key => $value)
  1079.         {
  1080.             $headers["x-ms-meta-" strtolower($key)$value;
  1081.         }
  1082.         
  1083.         // Additional headers?
  1084.         foreach ($additionalHeaders as $key => $value)
  1085.         {
  1086.             $headers[$key$value;
  1087.         }
  1088.         
  1089.         // Perform request
  1090.         $response $this->performRequest($containerName '/' $blobName'?comp=metadata'Microsoft_Http_Transport::VERB_PUT$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials::PERMISSION_WRITE);
  1091.         if (!$response->isSuccessful())
  1092.         {
  1093.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  1094.         }
  1095.     }
  1096.     
  1097.     /**
  1098.      * Delete blob
  1099.      *
  1100.      * @param string $containerName      Container name
  1101.      * @param string $blobName           Blob name
  1102.      * @param array  $additionalHeaders  Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  1103.      * @throws Microsoft_WindowsAzure_Exception
  1104.      */
  1105.     public function deleteBlob($containerName ''$blobName ''$additionalHeaders array())
  1106.     {
  1107.         if ($containerName === '')
  1108.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1109.         if (!self::isValidContainerName($containerName))
  1110.             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.');
  1111.         if ($blobName === '')
  1112.             throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1113.         if ($containerName === '$root' && strpos($blobName'/'!== false)
  1114.             throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1115.             
  1116.         // Additional headers?
  1117.         $headers array();
  1118.         foreach ($additionalHeaders as $key => $value)
  1119.         {
  1120.             $headers[$key$value;
  1121.         }
  1122.         
  1123.         // Resource name
  1124.         $resourceName self::createResourceName($containerName $blobName);
  1125.         
  1126.         // Perform request
  1127.         $response $this->performRequest($resourceName''Microsoft_Http_Transport::VERB_DELETE$headersfalsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials::PERMISSION_WRITE);
  1128.         if (!$response->isSuccessful())
  1129.         {
  1130.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  1131.         }
  1132.     }
  1133.     
  1134.     /**
  1135.      * List blobs
  1136.      *
  1137.      * @param string $containerName Container name
  1138.      * @param string $prefix     Optional. Filters the results to return only blobs whose name begins with the specified prefix.
  1139.      * @param string $delimiter  Optional. Delimiter, i.e. '/', for specifying folder hierarchy
  1140.      * @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)
  1141.      * @param string $marker     Optional string value that identifies the portion of the list to be returned with the next list operation.
  1142.      * @param int    $currentResultCount Current result count (internal use)
  1143.      * @return array 
  1144.      * @throws Microsoft_WindowsAzure_Exception
  1145.      */
  1146.     public function listBlobs($containerName ''$prefix ''$delimiter ''$maxResults null$marker null$currentResultCount 0)
  1147.     {
  1148.         if ($containerName === '')
  1149.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1150.         if (!self::isValidContainerName($containerName))
  1151.             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.');
  1152.             
  1153.         // Build query string
  1154.         $queryString '?restype=container&comp=list';
  1155.         if (!is_null($prefix))
  1156.             $queryString .= '&prefix=' $prefix;
  1157.         if ($delimiter !== '')
  1158.             $queryString .= '&delimiter=' $delimiter;
  1159.         if (!is_null($maxResults))
  1160.             $queryString .= '&maxresults=' $maxResults;
  1161.         if (!is_null($marker))
  1162.             $queryString .= '&marker=' $marker;
  1163.  
  1164.         // Perform request
  1165.         $response $this->performRequest($containerName$queryStringMicrosoft_Http_Transport::VERB_GETarray()falsenullMicrosoft_WindowsAzure_Storage::RESOURCE_BLOBMicrosoft_WindowsAzure_Credentials::PERMISSION_LIST);
  1166.         if ($response->isSuccessful())
  1167.         {
  1168.             // Return value
  1169.             $blobs array();
  1170.             
  1171.             // Blobs
  1172.             $xmlBlobs $this->parseResponse($response)->Blobs->Blob;
  1173.             if (!is_null($xmlBlobs))
  1174.             {
  1175.                 for ($i 0$i count($xmlBlobs)$i++)
  1176.                 {
  1177.                     $blobs[new Microsoft_WindowsAzure_Storage_BlobInstance(
  1178.                         $containerName,
  1179.                         (string)$xmlBlobs[$i]->Name,
  1180.                         (string)$xmlBlobs[$i]->Etag,
  1181.                         (string)$xmlBlobs[$i]->LastModified,
  1182.                         (string)$xmlBlobs[$i]->Url,
  1183.                         (string)$xmlBlobs[$i]->Size,
  1184.                         (string)$xmlBlobs[$i]->ContentType,
  1185.                         (string)$xmlBlobs[$i]->ContentEncoding,
  1186.                         (string)$xmlBlobs[$i]->ContentLanguage,
  1187.                         false
  1188.                     );
  1189.                 }
  1190.             }
  1191.             
  1192.             // Blob prefixes (folders)
  1193.             $xmlBlobs $this->parseResponse($response)->Blobs->BlobPrefix;
  1194.             
  1195.             if (!is_null($xmlBlobs))
  1196.             {
  1197.                 for ($i 0$i count($xmlBlobs)$i++)
  1198.                 {
  1199.                     $blobs[new Microsoft_WindowsAzure_Storage_BlobInstance(
  1200.                         $containerName,
  1201.                         (string)$xmlBlobs[$i]->Name,
  1202.                         '',
  1203.                         '',
  1204.                         '',
  1205.                         0,
  1206.                         '',
  1207.                         '',
  1208.                         '',
  1209.                         true
  1210.                     );
  1211.                 }
  1212.             }
  1213.             
  1214.             // More blobs?
  1215.             $xmlMarker = (string)$this->parseResponse($response)->NextMarker;
  1216.             $currentResultCount $currentResultCount count($blobs);
  1217.             if (!is_null($maxResults&& $currentResultCount $maxResults)
  1218.             {
  1219.                 if (!is_null($xmlMarker&& $xmlMarker != '')
  1220.                 {
  1221.                     $blobs array_merge($blobs$this->listBlobs($containerName$prefix$delimiter$maxResults$marker$currentResultCount));
  1222.                 }
  1223.             }
  1224.             if (!is_null($maxResults&& count($blobs$maxResults)
  1225.                 $blobs array_slice($blobs0$maxResults);
  1226.             
  1227.             return $blobs;
  1228.         }
  1229.         else 
  1230.         {                
  1231.             throw new Microsoft_WindowsAzure_Exception($this->getErrorMessage($response'Resource could not be accessed.'));
  1232.         }
  1233.     }
  1234.     
  1235.     /**
  1236.      * Generate shared access URL
  1237.      * 
  1238.      * @param string $containerName  Container name
  1239.      * @param string $blobName       Blob name
  1240.      * @param string $resource       Signed resource - container (c) - blob (b)
  1241.      * @param string $permissions    Signed permissions - read (r), write (w), delete (d) and list (l)
  1242.      * @param string $start          The time at which the Shared Access Signature becomes valid.
  1243.      * @param string $expiry         The time at which the Shared Access Signature becomes invalid.
  1244.      * @param string $identifier     Signed identifier
  1245.      * @return string 
  1246.      */
  1247.     public function generateSharedAccessUrl($containerName ''$blobName ''$resource 'b'$permissions 'r'$start ''$expiry ''$identifier '')
  1248.     {
  1249.         if ($containerName === '')
  1250.             throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1251.         if (!self::isValidContainerName($containerName))
  1252.             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.');
  1253.  
  1254.         // Resource name
  1255.         $resourceName self::createResourceName($containerName $blobName);
  1256.  
  1257.         // Generate URL
  1258.         return $this->getBaseUrl('/' $resourceName '?' .
  1259.             $this->_sharedAccessSignatureCredentials->createSignedQueryString(
  1260.                 $resourceName,
  1261.                 '',
  1262.                 $resource,
  1263.                 $permissions,
  1264.                 $start,
  1265.                 $expiry,
  1266.                 $identifier);
  1267.     }
  1268.     
  1269.     /**
  1270.      * Register this object as stream wrapper client
  1271.      *
  1272.      * @param  string $name Protocol name
  1273.      * @return Microsoft_WindowsAzure_Storage_Blob 
  1274.      */
  1275.     public function registerAsClient($name)
  1276.     {
  1277.         self::$_wrapperClients[$name$this;
  1278.         return $this;
  1279.     }
  1280.  
  1281.     /**
  1282.      * Unregister this object as stream wrapper client
  1283.      *
  1284.      * @param  string $name Protocol name
  1285.      * @return Microsoft_WindowsAzure_Storage_Blob 
  1286.      */
  1287.     public function unregisterAsClient($name)
  1288.     {
  1289.         unset(self::$_wrapperClients[$name]);
  1290.         return $this;
  1291.     }
  1292.  
  1293.     /**
  1294.      * Get wrapper client for stream type
  1295.      *
  1296.      * @param  string $name Protocol name
  1297.      * @return Microsoft_WindowsAzure_Storage_Blob 
  1298.      */
  1299.     public static function getWrapperClient($name)
  1300.     {
  1301.         return self::$_wrapperClients[$name];
  1302.     }
  1303.  
  1304.     /**
  1305.      * Register this object as stream wrapper
  1306.      *
  1307.      * @param  string $name Protocol name
  1308.      */
  1309.     public function registerStreamWrapper($name 'azure')
  1310.     {
  1311.         /**
  1312.          * @see Microsoft_WindowsAzure_Storage_Blob_Stream
  1313.          */
  1314.         require_once 'Microsoft/WindowsAzure/Storage/Blob/Stream.php';
  1315.  
  1316.         stream_register_wrapper($name'Microsoft_WindowsAzure_Storage_Blob_Stream');
  1317.         $this->registerAsClient($name);
  1318.     }
  1319.  
  1320.     /**
  1321.      * Unregister this object as stream wrapper
  1322.      *
  1323.      * @param  string $name Protocol name
  1324.      * @return Microsoft_WindowsAzure_Storage_Blob 
  1325.      */
  1326.     public function unregisterStreamWrapper($name 'azure')
  1327.     {
  1328.         stream_wrapper_unregister($name);
  1329.         $this->unregisterAsClient($name);
  1330.     }
  1331.     
  1332.     /**
  1333.      * Create resource name
  1334.      * 
  1335.      * @param string $containerName  Container name
  1336.      * @param string $blobName Blob name
  1337.      * @return string 
  1338.      */
  1339.     public static function createResourceName($containerName ''$blobName '')
  1340.     {
  1341.         // Resource name
  1342.         $resourceName $containerName '/' $blobName;
  1343.         if ($containerName === '' || $containerName === '$root')
  1344.             $resourceName $blobName;
  1345.         if ($blobName === '')
  1346.             $resourceName $containerName;
  1347.             
  1348.         return $resourceName;
  1349.     }
  1350.     
  1351.     /**
  1352.      * Is valid container name?
  1353.      *
  1354.      * @param string $containerName Container name
  1355.      * @return boolean 
  1356.      */
  1357.     public static function isValidContainerName($containerName '')
  1358.     {
  1359.         if ($containerName == '$root')
  1360.             return true;
  1361.             
  1362.         if (!ereg("^[a-z0-9][a-z0-9-]*$"$containerName))
  1363.             return false;
  1364.     
  1365.         if (strpos($containerName'--'!== false)
  1366.             return false;
  1367.     
  1368.         if (strtolower($containerName!= $containerName)
  1369.             return false;
  1370.     
  1371.         if (strlen($containerName|| strlen($containerName63)
  1372.             return false;
  1373.             
  1374.         if (substr($containerName-1== '-')
  1375.             return false;
  1376.     
  1377.         return true;
  1378.     }
  1379.     
  1380.     /**
  1381.      * Get error message from Microsoft_Http_Response
  1382.      * 
  1383.      * @param Microsoft_Http_Response $response Repsonse
  1384.      * @param string $alternativeError Alternative error message
  1385.      * @return string 
  1386.      */
  1387.     protected function getErrorMessage(Microsoft_Http_Response $response$alternativeError 'Unknown error.')
  1388.     {
  1389.         $response $this->parseResponse($response);
  1390.         if ($response && $response->Message)
  1391.             return (string)$response->Message;
  1392.         else
  1393.             return $alternativeError;
  1394.     }
  1395.     
  1396.     /**
  1397.      * Generate block id
  1398.      * 
  1399.      * @param int $part Block number
  1400.      * @return string Windows Azure Blob Storage block number
  1401.      */
  1402.     protected function generateBlockId($part 0)
  1403.     {
  1404.         $returnValue $part;
  1405.         while (strlen($returnValue64)
  1406.         {
  1407.             $returnValue '0' $returnValue;
  1408.         }
  1409.         
  1410.         return $returnValue;
  1411.     }
  1412. }

Documentation generated on Thu, 26 Nov 2009 08:04:45 +0100 by phpDocumentor 1.4.3