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