PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/Zend/Service/WindowsAzure/Storage/Blob.php

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