[ Index ] |
|
Code source de Horde 3.1.3 |
1 <?php 2 /** 3 * VFS implementation for a standard filesystem. 4 * 5 * Required parameters:<pre> 6 * 'vfsroot' The root path</pre> 7 * 8 * Note: The user that your webserver runs as (commonly 'nobody', 9 * 'apache', or 'www-data') MUST have read/write permission to the 10 * directory you specify as the 'vfsroot'. 11 * 12 * $Horde: framework/VFS/VFS/file.php,v 1.63.4.21 2006/05/31 04:50:02 slusarz Exp $ 13 * 14 * Copyright 2002-2006 Chuck Hagenbuch <chuck@horde.org> 15 * 16 * See the enclosed file COPYING for license information (LGPL). If you 17 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. 18 * 19 * @author Chuck Hagenbuch 20 * @package VFS 21 */ 22 class VFS_file extends VFS { 23 24 /** 25 * List of permissions and if they can be changed in this VFS 26 * backend. 27 * 28 * @var array 29 */ 30 var $_permissions = array( 31 'owner' => array('read' => true, 'write' => true, 'execute' => true), 32 'group' => array('read' => true, 'write' => true, 'execute' => true), 33 'all' => array('read' => true, 'write' => true, 'execute' => true) 34 ); 35 36 /** 37 * Constructs a new Filesystem based VFS object. 38 * 39 * @param array $params A hash containing connection parameters. 40 */ 41 function VFS_file($params = array()) 42 { 43 parent::VFS($params); 44 45 if (!empty($this->_params['vfsroot'])) { 46 if (substr($this->_params['vfsroot'], -1) == '/' || 47 substr($this->_params['vfsroot'], -1) == '\\') { 48 $this->_params['vfsroot'] = substr($this->_params['vfsroot'], 0, strlen($this->_params['vfsroot']) - 1); 49 } 50 } 51 } 52 53 /** 54 * Retrieves the filesize from the VFS. 55 * 56 * @param string $path The pathname to the file. 57 * @param string $name The filename to retrieve. 58 * 59 * @return integer The file size. 60 */ 61 function size($path, $name) 62 { 63 $size = @filesize($this->_getNativePath($path, $name)); 64 if ($size === false) { 65 return PEAR::raiseError(sprintf(_("Unable to check file size of \"%s/%s\"."), $path, $name)); 66 } 67 return $size; 68 } 69 70 /** 71 * Retrieve a file from the VFS. 72 * 73 * @param string $path The pathname to the file. 74 * @param string $name The filename to retrieve. 75 * 76 * @return string The file data. 77 */ 78 function read($path, $name) 79 { 80 $file = $this->_getNativePath($path, $name); 81 if (function_exists('file_get_contents')) { 82 $data = file_get_contents($file); 83 } else { 84 $fp = @fopen($file, 'rb'); 85 if (!$fp) { 86 return PEAR::raiseError(_("Unable to open VFS file.")); 87 } 88 $filesize = filesize($file); 89 if ($filesize == 0) { 90 $data = ''; 91 } else { 92 $data = fread($fp, $filesize); 93 } 94 fclose($fp); 95 } 96 97 return $data; 98 } 99 100 /** 101 * Retrieves a part of a file from the VFS. Particularly useful when 102 * reading large files which would exceed the PHP memory limits if they 103 * were stored in a string. 104 * 105 * @abstract 106 * 107 * @param string $path The pathname to the file. 108 * @param string $name The filename to retrieve. 109 * @param integer $offset The offset of the part. (The new offset will 110 * be stored in here). 111 * @param integer $length The length of the part. If the length = -1, 112 * the whole part after the offset is retrieved. 113 * If more bytes are given as exists after the 114 * given offset. Only the available bytes are 115 * read. 116 * @param integer $remaining The bytes that are left, after the part that 117 * is retrieved. 118 * 119 * @return string The file data. 120 */ 121 function readByteRange($path, $name, &$offset, $length = -1, &$remaining) 122 { 123 if ($offset < 0) { 124 return PEAR::raiseError(sprintf(_("Wrong offset %d while reading a VFS file."), $offset)); 125 } 126 127 // Calculate how many bytes MUST be read, so the remainging 128 // bytes and the new offset can be calculated correctly. 129 $file = $this->_getNativePath($path, $name); 130 $size = filesize ($file); 131 if ($length == -1 || (($length + $offset) > $size)) { 132 $length = $size - $offset; 133 } 134 if ($remaining < 0) { 135 $remaining = 0; 136 } 137 138 $fp = @fopen($file, 'rb'); 139 if (!$fp) { 140 return PEAR::raiseError(_("Unable to open VFS file.")); 141 } 142 fseek($fp, $offset); 143 $data = fread($fp, $length); 144 $offset = ftell($fp); 145 $remaining = $size - $offset; 146 147 fclose($fp); 148 149 return $data; 150 } 151 152 /** 153 * Store a file in the VFS, with the data copied from a temporary 154 * file. 155 * 156 * @param string $path The path to store the file in. 157 * @param string $name The filename to use. 158 * @param string $tmpFile The temporary file containing the data to be 159 * stored. 160 * @param boolean $autocreate Automatically create directories? 161 * 162 * @return mixed True on success or a PEAR_Error object on failure. 163 */ 164 function write($path, $name, $tmpFile, $autocreate = true) 165 { 166 if (!@is_dir($this->_getNativePath($path))) { 167 if ($autocreate) { 168 $res = $this->autocreatePath($path); 169 if (is_a($res, 'PEAR_Error')) { 170 return $res; 171 } 172 } else { 173 return PEAR::raiseError(_("VFS directory does not exist.")); 174 } 175 } 176 177 $res = $this->_checkQuotaWrite('file', $tmpFile); 178 if (is_a($res, 'PEAR_Error')) { 179 return $res; 180 } 181 182 // Since we already have the data in a file, don't read it 183 // into PHP's memory at all - just copy() it to the new 184 // location. We leave it to the caller to clean up the 185 // temporary file, so we don't use rename(). 186 if (@copy($tmpFile, $this->_getNativePath($path, $name))) { 187 return true; 188 } else { 189 return PEAR::raiseError(_("Unable to write VFS file (copy() failed).")); 190 } 191 } 192 193 /** 194 * Moves a file in the database and the file system. 195 * 196 * @param string $path The path to store the file in. 197 * @param string $name The filename to use. 198 * 199 * @return mixed True on success or a PEAR_Error object on failure. 200 */ 201 function move($path, $name, $dest) 202 { 203 $orig = $this->_getNativePath($path, $name); 204 if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { 205 return PEAR::raiseError(_("Cannot move file(s) - destination is within source.")); 206 } 207 208 $fileCheck = $this->listFolder($dest, false); 209 foreach ($fileCheck as $file) { 210 if ($file['name'] == $name) { 211 return PEAR::raiseError(_("Unable to move VFS file.")); 212 } 213 } 214 215 if (!@rename($orig, $this->_getNativePath($dest, $name))) { 216 return PEAR::raiseError(_("Unable to move VFS file.")); 217 } 218 219 return true; 220 } 221 222 /** 223 * Copies a file through the backend. 224 * 225 * @param string $path The path to store the file in. 226 * @param string $name The filename to use. 227 * @param string $dest The destination of the file. 228 * 229 * @return mixed True on success or a PEAR_Error object on failure. 230 */ 231 function copy($path, $name, $dest) 232 { 233 $orig = $this->_getNativePath($path, $name); 234 if (preg_match('|^' . preg_quote($orig) . '/?$|', $dest)) { 235 return PEAR::raiseError(_("Cannot copy file(s) - source and destination are the same.")); 236 } 237 238 $fileCheck = $this->listFolder($dest, false); 239 foreach ($fileCheck as $file) { 240 if ($file['name'] == $name) { 241 return PEAR::raiseError(_("Unable to copy VFS file.")); 242 } 243 } 244 245 if (!@copy($orig, $this->_getNativePath($dest, $name))) { 246 return PEAR::raiseError(_("Unable to copy VFS file.")); 247 } 248 249 return true; 250 } 251 252 /** 253 * Store a file in the VFS from raw data. 254 * 255 * @param string $path The path to store the file in. 256 * @param string $name The filename to use. 257 * @param string $data The file data. 258 * @param boolean $autocreate Automatically create directories? 259 * 260 * @return mixed True on success or a PEAR_Error object on failure. 261 */ 262 function writeData($path, $name, $data, $autocreate = true) 263 { 264 if (!@is_dir($this->_getNativePath($path))) { 265 if ($autocreate) { 266 $res = $this->autocreatePath($path); 267 if (is_a($res, 'PEAR_Error')) { 268 return $res; 269 } 270 } else { 271 return PEAR::raiseError(_("VFS directory does not exist.")); 272 } 273 } 274 275 // Treat an attempt to write an empty file as a touch() call, 276 // since otherwise the file will not be created at all. 277 if (!strlen($data)) { 278 if (@touch($this->_getNativePath($path, $name))) { 279 return true; 280 } else { 281 return PEAR::raiseError(_("Unable to create empty VFS file.")); 282 } 283 } 284 285 $res = $this->_checkQuotaWrite('string', $data); 286 if (is_a($res, 'PEAR_Error')) { 287 return $res; 288 } 289 290 // Otherwise we go ahead and try to write out the file. 291 $fp = @fopen($this->_getNativePath($path, $name), 'w'); 292 if (!$fp) { 293 return PEAR::raiseError(_("Unable to open VFS file for writing.")); 294 } 295 296 if (!@fwrite($fp, $data)) { 297 return PEAR::raiseError(_("Unable to write VFS file data.")); 298 } 299 300 return true; 301 } 302 303 /** 304 * Delete a file from the VFS. 305 * 306 * @param string $path The path to store the file in. 307 * @param string $name The filename to use. 308 * 309 * @return mixed True on success or a PEAR_Error object on failure. 310 */ 311 function deleteFile($path, $name) 312 { 313 $res = $this->_checkQuotaDelete($path, $name); 314 if (is_a($res, 'PEAR_Error')) { 315 return $res; 316 } 317 318 if (!@unlink($this->_getNativePath($path, $name))) { 319 return PEAR::raiseError(_("Unable to delete VFS file.")); 320 } 321 322 return true; 323 } 324 325 /** 326 * Delete a folder from the VFS. 327 * 328 * @param string $path The path to delete the folder from. 329 * @param string $name The foldername to use. 330 * @param boolean $recursive Force a recursive delete? 331 * 332 * @return mixed True on success or a PEAR_Error object on failure. 333 */ 334 function deleteFolder($path, $name, $recursive = false) 335 { 336 if ($recursive) { 337 $result = $this->emptyFolder($path . '/' . $name); 338 if (is_a($result, 'PEAR_Error')) { 339 return $result; 340 } 341 } else { 342 $list = $this->listFolder($path . '/' . $name); 343 if (is_a($list, 'PEAR_Error')) { 344 return $list; 345 } 346 if (count($list)) { 347 return PEAR::raiseError(sprintf(_("Unable to delete %s, the directory is not empty"), 348 $path . '/' . $name)); 349 } 350 } 351 352 if (!@rmdir($this->_getNativePath($path, $name))) { 353 return PEAR::raiseError(_("Unable to delete VFS directory.")); 354 } 355 356 return true; 357 } 358 359 /** 360 * Creates a folder on the VFS. 361 * 362 * @param string $path The path to delete the folder from. 363 * @param string $name The foldername to use. 364 * 365 * @return mixed True on success or a PEAR_Error object on failure. 366 */ 367 function createFolder($path, $name) 368 { 369 if (!@mkdir($this->_getNativePath($path, $name))) { 370 return PEAR::raiseError(_("Unable to create VFS directory.")); 371 } 372 373 return true; 374 } 375 376 /** 377 * Check if a given pathname is a folder. 378 * 379 * @param string $path The path to the folder. 380 * @param string $name The file/folder name. 381 * 382 * @return boolean True if it is a folder, false otherwise. 383 */ 384 function isFolder($path, $name) 385 { 386 return @is_dir($this->_getNativePath($path, $name)); 387 } 388 389 /** 390 * Changes permissions for an item in the VFS. 391 * 392 * @param string $path The path of directory of the item. 393 * @param string $name The name of the item. 394 * @param integer $permission The octal value of the new permission. 395 * 396 * @return mixed True on success or a PEAR_Error object on failure. 397 */ 398 function changePermissions($path, $name, $permission) 399 { 400 if (!@chmod($this->_getNativePath($path, $name), $permission)) { 401 return PEAR::raiseError(sprintf(_("Unable to change permission for VFS file %s/%s."), $path, $name)); 402 } 403 404 return true; 405 } 406 407 /** 408 * Return a list of the contents of a folder. 409 * 410 * @param string $path The path of the directory. 411 * @param mixed $filter String/hash to filter file/dirname on. 412 * @param boolean $dotfiles Show dotfiles? 413 * @param boolean $dironly Show only directories? 414 * 415 * @return array File list on success, PEAR_Error on error. 416 */ 417 function _listFolder($path, $filter = null, $dotfiles = true, 418 $dironly = false) 419 { 420 $files = array(); 421 $path = isset($path) ? $this->_getNativePath($path) : $this->_getNativePath(); 422 423 if (!@is_dir($path)) { 424 return PEAR::raiseError(_("Not a directory")); 425 } 426 427 if (!@chdir($path)) { 428 return PEAR::raiseError(_("Unable to access VFS directory.")); 429 } 430 431 $handle = opendir($path); 432 while (($entry = readdir($handle)) !== false) { 433 // Filter out '.' and '..' entries. 434 if ($entry == '.' || $entry == '..') { 435 continue; 436 } 437 438 // Filter out dotfiles if they aren't wanted. 439 if (!$dotfiles && substr($entry, 0, 1) == '.') { 440 continue; 441 } 442 443 // File name 444 $file['name'] = $entry; 445 446 // Unix style file permissions 447 $file['perms'] = $this->_getUnixPerms(fileperms($entry)); 448 449 // Owner 450 $file['owner'] = fileowner($entry); 451 if (function_exists('posix_getpwuid')) { 452 $owner = posix_getpwuid($file['owner']); 453 $file['owner'] = $owner['name']; 454 } 455 456 // Group 457 $file['group'] = filegroup($entry); 458 if (function_exists('posix_getgrgid')) { 459 $group = posix_getgrgid($file['group']); 460 $file['group'] = $group['name']; 461 } 462 463 // Size 464 $file['size'] = filesize($entry); 465 466 // Date 467 $file['date'] = filemtime($entry); 468 469 // Type 470 if (@is_dir($entry) && !is_link($entry)) { 471 $file['perms'] = 'd' . $file['perms']; 472 $file['type'] = '**dir'; 473 $file['size'] = -1; 474 } elseif (is_link($entry)) { 475 $file['perms'] = 'l' . $file['perms']; 476 $file['type'] = '**sym'; 477 $file['link'] = readlink($entry); 478 $file['linktype'] = '**none'; 479 if (file_exists($file['link'])) { 480 if (is_dir($file['link'])) { 481 $file['linktype'] = '**dir'; 482 } elseif (is_link($file['link'])) { 483 $file['linktype'] = '**sym'; 484 } elseif (is_file($file['link'])) { 485 $ext = explode('.', $file['link']); 486 if (!(count($ext) == 1 || ($ext[0] === '' && count($ext) == 2))) { 487 $file['linktype'] = VFS::strtolower($ext[count($ext) - 1]); 488 } 489 } 490 } else { 491 $file['linktype'] = '**broken'; 492 } 493 } elseif (is_file($entry)) { 494 $file['perms'] = '-' . $file['perms']; 495 $ext = explode('.', $entry); 496 497 if (count($ext) == 1 || (substr($file['name'], 0, 1) === '.' && count($ext) == 2)) { 498 $file['type'] = '**none'; 499 } else { 500 $file['type'] = VFS::strtolower($ext[count($ext) - 1]); 501 } 502 } else { 503 $file['type'] = '**none'; 504 if ((fileperms($entry) & 0xC000) == 0xC000) { 505 $file['perms'] = 's' . $file['perms']; 506 } elseif ((fileperms($entry) & 0x6000) == 0x6000) { 507 $file['perms'] = 'b' . $file['perms']; 508 } elseif ((fileperms($entry) & 0x2000) == 0x2000) { 509 $file['perms'] = 'c' . $file['perms']; 510 } elseif ((fileperms($entry) & 0x1000) == 0x1000) { 511 $file['perms'] = 'p' . $file['perms']; 512 } else { 513 $file['perms'] = '?' . $file['perms']; 514 } 515 } 516 517 // Filtering. 518 if ($this->_filterMatch($filter, $file['name'])) { 519 unset($file); 520 continue; 521 } 522 if ($dironly && $file['type'] !== '**dir') { 523 unset($file); 524 continue; 525 } 526 527 $files[$file['name']] = $file; 528 unset($file); 529 } 530 531 return $files; 532 } 533 534 /** 535 * Returns a sorted list of folders in specified directory. 536 * 537 * @param string $path The path of the directory to get the 538 * directory list for. 539 * @param mixed $filter Hash of items to filter based on folderlist. 540 * @param boolean $dotfolders Include dotfolders? 541 * 542 * @return mixed Folder list on success or a PEAR_Error object on failure. 543 */ 544 function listFolders($path = '', $filter = null, $dotfolders = true) 545 { 546 $conn = $this->_connect(); 547 if (is_a($conn, 'PEAR_Error')) { 548 return $conn; 549 } 550 551 $folders = array(); 552 $folders[dirname($path)] = array('val' => dirname($path), 553 'abbrev' => '..', 554 'label' => '..'); 555 556 $folderList = $this->listFolder($path, null, $dotfolders, true); 557 if (is_a($folderList, 'PEAR_Error')) { 558 return $folderList; 559 } 560 561 foreach ($folderList as $name => $files) { 562 $folders[$name] = array('val' => $path . '/' . $files['name'], 563 'abbrev' => $files['name'], 564 'label' => $path . '/' . $files['name']); 565 } 566 567 ksort($folders); 568 569 return $folders; 570 } 571 572 /** 573 * Return Unix style perms. 574 * 575 * @access private 576 * 577 * @param integer $perms The permissions to set. 578 * 579 * @return string Unix style perms. 580 */ 581 function _getUnixPerms($perms) 582 { 583 // Determine permissions 584 $owner['read'] = ($perms & 00400) ? 'r' : '-'; 585 $owner['write'] = ($perms & 00200) ? 'w' : '-'; 586 $owner['execute'] = ($perms & 00100) ? 'x' : '-'; 587 $group['read'] = ($perms & 00040) ? 'r' : '-'; 588 $group['write'] = ($perms & 00020) ? 'w' : '-'; 589 $group['execute'] = ($perms & 00010) ? 'x' : '-'; 590 $world['read'] = ($perms & 00004) ? 'r' : '-'; 591 $world['write'] = ($perms & 00002) ? 'w' : '-'; 592 $world['execute'] = ($perms & 00001) ? 'x' : '-'; 593 594 // Adjust for SUID, SGID and sticky bit 595 if ($perms & 0x800) { 596 $owner['execute'] = ($owner['execute'] == 'x') ? 's' : 'S'; 597 } 598 if ($perms & 0x400) { 599 $group['execute'] = ($group['execute'] == 'x') ? 's' : 'S'; 600 } 601 if ($perms & 0x200) { 602 $world['execute'] = ($world['execute'] == 'x') ? 't' : 'T'; 603 } 604 605 $unixPerms = $owner['read'] . $owner['write'] . $owner['execute'] . 606 $group['read'] . $group['write'] . $group['execute'] . 607 $world['read'] . $world['write'] . $world['execute']; 608 609 return $unixPerms; 610 } 611 612 /** 613 * Rename a file or folder in the VFS. 614 * 615 * @param string $oldpath The old path to the file. 616 * @param string $oldname The old filename. 617 * @param string $newpath The new path of the file. 618 * @param string $newname The new filename. 619 * 620 * @return mixed True on success or a PEAR_Error object on failure. 621 */ 622 function rename($oldpath, $oldname, $newpath, $newname) 623 { 624 if (!@is_dir($this->_getNativePath($newpath))) { 625 if (is_a($res = $this->autocreatePath($newpath), 'PEAR_Error')) { 626 return $res; 627 } 628 } 629 630 if (!@rename($this->_getNativePath($oldpath, $oldname), 631 $this->_getNativePath($newpath, $newname))) { 632 return PEAR::raiseError(sprintf(_("Unable to rename VFS file %s/%s."), $oldpath, $oldname)); 633 } 634 635 return true; 636 } 637 638 /** 639 * Return a full filename on the native filesystem, from a VFS 640 * path and name. 641 * 642 * @access private 643 * 644 * @param string $path The VFS file path. 645 * @param string $name The VFS filename. 646 * 647 * @return string The full native filename. 648 */ 649 function _getNativePath($path = '', $name = '') 650 { 651 $name = basename($name); 652 if (!empty($name)) { 653 $name = str_replace('..', '', $name); 654 if (substr($name, 0, 1) != '/') { 655 $name = '/' . $name; 656 } 657 } 658 659 if (!empty($path)) { 660 if (isset($this->_params['home']) && 661 preg_match('|^~/?(.*)$|', $path, $matches)) { 662 $path = $this->_params['home'] . '/' . $matches[1]; 663 } 664 665 $path = str_replace('..', '', $path); 666 if (substr($path, 0, 1) == '/') { 667 return $this->_params['vfsroot'] . $path . $name; 668 } else { 669 return $this->_params['vfsroot'] . '/' . $path . $name; 670 } 671 } else { 672 return $this->_params['vfsroot'] . $name; 673 } 674 } 675 676 /** 677 * Stub to check if we have a valid connection. Makes sure that 678 * the vfsroot is readable. 679 * 680 * @access private 681 * 682 * @return mixed True if vfsroot is readable, PEAR_Error if it isn't. 683 */ 684 function _connect() 685 { 686 if ((@is_dir($this->_params['vfsroot']) && 687 @is_readable($this->_params['vfsroot'])) || 688 @mkdir($this->_params['vfsroot'])) { 689 return true; 690 } else { 691 return PEAR::raiseError(_("Unable to read the vfsroot directory.")); 692 } 693 } 694 695 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 18:01:28 2007 | par Balluche grâce à PHPXref 0.7 |