|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00026 require_once 'Zend/Service/Amazon/S3.php'; 00027 00037 class Zend_Service_Amazon_S3_Stream 00038 { 00042 private $_writeBuffer = false; 00043 00047 private $_position = 0; 00048 00052 private $_objectSize = 0; 00053 00057 private $_objectName = null; 00058 00062 private $_objectBuffer = null; 00063 00067 private $_bucketList = array(); 00068 00072 private $_s3 = null; 00073 00080 protected function _getS3Client($path) 00081 { 00082 if ($this->_s3 === null) { 00083 $url = explode(':', $path); 00084 00085 if (!$url) { 00089 require_once 'Zend/Service/Amazon/S3/Exception.php'; 00090 throw new Zend_Service_Amazon_S3_Exception("Unable to parse URL $path"); 00091 } 00092 00093 $this->_s3 = Zend_Service_Amazon_S3::getWrapperClient($url[0]); 00094 if (!$this->_s3) { 00098 require_once 'Zend/Service/Amazon/S3/Exception.php'; 00099 throw new Zend_Service_Amazon_S3_Exception("Unknown client for wrapper {$url[0]}"); 00100 } 00101 } 00102 00103 return $this->_s3; 00104 } 00105 00112 protected function _getNamePart($path) 00113 { 00114 $url = parse_url($path); 00115 if ($url['host']) { 00116 return !empty($url['path']) ? $url['host'].$url['path'] : $url['host']; 00117 } 00118 00119 return ''; 00120 } 00130 public function stream_open($path, $mode, $options, $opened_path) 00131 { 00132 $name = $this->_getNamePart($path); 00133 // If we open the file for writing, just return true. Create the object 00134 // on fflush call 00135 if (strpbrk($mode, 'wax')) { 00136 $this->_objectName = $name; 00137 $this->_objectBuffer = null; 00138 $this->_objectSize = 0; 00139 $this->_position = 0; 00140 $this->_writeBuffer = true; 00141 $this->_getS3Client($path); 00142 return true; 00143 } 00144 else { 00145 // Otherwise, just see if the file exists or not 00146 $info = $this->_getS3Client($path)->getInfo($name); 00147 if ($info) { 00148 $this->_objectName = $name; 00149 $this->_objectBuffer = null; 00150 $this->_objectSize = $info['size']; 00151 $this->_position = 0; 00152 $this->_writeBuffer = false; 00153 $this->_getS3Client($path); 00154 return true; 00155 } 00156 } 00157 return false; 00158 } 00159 00165 public function stream_close() 00166 { 00167 $this->_objectName = null; 00168 $this->_objectBuffer = null; 00169 $this->_objectSize = 0; 00170 $this->_position = 0; 00171 $this->_writeBuffer = false; 00172 unset($this->_s3); 00173 } 00174 00181 public function stream_read($count) 00182 { 00183 if (!$this->_objectName) { 00184 return false; 00185 } 00186 00187 $range_start = $this->_position; 00188 $range_end = $this->_position+$count; 00189 00190 // Only fetch more data from S3 if we haven't fetched any data yet (postion=0) 00191 // OR, the range end position is greater than the size of the current object 00192 // buffer AND if the range end position is less than or equal to the object's 00193 // size returned by S3 00194 if (($this->_position == 0) || (($range_end > strlen($this->_objectBuffer)) && ($range_end <= $this->_objectSize))) { 00195 00196 $headers = array( 00197 'Range' => "$range_start-$range_end" 00198 ); 00199 00200 $response = $this->_s3->_makeRequest('GET', $this->_objectName, null, $headers); 00201 00202 if ($response->getStatus() == 200) { 00203 $this->_objectBuffer .= $response->getBody(); 00204 } 00205 } 00206 00207 $data = substr($this->_objectBuffer, $this->_position, $count); 00208 $this->_position += strlen($data); 00209 return $data; 00210 } 00211 00218 public function stream_write($data) 00219 { 00220 if (!$this->_objectName) { 00221 return 0; 00222 } 00223 $len = strlen($data); 00224 $this->_objectBuffer .= $data; 00225 $this->_objectSize += $len; 00226 // TODO: handle current position for writing! 00227 return $len; 00228 } 00229 00235 public function stream_eof() 00236 { 00237 if (!$this->_objectName) { 00238 return true; 00239 } 00240 00241 return ($this->_position >= $this->_objectSize); 00242 } 00243 00249 public function stream_tell() 00250 { 00251 return $this->_position; 00252 } 00253 00261 public function stream_seek($offset, $whence) 00262 { 00263 if (!$this->_objectName) { 00264 return false; 00265 } 00266 00267 switch ($whence) { 00268 case SEEK_CUR: 00269 // Set position to current location plus $offset 00270 $new_pos = $this->_position + $offset; 00271 break; 00272 case SEEK_END: 00273 // Set position to end-of-file plus $offset 00274 $new_pos = $this->_objectSize + $offset; 00275 break; 00276 case SEEK_SET: 00277 default: 00278 // Set position equal to $offset 00279 $new_pos = $offset; 00280 break; 00281 } 00282 $ret = ($new_pos >= 0 && $new_pos <= $this->_objectSize); 00283 if ($ret) { 00284 $this->_position = $new_pos; 00285 } 00286 return $ret; 00287 } 00288 00294 public function stream_flush() 00295 { 00296 // If the stream wasn't opened for writing, just return false 00297 if (!$this->_writeBuffer) { 00298 return false; 00299 } 00300 00301 $ret = $this->_s3->putObject($this->_objectName, $this->_objectBuffer); 00302 00303 $this->_objectBuffer = null; 00304 00305 return $ret; 00306 } 00307 00313 public function stream_stat() 00314 { 00315 if (!$this->_objectName) { 00316 return false; 00317 } 00318 00319 $stat = array(); 00320 $stat['dev'] = 0; 00321 $stat['ino'] = 0; 00322 $stat['mode'] = 0777; 00323 $stat['nlink'] = 0; 00324 $stat['uid'] = 0; 00325 $stat['gid'] = 0; 00326 $stat['rdev'] = 0; 00327 $stat['size'] = 0; 00328 $stat['atime'] = 0; 00329 $stat['mtime'] = 0; 00330 $stat['ctime'] = 0; 00331 $stat['blksize'] = 0; 00332 $stat['blocks'] = 0; 00333 00334 if(($slash = strchr($this->_objectName, '/')) === false || $slash == strlen($this->_objectName)-1) { 00335 /* bucket */ 00336 $stat['mode'] |= 040000; 00337 } else { 00338 $stat['mode'] |= 0100000; 00339 } 00340 $info = $this->_s3->getInfo($this->_objectName); 00341 if (!empty($info)) { 00342 $stat['size'] = $info['size']; 00343 $stat['atime'] = time(); 00344 $stat['mtime'] = $info['mtime']; 00345 } 00346 00347 return $stat; 00348 } 00349 00356 public function unlink($path) 00357 { 00358 return $this->_getS3Client($path)->removeObject($this->_getNamePart($path)); 00359 } 00360 00368 public function rename($path_from, $path_to) 00369 { 00370 // TODO: Renaming isn't supported, always return false 00371 return false; 00372 } 00373 00382 public function mkdir($path, $mode, $options) 00383 { 00384 return $this->_getS3Client($path)->createBucket(parse_url($path, PHP_URL_HOST)); 00385 } 00386 00394 public function rmdir($path, $options) 00395 { 00396 return $this->_getS3Client($path)->removeBucket(parse_url($path, PHP_URL_HOST)); 00397 } 00398 00406 public function dir_opendir($path, $options) 00407 { 00408 00409 if (preg_match('@^([a-z0-9+.]|-)+://$@', $path)) { 00410 $this->_bucketList = $this->_getS3Client($path)->getBuckets(); 00411 } 00412 else { 00413 $host = parse_url($path, PHP_URL_HOST); 00414 $this->_bucketList = $this->_getS3Client($path)->getObjectsByBucket($host); 00415 } 00416 00417 return ($this->_bucketList !== false); 00418 } 00419 00427 public function url_stat($path, $flags) 00428 { 00429 $stat = array(); 00430 $stat['dev'] = 0; 00431 $stat['ino'] = 0; 00432 $stat['mode'] = 0777; 00433 $stat['nlink'] = 0; 00434 $stat['uid'] = 0; 00435 $stat['gid'] = 0; 00436 $stat['rdev'] = 0; 00437 $stat['size'] = 0; 00438 $stat['atime'] = 0; 00439 $stat['mtime'] = 0; 00440 $stat['ctime'] = 0; 00441 $stat['blksize'] = 0; 00442 $stat['blocks'] = 0; 00443 00444 $name = $this->_getNamePart($path); 00445 if(($slash = strchr($name, '/')) === false || $slash == strlen($name)-1) { 00446 /* bucket */ 00447 $stat['mode'] |= 040000; 00448 } else { 00449 $stat['mode'] |= 0100000; 00450 } 00451 $info = $this->_getS3Client($path)->getInfo($name); 00452 00453 if (!empty($info)) { 00454 $stat['size'] = $info['size']; 00455 $stat['atime'] = time(); 00456 $stat['mtime'] = $info['mtime']; 00457 } 00458 00459 return $stat; 00460 } 00461 00467 public function dir_readdir() 00468 { 00469 $object = current($this->_bucketList); 00470 if ($object !== false) { 00471 next($this->_bucketList); 00472 } 00473 return $object; 00474 } 00475 00481 public function dir_rewinddir() 00482 { 00483 reset($this->_bucketList); 00484 return true; 00485 } 00486 00492 public function dir_closedir() 00493 { 00494 $this->_bucketList = array(); 00495 return true; 00496 } 00497 }