[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/lib/zend/Zend/Service/WindowsAzure/Storage/ -> Blob.php (source)

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


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1