PageRenderTime 43ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/Microsoft/WindowsAzure/Storage/Blob/Stream.php

https://bitbucket.org/ktos/tinyshare
PHP | 563 lines | 283 code | 60 blank | 220 comment | 31 complexity | 64d24433ccf26b0fc49406bd2bf095ae MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Copyright (c) 2009 - 2011, 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_Storage
  30. * @subpackage Blob
  31. * @copyright Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
  32. * @license http://todo name_todo
  33. * @version $Id: Blob.php 24511 2009-07-28 09:17:56Z unknown $
  34. */
  35. /**
  36. * @see Microsoft_AutoLoader
  37. */
  38. require_once dirname(__FILE__) . '/../../../AutoLoader.php';
  39. /**
  40. * @category Microsoft
  41. * @package Microsoft_WindowsAzure_Storage
  42. * @subpackage Blob
  43. * @copyright Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
  44. * @license http://phpazure.codeplex.com/license
  45. */
  46. class Microsoft_WindowsAzure_Storage_Blob_Stream
  47. {
  48. /**
  49. * Current file name
  50. *
  51. * @var string
  52. */
  53. protected $_fileName = null;
  54. /**
  55. * Temporary file name
  56. *
  57. * @var string
  58. */
  59. protected $_temporaryFileName = null;
  60. /**
  61. * Temporary file handle
  62. *
  63. * @var resource
  64. */
  65. protected $_temporaryFileHandle = null;
  66. /**
  67. * Blob storage client
  68. *
  69. * @var Microsoft_WindowsAzure_Storage_Blob
  70. */
  71. protected $_storageClient = null;
  72. /**
  73. * Write mode?
  74. *
  75. * @var boolean
  76. */
  77. protected $_writeMode = false;
  78. /**
  79. * List of blobs
  80. *
  81. * @var array
  82. */
  83. protected $_blobs = null;
  84. /**
  85. * Retrieve storage client for this stream type
  86. *
  87. * @param string $path
  88. * @return Microsoft_WindowsAzure_Storage_Blob
  89. */
  90. protected function _getStorageClient($path = '')
  91. {
  92. if (is_null($this->_storageClient)) {
  93. $url = explode(':', $path);
  94. if (!$url) {
  95. throw new Microsoft_WindowsAzure_Exception('Could not parse path "' . $path . '".');
  96. }
  97. $this->_storageClient = Microsoft_WindowsAzure_Storage_Blob::getWrapperClient($url[0]);
  98. if (!$this->_storageClient) {
  99. throw new Microsoft_WindowsAzure_Exception('No storage client registered for stream type "' . $url[0] . '://".');
  100. }
  101. }
  102. return $this->_storageClient;
  103. }
  104. /**
  105. * Extract container name
  106. *
  107. * @param string $path
  108. * @return string
  109. */
  110. protected function _getContainerName($path)
  111. {
  112. $url = parse_url($path);
  113. if ($url['host']) {
  114. return $url['host'];
  115. }
  116. return '';
  117. }
  118. /**
  119. * Extract file name
  120. *
  121. * @param string $path
  122. * @return string
  123. */
  124. protected function _getFileName($path)
  125. {
  126. $url = parse_url($path);
  127. if ($url['host']) {
  128. $fileName = isset($url['path']) ? $url['path'] : $url['host'];
  129. if (strpos($fileName, '/') === 0) {
  130. $fileName = substr($fileName, 1);
  131. }
  132. return $fileName;
  133. }
  134. return '';
  135. }
  136. /**
  137. * Open the stream
  138. *
  139. * @param string $path
  140. * @param string $mode
  141. * @param integer $options
  142. * @param string $opened_path
  143. * @return boolean
  144. */
  145. public function stream_open($path, $mode, $options, &$opened_path)
  146. {
  147. $this->_fileName = $path;
  148. $this->_temporaryFileName = tempnam(sys_get_temp_dir(), 'azure');
  149. // Check the file can be opened
  150. $fh = @fopen($this->_temporaryFileName, $mode);
  151. if ($fh === false) {
  152. return false;
  153. }
  154. fclose($fh);
  155. // Write mode?
  156. if (strpbrk($mode, 'wax+')) {
  157. $this->_writeMode = true;
  158. } else {
  159. $this->_writeMode = false;
  160. }
  161. // If read/append, fetch the file
  162. if (!$this->_writeMode || strpbrk($mode, 'ra+')) {
  163. $this->_getStorageClient($this->_fileName)->getBlob(
  164. $this->_getContainerName($this->_fileName),
  165. $this->_getFileName($this->_fileName),
  166. $this->_temporaryFileName
  167. );
  168. }
  169. // Open temporary file handle
  170. $this->_temporaryFileHandle = fopen($this->_temporaryFileName, $mode);
  171. // Ok!
  172. return true;
  173. }
  174. /**
  175. * Close the stream
  176. *
  177. * @return void
  178. */
  179. public function stream_close()
  180. {
  181. @fclose($this->_temporaryFileHandle);
  182. // Upload the file?
  183. if ($this->_writeMode) {
  184. // Make sure the container exists
  185. $containerExists = $this->_getStorageClient($this->_fileName)->containerExists(
  186. $this->_getContainerName($this->_fileName)
  187. );
  188. if (!$containerExists) {
  189. $this->_getStorageClient($this->_fileName)->createContainer(
  190. $this->_getContainerName($this->_fileName)
  191. );
  192. }
  193. // Upload the file
  194. try {
  195. $this->_getStorageClient($this->_fileName)->putBlob(
  196. $this->_getContainerName($this->_fileName),
  197. $this->_getFileName($this->_fileName),
  198. $this->_temporaryFileName
  199. );
  200. } catch (Microsoft_WindowsAzure_Exception $ex) {
  201. @unlink($this->_temporaryFileName);
  202. unset($this->_storageClient);
  203. throw $ex;
  204. }
  205. }
  206. @unlink($this->_temporaryFileName);
  207. unset($this->_storageClient);
  208. }
  209. /**
  210. * Read from the stream
  211. *
  212. * @param integer $count
  213. * @return string
  214. */
  215. public function stream_read($count)
  216. {
  217. if (!$this->_temporaryFileHandle) {
  218. return false;
  219. }
  220. return fread($this->_temporaryFileHandle, $count);
  221. }
  222. /**
  223. * Write to the stream
  224. *
  225. * @param string $data
  226. * @return integer
  227. */
  228. public function stream_write($data)
  229. {
  230. if (!$this->_temporaryFileHandle) {
  231. return 0;
  232. }
  233. $len = strlen($data);
  234. fwrite($this->_temporaryFileHandle, $data, $len);
  235. return $len;
  236. }
  237. /**
  238. * End of the stream?
  239. *
  240. * @return boolean
  241. */
  242. public function stream_eof()
  243. {
  244. if (!$this->_temporaryFileHandle) {
  245. return true;
  246. }
  247. return feof($this->_temporaryFileHandle);
  248. }
  249. /**
  250. * What is the current read/write position of the stream?
  251. *
  252. * @return integer
  253. */
  254. public function stream_tell()
  255. {
  256. return ftell($this->_temporaryFileHandle);
  257. }
  258. /**
  259. * Update the read/write position of the stream
  260. *
  261. * @param integer $offset
  262. * @param integer $whence
  263. * @return boolean
  264. */
  265. public function stream_seek($offset, $whence)
  266. {
  267. if (!$this->_temporaryFileHandle) {
  268. return false;
  269. }
  270. return (fseek($this->_temporaryFileHandle, $offset, $whence) === 0);
  271. }
  272. /**
  273. * Flush current cached stream data to storage
  274. *
  275. * @return boolean
  276. */
  277. public function stream_flush()
  278. {
  279. $result = fflush($this->_temporaryFileHandle);
  280. // Upload the file?
  281. if ($this->_writeMode) {
  282. // Make sure the container exists
  283. $containerExists = $this->_getStorageClient($this->_fileName)->containerExists(
  284. $this->_getContainerName($this->_fileName)
  285. );
  286. if (!$containerExists) {
  287. $this->_getStorageClient($this->_fileName)->createContainer(
  288. $this->_getContainerName($this->_fileName)
  289. );
  290. }
  291. // Upload the file
  292. try {
  293. $this->_getStorageClient($this->_fileName)->putBlob(
  294. $this->_getContainerName($this->_fileName),
  295. $this->_getFileName($this->_fileName),
  296. $this->_temporaryFileName
  297. );
  298. } catch (Microsoft_WindowsAzure_Exception $ex) {
  299. @unlink($this->_temporaryFileName);
  300. unset($this->_storageClient);
  301. throw $ex;
  302. }
  303. }
  304. return $result;
  305. }
  306. /**
  307. * Returns data array of stream variables
  308. *
  309. * @return array
  310. */
  311. public function stream_stat()
  312. {
  313. if (!$this->_temporaryFileHandle) {
  314. return false;
  315. }
  316. return $this->url_stat($this->_fileName, 0);
  317. }
  318. /**
  319. * Attempt to delete the item
  320. *
  321. * @param string $path
  322. * @return boolean
  323. */
  324. public function unlink($path)
  325. {
  326. $this->_getStorageClient($path)->deleteBlob(
  327. $this->_getContainerName($path),
  328. $this->_getFileName($path)
  329. );
  330. // Clear the stat cache for this path.
  331. clearstatcache(true, $path);
  332. return true;
  333. }
  334. /**
  335. * Attempt to rename the item
  336. *
  337. * @param string $path_from
  338. * @param string $path_to
  339. * @return boolean False
  340. */
  341. public function rename($path_from, $path_to)
  342. {
  343. if ($this->_getContainerName($path_from) != $this->_getContainerName($path_to)) {
  344. throw new Microsoft_WindowsAzure_Exception('Container name can not be changed.');
  345. }
  346. if ($this->_getFileName($path_from) == $this->_getContainerName($path_to)) {
  347. return true;
  348. }
  349. $this->_getStorageClient($path_from)->copyBlob(
  350. $this->_getContainerName($path_from),
  351. $this->_getFileName($path_from),
  352. $this->_getContainerName($path_to),
  353. $this->_getFileName($path_to)
  354. );
  355. $this->_getStorageClient($path_from)->deleteBlob(
  356. $this->_getContainerName($path_from),
  357. $this->_getFileName($path_from)
  358. );
  359. // Clear the stat cache for the affected paths.
  360. clearstatcache(true, $path_from);
  361. clearstatcache(true, $path_to);
  362. return true;
  363. }
  364. /**
  365. * Return array of URL variables
  366. *
  367. * @param string $path
  368. * @param integer $flags
  369. * @return array
  370. */
  371. public function url_stat($path, $flags)
  372. {
  373. $stat = array();
  374. $stat['dev'] = 0;
  375. $stat['ino'] = 0;
  376. $stat['mode'] = 0;
  377. $stat['nlink'] = 0;
  378. $stat['uid'] = 0;
  379. $stat['gid'] = 0;
  380. $stat['rdev'] = 0;
  381. $stat['size'] = 0;
  382. $stat['atime'] = 0;
  383. $stat['mtime'] = 0;
  384. $stat['ctime'] = 0;
  385. $stat['blksize'] = 0;
  386. $stat['blocks'] = 0;
  387. $info = null;
  388. try {
  389. $info = $this->_getStorageClient($path)->getBlobInstance(
  390. $this->_getContainerName($path),
  391. $this->_getFileName($path)
  392. );
  393. $stat['size'] = $info->Size;
  394. // Set the modification time and last modified to the Last-Modified header.
  395. $lastmodified = strtotime($info->LastModified);
  396. $stat['mtime'] = $lastmodified;
  397. $stat['ctime'] = $lastmodified;
  398. // Entry is a regular file.
  399. $stat['mode'] = 0100000;
  400. return array_values($stat) + $stat;
  401. } catch (Microsoft_WindowsAzure_Exception $ex) {
  402. // Unexisting file...
  403. return false;
  404. }
  405. }
  406. /**
  407. * Create a new directory
  408. *
  409. * @param string $path
  410. * @param integer $mode
  411. * @param integer $options
  412. * @return boolean
  413. */
  414. public function mkdir($path, $mode, $options)
  415. {
  416. if ($this->_getContainerName($path) == $this->_getFileName($path)) {
  417. // Create container
  418. try {
  419. $this->_getStorageClient($path)->createContainer(
  420. $this->_getContainerName($path)
  421. );
  422. return true;
  423. } catch (Microsoft_WindowsAzure_Exception $ex) {
  424. return false;
  425. }
  426. } else {
  427. throw new Microsoft_WindowsAzure_Exception('mkdir() with multiple levels is not supported on Windows Azure Blob Storage.');
  428. }
  429. }
  430. /**
  431. * Remove a directory
  432. *
  433. * @param string $path
  434. * @param integer $options
  435. * @return boolean
  436. */
  437. public function rmdir($path, $options)
  438. {
  439. if ($this->_getContainerName($path) == $this->_getFileName($path)) {
  440. // Clear the stat cache so that affected paths are refreshed.
  441. clearstatcache();
  442. // Delete container
  443. try {
  444. $this->_getStorageClient($path)->deleteContainer(
  445. $this->_getContainerName($path)
  446. );
  447. return true;
  448. } catch (Microsoft_WindowsAzure_Exception $ex) {
  449. return false;
  450. }
  451. } else {
  452. throw new Microsoft_WindowsAzure_Exception('rmdir() with multiple levels is not supported on Windows Azure Blob Storage.');
  453. }
  454. }
  455. /**
  456. * Attempt to open a directory
  457. *
  458. * @param string $path
  459. * @param integer $options
  460. * @return boolean
  461. */
  462. public function dir_opendir($path, $options)
  463. {
  464. $this->_blobs = $this->_getStorageClient($path)->listBlobs(
  465. $this->_getContainerName($path)
  466. );
  467. return is_array($this->_blobs);
  468. }
  469. /**
  470. * Return the next filename in the directory
  471. *
  472. * @return string
  473. */
  474. public function dir_readdir()
  475. {
  476. $object = current($this->_blobs);
  477. if ($object !== false) {
  478. next($this->_blobs);
  479. return $object->Name;
  480. }
  481. return false;
  482. }
  483. /**
  484. * Reset the directory pointer
  485. *
  486. * @return boolean True
  487. */
  488. public function dir_rewinddir()
  489. {
  490. reset($this->_blobs);
  491. return true;
  492. }
  493. /**
  494. * Close a directory
  495. *
  496. * @return boolean True
  497. */
  498. public function dir_closedir()
  499. {
  500. $this->_blobs = null;
  501. return true;
  502. }
  503. }