| [ Index ] |
|
Code source de b2evolution 2.1.0-beta |
1 <?php 2 /** 3 * This file implements the File class. 4 * 5 * This file is part of the evoCore framework - {@link http://evocore.net/} 6 * See also {@link http://sourceforge.net/projects/evocms/}. 7 * 8 * @copyright (c)2003-2007 by Francois PLANQUE - {@link http://fplanque.net/} 9 * Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}. 10 * 11 * {@internal License choice 12 * - If you have received this file as part of a package, please find the license.txt file in 13 * the same folder or the closest folder above for complete license terms. 14 * - If you have received this file individually (e-g: from http://evocms.cvs.sourceforge.net/) 15 * then you must choose one of the following licenses before using the file: 16 * - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php 17 * - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php 18 * }} 19 * 20 * {@internal Open Source relicensing agreement: 21 * Daniel HAHLER grants Francois PLANQUE the right to license 22 * Daniel HAHLER's contributions to this file and the b2evolution project 23 * under any OSI approved OSS license (http://www.opensource.org/licenses/). 24 * }} 25 * 26 * @package evocore 27 * 28 * {@internal Below is a list of authors who have contributed to design/coding of this file: }} 29 * @author blueyed: Daniel HAHLER. 30 * @author fplanque: Francois PLANQUE. 31 * 32 * @version $Id: _file.class.php,v 1.1 2007/06/25 10:59:54 fplanque Exp $ 33 * 34 */ 35 if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' ); 36 37 38 /** 39 * Represents a file or folder on disk. Optionnaly stores meta data from DB. 40 * 41 * Use {@link FileCache::get_by_path()} to create an instance. 42 * This is based on {@link DataObject} for the meta data. 43 * 44 * @package evocore 45 */ 46 class File extends DataObject 47 { 48 /** 49 * Have we checked for meta data in the DB yet? 50 * @var string 51 */ 52 var $meta = 'unknown'; 53 54 /** 55 * Meta data: Long title 56 * @var string 57 */ 58 var $title; 59 60 /** 61 * Meta data: ALT text for images 62 * @var string 63 */ 64 var $alt; 65 66 /** 67 * Meta data: Description 68 * @var string 69 */ 70 var $desc; 71 72 /** 73 * FileRoot of this file 74 * @var Fileroot 75 * @access protected 76 */ 77 var $_FileRoot; 78 79 /** 80 * Posix subpath for this file/folder, relative the associated root (No trailing slash) 81 * @var string 82 * @access protected 83 */ 84 var $_rdfp_rel_path; 85 86 /** 87 * Full path for this file/folder, WITHOUT trailing slash. 88 * @var string 89 * @access protected 90 */ 91 var $_adfp_full_path; 92 93 /** 94 * Directory path for this file/folder, including trailing slash. 95 * @var string 96 * @see get_dir() 97 * @access protected 98 */ 99 var $_dir; 100 101 /** 102 * Name of this file/folder, without path. 103 * @var string 104 * @access protected 105 */ 106 var $_name; 107 108 /** 109 * MD5 hash of full pathname. 110 * 111 * This is useful to refer to files in hidden form fields, but might be replaced by the root_ID+relpath. 112 * 113 * @todo fplanque>> get rid of it 114 * 115 * @var string 116 * @see get_md5_ID() 117 * @access protected 118 */ 119 var $_md5ID; 120 121 /** 122 * Does the File/folder exist on disk? 123 * @var boolean 124 * @see exists() 125 * @access protected 126 */ 127 var $_exists; 128 129 /** 130 * Is the File a directory? 131 * @var boolean 132 * @see is_dir() 133 * @access protected 134 */ 135 var $_is_dir; 136 137 /** 138 * File size in bytes. 139 * @var integer 140 * @see get_size() 141 * @access protected 142 */ 143 var $_size; 144 145 /** 146 * UNIX timestamp of last modification on disk. 147 * @var integer 148 * @see get_lastmod_ts() 149 * @see get_lastmod_formatted() 150 * @access protected 151 */ 152 var $_lastmod_ts; 153 154 /** 155 * Filesystem file permissions. 156 * @var integer 157 * @see get_perms() 158 * @access protected 159 */ 160 var $_perms; 161 162 /** 163 * File owner. NULL if unknown 164 * @var string 165 * @see get_fsowner_name() 166 * @access protected 167 */ 168 var $_fsowner_name; 169 170 /** 171 * File group. NULL if unknown 172 * @var string 173 * @see get_fsgroup_name() 174 * @access protected 175 */ 176 var $_fsgroup_name; 177 178 /** 179 * Is the File an image? NULL if unknown 180 * @var boolean 181 * @see is_image() 182 * @access protected 183 */ 184 var $_is_image; 185 186 /** 187 * Extension, Mime type, icon, viewtype and 'allowed extension' of the file 188 * @var Filetype 189 */ 190 var $Filetype; 191 192 193 /** 194 * Constructor, not meant to be called directly. Use {@link FileCache::get_by_path()} 195 * instead, which provides caching and checks that only one object for 196 * a unique file exists (references). 197 * 198 * @param string Root type: 'user', 'group', 'collection' or 'absolute' 199 * @param integer ID of the user, the group or the collection the file belongs to... 200 * @param string Posix subpath for this file/folder, relative to the associated root (no trailing slash) 201 * @param boolean check for meta data? 202 * @return mixed false on failure, File object on success 203 */ 204 function File( $root_type, $root_ID, $rdfp_rel_path, $load_meta = false ) 205 { 206 global $Debuglog; 207 208 $Debuglog->add( "new File( $root_type, $root_ID, $rdfp_rel_path, load_meta=$load_meta)", 'files' ); 209 210 // Call parent constructor 211 parent::DataObject( 'T_files', 'file_', 'file_ID', '', '', '', '' ); 212 213 $this->delete_restrictions = array( 214 array( 'table'=>'T_links', 'fk'=>'link_file_ID', 'msg'=>T_('%d linked items') ), 215 ); 216 217 // Memorize filepath: 218 $FileRootCache = & get_Cache( 'FileRootCache' ); 219 $this->_FileRoot = & $FileRootCache->get_by_type_and_ID( $root_type, $root_ID ); 220 $this->_rdfp_rel_path = no_trailing_slash(str_replace( '\\', '/', $rdfp_rel_path )); 221 $this->_adfp_full_path = $this->_FileRoot->ads_path.$this->_rdfp_rel_path; 222 $this->_name = basename( $this->_adfp_full_path ); 223 $this->_dir = dirname( $this->_adfp_full_path ).'/'; 224 $this->_md5ID = md5( $this->_adfp_full_path ); 225 226 // Create the filetype with the extension of the file if the extension exist in database 227 if( $ext = $this->get_ext() ) 228 { // The file has an extension, load filetype object 229 $FiletypeCache = & get_Cache( 'FiletypeCache' ); 230 $this->Filetype = & $FiletypeCache->get_by_extension( strtolower( $ext ), false ); 231 } 232 233 // Initializes file properties (type, size, perms...) 234 $this->load_properties(); 235 236 if( $load_meta ) 237 { // Try to load DB meta info: 238 $this->load_meta(); 239 } 240 } 241 242 243 /** 244 * Attempt to load meta data. 245 * 246 * Will attempt only once and cache the result. 247 * 248 * @param boolean create meta data in DB if it doesn't exist yet? (generates a $File->ID) 249 * @param object database row containing all fields needed to initialize meta data 250 * @return boolean true if meta data has been loaded/initialized. 251 */ 252 function load_meta( $force_creation = false, $row = NULL ) 253 { 254 global $DB, $Debuglog; 255 256 if( $this->meta == 'unknown' ) 257 { // We haven't tried loading yet: 258 if( is_null( $row ) ) 259 { // No DB data has been provided: 260 $row = $DB->get_row( " 261 SELECT * FROM T_files 262 WHERE file_root_type = '".$this->_FileRoot->type."' 263 AND file_root_ID = ".$this->_FileRoot->in_type_ID." 264 AND file_path = ".$DB->quote($this->_rdfp_rel_path), 265 OBJECT, 0, 'Load file meta data' ); 266 } 267 268 // We check that we got something AND that the CASE matches (because of case insensitive collations on MySQL) 269 if( $row && $row->file_path == $this->_rdfp_rel_path ) 270 { // We found meta data 271 $Debuglog->add( "Loaded metadata for {$this->_FileRoot->ID}:{$this->_rdfp_rel_path}", 'files' ); 272 $this->meta = 'loaded'; 273 $this->ID = $row->file_ID; 274 $this->title = $row->file_title; 275 $this->alt = $row->file_alt; 276 $this->desc = $row->file_desc; 277 278 // Store this in the FileCache: 279 $FileCache = & get_Cache( 'FileCache' ); 280 $FileCache->add( $this ); 281 } 282 else 283 { // No meta data... 284 $Debuglog->add( "No metadata could be loaded for {$this->_FileRoot->ID}:$this->_rdfp_rel_path", 'files' ); 285 $this->meta = 'notfound'; 286 287 if( $force_creation ) 288 { // No meta data, we have to create it now! 289 $this->dbinsert(); 290 } 291 } 292 } 293 294 return ($this->meta == 'loaded'); 295 } 296 297 298 /** 299 * Create the file/folder on disk, if it does not exist yet. 300 * 301 * Also sets file permissions. 302 * Also inserts meta data into DB (if file/folder was successfully created). 303 * 304 * @param string type ('dir'|'file') 305 * @param string optional permissions (octal format), otherwise the default from {@link $Settings} gets used 306 * @return boolean true if file/folder was created, false on failure 307 */ 308 function create( $type = 'file', $chmod = NULL ) 309 { 310 if( $type == 'dir' ) 311 { // Create an empty directory: 312 $success = @mkdir( $this->_adfp_full_path ); 313 $this->_is_dir = true; // used by chmod 314 } 315 else 316 { // Create an empty file: 317 $success = touch( $this->_adfp_full_path ); 318 $this->_is_dir = false; // used by chmod 319 } 320 $this->chmod( $chmod ); // uses $Settings for NULL 321 322 if( $success ) 323 { // The file/folder has been successfully created: 324 325 // Initializes file properties (type, size, perms...) 326 $this->load_properties(); 327 328 // If there was meta data for this file in the DB: 329 // (maybe the file had existed before?) 330 // Let's recycle it! : 331 if( ! $this->load_meta() ) 332 { // No meta data could be loaded, let's make sure localization info gets recorded: 333 $this->set( 'root_type', $this->_FileRoot->type ); 334 $this->set( 'root_ID', $this->_FileRoot->in_type_ID ); 335 $this->set( 'path', $this->_rdfp_rel_path ); 336 } 337 338 // Record to DB: 339 $this->dbsave(); 340 } 341 342 return $success; 343 } 344 345 346 /** 347 * Initializes or refreshes file properties (type, size, perms...) 348 */ 349 function load_properties() 350 { 351 // Unset values that will be determined (and cached) upon request 352 $this->_is_image = NULL; 353 354 $this->_exists = file_exists( $this->_adfp_full_path ); 355 356 if( is_dir( $this->_adfp_full_path ) ) 357 { // The File is a directory: 358 $this->_is_dir = true; 359 $this->_size = NULL; 360 } 361 else 362 { // The File is a regular file: 363 $this->_is_dir = false; 364 $this->_size = @filesize( $this->_adfp_full_path ); 365 } 366 367 // for files and dirs: 368 $this->_lastmod_ts = @filemtime( $this->_adfp_full_path ); 369 $this->_perms = @fileperms( $this->_adfp_full_path ); 370 } 371 372 373 /** 374 * Does the File/folder exist on disk? 375 * 376 * @return boolean true, if the file or dir exists; false if not 377 */ 378 function exists() 379 { 380 return $this->_exists; 381 } 382 383 384 /** 385 * Is the File a directory? 386 * 387 * @return boolean true if the object is a directory, false if not 388 */ 389 function is_dir() 390 { 391 return $this->_is_dir; 392 } 393 394 395 /** 396 * Is the File an image? 397 * 398 * Tries to determine if it is and caches the info. 399 * 400 * @return boolean true if the object is an image, false if not 401 */ 402 function is_image() 403 { 404 if( is_null( $this->_is_image ) ) 405 { // We don't know yet 406 $this->_is_image = ( $this->get_image_size() !== false ); 407 } 408 409 return $this->_is_image; 410 } 411 412 413 /** 414 * Is the file editable? 415 * 416 * @param boolean allow locked file types? 417 */ 418 function is_editable( $allow_locked = false ) 419 { 420 if( $this->is_dir() // we cannot edit dirs 421 || !isset($this->Filetype) 422 || $this->Filetype->viewtype != 'text' ) // we can only edit text files 423 { 424 return false; 425 } 426 427 if( ! $this->Filetype->allowed && ! $allow_locked ) 428 { // We cannot edit locked file types: 429 return false; 430 } 431 432 return true; 433 } 434 435 436 /** 437 * Get the File's ID (MD5 of path and name) 438 * 439 * @return string 440 */ 441 function get_md5_ID() 442 { 443 return $this->_md5ID; 444 } 445 446 447 /** 448 * Get a member param by its name 449 * 450 * @param mixed Name of parameter 451 * @return mixed Value of parameter 452 */ 453 function get( $parname ) 454 { 455 switch( $parname ) 456 { 457 case 'name': 458 return $this->_name; 459 460 default: 461 return parent::get( $parname ); 462 } 463 } 464 465 466 /** 467 * Get the File's name. 468 * 469 * @return string 470 */ 471 function get_name() 472 { 473 return $this->_name; 474 } 475 476 477 /** 478 * Get the name prefixed either with "Directory" or "File". 479 * 480 * Returned string is localized. 481 * 482 * @return string 483 */ 484 function get_prefixed_name() 485 { 486 if( $this->is_dir() ) 487 { 488 return sprintf( T_('Directory «%s»'), $this->_name ); 489 } 490 else 491 { 492 return sprintf( T_('File «%s»'), $this->_name ); 493 } 494 } 495 496 497 /** 498 * Get the File's directory. 499 * 500 * @return string 501 */ 502 function get_dir() 503 { 504 return $this->_dir; 505 } 506 507 508 /** 509 * Get the file posix path relative to it's root (no trailing /) 510 * 511 * @return string full path 512 */ 513 function get_rdfp_rel_path() 514 { 515 return $this->_rdfp_rel_path; 516 } 517 518 519 /** 520 * Get the file path relative to it's root, WITH trailing slash. 521 * 522 * @return string full path 523 */ 524 function get_rdfs_rel_path() 525 { 526 return $this->_rdfp_rel_path.( $this->_is_dir ? '/' : '' ); 527 } 528 529 530 /** 531 * Get the full path (directory and name) to the file. 532 * 533 * If the File is a directory, the Path ends with a / 534 * 535 * @return string full path 536 */ 537 function get_full_path() 538 { 539 return $this->_adfp_full_path.( $this->_is_dir ? '/' : '' ); 540 } 541 542 543 /** 544 * Get the absolute file url if the file is public 545 * Get the getfile.php url if we need to check permission before delivering the file 546 */ 547 function get_url() 548 { 549 global $public_access_to_media, $htsrv_url; 550 551 if( $this->is_dir() ) 552 { // Directory 553 if( $public_access_to_media ) 554 { // Public access: full path 555 $url = $this->_FileRoot->ads_url.$this->get_rdfs_rel_path(); 556 } 557 else 558 { // No Access 559 debug_die( 'Private directory! '); 560 } 561 } 562 else 563 { // File 564 if( $public_access_to_media ) 565 { // Public Access : full path 566 $url = $this->_FileRoot->ads_url.$this->_rdfp_rel_path; 567 } 568 else 569 { // Private Access: doesn't show the full path 570 $root = $this->_FileRoot->ID; 571 $url = $htsrv_url.'getfile.php/' 572 // This is for clean 'save as': 573 .rawurlencode( $this->_name ) 574 // This is for locating the file: 575 .'?root='.$root.'&path='.$this->_rdfp_rel_path; 576 } 577 } 578 return $url; 579 } 580 581 582 /** 583 * Get location of file with its root (for display) 584 */ 585 function get_root_and_rel_path() 586 { 587 return $this->_FileRoot->name.':'.$this->get_rdfs_rel_path(); 588 } 589 590 591 /** 592 * Get the File's FileRoot. 593 * 594 * @return FileRoot 595 */ 596 function & get_FileRoot() 597 { 598 return $this->_FileRoot; 599 } 600 601 602 /** 603 * Get the file's extension. 604 * 605 * @return string the extension 606 */ 607 function get_ext() 608 { 609 if( preg_match('/\.([^.]+)$/', $this->_name, $match) ) 610 { 611 return $match[1]; 612 } 613 else 614 { 615 return ''; 616 } 617 } 618 619 620 /** 621 * Get the file type as a descriptive localized string. 622 * 623 * @return string localized type name or 'Directory' or 'Unknown' 624 */ 625 function get_type() 626 { 627 if( isset( $this->_type ) ) 628 { // The type is already cached for this object: 629 return $this->_type; 630 } 631 632 if( $this->is_dir() ) 633 { 634 $this->_type = T_('Directory'); 635 return $this->_type; 636 } 637 638 if( isset( $this->Filetype->mimetype ) ) 639 { 640 $this->_type = $this->Filetype->name; 641 return $this->_type; 642 } 643 644 $this->_type = T_('Unknown'); 645 return $this->_type; 646 } 647 648 649 /** 650 * Get file size in bytes. 651 * 652 * @return integer bytes 653 */ 654 function get_size() 655 { 656 return $this->_size; 657 } 658 659 660 /** 661 * Get timestamp of last modification. 662 * 663 * @return integer Timestamp 664 */ 665 function get_lastmod_ts() 666 { 667 return $this->_lastmod_ts; 668 } 669 670 671 /** 672 * Get date/time of last modification, formatted. 673 * 674 $ @param string date format or 'date' or 'time' for default locales. 675 * @return string locale formatted date/time 676 */ 677 function get_lastmod_formatted( $format = '#' ) 678 { 679 global $localtimenow; 680 681 switch( $format ) 682 { 683 case 'date': 684 return date_i18n( locale_datefmt(), $this->_lastmod_ts ); 685 686 case 'time': 687 return date_i18n( locale_timefmt(), $this->_lastmod_ts ); 688 689 case 'compact': 690 $age = $localtimenow - $this->_lastmod_ts; 691 if( $age < 3600 ) 692 { // Less than 1 hour: return full time 693 return date_i18n( 'H:i:s', $this->_lastmod_ts ); 694 } 695 if( $age < 86400 ) 696 { // Less than 24 hours: return compact time 697 return date_i18n( 'H:i', $this->_lastmod_ts ); 698 } 699 if( $age < 31536000 ) 700 { // Less than 365 days: Month and day 701 return date_i18n( 'M, d', $this->_lastmod_ts ); 702 } 703 // Older: return yeat 704 return date_i18n( 'Y', $this->_lastmod_ts ); 705 break; 706 707 case '#': 708 default: 709 $format = locale_datefmt().' '.locale_timefmt(); 710 return date_i18n( $format, $this->_lastmod_ts ); 711 } 712 } 713 714 715 /** 716 * Get permissions 717 * 718 * Possible return formats are: 719 * - 'raw'=integer 720 * - 'lsl'=string like 'ls -l' 721 * - 'octal'=3 digits 722 * 723 * Default value: 724 * - 'r'/'r+w' for windows 725 * - 'octal' for other OS 726 * 727 * @param string type, see desc above. 728 * @return mixed permissions 729 */ 730 function get_perms( $type = NULL ) 731 { 732 switch( $type ) 733 { 734 case 'raw': 735 return $this->_perms; 736 737 case 'lsl': 738 $sP = ''; 739 740 if(($this->_perms & 0xC000) == 0xC000) // Socket 741 $sP = 's'; 742 elseif(($this->_perms & 0xA000) == 0xA000) // Symbolic Link 743 $sP = 'l'; 744 elseif(($this->_perms & 0x8000) == 0x8000) // Regular 745 $sP = '−'; 746 elseif(($this->_perms & 0x6000) == 0x6000) // Block special 747 $sP = 'b'; 748 elseif(($this->_perms & 0x4000) == 0x4000) // Directory 749 $sP = 'd'; 750 elseif(($this->_perms & 0x2000) == 0x2000) // Character special 751 $sP = 'c'; 752 elseif(($this->_perms & 0x1000) == 0x1000) // FIFO pipe 753 $sP = 'p'; 754 else // UNKNOWN 755 $sP = 'u'; 756 757 // owner 758 $sP .= (($this->_perms & 0x0100) ? 'r' : '−') . 759 (($this->_perms & 0x0080) ? 'w' : '−') . 760 (($this->_perms & 0x0040) ? (($this->_perms & 0x0800) ? 's' : 'x' ) 761 : (($this->_perms & 0x0800) ? 'S' : '−')); 762 763 // group 764 $sP .= (($this->_perms & 0x0020) ? 'r' : '−') . 765 (($this->_perms & 0x0010) ? 'w' : '−') . 766 (($this->_perms & 0x0008) ? (($this->_perms & 0x0400) ? 's' : 'x' ) 767 : (($this->_perms & 0x0400) ? 'S' : '−')); 768 769 // world 770 $sP .= (($this->_perms & 0x0004) ? 'r' : '−') . 771 (($this->_perms & 0x0002) ? 'w' : '−') . 772 (($this->_perms & 0x0001) ? (($this->_perms & 0x0200) ? 't' : 'x' ) 773 : (($this->_perms & 0x0200) ? 'T' : '−')); 774 return $sP; 775 776 case NULL: 777 if( is_windows() ) 778 { 779 if( $this->_perms & 0x0080 ) 780 { 781 return 'r+w'; 782 } 783 else return 'r'; 784 } 785 786 case 'octal': 787 return substr( sprintf('%o', $this->_perms), -3 ); 788 } 789 790 return false; 791 } 792 793 794 /** 795 * Get the owner name of the file. 796 * 797 * @todo Can this be fixed for windows? filegroup() might only return 0 or 1 nad posix_getgrgid() is not available.. 798 * @return NULL|string 799 */ 800 function get_fsgroup_name() 801 { 802 if( ! isset( $this->_fsgroup_name ) ) 803 { 804 $gid = @filegroup( $this->_adfp_full_path ); // might spit a warning for a dangling symlink 805 806 if( $gid !== false 807 && function_exists( 'posix_getgrgid' ) ) // func does not exist on windows 808 { 809 $posix_group = posix_getgrgid( $gid ); 810 if( is_array($posix_group) ) 811 { 812 $this->_fsgroup_name = $posix_group['name']; 813 } 814 } 815 } 816 817 return $this->_fsgroup_name; 818 } 819 820 821 /** 822 * Get the owner name of the file. 823 * 824 * @todo Can this be fixed for windows? fileowner() might only return 0 or 1 nad posix_getpwuid() is not available.. 825 * @return NULL|string 826 */ 827 function get_fsowner_name() 828 { 829 if( ! isset( $this->_fsowner_name ) ) 830 { 831 $uid = @fileowner( $this->_adfp_full_path ); // might spit a warning for a dangling symlink 832 if( $uid !== false 833 && function_exists( 'posix_getpwuid' ) ) // func does not exist on windows 834 { 835 $posix_user = posix_getpwuid( $uid ); 836 if( is_array($posix_user) ) 837 { 838 $this->_fsowner_name = $posix_user['name']; 839 } 840 } 841 } 842 843 return $this->_fsowner_name; 844 } 845 846 847 /** 848 * Get icon for this file. 849 * 850 * Looks at the file's extension. 851 * 852 * @uses get_icon() 853 * @return string img tag 854 */ 855 function get_icon() 856 { 857 if( $this->is_dir() ) 858 { // Directory icon: 859 $icon = 'folder'; 860 } 861 elseif( isset( $this->Filetype->icon ) && $this->Filetype->icon ) 862 { // Return icon for known type of the file 863 return $this->Filetype->get_icon(); 864 } 865 else 866 { // Icon for unknown file type: 867 $icon = 'file_unknown'; 868 } 869 // Return Icon for a directory or unknown type file: 870 return get_icon( $icon, 'imgtag', array( 'alt'=>$this->get_ext(), 'title'=>$this->get_type() ) ); 871 } 872 873 874 /** 875 * Get size of an image or false if not an image 876 * 877 * @todo cache this data (NOTE: we have different params here! - imgsize() does caching already!) 878 * 879 * @uses imgsize() 880 * @param string {@link imgsize()} 881 * @return false|mixed false if the File is not an image, the requested data otherwise 882 */ 883 function get_image_size( $param = 'widthxheight' ) 884 { 885 return imgsize( $this->_adfp_full_path, $param ); 886 } 887 888 889 /** 890 * Get size of the file, formatted to nearest unit (kb, mb, etc.) 891 * 892 * @uses bytesreadable() 893 * @return string size as b/kb/mb/gd; or '<dir>' 894 */ 895 function get_size_formatted() 896 { 897 if( $this->_size === NULL ) 898 { 899 return /* TRANS: short for '<directory>' */ T_('<dir>'); 900 } 901 else 902 { 903 return bytesreadable( $this->_size ); 904 } 905 } 906 907 908 /** 909 * Get a complete tag (IMG or A HREF) pointing to this file. 910 * 911 * @param string 912 * @param string NULL for no legend 913 * @param string 914 * @param string 915 * @param string 916 */ 917 function get_tag( $before_image = '<div class="image_block">', 918 $before_image_legend = '<div class="image_legend">', 919 $after_image_legend = '</div>', 920 $after_image = '</div>', 921 $size_name = 'original' ) 922 { 923 if( $this->is_dir() ) 924 { // We can't reference a directory 925 return ''; 926 } 927 928 $this->load_meta(); 929 930 if( $this->is_image() ) 931 { // Make an IMG link: 932 $r = $before_image; 933 if( $size_name == 'original' ) 934 { 935 $r .= '<img src="'.$this->get_url().'" ' 936 .'alt="'.$this->dget('alt', 'htmlattr').'" ' 937 .'title="'.$this->dget('title', 'htmlattr').'" ' 938 .$this->get_image_size( 'string' ).' />'; 939 } 940 else 941 { 942 $r .= '<img src="'.$this->get_thumb_url( $size_name ).'" ' 943 .'alt="'.$this->dget('alt', 'htmlattr').'" ' 944 .'title="'.$this->dget('title', 'htmlattr').'" />'; 945 // TODO: size 946 } 947 $desc = $this->dget('desc'); 948 if( !empty($desc) and !is_null($before_image_legend) ) 949 { 950 $r .= $before_image_legend 951 .$this->dget('desc') 952 .$after_image_legend; 953 } 954 $r .= $after_image; 955 } 956 else 957 { // Make an A HREF link: 958 $r = '<a href="'.$this->get_url() 959 .'" title="'.$this->dget('desc', 'htmlattr').'">' 960 .$this->dget('title').'</a>'; 961 } 962 963 return $r; 964 } 965 966 967 /** 968 * Internally sets the file/directory size 969 * 970 * This is used when the FileList wants to set the recursive size of a directory! 971 * 972 * @todo pass a param to the constructor telling it we want to store a recursive size for the direcrory. 973 * @todo store the recursive size separately (in another member), to avoid confusion 974 * 975 * @access public 976 * @param integer 977 */ 978 function setSize( $bytes ) 979 { 980 $this->_size = $bytes; 981 } 982 983 984 /** 985 * Rename the file in its current directory on disk. 986 * 987 * Also update meta data in DB. 988 * 989 * @access public 990 * @param string new name (without path!) 991 * @return boolean true on success, false on failure 992 */ 993 function rename_to( $newname ) 994 { 995 // echo "newname= $newname "; 996 997 // rename() will fail if newname already exists on windows 998 // if it doesn't work that way on linux we need the extra check below 999 // but then we have an integrity issue!! :( 1000 if( file_exists($this->_dir.$newname) ) 1001 { 1002 return false; 1003 } 1004 1005 // Note: what happens if someone else creates $newname right at this moment here? 1006 1007 if( ! @rename( $this->_adfp_full_path, $this->_dir.$newname ) ) 1008 { // Rename will fail if $newname already exists (at least on windows) 1009 return false; 1010 } 1011 1012 // Delete thumb caches for old name: 1013 // Note: new name = new usage : there is a fair chance we won't need the same cache sizes in the new loc. 1014 $this->rm_cache(); 1015 1016 // Get Meta data (before we change name) (we may need to update it later): 1017 $this->load_meta(); 1018 1019 $this->_name = $newname; 1020 1021 $rel_dir = dirname( $this->_rdfp_rel_path ).'/'; 1022 if( $rel_dir == './' ) 1023 { 1024 $rel_dir = ''; 1025 } 1026 $this->_rdfp_rel_path = $rel_dir.$this->_name; 1027 1028 $this->_adfp_full_path = $this->_dir.$this->_name; 1029 $this->_md5ID = md5( $this->_adfp_full_path ); 1030 1031 if( $this->meta == 'loaded' ) 1032 { // We have meta data, we need to deal with it: 1033 // unchanged : $this->set( 'root_type', $this->_FileRoot->type ); 1034 // unchanged : $this->set( 'root_ID', $this->_FileRoot->in_type_ID ); 1035 $this->set( 'path', $this->_rdfp_rel_path ); 1036 // Record to DB: 1037 $this->dbupdate(); 1038 } 1039 else 1040 { // There might be some old meta data to *recycle* in the DB... 1041 // This can happen if there has been a file in the same location in the past and if that file 1042 // has been manually deleted or moved since then. When the new file arrives here, we'll recover 1043 // the zombie meta data and we don't reset it on purpose. Actually, we consider that the meta data 1044 // has been *accidentaly* lost and that the user is attempting to recover it by putting back the 1045 // file where it was before. Of course the logical way would be to put back the file manually, but 1046 // experience proves that users are inconsistent! 1047 $this->load_meta(); 1048 } 1049 1050 return true; 1051 } 1052 1053 1054 /** 1055 * Move the file to another location 1056 * 1057 * Also updates meta data in DB 1058 * 1059 * @param string Root type: 'user', 'group', 'collection' or 'absolute' 1060 * @param integer ID of the user, the group or the collection the file belongs to... 1061 * @param string Subpath for this file/folder, relative the associated root (no trailing slash) 1062 * @return boolean true on success, false on failure 1063 */ 1064 function move_to( $root_type, $root_ID, $rdfp_rel_path ) 1065 { 1066 // echo "relpath= $rel_path "; 1067 1068 $rdfp_rel_path = str_replace( '\\', '/', $rdfp_rel_path ); 1069 $FileRootCache = & get_Cache( 'FileRootCache' ); 1070 1071 $new_FileRoot = & $FileRootCache->get_by_type_and_ID( $root_type, $root_ID, true ); 1072 $adfp_posix_path = $new_FileRoot->ads_path.$rdfp_rel_path; 1073 1074 if( ! @rename( $this->_adfp_full_path, $adfp_posix_path ) ) 1075 { 1076 return false; 1077 } 1078 1079 // Delete thumb caches from old location: 1080 // Note: new location = new usage : there is a fair chance we won't need the same cache sizes in the new loc. 1081 $this->rm_cache(); 1082 1083 // Get Meta data (before we change name) (we may need to update it later): 1084 $this->load_meta(); 1085 1086 // Memorize new filepath: 1087 $this->_FileRoot = & $new_FileRoot; 1088 $this->_rdfp_rel_path = $rdfp_rel_path; 1089 $this->_adfp_full_path = $adfp_posix_path; 1090 $this->_name = basename( $this->_adfp_full_path ); 1091 $this->_dir = dirname( $this->_adfp_full_path ).'/'; 1092 $this->_md5ID = md5( $this->_adfp_full_path ); 1093 1094 if( $this->meta == 'loaded' ) 1095 { // We have meta data, we need to deal with it: 1096 $this->set( 'root_type', $this->_FileRoot->type ); 1097 $this->set( 'root_ID', $this->_FileRoot->in_type_ID ); 1098 $this->set( 'path', $this->_rdfp_rel_path ); 1099 // Record to DB: 1100 $this->dbupdate(); 1101 } 1102 else 1103 { // There might be some old meta data to *recycle* in the DB... 1104 // This can happen if there has been a file in the same location in the past and if that file 1105 // has been manually deleted or moved since then. When the new file arrives here, we'll recover 1106 // the zombie meta data and we don't reset it on purpose. Actually, we consider that the meta data 1107 // has been *accidentaly* lost and that the user is attempting to recover it by putting back the 1108 // file where it was before. Of course the logical way would be to put back the file manually, but 1109 // experience proves that users are inconsistent! 1110 $this->load_meta(); 1111 } 1112 1113 return true; 1114 } 1115 1116 1117 /** 1118 * Copy this file to a new location 1119 * 1120 * Also copy meta data in Object 1121 * 1122 * @param File the target file (expected to not exist) 1123 * @return boolean true on success, false on failure 1124 */ 1125 function copy_to( & $dest_File ) 1126 { 1127 if( ! $this->exists() || $dest_File->exists() ) 1128 { 1129 return false; 1130 } 1131 1132 // Note: what happens if someone else creates the destination file right at this moment here? 1133 1134 if( ! @copy( $this->get_full_path(), $dest_File->get_full_path() ) ) 1135 { // Note: unlike rename() (at least on Windows), copy() will not fail if destination already exists 1136 // this is probably a permission problem 1137 return false; 1138 } 1139 1140 // Initializes file properties (type, size, perms...) 1141 $dest_File->load_properties(); 1142 1143 // Meta data...: 1144 if( $this->load_meta() ) 1145 { // We have source meta data, we need to copy it: 1146 // Try to load DB meta info for destination file: 1147 $dest_File->load_meta(); 1148 1149 // Copy meta data: 1150 $dest_File->set( 'title', $this->title ); 1151 $dest_File->set( 'alt' , $this->alt ); 1152 $dest_File->set( 'desc' , $this->desc ); 1153 1154 // Save meta data: 1155 $dest_File->dbsave(); 1156 } 1157 1158 return true; 1159 } 1160 1161 1162 /** 1163 * Unlink/Delete the file or folder from disk. 1164 * 1165 * Also removes meta data from DB. 1166 * 1167 * @access public 1168 * @return boolean true on success, false on failure 1169 */ 1170 function unlink() 1171 { 1172 global $DB; 1173 1174 $DB->begin(); 1175 1176 // Check if there is meta data to be removed: 1177 if( $this->load_meta() ) 1178 { // remove meta data from DB: 1179 $this->dbdelete(); 1180 } 1181 1182 //Remove thumb cache: 1183 $this->rm_cache(); 1184 1185 // Physically remove file from disk: 1186 if( $this->is_dir() ) 1187 { 1188 $unlinked = @rmdir( $this->_adfp_full_path ); 1189 } 1190 else 1191 { 1192 $unlinked = @unlink( $this->_adfp_full_path ); 1193 } 1194 1195 if( !$unlinked ) 1196 { 1197 $DB->rollback(); 1198 1199 return false; 1200 } 1201 1202 $this->_exists = false; 1203 1204 $DB->commit(); 1205 1206 return true; 1207 } 1208 1209 1210 /** 1211 * Change file permissions on disk. 1212 * 1213 * @access public 1214 * @param string chmod (octal three-digit-format, eg '777'), uses {@link $Settings} for NULL 1215 * (fm_default_chmod_dir, fm_default_chmod_file) 1216 * @return mixed new permissions on success (octal format), false on failure 1217 */ 1218 function chmod( $chmod = NULL ) 1219 { 1220 if( $chmod === NULL ) 1221 { 1222 global $Settings; 1223 1224 $chmod = $this->is_dir() 1225 ? $Settings->get( 'fm_default_chmod_dir' ) 1226 : $Settings->get( 'fm_default_chmod_file' ); 1227 } 1228 1229 if( @chmod( $this->_adfp_full_path, octdec( $chmod ) ) ) 1230 { 1231 clearstatcache(); 1232 // update current entry 1233 $this->_perms = fileperms( $this->_adfp_full_path ); 1234 1235 return $this->_perms; 1236 } 1237 else 1238 { 1239 return false; 1240 } 1241 } 1242 1243 1244 /** 1245 * Insert object into DB based on previously recorded changes 1246 * 1247 * @return boolean true on success, false on failure 1248 */ 1249 function dbinsert( ) 1250 { 1251 global $Debuglog; 1252 1253 if( $this->meta == 'unknown' ) 1254 { 1255 debug_die( 'cannot insert File if meta data has not been checked before' ); 1256 } 1257 1258 if( ($this->ID != 0) || ($this->meta != 'notfound') ) 1259 { 1260 debug_die( 'Existing file object cannot be inserted!' ); 1261 } 1262 1263 $Debuglog->add( 'Inserting meta data for new file into db', 'files' ); 1264 1265 // Let's make sure the bare minimum gets saved to DB: 1266 $this->set_param( 'root_type', 'string', $this->_FileRoot->type ); 1267 $this->set_param( 'root_ID', 'integer', $this->_FileRoot->in_type_ID ); 1268 $this->set_param( 'path', 'string', $this->_rdfp_rel_path ); 1269 1270 // Let parent do the insert: 1271 $r = parent::dbinsert(); 1272 1273 // We can now consider the meta data has been loaded: 1274 $this->meta = 'loaded'; 1275 1276 return $r; 1277 } 1278 1279 1280 /** 1281 * Update the DB based on previously recorded changes 1282 * 1283 * @return boolean true on success, false on failure / no changes 1284 */ 1285 function dbupdate( ) 1286 { 1287 if( $this->meta == 'unknown' ) 1288 { 1289 debug_die( 'cannot update File if meta data has not been checked before' ); 1290 } 1291 1292 // Let parent do the update: 1293 return parent::dbupdate(); 1294 } 1295 1296 1297 /** 1298 * Get URL to view the file (either with viewer of with browser, etc...) 1299 */ 1300 function get_view_url( $always_open_dirs_in_fm = true ) 1301 { 1302 global $htsrv_url, $public_access_to_media; 1303 1304 // Get root code 1305 $root_ID = $this->_FileRoot->ID; 1306 1307 if( $this->is_dir() ) 1308 { // Directory 1309 if( $always_open_dirs_in_fm || ! $public_access_to_media ) 1310 { // open the dir in the filemanager: 1311 // fp>> Note: we MUST NOT clear mode, especially when mode=upload, or else the IMG button disappears when entering a subdir 1312 return regenerate_url( 'root,path', 'root='.$root_ID.'&path='.$this->get_rdfs_rel_path() ); 1313 } 1314 else 1315 { // Public access: direct link to folder: 1316 return $this->get_url(); 1317 } 1318 } 1319 else 1320 { // File 1321 if( !isset( $this->Filetype->viewtype ) ) 1322 { 1323 return NULL; 1324 } 1325 switch( $this->Filetype->viewtype ) 1326 { 1327 case 'image': 1328 return $htsrv_url.'viewfile.php?root='.$root_ID.'&path='.$this->_rdfp_rel_path.'&viewtype=image'; 1329 1330 case 'text': 1331 return $htsrv_url.'viewfile.php?root='.$root_ID.'&path='.$this->_rdfp_rel_path.'&viewtype=text'; 1332 1333 case 'download': // will NOT open a popup and will insert a Content-disposition: attachment; header 1334 return $htsrv_url.'getfile.php?root='.$root_ID.'&path='.$this->_rdfp_rel_path; 1335 1336 case 'browser': // will open a popup 1337 case 'external': // will NOT open a popup 1338 default: 1339 return $this->get_url(); 1340 } 1341 } 1342 } 1343 1344 1345 /** 1346 * Get Link to view the file (either with viewer of with browser, etc...) 1347 */ 1348 function get_view_link( $text = NULL, $title = NULL, $no_access_text = NULL ) 1349 { 1350 if( is_null( $text ) ) 1351 { // Use file root+relpath+name by default 1352 $text = $this->get_root_and_rel_path(); 1353 } 1354 1355 if( is_null( $title ) ) 1356 { // Default link title 1357 $this->load_meta(); 1358 $title = $this->title; 1359 } 1360 1361 if( is_null( $no_access_text ) ) 1362 { // Default text when no access: 1363 $no_access_text = $text; 1364 } 1365 1366 // Get the URL for viewing the file/dir: 1367 $url = $this->get_view_url( false ); 1368 1369 if( empty($url) ) 1370 { 1371 return $no_access_text; 1372 } 1373 1374 if( isset($this->Filetype) && in_array( $this->Filetype->viewtype, array( 'external', 'download' ) ) ) 1375 { // Link to open in the curent window 1376 return '<a href="'.$url.'" title="'.$title.'">'.$text.'</a>'; 1377 } 1378 else 1379 { // Link to open in a new window 1380 $target = 'evo_fm_'.$this->get_md5_ID(); 1381 1382 // onclick: we unset target attrib and return the return value of pop_up_window() to make the browser not follow the regular href link (at least FF 1.5 needs the target reset) 1383 return '<a href="'.$url.'" target="'.$target.'" 1384 title="'.T_('Open in a new window').'" onclick="' 1385 ."this.target = ''; return pop_up_window( '$url', '$target', " 1386 .(( $width = $this->get_image_size( 'width' ) ) ? ( $width + 100 ) : 750 ).', ' 1387 .(( $height = $this->get_image_size( 'height' ) ) ? ( $height + 150 ) : 550 ).' )">'.$text.'</a>'; 1388 } 1389 } 1390 1391 1392 /** 1393 * Get link to edit linked file. 1394 * 1395 * @param integer ID of item to link to => will open the FM in link mode 1396 * @param string link text 1397 * @param string link title 1398 * @param string text to display if access denied 1399 * @param string page url for the edit action 1400 */ 1401 function get_linkedit_link( $link_itm_ID = NULL, $text = NULL, $title = NULL, $no_access_text = NULL, 1402 $actionurl = 'admin.php?ctrl=files' ) 1403 { 1404 if( is_null( $text ) ) 1405 { // Use file root+relpath+name by default 1406 $text = $this->get_root_and_rel_path(); 1407 } 1408 1409 if( is_null( $title ) ) 1410 { // Default link title 1411 $this->load_meta(); 1412 $title = $this->title; 1413 } 1414 1415 if( is_null( $no_access_text ) ) 1416 { // Default text when no access: 1417 $no_access_text = $text; 1418 } 1419 1420 if( $this->is_dir() ) 1421 { 1422 $rdfp_path = $this->_rdfp_rel_path; 1423 } 1424 else 1425 { 1426 $rdfp_path = dirname( $this->_rdfp_rel_path ); 1427 } 1428 1429 $url_params = 'root='.$this->_FileRoot->ID.'&path='.$rdfp_path.'/'; 1430 1431 if( ! is_null($link_itm_ID) ) 1432 { // We want to open the filemanager in link mode: 1433 $url_params .= '&fm_mode=link_item&item_ID='.$link_itm_ID; 1434 } 1435 1436 $url = url_add_param( $actionurl, $url_params ); 1437 1438 return '<a href="'.$url.'" title="'.$title.'">'.$text.'</a>'; 1439 } 1440 1441 1442 /** 1443 * Get the thumbnail URL for this file 1444 * 1445 * @param string not ready for being changed yet (fp) 1446 */ 1447 function get_thumb_url( $size_name = 'fit-80x80' ) 1448 { 1449 global $public_access_to_media, $htsrv_url; 1450 1451 if( ! $this->is_image() ) 1452 { // Not an image 1453 debug_die( 'Can only thumb images'); 1454 } 1455 1456 if( $public_access_to_media 1457 && $af_thumb_path = $this->get_af_thumb_path( $size_name, NULL, false ) ) 1458 { // If the thumbnail was already cached, we could publicly access it: 1459 if( @is_file( $af_thumb_path ) ) 1460 { // The thumb IS already cache! :) 1461 // Let's point directly into the cache: 1462 $url = $this->_FileRoot->ads_url.dirname($this->_rdfp_rel_path).'/.evocache/'.$this->_name.'/'.$size_name.'.'.$this->get_ext(); 1463 return $url; 1464 } 1465 } 1466 1467 // No thumbnail available (at least publicly), we need to go through getfile.php! 1468 $root = $this->_FileRoot->ID; 1469 $url = $htsrv_url.'getfile.php/' 1470 // This is for clean 'save as': 1471 .rawurlencode( $this->_name ) 1472 // This is for locating the file: 1473 .'?root='.$root.'&path='.$this->_rdfp_rel_path.'&size='.$size_name; 1474 1475 return $url; 1476 } 1477 1478 1479 /** 1480 * Displays a preview thumbnail which is clickable and opens a view popup 1481 * 1482 * @param string what do do with files that are not images? 'fulltype' 1483 * @return string HTML to display 1484 */ 1485 function get_preview_thumb( $format_for_non_images = '' ) 1486 { 1487 if( $this->is_image() ) 1488 { // Ok, it's an image: 1489 $img = '<img src="'.$this->get_thumb_url().'" alt="'.$this->get_type().'" title="'.$this->get_type().'" />'; 1490 1491 // Get link to view the file (fallback to no view link - just the img): 1492 $link = $this->get_view_link( $img ); 1493 if( ! $link ) 1494 { // no view link available: 1495 $link = $img; 1496 } 1497 1498 return $link; 1499 } 1500 1501 // Not an image... 1502 switch( $format_for_non_images ) 1503 { 1504 case 'fulltype': 1505 // Full: Icon + File type: 1506 return $this->get_view_link( $this->get_icon() ).' '.$this->get_type(); 1507 break; 1508 } 1509 1510 return ''; 1511 } 1512 1513 1514 /** 1515 * Get the full path to the thumbnail cache for this file. 1516 * 1517 * ads = Absolute Directory Slash 1518 * 1519 * @param boolean shall we create the dir if it doesn't exist? 1520 * @return string or NULL if can't be obtained 1521 */ 1522 function get_ads_evocache( $create_if_needed = false ) 1523 { 1524 if( strpos( $this->_dir, '/.evocache/' ) !== false ) 1525 { // We are already in an evocahce folder: refuse to go further! 1526 return NULL; 1527 } 1528 1529 $adp_evocache = $this->_dir.'.evocache/'.$this->_name; 1530 1531 if( $create_if_needed && !is_dir( $adp_evocache ) ) 1532 { // Create the directory: 1533 if( ! mkdir_r( $adp_evocache ) ) 1534 { // Could not create 1535 return NULL; 1536 } 1537 } 1538 1539 return $adp_evocache.'/'; 1540 } 1541 1542 1543 /** 1544 * Delete cache for a file 1545 */ 1546 function rm_cache() 1547 { 1548 // Remove cached elts for teh current file: 1549 $ads_filecache = $this->get_ads_evocache( false ); 1550 rmdir_r( $ads_filecache ); 1551 1552 // In case cache is now empty, delete the folder: 1553 $adp_evocache = $this->_dir.'.evocache'; 1554 @rmdir( $adp_evocache ); 1555 } 1556 1557 1558 /** 1559 * Get the full path to the thumbanil for this file. 1560 * 1561 * af = Absolute File 1562 * 1563 * @param string size name 1564 * @param string mimetype of thumbnail (NULL if we're ready to take wathever is available) 1565 * @param boolean shall we create the dir if it doesn't exist? 1566 * @return string or NULL if can't be obtained 1567 */ 1568 function get_af_thumb_path( $size_name, $thumb_mimetype = NULL, $create_evocache_if_needed = false ) 1569 { 1570 if( empty($thumb_mimetype) ) 1571 { 1572 $thumb_mimetype = $this->Filetype->mimetype; 1573 } 1574 elseif( $thumb_mimetype != $this->Filetype->mimetype ) 1575 { 1576 debug_die( 'Not supported. For now, thumbnails have to have same mime type as their parent file.' ); 1577 // TODO: extract prefered extension of filetypes config 1578 } 1579 1580 // Get the filename of the thumbnail 1581 if( $ads_evocache = $this->get_ads_evocache( $create_evocache_if_needed ) ) 1582 { 1583 return $ads_evocache.$size_name.'.'.$this->get_ext(); 1584 } 1585 1586 return NULL; 1587 } 1588 1589 1590 /** 1591 *Save thumbnail for file 1592 * 1593 * @param resource 1594 * @param string size name 1595 * @param string miemtype of thumbnail 1596 * @param string short error code 1597 */ 1598 function save_thumb_to_cache( $thumb_imh, $size_name, $thumb_mimetype, $thumb_quality = 90 ) 1599 { 1600 if( $af_thumb_path = $this->get_af_thumb_path( $size_name, $thumb_mimetype, true ) ) 1601 { // We obtained a path for the thumbnail to be saved: 1602 return save_image( $thumb_imh, $af_thumb_path, $thumb_mimetype, $thumb_quality ); 1603 } 1604 1605 return 'Ewr-access'; 1606 } 1607 1608 1609 /** 1610 * Output previously saved thumbnail for file 1611 * 1612 * @param string size name 1613 * @param string miemtype of thumbnail 1614 * @param string short error code 1615 */ 1616 function output_cached_thumb( $size_name, $thumb_mimetype ) 1617 { 1618 if( $af_thumb_path = $this->get_af_thumb_path( $size_name, $thumb_mimetype, false ) ) 1619 { // We obtained a path for the thumbnail to be saved: 1620 if( ! file_exists( $af_thumb_path ) ) 1621 { // The thumbnail was not found... 1622 return 'Enotcached'; 1623 } 1624 1625 if( ! is_readable( $af_thumb_path ) ) 1626 { 1627 return 'Eread'; 1628 } 1629 1630 header('Content-type: '.$thumb_mimetype ); 1631 header('Content-Length: '.filesize( $af_thumb_path ) ); 1632 // Output the content of the file 1633 readfile( $af_thumb_path ); 1634 return NULL; 1635 } 1636 1637 return 'Erd-access'; 1638 } 1639 1640 1641 1642 /** 1643 * This will spit out a content-type header followed by a thumbnail for this file. 1644 * 1645 * @todo a million things (fp) but you get the idea... 1646 * The generated thumb will be saved to a cached file here (fp) 1647 * The cache will be accessed through the File object (fp) 1648 * @todo cleanup memory resources 1649 * 1650 * @param string requested size: 'thumbnail' 1651 */ 1652 function thumbnail( $req_size ) 1653 { 1654 load_funcs( '/files/model/_image.funcs.php' ); 1655 1656 $size_name = $req_size; 1657 switch( $req_size ) 1658 { 1659 case 'fit-720x500'; 1660 $thumb_width = 720; 1661 $thumb_height = 500; 1662 $thumb_quality = 90; 1663 break; 1664 1665 case 'fit-640x480'; 1666 $thumb_width = 640; 1667 $thumb_height = 480; 1668 $thumb_quality = 90; 1669 break; 1670 1671 case 'fit-400x320'; 1672 $thumb_width = 400; 1673 $thumb_height = 320; 1674 $thumb_quality = 85; 1675 break; 1676 1677 case 'fit-320x320'; 1678 $thumb_width = 320; 1679 $thumb_height = 320; 1680 $thumb_quality = 85; 1681 break; 1682 1683 case 'fit-80x80'; 1684 default: 1685 $size_name = 'fit-80x80'; 1686 $thumb_width = 80; 1687 $thumb_height = 80; 1688 $thumb_quality = 75; 1689 } 1690 1691 $mimetype = $this->Filetype->mimetype; 1692 1693 // Try to output the cached thumbnail: 1694 $err = $this->output_cached_thumb( $size_name, $mimetype ); 1695 1696 if( $err == 'Enotcached' ) 1697 { // The thumbnail wasn't already in the cache, try to generate and cache it now: 1698 $err = NULL; // Short error code 1699 1700 list( $err, $err_info, $src_imh ) = load_image( $this->get_full_path(), $mimetype ); 1701 if( empty( $err ) ) 1702 { 1703 list( $err, $dest_imh ) = generate_thumb( $src_imh, $thumb_width, $thumb_height ); 1704 if( empty( $err ) ) 1705 { 1706 $err = $this->save_thumb_to_cache( $dest_imh, $size_name, $mimetype, $thumb_quality ); 1707 if( empty( $err ) ) 1708 { // File was saved. Ouput that same file immediately: 1709 // This is probably better than recompressing the memory image.. 1710 $err = $this->output_cached_thumb( $size_name, $mimetype ); 1711 } 1712 else 1713 { // File could not be saved. 1714 // fp> We might want to output dynamically... 1715 // $err = output_image( $dest_imh, $mimetype ); 1716 } 1717 } 1718 } 1719 } 1720 1721 if( !empty( $err ) ) 1722 { // Generate an error image and try to squeeze an error message inside: 1723 // Note: we write small and close to the upper left in order to have as much text as possible on small thumbs 1724 $im_handle = imagecreatetruecolor( $thumb_width, $thumb_height ); // Create a black image 1725 $text_color = imagecolorallocate( $im_handle, 255, 0, 0 ); 1726 imagestring( $im_handle, 2, 2, 1, $err, $text_color); 1727 if( !empty( $err_info ) ) 1728 { // Additional info 1729 $text_color = imagecolorallocate( $im_handle, 255, 255, 255 ); 1730 imagestring( $im_handle, 2, 2, 12, $err_info, $text_color); 1731 } 1732 header('Content-type: image/png' ); 1733 imagepng( $im_handle ); 1734 } 1735 } 1736 } 1737 1738 1739 /* 1740 * $Log: _file.class.php,v $ 1741 * Revision 1.1 2007/06/25 10:59:54 fplanque 1742 * MODULES (refactored MVC) 1743 * 1744 * Revision 1.45 2007/06/23 22:05:16 fplanque 1745 * fixes 1746 * 1747 * Revision 1.44 2007/06/18 20:59:02 fplanque 1748 * minor 1749 * 1750 * Revision 1.43 2007/04/26 00:11:10 fplanque 1751 * (c) 2007 1752 * 1753 * Revision 1.42 2007/03/20 07:43:44 fplanque 1754 * .evocache cleanup triggers 1755 * 1756 * Revision 1.41 2007/03/05 02:13:26 fplanque 1757 * improved dashboard 1758 * 1759 * Revision 1.40 2007/02/10 18:03:03 waltercruz 1760 * Changing double quotes to single quotes 1761 * 1762 * Revision 1.39 2007/01/26 02:12:06 fplanque 1763 * cleaner popup windows 1764 * 1765 * Revision 1.38 2007/01/25 03:37:14 fplanque 1766 * made bytesreadable() really readable for average people. 1767 * 1768 * Revision 1.37 2007/01/25 03:17:00 fplanque 1769 * visual cleanup for average users 1770 * geeky stuff preserved as options 1771 * 1772 * Revision 1.36 2007/01/24 05:57:55 fplanque 1773 * cleanup / settings 1774 * 1775 * Revision 1.35 2007/01/19 10:45:42 fplanque 1776 * images everywhere :D 1777 * At this point the photoblogging code can be considered operational. 1778 * 1779 * Revision 1.34 2007/01/19 09:31:05 fplanque 1780 * Provision for case sensitive file meta data handling 1781 * 1782 * Revision 1.33 2007/01/19 08:20:36 fplanque 1783 * Addressed resized image quality. 1784 * 1785 * Revision 1.32 2007/01/15 20:48:20 fplanque 1786 * constrained photoblog image size 1787 * TODO: sharpness issue 1788 * 1789 * Revision 1.31 2006/12/23 22:53:10 fplanque 1790 * extra security 1791 * 1792 * Revision 1.30 2006/12/14 01:46:29 fplanque 1793 * refactoring / factorized image preview display 1794 * 1795 * Revision 1.29 2006/12/14 00:33:53 fplanque 1796 * thumbnails & previews everywhere. 1797 * this is getting good :D 1798 * 1799 * Revision 1.28 2006/12/13 22:26:27 fplanque 1800 * This has reached the point of a functional eternal cache. 1801 * TODO: handle cache on delete, upload/overwrite, rename, move, copy. 1802 * 1803 * Revision 1.27 2006/12/13 21:23:56 fplanque 1804 * .evocache folders / saving of thumbnails 1805 * 1806 * Revision 1.26 2006/12/13 20:10:30 fplanque 1807 * object responsibility delegation? 1808 * 1809 * Revision 1.25 2006/12/13 03:08:28 fplanque 1810 * thumbnail implementation design demo 1811 * 1812 * Revision 1.24 2006/12/07 23:13:10 fplanque 1813 * @var needs to have only one argument: the variable type 1814 * Otherwise, I can't code! 1815 * 1816 * Revision 1.23 2006/12/07 20:03:32 fplanque 1817 * Woohoo! File editing... means all skin editing. 1818 * 1819 * Revision 1.22 2006/11/24 18:27:24 blueyed 1820 * Fixed link to b2evo CVS browsing interface in file docblocks 1821 * 1822 * Revision 1.21 2006/11/19 23:43:04 blueyed 1823 * Optimized icon and $IconLegend handling 1824 */ 1825 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Thu Nov 29 23:58:50 2007 | par Balluche grâce à PHPXref 0.7 |
|