[ Index ]
 

Code source de b2evolution 2.1.0-beta

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/blogs/inc/files/model/ -> _file.class.php (source)

   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 &laquo;%s&raquo;'), $this->_name );
 489          }
 490          else
 491          {
 492              return sprintf( T_('File &laquo;%s&raquo;'), $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.'&amp;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 = '&minus;';
 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' : '&minus;') .
 759                         (($this->_perms & 0x0080) ? 'w' : '&minus;') .
 760                         (($this->_perms & 0x0040) ? (($this->_perms & 0x0800) ? 's' : 'x' )
 761                                                   : (($this->_perms & 0x0800) ? 'S' : '&minus;'));
 762  
 763                  // group

 764                  $sP .= (($this->_perms & 0x0020) ? 'r' : '&minus;') .
 765                         (($this->_perms & 0x0010) ? 'w' : '&minus;') .
 766                         (($this->_perms & 0x0008) ? (($this->_perms & 0x0400) ? 's' : 'x' )
 767                                                   : (($this->_perms & 0x0400) ? 'S' : '&minus;'));
 768  
 769                  // world

 770                  $sP .= (($this->_perms & 0x0004) ? 'r' : '&minus;') .
 771                         (($this->_perms & 0x0002) ? 'w' : '&minus;') .
 772                         (($this->_perms & 0x0001) ? (($this->_perms & 0x0200) ? 't' : 'x' )
 773                                                   : (($this->_perms & 0x0200) ? 'T' : '&minus;'));
 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 '&lt;dir&gt;'

 894       */
 895  	function get_size_formatted()
 896      {
 897          if( $this->_size === NULL )
 898          {
 899              return /* TRANS: short for '<directory>' */ T_('&lt;dir&gt;');
 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.'&amp;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.'&amp;path='.$this->_rdfp_rel_path.'&amp;viewtype=image';
1329  
1330                  case 'text':
1331                      return $htsrv_url.'viewfile.php?root='.$root_ID.'&amp;path='.$this->_rdfp_rel_path.'&amp;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.'&amp;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.'&amp;path='.$rdfp_path.'/';
1430  
1431          if( ! is_null($link_itm_ID) )
1432          {    // We want to open the filemanager in link mode:
1433              $url_params .= '&amp;fm_mode=link_item&amp;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.'&amp;path='.$this->_rdfp_rel_path.'&amp;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  ?>


Généré le : Thu Nov 29 23:58:50 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics