|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00026 require_once 'Zend/Service/WindowsAzure/Credentials/SharedKey.php'; 00027 00031 require_once 'Zend/Service/WindowsAzure/Credentials/SharedAccessSignature.php'; 00032 00036 require_once 'Zend/Service/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php'; 00037 00041 require_once 'Zend/Http/Client.php'; 00042 00046 require_once 'Zend/Http/Response.php'; 00047 00051 require_once 'Zend/Service/WindowsAzure/Storage.php'; 00052 00056 require_once 'Zend/Service/WindowsAzure/Storage/BlobContainer.php'; 00057 00061 require_once 'Zend/Service/WindowsAzure/Storage/BlobInstance.php'; 00062 00066 require_once 'Zend/Service/WindowsAzure/Storage/SignedIdentifier.php'; 00067 00071 require_once 'Zend/Service/WindowsAzure/Exception.php'; 00072 00073 00081 class Zend_Service_WindowsAzure_Storage_Blob extends Zend_Service_WindowsAzure_Storage 00082 { 00086 const ACL_PRIVATE = false; 00087 00091 const ACL_PUBLIC = true; 00092 00096 const MAX_BLOB_SIZE = 67108864; 00097 00101 const MAX_BLOB_TRANSFER_SIZE = 4194304; 00102 00108 protected static $_wrapperClients = array(); 00109 00115 private $_sharedAccessSignatureCredentials = null; 00116 00126 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) 00127 { 00128 parent::__construct($host, $accountName, $accountKey, $usePathStyleUri, $retryPolicy); 00129 00130 // API version 00131 $this->_apiVersion = '2009-07-17'; 00132 00133 // SharedAccessSignature credentials 00134 $this->_sharedAccessSignatureCredentials = new Zend_Service_WindowsAzure_Credentials_SharedAccessSignature($accountName, $accountKey, $usePathStyleUri); 00135 } 00136 00144 public function blobExists($containerName = '', $blobName = '') 00145 { 00146 if ($containerName === '') { 00147 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00148 } 00149 if (!self::isValidContainerName($containerName)) { 00150 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.'); 00151 } 00152 if ($blobName === '') { 00153 throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); 00154 } 00155 00156 // List blobs 00157 $blobs = $this->listBlobs($containerName, $blobName, '', 1); 00158 foreach ($blobs as $blob) { 00159 if ($blob->Name == $blobName) { 00160 return true; 00161 } 00162 } 00163 00164 return false; 00165 } 00166 00173 public function containerExists($containerName = '') 00174 { 00175 if ($containerName === '') { 00176 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00177 } 00178 if (!self::isValidContainerName($containerName)) { 00179 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.'); 00180 } 00181 00182 // List containers 00183 $containers = $this->listContainers($containerName, 1); 00184 foreach ($containers as $container) { 00185 if ($container->Name == $containerName) { 00186 return true; 00187 } 00188 } 00189 00190 return false; 00191 } 00192 00201 public function createContainer($containerName = '', $metadata = array()) 00202 { 00203 if ($containerName === '') { 00204 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00205 } 00206 if (!self::isValidContainerName($containerName)) { 00207 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.'); 00208 } 00209 if (!is_array($metadata)) { 00210 throw new Zend_Service_WindowsAzure_Exception('Meta data should be an array of key and value pairs.'); 00211 } 00212 00213 // Create metadata headers 00214 $headers = array(); 00215 $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); 00216 00217 // Perform request 00218 $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); 00219 if ($response->isSuccessful()) { 00220 return new Zend_Service_WindowsAzure_Storage_BlobContainer( 00221 $containerName, 00222 $response->getHeader('Etag'), 00223 $response->getHeader('Last-modified'), 00224 $metadata 00225 ); 00226 } else { 00227 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 00228 } 00229 } 00230 00239 public function getContainerAcl($containerName = '', $signedIdentifiers = false) 00240 { 00241 if ($containerName === '') { 00242 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00243 } 00244 if (!self::isValidContainerName($containerName)) { 00245 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.'); 00246 } 00247 00248 // Perform request 00249 $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); 00250 if ($response->isSuccessful()) { 00251 if ($signedIdentifiers == false) { 00252 // Only public/private 00253 return $response->getHeader('x-ms-prop-publicaccess') == 'True'; 00254 } else { 00255 // Parse result 00256 $result = $this->_parseResponse($response); 00257 if (!$result) { 00258 return array(); 00259 } 00260 00261 $entries = null; 00262 if ($result->SignedIdentifier) { 00263 if (count($result->SignedIdentifier) > 1) { 00264 $entries = $result->SignedIdentifier; 00265 } else { 00266 $entries = array($result->SignedIdentifier); 00267 } 00268 } 00269 00270 // Return value 00271 $returnValue = array(); 00272 foreach ($entries as $entry) { 00273 $returnValue[] = new Zend_Service_WindowsAzure_Storage_SignedIdentifier( 00274 $entry->Id, 00275 $entry->AccessPolicy ? $entry->AccessPolicy->Start ? $entry->AccessPolicy->Start : '' : '', 00276 $entry->AccessPolicy ? $entry->AccessPolicy->Expiry ? $entry->AccessPolicy->Expiry : '' : '', 00277 $entry->AccessPolicy ? $entry->AccessPolicy->Permission ? $entry->AccessPolicy->Permission : '' : '' 00278 ); 00279 } 00280 00281 // Return 00282 return $returnValue; 00283 } 00284 } else { 00285 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 00286 } 00287 } 00288 00297 public function setContainerAcl($containerName = '', $acl = self::ACL_PRIVATE, $signedIdentifiers = array()) 00298 { 00299 if ($containerName === '') { 00300 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00301 } 00302 if (!self::isValidContainerName($containerName)) { 00303 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.'); 00304 } 00305 00306 // Policies 00307 $policies = null; 00308 if (is_array($signedIdentifiers) && count($signedIdentifiers) > 0) { 00309 $policies = ''; 00310 $policies .= '<?xml version="1.0" encoding="utf-8"?>' . "\r\n"; 00311 $policies .= '<SignedIdentifiers>' . "\r\n"; 00312 foreach ($signedIdentifiers as $signedIdentifier) { 00313 $policies .= ' <SignedIdentifier>' . "\r\n"; 00314 $policies .= ' <Id>' . $signedIdentifier->Id . '</Id>' . "\r\n"; 00315 $policies .= ' <AccessPolicy>' . "\r\n"; 00316 if ($signedIdentifier->Start != '') 00317 $policies .= ' <Start>' . $signedIdentifier->Start . '</Start>' . "\r\n"; 00318 if ($signedIdentifier->Expiry != '') 00319 $policies .= ' <Expiry>' . $signedIdentifier->Expiry . '</Expiry>' . "\r\n"; 00320 if ($signedIdentifier->Permissions != '') 00321 $policies .= ' <Permission>' . $signedIdentifier->Permissions . '</Permission>' . "\r\n"; 00322 $policies .= ' </AccessPolicy>' . "\r\n"; 00323 $policies .= ' </SignedIdentifier>' . "\r\n"; 00324 } 00325 $policies .= '</SignedIdentifiers>' . "\r\n"; 00326 } 00327 00328 // Perform request 00329 $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); 00330 if (!$response->isSuccessful()) { 00331 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 00332 } 00333 } 00334 00342 public function getContainer($containerName = '') 00343 { 00344 if ($containerName === '') { 00345 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00346 } 00347 if (!self::isValidContainerName($containerName)) { 00348 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.'); 00349 } 00350 00351 // Perform request 00352 $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); 00353 if ($response->isSuccessful()) { 00354 // Parse metadata 00355 $metadata = $this->_parseMetadataHeaders($response->getHeaders()); 00356 00357 // Return container 00358 return new Zend_Service_WindowsAzure_Storage_BlobContainer( 00359 $containerName, 00360 $response->getHeader('Etag'), 00361 $response->getHeader('Last-modified'), 00362 $metadata 00363 ); 00364 } else { 00365 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 00366 } 00367 } 00368 00376 public function getContainerMetadata($containerName = '') 00377 { 00378 if ($containerName === '') { 00379 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00380 } 00381 if (!self::isValidContainerName($containerName)) { 00382 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.'); 00383 } 00384 00385 return $this->getContainer($containerName)->Metadata; 00386 } 00387 00398 public function setContainerMetadata($containerName = '', $metadata = array(), $additionalHeaders = array()) 00399 { 00400 if ($containerName === '') { 00401 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00402 } 00403 if (!self::isValidContainerName($containerName)) { 00404 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.'); 00405 } 00406 if (!is_array($metadata)) { 00407 throw new Zend_Service_WindowsAzure_Exception('Meta data should be an array of key and value pairs.'); 00408 } 00409 if (count($metadata) == 0) { 00410 return; 00411 } 00412 00413 // Create metadata headers 00414 $headers = array(); 00415 $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); 00416 00417 // Additional headers? 00418 foreach ($additionalHeaders as $key => $value) { 00419 $headers[$key] = $value; 00420 } 00421 00422 // Perform request 00423 $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); 00424 if (!$response->isSuccessful()) { 00425 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 00426 } 00427 } 00428 00436 public function deleteContainer($containerName = '', $additionalHeaders = array()) 00437 { 00438 if ($containerName === '') { 00439 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00440 } 00441 if (!self::isValidContainerName($containerName)) { 00442 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.'); 00443 } 00444 00445 // Additional headers? 00446 $headers = array(); 00447 foreach ($additionalHeaders as $key => $value) { 00448 $headers[$key] = $value; 00449 } 00450 00451 // Perform request 00452 $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); 00453 if (!$response->isSuccessful()) { 00454 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 00455 } 00456 } 00457 00468 public function listContainers($prefix = null, $maxResults = null, $marker = null, $currentResultCount = 0) 00469 { 00470 // Build query string 00471 $queryString = '?comp=list'; 00472 if (!is_null($prefix)) { 00473 $queryString .= '&prefix=' . $prefix; 00474 } 00475 if (!is_null($maxResults)) { 00476 $queryString .= '&maxresults=' . $maxResults; 00477 } 00478 if (!is_null($marker)) { 00479 $queryString .= '&marker=' . $marker; 00480 } 00481 00482 // Perform request 00483 $response = $this->_performRequest('', $queryString, Zend_Http_Client::GET, array(), false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_CONTAINER, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_LIST); 00484 if ($response->isSuccessful()) { 00485 $xmlContainers = $this->_parseResponse($response)->Containers->Container; 00486 $xmlMarker = (string)$this->_parseResponse($response)->NextMarker; 00487 00488 $containers = array(); 00489 if (!is_null($xmlContainers)) { 00490 for ($i = 0; $i < count($xmlContainers); $i++) { 00491 $containers[] = new Zend_Service_WindowsAzure_Storage_BlobContainer( 00492 (string)$xmlContainers[$i]->Name, 00493 (string)$xmlContainers[$i]->Etag, 00494 (string)$xmlContainers[$i]->LastModified 00495 ); 00496 } 00497 } 00498 $currentResultCount = $currentResultCount + count($containers); 00499 if (!is_null($maxResults) && $currentResultCount < $maxResults) { 00500 if (!is_null($xmlMarker) && $xmlMarker != '') { 00501 $containers = array_merge($containers, $this->listContainers($prefix, $maxResults, $xmlMarker, $currentResultCount)); 00502 } 00503 } 00504 if (!is_null($maxResults) && count($containers) > $maxResults) { 00505 $containers = array_slice($containers, 0, $maxResults); 00506 } 00507 00508 return $containers; 00509 } else { 00510 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 00511 } 00512 } 00513 00525 public function putBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array(), $additionalHeaders = array()) 00526 { 00527 if ($containerName === '') { 00528 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00529 } 00530 if (!self::isValidContainerName($containerName)) { 00531 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.'); 00532 } 00533 if ($blobName === '') { 00534 throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); 00535 } 00536 if ($localFileName === '') { 00537 throw new Zend_Service_WindowsAzure_Exception('Local file name is not specified.'); 00538 } 00539 if (!file_exists($localFileName)) { 00540 throw new Zend_Service_WindowsAzure_Exception('Local file not found.'); 00541 } 00542 if ($containerName === '$root' && strpos($blobName, '/') !== false) { 00543 throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); 00544 } 00545 00546 // Check file size 00547 if (filesize($localFileName) >= self::MAX_BLOB_SIZE) { 00548 return $this->putLargeBlob($containerName, $blobName, $localFileName, $metadata); 00549 } 00550 00551 // Create metadata headers 00552 $headers = array(); 00553 $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); 00554 00555 // Additional headers? 00556 foreach ($additionalHeaders as $key => $value) { 00557 $headers[$key] = $value; 00558 } 00559 00560 // File contents 00561 $fileContents = file_get_contents($localFileName); 00562 00563 // Resource name 00564 $resourceName = self::createResourceName($containerName , $blobName); 00565 00566 // Perform request 00567 $response = $this->_performRequest($resourceName, '', Zend_Http_Client::PUT, $headers, false, $fileContents, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE); 00568 if ($response->isSuccessful()) { 00569 return new Zend_Service_WindowsAzure_Storage_BlobInstance( 00570 $containerName, 00571 $blobName, 00572 $response->getHeader('Etag'), 00573 $response->getHeader('Last-modified'), 00574 $this->getBaseUrl() . '/' . $containerName . '/' . $blobName, 00575 strlen($fileContents), 00576 '', 00577 '', 00578 '', 00579 false, 00580 $metadata 00581 ); 00582 } else { 00583 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 00584 } 00585 } 00586 00597 public function putLargeBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array()) 00598 { 00599 if ($containerName === '') { 00600 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00601 } 00602 if (!self::isValidContainerName($containerName)) { 00603 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.'); 00604 } 00605 if ($blobName === '') { 00606 throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); 00607 } 00608 if ($localFileName === '') { 00609 throw new Zend_Service_WindowsAzure_Exception('Local file name is not specified.'); 00610 } 00611 if (!file_exists($localFileName)) { 00612 throw new Zend_Service_WindowsAzure_Exception('Local file not found.'); 00613 } 00614 if ($containerName === '$root' && strpos($blobName, '/') !== false) { 00615 throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); 00616 } 00617 00618 // Check file size 00619 if (filesize($localFileName) < self::MAX_BLOB_SIZE) { 00620 return $this->putBlob($containerName, $blobName, $localFileName, $metadata); 00621 } 00622 00623 // Determine number of parts 00624 $numberOfParts = ceil( filesize($localFileName) / self::MAX_BLOB_TRANSFER_SIZE ); 00625 00626 // Generate block id's 00627 $blockIdentifiers = array(); 00628 for ($i = 0; $i < $numberOfParts; $i++) { 00629 $blockIdentifiers[] = $this->_generateBlockId($i); 00630 } 00631 00632 // Open file 00633 $fp = fopen($localFileName, 'r'); 00634 if ($fp === false) { 00635 throw new Zend_Service_WindowsAzure_Exception('Could not open local file.'); 00636 } 00637 00638 // Upload parts 00639 for ($i = 0; $i < $numberOfParts; $i++) { 00640 // Seek position in file 00641 fseek($fp, $i * self::MAX_BLOB_TRANSFER_SIZE); 00642 00643 // Read contents 00644 $fileContents = fread($fp, self::MAX_BLOB_TRANSFER_SIZE); 00645 00646 // Put block 00647 $this->putBlock($containerName, $blobName, $blockIdentifiers[$i], $fileContents); 00648 00649 // Dispose file contents 00650 $fileContents = null; 00651 unset($fileContents); 00652 } 00653 00654 // Close file 00655 fclose($fp); 00656 00657 // Put block list 00658 $this->putBlockList($containerName, $blobName, $blockIdentifiers, $metadata); 00659 00660 // Return information of the blob 00661 return $this->getBlobInstance($containerName, $blobName); 00662 } 00663 00673 public function putBlock($containerName = '', $blobName = '', $identifier = '', $contents = '') 00674 { 00675 if ($containerName === '') { 00676 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00677 } 00678 if (!self::isValidContainerName($containerName)) { 00679 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.'); 00680 } 00681 if ($identifier === '') { 00682 throw new Zend_Service_WindowsAzure_Exception('Block identifier is not specified.'); 00683 } 00684 if (strlen($contents) > self::MAX_BLOB_TRANSFER_SIZE) { 00685 throw new Zend_Service_WindowsAzure_Exception('Block size is too big.'); 00686 } 00687 if ($containerName === '$root' && strpos($blobName, '/') !== false) { 00688 throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); 00689 } 00690 00691 // Resource name 00692 $resourceName = self::createResourceName($containerName , $blobName); 00693 00694 // Upload 00695 $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); 00696 if (!$response->isSuccessful()) { 00697 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 00698 } 00699 } 00700 00711 public function putBlockList($containerName = '', $blobName = '', $blockList = array(), $metadata = array(), $additionalHeaders = array()) 00712 { 00713 if ($containerName === '') { 00714 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00715 } 00716 if (!self::isValidContainerName($containerName)) { 00717 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.'); 00718 } 00719 if ($blobName === '') { 00720 throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); 00721 } 00722 if (count($blockList) == 0) { 00723 throw new Zend_Service_WindowsAzure_Exception('Block list does not contain any elements.'); 00724 } 00725 if ($containerName === '$root' && strpos($blobName, '/') !== false) { 00726 throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); 00727 } 00728 00729 // Generate block list 00730 $blocks = ''; 00731 foreach ($blockList as $block) { 00732 $blocks .= ' <Latest>' . base64_encode($block) . '</Latest>' . "\n"; 00733 } 00734 00735 // Generate block list request 00736 $fileContents = utf8_encode(implode("\n", array( 00737 '<?xml version="1.0" encoding="utf-8"?>', 00738 '<BlockList>', 00739 $blocks, 00740 '</BlockList>' 00741 ))); 00742 00743 // Create metadata headers 00744 $headers = array(); 00745 $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); 00746 00747 // Additional headers? 00748 foreach ($additionalHeaders as $key => $value) { 00749 $headers[$key] = $value; 00750 } 00751 00752 // Resource name 00753 $resourceName = self::createResourceName($containerName , $blobName); 00754 00755 // Perform request 00756 $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); 00757 if (!$response->isSuccessful()) { 00758 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 00759 } 00760 } 00761 00771 public function getBlockList($containerName = '', $blobName = '', $type = 0) 00772 { 00773 if ($containerName === '') { 00774 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00775 } 00776 if (!self::isValidContainerName($containerName)) { 00777 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.'); 00778 } 00779 if ($blobName === '') { 00780 throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); 00781 } 00782 if ($type < 0 || $type > 2) { 00783 throw new Zend_Service_WindowsAzure_Exception('Invalid type of block list to retrieve.'); 00784 } 00785 00786 // Set $blockListType 00787 $blockListType = 'all'; 00788 if ($type == 1) { 00789 $blockListType = 'committed'; 00790 } 00791 if ($type == 2) { 00792 $blockListType = 'uncommitted'; 00793 } 00794 00795 // Resource name 00796 $resourceName = self::createResourceName($containerName , $blobName); 00797 00798 // Perform request 00799 $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); 00800 if ($response->isSuccessful()) { 00801 // Parse response 00802 $blockList = $this->_parseResponse($response); 00803 00804 // Create return value 00805 $returnValue = array(); 00806 if ($blockList->CommittedBlocks) { 00807 foreach ($blockList->CommittedBlocks->Block as $block) { 00808 $returnValue['CommittedBlocks'][] = (object)array( 00809 'Name' => (string)$block->Name, 00810 'Size' => (string)$block->Size 00811 ); 00812 } 00813 } 00814 if ($blockList->UncommittedBlocks) { 00815 foreach ($blockList->UncommittedBlocks->Block as $block) { 00816 $returnValue['UncommittedBlocks'][] = (object)array( 00817 'Name' => (string)$block->Name, 00818 'Size' => (string)$block->Size 00819 ); 00820 } 00821 } 00822 00823 return $returnValue; 00824 } else { 00825 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 00826 } 00827 } 00828 00841 public function copyBlob($sourceContainerName = '', $sourceBlobName = '', $destinationContainerName = '', $destinationBlobName = '', $metadata = array(), $additionalHeaders = array()) 00842 { 00843 if ($sourceContainerName === '') { 00844 throw new Zend_Service_WindowsAzure_Exception('Source container name is not specified.'); 00845 } 00846 if (!self::isValidContainerName($sourceContainerName)) { 00847 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.'); 00848 } 00849 if ($sourceBlobName === '') { 00850 throw new Zend_Service_WindowsAzure_Exception('Source blob name is not specified.'); 00851 } 00852 if ($destinationContainerName === '') { 00853 throw new Zend_Service_WindowsAzure_Exception('Destination container name is not specified.'); 00854 } 00855 if (!self::isValidContainerName($destinationContainerName)) { 00856 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.'); 00857 } 00858 if ($destinationBlobName === '') { 00859 throw new Zend_Service_WindowsAzure_Exception('Destination blob name is not specified.'); 00860 } 00861 if ($sourceContainerName === '$root' && strpos($sourceBlobName, '/') !== false) { 00862 throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); 00863 } 00864 if ($destinationContainerName === '$root' && strpos($destinationBlobName, '/') !== false) { 00865 throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); 00866 } 00867 00868 // Create metadata headers 00869 $headers = array(); 00870 $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); 00871 00872 // Additional headers? 00873 foreach ($additionalHeaders as $key => $value) { 00874 $headers[$key] = $value; 00875 } 00876 00877 // Resource names 00878 $sourceResourceName = self::createResourceName($sourceContainerName, $sourceBlobName); 00879 $destinationResourceName = self::createResourceName($destinationContainerName, $destinationBlobName); 00880 00881 // Set source blob 00882 $headers["x-ms-copy-source"] = '/' . $this->_accountName . '/' . $sourceResourceName; 00883 00884 // Perform request 00885 $response = $this->_performRequest($destinationResourceName, '', Zend_Http_Client::PUT, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE); 00886 if ($response->isSuccessful()) { 00887 return new Zend_Service_WindowsAzure_Storage_BlobInstance( 00888 $destinationContainerName, 00889 $destinationBlobName, 00890 $response->getHeader('Etag'), 00891 $response->getHeader('Last-modified'), 00892 $this->getBaseUrl() . '/' . $destinationContainerName . '/' . $destinationBlobName, 00893 0, 00894 '', 00895 '', 00896 '', 00897 false, 00898 $metadata 00899 ); 00900 } else { 00901 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 00902 } 00903 } 00904 00914 public function getBlob($containerName = '', $blobName = '', $localFileName = '', $additionalHeaders = array()) 00915 { 00916 if ($containerName === '') { 00917 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00918 } 00919 if (!self::isValidContainerName($containerName)) { 00920 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.'); 00921 } 00922 if ($blobName === '') { 00923 throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); 00924 } 00925 if ($localFileName === '') { 00926 throw new Zend_Service_WindowsAzure_Exception('Local file name is not specified.'); 00927 } 00928 00929 // Additional headers? 00930 $headers = array(); 00931 foreach ($additionalHeaders as $key => $value) { 00932 $headers[$key] = $value; 00933 } 00934 00935 // Resource name 00936 $resourceName = self::createResourceName($containerName , $blobName); 00937 00938 // Perform request 00939 $response = $this->_performRequest($resourceName, '', Zend_Http_Client::GET, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ); 00940 if ($response->isSuccessful()) { 00941 file_put_contents($localFileName, $response->getBody()); 00942 } else { 00943 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 00944 } 00945 } 00946 00956 public function getBlobInstance($containerName = '', $blobName = '', $additionalHeaders = array()) 00957 { 00958 if ($containerName === '') { 00959 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 00960 } 00961 if (!self::isValidContainerName($containerName)) { 00962 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.'); 00963 } 00964 if ($blobName === '') { 00965 throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); 00966 } 00967 if ($containerName === '$root' && strpos($blobName, '/') !== false) { 00968 throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); 00969 } 00970 00971 // Additional headers? 00972 $headers = array(); 00973 foreach ($additionalHeaders as $key => $value) { 00974 $headers[$key] = $value; 00975 } 00976 00977 // Resource name 00978 $resourceName = self::createResourceName($containerName , $blobName); 00979 00980 // Perform request 00981 $response = $this->_performRequest($resourceName, '', Zend_Http_Client::HEAD, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ); 00982 if ($response->isSuccessful()) { 00983 // Parse metadata 00984 $metadata = $this->_parseMetadataHeaders($response->getHeaders()); 00985 00986 // Return blob 00987 return new Zend_Service_WindowsAzure_Storage_BlobInstance( 00988 $containerName, 00989 $blobName, 00990 $response->getHeader('Etag'), 00991 $response->getHeader('Last-modified'), 00992 $this->getBaseUrl() . '/' . $containerName . '/' . $blobName, 00993 $response->getHeader('Content-Length'), 00994 $response->getHeader('Content-Type'), 00995 $response->getHeader('Content-Encoding'), 00996 $response->getHeader('Content-Language'), 00997 false, 00998 $metadata 00999 ); 01000 } else { 01001 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 01002 } 01003 } 01004 01013 public function getBlobMetadata($containerName = '', $blobName = '') 01014 { 01015 if ($containerName === '') { 01016 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 01017 } 01018 if (!self::isValidContainerName($containerName)) { 01019 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.'); 01020 } 01021 if ($blobName === '') { 01022 throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); 01023 } 01024 if ($containerName === '$root' && strpos($blobName, '/') !== false) { 01025 throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); 01026 } 01027 01028 return $this->getBlobInstance($containerName, $blobName)->Metadata; 01029 } 01030 01042 public function setBlobMetadata($containerName = '', $blobName = '', $metadata = array(), $additionalHeaders = array()) 01043 { 01044 if ($containerName === '') { 01045 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 01046 } 01047 if (!self::isValidContainerName($containerName)) { 01048 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.'); 01049 } 01050 if ($blobName === '') { 01051 throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); 01052 } 01053 if ($containerName === '$root' && strpos($blobName, '/') !== false) { 01054 throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); 01055 } 01056 if (count($metadata) == 0) { 01057 return; 01058 } 01059 01060 // Create metadata headers 01061 $headers = array(); 01062 $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata)); 01063 01064 // Additional headers? 01065 foreach ($additionalHeaders as $key => $value) { 01066 $headers[$key] = $value; 01067 } 01068 01069 // Perform request 01070 $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); 01071 if (!$response->isSuccessful()) { 01072 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 01073 } 01074 } 01075 01084 public function deleteBlob($containerName = '', $blobName = '', $additionalHeaders = array()) 01085 { 01086 if ($containerName === '') { 01087 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 01088 } 01089 if (!self::isValidContainerName($containerName)) { 01090 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.'); 01091 } 01092 if ($blobName === '') { 01093 throw new Zend_Service_WindowsAzure_Exception('Blob name is not specified.'); 01094 } 01095 if ($containerName === '$root' && strpos($blobName, '/') !== false) { 01096 throw new Zend_Service_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).'); 01097 } 01098 01099 // Additional headers? 01100 $headers = array(); 01101 foreach ($additionalHeaders as $key => $value) { 01102 $headers[$key] = $value; 01103 } 01104 01105 // Resource name 01106 $resourceName = self::createResourceName($containerName , $blobName); 01107 01108 // Perform request 01109 $response = $this->_performRequest($resourceName, '', Zend_Http_Client::DELETE, $headers, false, null, Zend_Service_WindowsAzure_Storage::RESOURCE_BLOB, Zend_Service_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE); 01110 if (!$response->isSuccessful()) { 01111 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 01112 } 01113 } 01114 01127 public function listBlobs($containerName = '', $prefix = '', $delimiter = '', $maxResults = null, $marker = null, $currentResultCount = 0) 01128 { 01129 if ($containerName === '') { 01130 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 01131 } 01132 if (!self::isValidContainerName($containerName)) { 01133 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.'); 01134 } 01135 01136 // Build query string 01137 $queryString = '?restype=container&comp=list'; 01138 if (!is_null($prefix)) { 01139 $queryString .= '&prefix=' . $prefix; 01140 } 01141 if ($delimiter !== '') { 01142 $queryString .= '&delimiter=' . $delimiter; 01143 } 01144 if (!is_null($maxResults)) { 01145 $queryString .= '&maxresults=' . $maxResults; 01146 } 01147 if (!is_null($marker)) { 01148 $queryString .= '&marker=' . $marker; 01149 } 01150 01151 // Perform request 01152 $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); 01153 if ($response->isSuccessful()) { 01154 // Return value 01155 $blobs = array(); 01156 01157 // Blobs 01158 $xmlBlobs = $this->_parseResponse($response)->Blobs->Blob; 01159 if (!is_null($xmlBlobs)) { 01160 for ($i = 0; $i < count($xmlBlobs); $i++) { 01161 $blobs[] = new Zend_Service_WindowsAzure_Storage_BlobInstance( 01162 $containerName, 01163 (string)$xmlBlobs[$i]->Name, 01164 (string)$xmlBlobs[$i]->Etag, 01165 (string)$xmlBlobs[$i]->LastModified, 01166 (string)$xmlBlobs[$i]->Url, 01167 (string)$xmlBlobs[$i]->Size, 01168 (string)$xmlBlobs[$i]->ContentType, 01169 (string)$xmlBlobs[$i]->ContentEncoding, 01170 (string)$xmlBlobs[$i]->ContentLanguage, 01171 false 01172 ); 01173 } 01174 } 01175 01176 // Blob prefixes (folders) 01177 $xmlBlobs = $this->_parseResponse($response)->Blobs->BlobPrefix; 01178 01179 if (!is_null($xmlBlobs)) { 01180 for ($i = 0; $i < count($xmlBlobs); $i++) { 01181 $blobs[] = new Zend_Service_WindowsAzure_Storage_BlobInstance( 01182 $containerName, 01183 (string)$xmlBlobs[$i]->Name, 01184 '', 01185 '', 01186 '', 01187 0, 01188 '', 01189 '', 01190 '', 01191 true 01192 ); 01193 } 01194 } 01195 01196 // More blobs? 01197 $xmlMarker = (string)$this->_parseResponse($response)->NextMarker; 01198 $currentResultCount = $currentResultCount + count($blobs); 01199 if (!is_null($maxResults) && $currentResultCount < $maxResults) { 01200 if (!is_null($xmlMarker) && $xmlMarker != '') { 01201 $blobs = array_merge($blobs, $this->listBlobs($containerName, $prefix, $delimiter, $maxResults, $marker, $currentResultCount)); 01202 } 01203 } 01204 if (!is_null($maxResults) && count($blobs) > $maxResults) { 01205 $blobs = array_slice($blobs, 0, $maxResults); 01206 } 01207 01208 return $blobs; 01209 } else { 01210 throw new Zend_Service_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.')); 01211 } 01212 } 01213 01226 public function generateSharedAccessUrl($containerName = '', $blobName = '', $resource = 'b', $permissions = 'r', $start = '', $expiry = '', $identifier = '') 01227 { 01228 if ($containerName === '') { 01229 throw new Zend_Service_WindowsAzure_Exception('Container name is not specified.'); 01230 } 01231 if (!self::isValidContainerName($containerName)) { 01232 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.'); 01233 } 01234 01235 // Resource name 01236 $resourceName = self::createResourceName($containerName , $blobName); 01237 01238 // Generate URL 01239 return $this->getBaseUrl() . '/' . $resourceName . '?' . 01240 $this->_sharedAccessSignatureCredentials->createSignedQueryString( 01241 $resourceName, 01242 '', 01243 $resource, 01244 $permissions, 01245 $start, 01246 $expiry, 01247 $identifier); 01248 } 01249 01256 public function registerAsClient($name) 01257 { 01258 self::$_wrapperClients[$name] = $this; 01259 return $this; 01260 } 01261 01268 public function unregisterAsClient($name) 01269 { 01270 unset(self::$_wrapperClients[$name]); 01271 return $this; 01272 } 01273 01280 public static function getWrapperClient($name) 01281 { 01282 return self::$_wrapperClients[$name]; 01283 } 01284 01290 public function registerStreamWrapper($name = 'azure') 01291 { 01295 require_once 'Zend/Service/WindowsAzure/Storage/Blob/Stream.php'; 01296 01297 stream_register_wrapper($name, 'Zend_Service_WindowsAzure_Storage_Blob_Stream'); 01298 $this->registerAsClient($name); 01299 } 01300 01307 public function unregisterStreamWrapper($name = 'azure') 01308 { 01309 stream_wrapper_unregister($name); 01310 $this->unregisterAsClient($name); 01311 } 01312 01320 public static function createResourceName($containerName = '', $blobName = '') 01321 { 01322 // Resource name 01323 $resourceName = $containerName . '/' . $blobName; 01324 if ($containerName === '' || $containerName === '$root') { 01325 $resourceName = $blobName; 01326 } 01327 if ($blobName === '') { 01328 $resourceName = $containerName; 01329 } 01330 01331 return $resourceName; 01332 } 01333 01340 public static function isValidContainerName($containerName = '') 01341 { 01342 if ($containerName == '$root') { 01343 return true; 01344 } 01345 01346 if (preg_match("/^[a-z0-9][a-z0-9-]*$/", $containerName) === 0) { 01347 return false; 01348 } 01349 01350 if (strpos($containerName, '--') !== false) { 01351 return false; 01352 } 01353 01354 if (strtolower($containerName) != $containerName) { 01355 return false; 01356 } 01357 01358 if (strlen($containerName) < 3 || strlen($containerName) > 63) { 01359 return false; 01360 } 01361 01362 if (substr($containerName, -1) == '-') { 01363 return false; 01364 } 01365 01366 return true; 01367 } 01368 01376 protected function _getErrorMessage(Zend_Http_Response $response, $alternativeError = 'Unknown error.') 01377 { 01378 $response = $this->_parseResponse($response); 01379 if ($response && $response->Message) { 01380 return (string)$response->Message; 01381 } else { 01382 return $alternativeError; 01383 } 01384 } 01385 01392 protected function _generateBlockId($part = 0) 01393 { 01394 $returnValue = $part; 01395 while (strlen($returnValue) < 64) { 01396 $returnValue = '0' . $returnValue; 01397 } 01398 01399 return $returnValue; 01400 } 01401 }