PageRenderTime 39ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

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

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