PageRenderTime 56ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/blog/wp-content/plugins/w3-total-cache/lib/Microsoft/WindowsAzure/Storage/Blob.php

https://bitbucket.org/bsnowman/classyblog
PHP | 2038 lines | 1203 code | 199 blank | 636 comment | 294 complexity | 03d91f7875c56a0ec0b4d3c7f977cedd MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * Copyright (c) 2009 - 2010, RealDolmen
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * * Neither the name of RealDolmen nor the
  14. * names of its contributors may be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY RealDolmen ''AS IS'' AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL RealDolmen BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  26. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. *
  28. * @category Microsoft
  29. * @package Microsoft_WindowsAzure
  30. * @subpackage Storage
  31. * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
  32. * @license http://todo name_todo
  33. * @version $Id: Blob.php 53747 2010-11-18 19:34:25Z unknown $
  34. */
  35. if (!defined('W3TC')) {
  36. die();
  37. }
  38. /**
  39. * @see Microsoft_WindowsAzure_Credentials_CredentialsAbstract_SharedKey
  40. */
  41. require_once 'Microsoft/WindowsAzure/Credentials/SharedKey.php';
  42. /**
  43. * @see Microsoft_WindowsAzure_Credentials_SharedAccessSignature
  44. */
  45. require_once 'Microsoft/WindowsAzure/Credentials/SharedAccessSignature.php';
  46. /**
  47. * @see Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract
  48. */
  49. require_once 'Microsoft/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
  50. /**
  51. * @see Microsoft_Http_Client
  52. */
  53. require_once 'Microsoft/Http/Client.php';
  54. /**
  55. * @see Microsoft_Http_Response
  56. */
  57. require_once 'Microsoft/Http/Response.php';
  58. /**
  59. * @see Microsoft_WindowsAzure_Storage
  60. */
  61. require_once 'Microsoft/WindowsAzure/Storage.php';
  62. /**
  63. * @see Microsoft_WindowsAzure_Storage_BlobContainer
  64. */
  65. require_once 'Microsoft/WindowsAzure/Storage/BlobContainer.php';
  66. /**
  67. * @see Microsoft_WindowsAzure_Storage_BlobInstance
  68. */
  69. require_once 'Microsoft/WindowsAzure/Storage/BlobInstance.php';
  70. /**
  71. * @see Microsoft_WindowsAzure_Storage_PageRegionInstance
  72. */
  73. require_once 'Microsoft/WindowsAzure/Storage/PageRegionInstance.php';
  74. /**
  75. * @see Microsoft_WindowsAzure_Storage_LeaseInstance
  76. */
  77. require_once 'Microsoft/WindowsAzure/Storage/LeaseInstance.php';
  78. /**
  79. * @see Microsoft_WindowsAzure_Storage_SignedIdentifier
  80. */
  81. require_once 'Microsoft/WindowsAzure/Storage/SignedIdentifier.php';
  82. /**
  83. * @see Microsoft_WindowsAzure_Exception
  84. */
  85. require_once 'Microsoft/WindowsAzure/Exception.php';
  86. /**
  87. * @category Microsoft
  88. * @package Microsoft_WindowsAzure
  89. * @subpackage Storage
  90. * @copyright Copyright (c) 2009 - 2010, RealDolmen (http://www.realdolmen.com)
  91. * @license http://phpazure.codeplex.com/license
  92. */
  93. class Microsoft_WindowsAzure_Storage_Blob extends Microsoft_WindowsAzure_Storage
  94. {
  95. /**
  96. * ACL - Private access
  97. */
  98. const ACL_PRIVATE = null;
  99. /**
  100. * ACL - Public access (read all blobs)
  101. *
  102. * @deprecated Use ACL_PUBLIC_CONTAINER or ACL_PUBLIC_BLOB instead.
  103. */
  104. const ACL_PUBLIC = 'container';
  105. /**
  106. * ACL - Blob Public access (read all blobs)
  107. */
  108. const ACL_PUBLIC_BLOB = 'blob';
  109. /**
  110. * ACL - Container Public access (enumerate and read all blobs)
  111. */
  112. const ACL_PUBLIC_CONTAINER = 'container';
  113. /**
  114. * Blob lease constants
  115. */
  116. const LEASE_ACQUIRE = 'acquire';
  117. const LEASE_RENEW = 'renew';
  118. const LEASE_RELEASE = 'release';
  119. const LEASE_BREAK = 'break';
  120. /**
  121. * Maximal blob size (in bytes)
  122. */
  123. const MAX_BLOB_SIZE = 67108864;
  124. /**
  125. * Maximal blob transfer size (in bytes)
  126. */
  127. const MAX_BLOB_TRANSFER_SIZE = 4194304;
  128. /**
  129. * Blob types
  130. */
  131. const BLOBTYPE_BLOCK = 'BlockBlob';
  132. const BLOBTYPE_PAGE = 'PageBlob';
  133. /**
  134. * Put page write options
  135. */
  136. const PAGE_WRITE_UPDATE = 'update';
  137. const PAGE_WRITE_CLEAR = 'clear';
  138. /**
  139. * Stream wrapper clients
  140. *
  141. * @var array
  142. */
  143. protected static $_wrapperClients = array();
  144. /**
  145. * SharedAccessSignature credentials
  146. *
  147. * @var Microsoft_WindowsAzure_Credentials_SharedAccessSignature
  148. */
  149. private $_sharedAccessSignatureCredentials = null;
  150. /**
  151. * Creates a new Microsoft_WindowsAzure_Storage_Blob instance
  152. *
  153. * @param string $host Storage host name
  154. * @param string $accountName Account name for Windows Azure
  155. * @param string $accountKey Account key for Windows Azure
  156. * @param boolean $usePathStyleUri Use path-style URI's
  157. * @param Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
  158. */
  159. public function __construct($host = Microsoft_WindowsAzure_Storage::URL_DEV_BLOB, $accountName = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_ACCOUNT, $accountKey = Microsoft_WindowsAzure_Credentials_CredentialsAbstract::DEVSTORE_KEY, $usePathStyleUri = false, Microsoft_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
  160. {
  161. parent::__construct($host, $accountName, $accountKey, $usePathStyleUri, $retryPolicy);
  162. // API version
  163. $this->_apiVersion = '2009-09-19';
  164. // SharedAccessSignature credentials
  165. $this->_sharedAccessSignatureCredentials = new Microsoft_WindowsAzure_Credentials_SharedAccessSignature($accountName, $accountKey, $usePathStyleUri);
  166. }
  167. /**
  168. * Check if a blob exists
  169. *
  170. * @param string $containerName Container name
  171. * @param string $blobName Blob name
  172. * @param string $snapshotId Snapshot identifier
  173. * @return boolean
  174. */
  175. public function blobExists($containerName = '', $blobName = '', $snapshotId = null)
  176. {
  177. if ($containerName === '') {
  178. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  179. }
  180. if (!self::isValidContainerName($containerName)) {
  181. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  182. }
  183. if ($blobName === '') {
  184. throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  185. }
  186. // Get blob instance
  187. try {
  188. $this->getBlobInstance($containerName, $blobName, $snapshotId);
  189. } catch (Microsoft_WindowsAzure_Exception $e) {
  190. return false;
  191. }
  192. return true;
  193. }
  194. /**
  195. * Check if a container exists
  196. *
  197. * @param string $containerName Container name
  198. * @return boolean
  199. */
  200. public function containerExists($containerName = '')
  201. {
  202. if ($containerName === '') {
  203. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  204. }
  205. if (!self::isValidContainerName($containerName)) {
  206. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  207. }
  208. // List containers
  209. $containers = $this->listContainers($containerName, 1);
  210. foreach ($containers as $container) {
  211. if ($container->Name == $containerName) {
  212. return true;
  213. }
  214. }
  215. return false;
  216. }
  217. /**
  218. * Create container
  219. *
  220. * @param string $containerName Container name
  221. * @param array $metadata Key/value pairs of meta data
  222. * @return object Container properties
  223. * @throws Microsoft_WindowsAzure_Exception
  224. */
  225. public function createContainer($containerName = '', $metadata = array())
  226. {
  227. if ($containerName === '') {
  228. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  229. }
  230. if (!self::isValidContainerName($containerName)) {
  231. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  232. }
  233. if (!is_array($metadata)) {
  234. throw new Microsoft_WindowsAzure_Exception('Meta data should be an array of key and value pairs.');
  235. }
  236. // Create metadata headers
  237. $headers = array();
  238. $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
  239. // Perform request
  240. $response = $this->_performRequest($containerName, '?restype=container', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  241. if ($response->isSuccessful()) {
  242. return new Microsoft_WindowsAzure_Storage_BlobContainer(
  243. $containerName,
  244. $response->getHeader('Etag'),
  245. $response->getHeader('Last-modified'),
  246. $metadata
  247. );
  248. } else {
  249. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  250. }
  251. }
  252. /**
  253. * Create container if it does not exist
  254. *
  255. * @param string $containerName Container name
  256. * @param array $metadata Key/value pairs of meta data
  257. * @throws Microsoft_WindowsAzure_Exception
  258. */
  259. public function createContainerIfNotExists($containerName = '', $metadata = array())
  260. {
  261. if (!$this->containerExists($containerName)) {
  262. $this->createContainer($containerName, $metadata);
  263. }
  264. }
  265. /**
  266. * Get container ACL
  267. *
  268. * @param string $containerName Container name
  269. * @param bool $signedIdentifiers Display only private/blob/container or display signed identifiers?
  270. * @return string Acl, to be compared with Microsoft_WindowsAzure_Storage_Blob::ACL_*
  271. * @throws Microsoft_WindowsAzure_Exception
  272. */
  273. public function getContainerAcl($containerName = '', $signedIdentifiers = false)
  274. {
  275. if ($containerName === '') {
  276. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  277. }
  278. if (!self::isValidContainerName($containerName)) {
  279. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  280. }
  281. // Perform request
  282. $response = $this->_performRequest($containerName, '?restype=container&comp=acl', Microsoft_Http_Client::GET, array(), false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
  283. if ($response->isSuccessful()) {
  284. if ($signedIdentifiers == false) {
  285. // Only private/blob/container
  286. $accessType = $response->getHeader(Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-public-access');
  287. if (strtolower($accessType) == 'true') {
  288. $accessType = self::ACL_PUBLIC_CONTAINER;
  289. }
  290. return $accessType;
  291. } else {
  292. // Parse result
  293. $result = $this->_parseResponse($response);
  294. if (!$result) {
  295. return array();
  296. }
  297. $entries = null;
  298. if ($result->SignedIdentifier) {
  299. if (count($result->SignedIdentifier) > 1) {
  300. $entries = $result->SignedIdentifier;
  301. } else {
  302. $entries = array($result->SignedIdentifier);
  303. }
  304. }
  305. // Return value
  306. $returnValue = array();
  307. foreach ($entries as $entry) {
  308. $returnValue[] = new Microsoft_WindowsAzure_Storage_SignedIdentifier(
  309. $entry->Id,
  310. $entry->AccessPolicy ? $entry->AccessPolicy->Start ? $entry->AccessPolicy->Start : '' : '',
  311. $entry->AccessPolicy ? $entry->AccessPolicy->Expiry ? $entry->AccessPolicy->Expiry : '' : '',
  312. $entry->AccessPolicy ? $entry->AccessPolicy->Permission ? $entry->AccessPolicy->Permission : '' : ''
  313. );
  314. }
  315. // Return
  316. return $returnValue;
  317. }
  318. } else {
  319. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  320. }
  321. }
  322. /**
  323. * Set container ACL
  324. *
  325. * @param string $containerName Container name
  326. * @param bool $acl Microsoft_WindowsAzure_Storage_Blob::ACL_*
  327. * @param array $signedIdentifiers Signed identifiers
  328. * @throws Microsoft_WindowsAzure_Exception
  329. */
  330. public function setContainerAcl($containerName = '', $acl = self::ACL_PRIVATE, $signedIdentifiers = array())
  331. {
  332. if ($containerName === '') {
  333. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  334. }
  335. if (!self::isValidContainerName($containerName)) {
  336. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  337. }
  338. // Headers
  339. $headers = array();
  340. // Acl specified?
  341. if ($acl != self::ACL_PRIVATE && !is_null($acl) && $acl != '') {
  342. $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-public-access'] = $acl;
  343. }
  344. // Policies
  345. $policies = null;
  346. if (is_array($signedIdentifiers) && count($signedIdentifiers) > 0) {
  347. $policies = '';
  348. $policies .= '<?xml version="1.0" encoding="utf-8"?>' . "\r\n";
  349. $policies .= '<SignedIdentifiers>' . "\r\n";
  350. foreach ($signedIdentifiers as $signedIdentifier) {
  351. $policies .= ' <SignedIdentifier>' . "\r\n";
  352. $policies .= ' <Id>' . $signedIdentifier->Id . '</Id>' . "\r\n";
  353. $policies .= ' <AccessPolicy>' . "\r\n";
  354. if ($signedIdentifier->Start != '')
  355. $policies .= ' <Start>' . $signedIdentifier->Start . '</Start>' . "\r\n";
  356. if ($signedIdentifier->Expiry != '')
  357. $policies .= ' <Expiry>' . $signedIdentifier->Expiry . '</Expiry>' . "\r\n";
  358. if ($signedIdentifier->Permissions != '')
  359. $policies .= ' <Permission>' . $signedIdentifier->Permissions . '</Permission>' . "\r\n";
  360. $policies .= ' </AccessPolicy>' . "\r\n";
  361. $policies .= ' </SignedIdentifier>' . "\r\n";
  362. }
  363. $policies .= '</SignedIdentifiers>' . "\r\n";
  364. }
  365. // Perform request
  366. $response = $this->_performRequest($containerName, '?restype=container&comp=acl', Microsoft_Http_Client::PUT, $headers, false, $policies, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  367. if (!$response->isSuccessful()) {
  368. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  369. }
  370. }
  371. /**
  372. * Get container
  373. *
  374. * @param string $containerName Container name
  375. * @return Microsoft_WindowsAzure_Storage_BlobContainer
  376. * @throws Microsoft_WindowsAzure_Exception
  377. */
  378. public function getContainer($containerName = '')
  379. {
  380. if ($containerName === '') {
  381. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  382. }
  383. if (!self::isValidContainerName($containerName)) {
  384. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  385. }
  386. // Perform request
  387. $response = $this->_performRequest($containerName, '?restype=container', Microsoft_Http_Client::GET, array(), false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
  388. if ($response->isSuccessful()) {
  389. // Parse metadata
  390. $metadata = $this->_parseMetadataHeaders($response->getHeaders());
  391. // Return container
  392. return new Microsoft_WindowsAzure_Storage_BlobContainer(
  393. $containerName,
  394. $response->getHeader('Etag'),
  395. $response->getHeader('Last-modified'),
  396. $metadata
  397. );
  398. } else {
  399. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  400. }
  401. }
  402. /**
  403. * Get container metadata
  404. *
  405. * @param string $containerName Container name
  406. * @return array Key/value pairs of meta data
  407. * @throws Microsoft_WindowsAzure_Exception
  408. */
  409. public function getContainerMetadata($containerName = '')
  410. {
  411. if ($containerName === '') {
  412. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  413. }
  414. if (!self::isValidContainerName($containerName)) {
  415. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  416. }
  417. return $this->getContainer($containerName)->Metadata;
  418. }
  419. /**
  420. * Set container metadata
  421. *
  422. * 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.
  423. *
  424. * @param string $containerName Container name
  425. * @param array $metadata Key/value pairs of meta data
  426. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  427. * @throws Microsoft_WindowsAzure_Exception
  428. */
  429. public function setContainerMetadata($containerName = '', $metadata = array(), $additionalHeaders = array())
  430. {
  431. if ($containerName === '') {
  432. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  433. }
  434. if (!self::isValidContainerName($containerName)) {
  435. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  436. }
  437. if (!is_array($metadata)) {
  438. throw new Microsoft_WindowsAzure_Exception('Meta data should be an array of key and value pairs.');
  439. }
  440. if (count($metadata) == 0) {
  441. return;
  442. }
  443. // Create metadata headers
  444. $headers = array();
  445. $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
  446. // Additional headers?
  447. foreach ($additionalHeaders as $key => $value) {
  448. $headers[$key] = $value;
  449. }
  450. // Perform request
  451. $response = $this->_performRequest($containerName, '?restype=container&comp=metadata', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  452. if (!$response->isSuccessful()) {
  453. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  454. }
  455. }
  456. /**
  457. * Delete container
  458. *
  459. * @param string $containerName Container name
  460. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  461. * @throws Microsoft_WindowsAzure_Exception
  462. */
  463. public function deleteContainer($containerName = '', $additionalHeaders = array())
  464. {
  465. if ($containerName === '') {
  466. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  467. }
  468. if (!self::isValidContainerName($containerName)) {
  469. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  470. }
  471. // Additional headers?
  472. $headers = array();
  473. foreach ($additionalHeaders as $key => $value) {
  474. $headers[$key] = $value;
  475. }
  476. // Perform request
  477. $response = $this->_performRequest($containerName, '?restype=container', Microsoft_Http_Client::DELETE, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  478. if (!$response->isSuccessful()) {
  479. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  480. }
  481. }
  482. /**
  483. * List containers
  484. *
  485. * @param string $prefix Optional. Filters the results to return only containers whose name begins with the specified prefix.
  486. * @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)
  487. * @param string $marker Optional string value that identifies the portion of the list to be returned with the next list operation.
  488. * @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')
  489. * @param int $currentResultCount Current result count (internal use)
  490. * @return array
  491. * @throws Microsoft_WindowsAzure_Exception
  492. */
  493. public function listContainers($prefix = null, $maxResults = null, $marker = null, $include = null, $currentResultCount = 0)
  494. {
  495. // Build query string
  496. $queryString = array('comp=list');
  497. if (!is_null($prefix)) {
  498. $queryString[] = 'prefix=' . $prefix;
  499. }
  500. if (!is_null($maxResults)) {
  501. $queryString[] = 'maxresults=' . $maxResults;
  502. }
  503. if (!is_null($marker)) {
  504. $queryString[] = 'marker=' . $marker;
  505. }
  506. if (!is_null($include)) {
  507. $queryString[] = 'include=' . $include;
  508. }
  509. $queryString = self::createQueryStringFromArray($queryString);
  510. // Perform request
  511. $response = $this->_performRequest('', $queryString, Microsoft_Http_Client::GET, array(), false, null, Microsoft_WindowsAzure_Storage::RESOURCE_CONTAINER, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_LIST);
  512. if ($response->isSuccessful()) {
  513. $xmlContainers = $this->_parseResponse($response)->Containers->Container;
  514. $xmlMarker = (string)$this->_parseResponse($response)->NextMarker;
  515. $containers = array();
  516. if (!is_null($xmlContainers)) {
  517. for ($i = 0; $i < count($xmlContainers); $i++) {
  518. $containers[] = new Microsoft_WindowsAzure_Storage_BlobContainer(
  519. (string)$xmlContainers[$i]->Name,
  520. (string)$xmlContainers[$i]->Etag,
  521. (string)$xmlContainers[$i]->LastModified,
  522. $this->_parseMetadataElement($xmlContainers[$i])
  523. );
  524. }
  525. }
  526. $currentResultCount = $currentResultCount + count($containers);
  527. if (!is_null($maxResults) && $currentResultCount < $maxResults) {
  528. if (!is_null($xmlMarker) && $xmlMarker != '') {
  529. $containers = array_merge($containers, $this->listContainers($prefix, $maxResults, $xmlMarker, $include, $currentResultCount));
  530. }
  531. }
  532. if (!is_null($maxResults) && count($containers) > $maxResults) {
  533. $containers = array_slice($containers, 0, $maxResults);
  534. }
  535. return $containers;
  536. } else {
  537. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  538. }
  539. }
  540. /**
  541. * Put blob
  542. *
  543. * @param string $containerName Container name
  544. * @param string $blobName Blob name
  545. * @param string $localFileName Local file name to be uploaded
  546. * @param array $metadata Key/value pairs of meta data
  547. * @param string $leaseId Lease identifier
  548. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  549. * @return object Partial blob properties
  550. * @throws Microsoft_WindowsAzure_Exception
  551. */
  552. public function putBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
  553. {
  554. if ($containerName === '') {
  555. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  556. }
  557. if (!self::isValidContainerName($containerName)) {
  558. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  559. }
  560. if ($blobName === '') {
  561. throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  562. }
  563. if ($localFileName === '') {
  564. throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
  565. }
  566. if (!file_exists($localFileName)) {
  567. throw new Microsoft_WindowsAzure_Exception('Local file not found.');
  568. }
  569. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  570. throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  571. }
  572. // Check file size
  573. if (filesize($localFileName) >= self::MAX_BLOB_SIZE) {
  574. return $this->putLargeBlob($containerName, $blobName, $localFileName, $metadata, $leaseId, $additionalHeaders);
  575. }
  576. // Put the data to Windows Azure Storage
  577. return $this->putBlobData($containerName, $blobName, file_get_contents($localFileName), $metadata, $leaseId, $additionalHeaders);
  578. }
  579. /**
  580. * Put blob data
  581. *
  582. * @param string $containerName Container name
  583. * @param string $blobName Blob name
  584. * @param mixed $data Data to store
  585. * @param array $metadata Key/value pairs of meta data
  586. * @param string $leaseId Lease identifier
  587. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  588. * @return object Partial blob properties
  589. * @throws Microsoft_WindowsAzure_Exception
  590. */
  591. public function putBlobData($containerName = '', $blobName = '', $data = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
  592. {
  593. if ($containerName === '') {
  594. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  595. }
  596. if (!self::isValidContainerName($containerName)) {
  597. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  598. }
  599. if ($blobName === '') {
  600. throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  601. }
  602. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  603. throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  604. }
  605. // Create metadata headers
  606. $headers = array();
  607. if (!is_null($leaseId)) {
  608. $headers['x-ms-lease-id'] = $leaseId;
  609. }
  610. $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
  611. // Additional headers?
  612. foreach ($additionalHeaders as $key => $value) {
  613. $headers[$key] = $value;
  614. }
  615. // Specify blob type
  616. $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-type'] = self::BLOBTYPE_BLOCK;
  617. // Resource name
  618. $resourceName = self::createResourceName($containerName , $blobName);
  619. // Perform request
  620. $response = $this->_performRequest($resourceName, '', Microsoft_Http_Client::PUT, $headers, false, $data, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  621. if ($response->isSuccessful()) {
  622. return new Microsoft_WindowsAzure_Storage_BlobInstance(
  623. $containerName,
  624. $blobName,
  625. null,
  626. $response->getHeader('Etag'),
  627. $response->getHeader('Last-modified'),
  628. $this->getBaseUrl() . '/' . $containerName . '/' . $blobName,
  629. strlen($data),
  630. '',
  631. '',
  632. '',
  633. '',
  634. false,
  635. $metadata
  636. );
  637. } else {
  638. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  639. }
  640. }
  641. /**
  642. * Put large blob (> 64 MB)
  643. *
  644. * @param string $containerName Container name
  645. * @param string $blobName Blob name
  646. * @param string $localFileName Local file name to be uploaded
  647. * @param array $metadata Key/value pairs of meta data
  648. * @param string $leaseId Lease identifier
  649. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  650. * @return object Partial blob properties
  651. * @throws Microsoft_WindowsAzure_Exception
  652. */
  653. public function putLargeBlob($containerName = '', $blobName = '', $localFileName = '', $metadata = array(), $leaseId = null, $additionalHeaders = array())
  654. {
  655. if ($containerName === '') {
  656. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  657. }
  658. if (!self::isValidContainerName($containerName)) {
  659. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  660. }
  661. if ($blobName === '') {
  662. throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  663. }
  664. if ($localFileName === '') {
  665. throw new Microsoft_WindowsAzure_Exception('Local file name is not specified.');
  666. }
  667. if (!file_exists($localFileName)) {
  668. throw new Microsoft_WindowsAzure_Exception('Local file not found.');
  669. }
  670. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  671. throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  672. }
  673. // Check file size
  674. if (filesize($localFileName) < self::MAX_BLOB_SIZE) {
  675. return $this->putBlob($containerName, $blobName, $localFileName, $metadata, $leaseId, $additionalHeaders);
  676. }
  677. // Determine number of parts
  678. $numberOfParts = ceil( filesize($localFileName) / self::MAX_BLOB_TRANSFER_SIZE );
  679. // Generate block id's
  680. $blockIdentifiers = array();
  681. for ($i = 0; $i < $numberOfParts; $i++) {
  682. $blockIdentifiers[] = $this->_generateBlockId($i);
  683. }
  684. // Open file
  685. $fp = fopen($localFileName, 'r');
  686. if ($fp === false) {
  687. throw new Microsoft_WindowsAzure_Exception('Could not open local file.');
  688. }
  689. // Upload parts
  690. for ($i = 0; $i < $numberOfParts; $i++) {
  691. // Seek position in file
  692. fseek($fp, $i * self::MAX_BLOB_TRANSFER_SIZE);
  693. // Read contents
  694. $fileContents = fread($fp, self::MAX_BLOB_TRANSFER_SIZE);
  695. // Put block
  696. $this->putBlock($containerName, $blobName, $blockIdentifiers[$i], $fileContents, $leaseId);
  697. // Dispose file contents
  698. $fileContents = null;
  699. unset($fileContents);
  700. }
  701. // Close file
  702. fclose($fp);
  703. // Put block list
  704. $this->putBlockList($containerName, $blobName, $blockIdentifiers, $metadata, $leaseId, $additionalHeaders);
  705. // Return information of the blob
  706. return $this->getBlobInstance($containerName, $blobName, null, $leaseId);
  707. }
  708. /**
  709. * Put large blob block
  710. *
  711. * @param string $containerName Container name
  712. * @param string $blobName Blob name
  713. * @param string $identifier Block ID
  714. * @param array $contents Contents of the block
  715. * @param string $leaseId Lease identifier
  716. * @throws Microsoft_WindowsAzure_Exception
  717. */
  718. public function putBlock($containerName = '', $blobName = '', $identifier = '', $contents = '', $leaseId = null)
  719. {
  720. if ($containerName === '') {
  721. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  722. }
  723. if (!self::isValidContainerName($containerName)) {
  724. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  725. }
  726. if ($identifier === '') {
  727. throw new Microsoft_WindowsAzure_Exception('Block identifier is not specified.');
  728. }
  729. if (strlen($contents) > self::MAX_BLOB_TRANSFER_SIZE) {
  730. throw new Microsoft_WindowsAzure_Exception('Block size is too big.');
  731. }
  732. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  733. throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  734. }
  735. // Headers
  736. $headers = array();
  737. if (!is_null($leaseId)) {
  738. $headers['x-ms-lease-id'] = $leaseId;
  739. }
  740. // Resource name
  741. $resourceName = self::createResourceName($containerName , $blobName);
  742. // Upload
  743. $response = $this->_performRequest($resourceName, '?comp=block&blockid=' . base64_encode($identifier), Microsoft_Http_Client::PUT, $headers, false, $contents, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  744. if (!$response->isSuccessful()) {
  745. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  746. }
  747. }
  748. /**
  749. * Put block list
  750. *
  751. * @param string $containerName Container name
  752. * @param string $blobName Blob name
  753. * @param array $blockList Array of block identifiers
  754. * @param array $metadata Key/value pairs of meta data
  755. * @param string $leaseId Lease identifier
  756. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  757. * @throws Microsoft_WindowsAzure_Exception
  758. */
  759. public function putBlockList($containerName = '', $blobName = '', $blockList = array(), $metadata = array(), $leaseId = null, $additionalHeaders = array())
  760. {
  761. if ($containerName === '') {
  762. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  763. }
  764. if (!self::isValidContainerName($containerName)) {
  765. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  766. }
  767. if ($blobName === '') {
  768. throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  769. }
  770. if (count($blockList) == 0) {
  771. throw new Microsoft_WindowsAzure_Exception('Block list does not contain any elements.');
  772. }
  773. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  774. throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  775. }
  776. // Generate block list
  777. $blocks = '';
  778. foreach ($blockList as $block) {
  779. $blocks .= ' <Latest>' . base64_encode($block) . '</Latest>' . "\n";
  780. }
  781. // Generate block list request
  782. $fileContents = utf8_encode(implode("\n", array(
  783. '<?xml version="1.0" encoding="utf-8"?>',
  784. '<BlockList>',
  785. $blocks,
  786. '</BlockList>'
  787. )));
  788. // Create metadata headers
  789. $headers = array();
  790. if (!is_null($leaseId)) {
  791. $headers['x-ms-lease-id'] = $leaseId;
  792. }
  793. $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
  794. // Additional headers?
  795. foreach ($additionalHeaders as $key => $value) {
  796. $headers[$key] = $value;
  797. }
  798. // Resource name
  799. $resourceName = self::createResourceName($containerName , $blobName);
  800. // Perform request
  801. $response = $this->_performRequest($resourceName, '?comp=blocklist', Microsoft_Http_Client::PUT, $headers, false, $fileContents, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  802. if (!$response->isSuccessful()) {
  803. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  804. }
  805. }
  806. /**
  807. * Get block list
  808. *
  809. * @param string $containerName Container name
  810. * @param string $blobName Blob name
  811. * @param string $snapshotId Snapshot identifier
  812. * @param string $leaseId Lease identifier
  813. * @param integer $type Type of block list to retrieve. 0 = all, 1 = committed, 2 = uncommitted
  814. * @return array
  815. * @throws Microsoft_WindowsAzure_Exception
  816. */
  817. public function getBlockList($containerName = '', $blobName = '', $snapshotId = null, $leaseId = null, $type = 0)
  818. {
  819. if ($containerName === '') {
  820. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  821. }
  822. if (!self::isValidContainerName($containerName)) {
  823. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  824. }
  825. if ($blobName === '') {
  826. throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  827. }
  828. if ($type < 0 || $type > 2) {
  829. throw new Microsoft_WindowsAzure_Exception('Invalid type of block list to retrieve.');
  830. }
  831. // Set $blockListType
  832. $blockListType = 'all';
  833. if ($type == 1) {
  834. $blockListType = 'committed';
  835. }
  836. if ($type == 2) {
  837. $blockListType = 'uncommitted';
  838. }
  839. // Headers
  840. $headers = array();
  841. if (!is_null($leaseId)) {
  842. $headers['x-ms-lease-id'] = $leaseId;
  843. }
  844. // Build query string
  845. $queryString = array('comp=blocklist', 'blocklisttype=' . $blockListType);
  846. if (!is_null($snapshotId)) {
  847. $queryString[] = 'snapshot=' . $snapshotId;
  848. }
  849. $queryString = self::createQueryStringFromArray($queryString);
  850. // Resource name
  851. $resourceName = self::createResourceName($containerName , $blobName);
  852. // Perform request
  853. $response = $this->_performRequest($resourceName, $queryString, Microsoft_Http_Client::GET, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_READ);
  854. if ($response->isSuccessful()) {
  855. // Parse response
  856. $blockList = $this->_parseResponse($response);
  857. // Create return value
  858. $returnValue = array();
  859. if ($blockList->CommittedBlocks) {
  860. foreach ($blockList->CommittedBlocks->Block as $block) {
  861. $returnValue['CommittedBlocks'][] = (object)array(
  862. 'Name' => (string)$block->Name,
  863. 'Size' => (string)$block->Size
  864. );
  865. }
  866. }
  867. if ($blockList->UncommittedBlocks) {
  868. foreach ($blockList->UncommittedBlocks->Block as $block) {
  869. $returnValue['UncommittedBlocks'][] = (object)array(
  870. 'Name' => (string)$block->Name,
  871. 'Size' => (string)$block->Size
  872. );
  873. }
  874. }
  875. return $returnValue;
  876. } else {
  877. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  878. }
  879. }
  880. /**
  881. * Create page blob
  882. *
  883. * @param string $containerName Container name
  884. * @param string $blobName Blob name
  885. * @param int $size Size of the page blob in bytes
  886. * @param array $metadata Key/value pairs of meta data
  887. * @param string $leaseId Lease identifier
  888. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  889. * @return object Partial blob properties
  890. * @throws Microsoft_WindowsAzure_Exception
  891. */
  892. public function createPageBlob($containerName = '', $blobName = '', $size = 0, $metadata = array(), $leaseId = null, $additionalHeaders = array())
  893. {
  894. if ($containerName === '') {
  895. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  896. }
  897. if (!self::isValidContainerName($containerName)) {
  898. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  899. }
  900. if ($blobName === '') {
  901. throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  902. }
  903. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  904. throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  905. }
  906. if ($size <= 0) {
  907. throw new Microsoft_WindowsAzure_Exception('Page blob size must be specified.');
  908. }
  909. // Create metadata headers
  910. $headers = array();
  911. if (!is_null($leaseId)) {
  912. $headers['x-ms-lease-id'] = $leaseId;
  913. }
  914. $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
  915. // Additional headers?
  916. foreach ($additionalHeaders as $key => $value) {
  917. $headers[$key] = $value;
  918. }
  919. // Specify blob type & blob length
  920. $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-type'] = self::BLOBTYPE_PAGE;
  921. $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'blob-content-length'] = $size;
  922. $headers['Content-Length'] = 0;
  923. // Resource name
  924. $resourceName = self::createResourceName($containerName , $blobName);
  925. // Perform request
  926. $response = $this->_performRequest($resourceName, '', Microsoft_Http_Client::PUT, $headers, false, '', Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  927. if ($response->isSuccessful()) {
  928. return new Microsoft_WindowsAzure_Storage_BlobInstance(
  929. $containerName,
  930. $blobName,
  931. null,
  932. $response->getHeader('Etag'),
  933. $response->getHeader('Last-modified'),
  934. $this->getBaseUrl() . '/' . $containerName . '/' . $blobName,
  935. $size,
  936. '',
  937. '',
  938. '',
  939. '',
  940. false,
  941. $metadata
  942. );
  943. } else {
  944. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  945. }
  946. }
  947. /**
  948. * Put page in page blob
  949. *
  950. * @param string $containerName Container name
  951. * @param string $blobName Blob name
  952. * @param int $startByteOffset Start byte offset
  953. * @param int $endByteOffset End byte offset
  954. * @param mixed $contents Page contents
  955. * @param string $writeMethod Write method (Microsoft_WindowsAzure_Storage_Blob::PAGE_WRITE_*)
  956. * @param string $leaseId Lease identifier
  957. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd179371.aspx for more information.
  958. * @throws Microsoft_WindowsAzure_Exception
  959. */
  960. public function putPage($containerName = '', $blobName = '', $startByteOffset = 0, $endByteOffset = 0, $contents = '', $writeMethod = self::PAGE_WRITE_UPDATE, $leaseId = null, $additionalHeaders = array())
  961. {
  962. if ($containerName === '') {
  963. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  964. }
  965. if (!self::isValidContainerName($containerName)) {
  966. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  967. }
  968. if ($blobName === '') {
  969. throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  970. }
  971. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  972. throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  973. }
  974. if ($startByteOffset % 512 != 0) {
  975. throw new Microsoft_WindowsAzure_Exception('Start byte offset must be a modulus of 512.');
  976. }
  977. if (($endByteOffset + 1) % 512 != 0) {
  978. throw new Microsoft_WindowsAzure_Exception('End byte offset must be a modulus of 512 minus 1.');
  979. }
  980. // Determine size
  981. $size = strlen($contents);
  982. if ($size >= self::MAX_BLOB_TRANSFER_SIZE) {
  983. throw new Microsoft_WindowsAzure_Exception('Page blob size must not be larger than ' + self::MAX_BLOB_TRANSFER_SIZE . ' bytes.');
  984. }
  985. // Create metadata headers
  986. $headers = array();
  987. if (!is_null($leaseId)) {
  988. $headers['x-ms-lease-id'] = $leaseId;
  989. }
  990. // Additional headers?
  991. foreach ($additionalHeaders as $key => $value) {
  992. $headers[$key] = $value;
  993. }
  994. // Specify range
  995. $headers['Range'] = 'bytes=' . $startByteOffset . '-' . $endByteOffset;
  996. // Write method
  997. $headers[Microsoft_WindowsAzure_Storage::PREFIX_STORAGE_HEADER . 'page-write'] = $writeMethod;
  998. // Resource name
  999. $resourceName = self::createResourceName($containerName , $blobName);
  1000. // Perform request
  1001. $response = $this->_performRequest($resourceName, '?comp=page', Microsoft_Http_Client::PUT, $headers, false, $contents, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  1002. if (!$response->isSuccessful()) {
  1003. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  1004. }
  1005. }
  1006. /**
  1007. * Put page in page blob
  1008. *
  1009. * @param string $containerName Container name
  1010. * @param string $blobName Blob name
  1011. * @param int $startByteOffset Start byte offset
  1012. * @param int $endByteOffset End byte offset
  1013. * @param string $leaseId Lease identifier
  1014. * @return array Array of page ranges
  1015. * @throws Microsoft_WindowsAzure_Exception
  1016. */
  1017. public function getPageRegions($containerName = '', $blobName = '', $startByteOffset = 0, $endByteOffset = 0, $leaseId = null)
  1018. {
  1019. if ($containerName === '') {
  1020. throw new Microsoft_WindowsAzure_Exception('Container name is not specified.');
  1021. }
  1022. if (!self::isValidContainerName($containerName)) {
  1023. throw new Microsoft_WindowsAzure_Exception('Container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1024. }
  1025. if ($blobName === '') {
  1026. throw new Microsoft_WindowsAzure_Exception('Blob name is not specified.');
  1027. }
  1028. if ($containerName === '$root' && strpos($blobName, '/') !== false) {
  1029. throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1030. }
  1031. if ($startByteOffset % 512 != 0) {
  1032. throw new Microsoft_WindowsAzure_Exception('Start byte offset must be a modulus of 512.');
  1033. }
  1034. if ($endByteOffset > 0 && ($endByteOffset + 1) % 512 != 0) {
  1035. throw new Microsoft_WindowsAzure_Exception('End byte offset must be a modulus of 512 minus 1.');
  1036. }
  1037. // Create metadata headers
  1038. $headers = array();
  1039. if (!is_null($leaseId)) {
  1040. $headers['x-ms-lease-id'] = $leaseId;
  1041. }
  1042. // Specify range?
  1043. if ($endByteOffset > 0) {
  1044. $headers['Range'] = 'bytes=' . $startByteOffset . '-' . $endByteOffset;
  1045. }
  1046. // Resource name
  1047. $resourceName = self::createResourceName($containerName , $blobName);
  1048. // Perform request
  1049. $response = $this->_performRequest($resourceName, '?comp=pagelist', Microsoft_Http_Client::GET, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  1050. if ($response->isSuccessful()) {
  1051. $result = $this->_parseResponse($response);
  1052. $xmlRanges = null;
  1053. if (count($result->PageRange) > 1) {
  1054. $xmlRanges = $result->PageRange;
  1055. } else {
  1056. $xmlRanges = array($result->PageRange);
  1057. }
  1058. $ranges = array();
  1059. for ($i = 0; $i < count($xmlRanges); $i++) {
  1060. $ranges[] = new Microsoft_WindowsAzure_Storage_PageRegionInstance(
  1061. (int)$xmlRanges[$i]->Start,
  1062. (int)$xmlRanges[$i]->End
  1063. );
  1064. }
  1065. return $ranges;
  1066. } else {
  1067. throw new Microsoft_WindowsAzure_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
  1068. }
  1069. }
  1070. /**
  1071. * Copy blob
  1072. *
  1073. * @param string $sourceContainerName Source container name
  1074. * @param string $sourceBlobName Source blob name
  1075. * @param string $destinationContainerName Destination container name
  1076. * @param string $destinationBlobName Destination blob name
  1077. * @param array $metadata Key/value pairs of meta data
  1078. * @param string $sourceSnapshotId Source snapshot identifier
  1079. * @param string $destinationLeaseId Destination lease identifier
  1080. * @param array $additionalHeaders Additional headers. See http://msdn.microsoft.com/en-us/library/dd894037.aspx for more information.
  1081. * @return object Partial blob properties
  1082. * @throws Microsoft_WindowsAzure_Exception
  1083. */
  1084. public function copyBlob($sourceContainerName = '', $sourceBlobName = '', $destinationContainerName = '', $destinationBlobName = '', $metadata = array(), $sourceSnapshotId = null, $destinationLeaseId = null, $additionalHeaders = array())
  1085. {
  1086. if ($sourceContainerName === '') {
  1087. throw new Microsoft_WindowsAzure_Exception('Source container name is not specified.');
  1088. }
  1089. if (!self::isValidContainerName($sourceContainerName)) {
  1090. throw new Microsoft_WindowsAzure_Exception('Source container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1091. }
  1092. if ($sourceBlobName === '') {
  1093. throw new Microsoft_WindowsAzure_Exception('Source blob name is not specified.');
  1094. }
  1095. if ($destinationContainerName === '') {
  1096. throw new Microsoft_WindowsAzure_Exception('Destination container name is not specified.');
  1097. }
  1098. if (!self::isValidContainerName($destinationContainerName)) {
  1099. throw new Microsoft_WindowsAzure_Exception('Destination container name does not adhere to container naming conventions. See http://msdn.microsoft.com/en-us/library/dd135715.aspx for more information.');
  1100. }
  1101. if ($destinationBlobName === '') {
  1102. throw new Microsoft_WindowsAzure_Exception('Destination blob name is not specified.');
  1103. }
  1104. if ($sourceContainerName === '$root' && strpos($sourceBlobName, '/') !== false) {
  1105. throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1106. }
  1107. if ($destinationContainerName === '$root' && strpos($destinationBlobName, '/') !== false) {
  1108. throw new Microsoft_WindowsAzure_Exception('Blobs stored in the root container can not have a name containing a forward slash (/).');
  1109. }
  1110. // Create metadata headers
  1111. $headers = array();
  1112. if (!is_null($destinationLeaseId)) {
  1113. $headers['x-ms-lease-id'] = $destinationLeaseId;
  1114. }
  1115. $headers = array_merge($headers, $this->_generateMetadataHeaders($metadata));
  1116. // Additional headers?
  1117. foreach ($additionalHeaders as $key => $value) {
  1118. $headers[$key] = $value;
  1119. }
  1120. // Resource names
  1121. $sourceResourceName = self::createResourceName($sourceContainerName, $sourceBlobName);
  1122. if (!is_null($sourceSnapshotId)) {
  1123. $sourceResourceName .= '?snapshot=' . $sourceSnapshotId;
  1124. }
  1125. $destinationResourceName = self::createResourceName($destinationContainerName, $destinationBlobName);
  1126. // Set source blob
  1127. $headers["x-ms-copy-source"] = '/' . $this->_accountName . '/' . $sourceResourceName;
  1128. // Perform request
  1129. $response = $this->_performRequest($destinationResourceName, '', Microsoft_Http_Client::PUT, $headers, false, null, Microsoft_WindowsAzure_Storage::RESOURCE_BLOB, Microsoft_WindowsAzure_Credentials_CredentialsAbstract::PERMISSION_WRITE);
  1130. if ($response->isSuccessful()) {
  1131. return new Microsoft_WindowsAzure_Storage_BlobInstance(
  1132. $destinationContainerName,
  1133. $destinationBlobName,
  1134. null,
  1135. $response->getHeader('…

Large files files are truncated, but you can click here to view the full file