MODX Revolution PHP Cross Reference Content Management Systems

Source: /core/model/phpthumb/modphpthumb.class.php - 317 lines - 17617 bytes - Summary - Text - Print

   1  <?php
   2  /**
   3   * @package modx
   4   * @subpackage phpthumb
   5   */
   6  require_once MODX_CORE_PATH.'model/phpthumb/phpthumb.class.php';
   7  /**
   8   * Helper class to extend phpThumb and simplify thumbnail generation process
   9   * since phpThumb class is overly convoluted and doesn't do enough.
  10   *
  11   * @package modx
  12   * @subpackage phpthumb
  13   */
  14  class modPhpThumb extends phpThumb {
  15  
  16      function __construct(modX &$modx,array $config = array()) {
  17          $this->modx =& $modx;
  18          $this->config = array_merge(array(
  19  
  20          ),$config);
  21          parent::__construct();
  22      }
  23  
  24      /**
  25       * Setup some site-wide phpthumb options from modx config
  26       */
  27      public function initialize() {
  28          $cachePath = $this->modx->getOption('core_path',null,MODX_CORE_PATH).'cache/phpthumb/';
  29          if (!is_dir($cachePath)) $this->modx->cacheManager->writeTree($cachePath);
  30          $this->setParameter('config_cache_directory',$cachePath);
  31          $this->setCacheDirectory();
  32  
  33          $this->setParameter('config_allow_src_above_docroot',(boolean)$this->modx->getOption('phpthumb_allow_src_above_docroot',$this->config,false));
  34          $this->setParameter('config_cache_maxage',(float)$this->modx->getOption('phpthumb_cache_maxage',$this->config,30) * 86400);
  35          $this->setParameter('config_cache_maxsize',(float)$this->modx->getOption('phpthumb_cache_maxsize',$this->config,100) * 1024 * 1024);
  36          $this->setParameter('config_cache_maxfiles',(int)$this->modx->getOption('phpthumb_cache_maxfiles',$this->config,10000));
  37          $this->setParameter('config_error_bgcolor',(string)$this->modx->getOption('phpthumb_error_bgcolor',$this->config,'CCCCFF'));
  38          $this->setParameter('config_error_textcolor',(string)$this->modx->getOption('phpthumb_error_textcolor',$this->config,'FF0000'));
  39          $this->setParameter('config_error_fontsize',(int)$this->modx->getOption('phpthumb_error_fontsize',$this->config,1));
  40          $this->setParameter('config_nohotlink_enabled',(boolean)$this->modx->getOption('phpthumb_nohotlink_enabled',$this->config,true));
  41          $this->setParameter('config_nohotlink_valid_domains',explode(',', $this->modx->getOption('phpthumb_nohotlink_valid_domains',$this->config,$this->modx->getOption('http_host'))));
  42          $this->setParameter('config_nohotlink_erase_image',(boolean)$this->modx->getOption('phpthumb_nohotlink_erase_image',$this->config,true));
  43          $this->setParameter('config_nohotlink_text_message',(string)$this->modx->getOption('phpthumb_nohotlink_text_message',$this->config,'Off-server thumbnailing is not allowed'));
  44          $this->setParameter('config_nooffsitelink_enabled',(boolean)$this->modx->getOption('phpthumb_nooffsitelink_enabled',$this->config,false));
  45          $this->setParameter('config_nooffsitelink_valid_domains',explode(',', $this->modx->getOption('phpthumb_nooffsitelink_valid_domains',$this->config,$this->modx->getOption('http_host'))));
  46          $this->setParameter('config_nooffsitelink_require_refer',(boolean)$this->modx->getOption('phpthumb_nooffsitelink_require_refer',$this->config,false));
  47          $this->setParameter('config_nooffsitelink_erase_image',(boolean)$this->modx->getOption('phpthumb_nooffsitelink_erase_image',$this->config,true));
  48          $this->setParameter('config_nooffsitelink_watermark_src',(string)$this->modx->getOption('phpthumb_nooffsitelink_watermark_src',$this->config,''));
  49          $this->setParameter('config_nooffsitelink_text_message',(string)$this->modx->getOption('phpthumb_nooffsitelink_text_message',$this->config,'Off-server linking is not allowed'));
  50          $this->setParameter('cache_source_enabled',(boolean)$this->modx->getOption('phpthumb_cache_source_enabled',$this->config,false));
  51          $this->setParameter('cache_source_directory',$cachePath.'source/');
  52          $this->setParameter('allow_local_http_src',true);
  53          $this->setParameter('zc',$this->modx->getOption('zc',$_REQUEST,$this->modx->getOption('phpthumb_zoomcrop',$this->config,0)));
  54          $this->setParameter('far',$this->modx->getOption('far',$_REQUEST,$this->modx->getOption('phpthumb_far',$this->config,'C')));
  55          $this->setParameter('cache_directory_depth',4);
  56          $this->setParameter('config_ttf_directory',$this->modx->getOption('core_path',$this->config,MODX_CORE_PATH).'model/phpthumb/fonts/');
  57  
  58          $documentRoot = $this->modx->getOption('phpthumb_document_root',$this->config, '');
  59          if ($documentRoot == '') $documentRoot = $this->modx->getOption('base_path', null, '');
  60          if (!empty($documentRoot)) {
  61              $this->setParameter('config_document_root',$documentRoot);
  62          }
  63  
  64          /* iterate through properties */
  65          foreach ($this->config as $property => $value) {
  66              $this->setParameter($property,$value);
  67          }
  68          return true;
  69      }
  70  
  71      /**
  72       * Sets the source image
  73       */
  74      public function set($src) {
  75          $src = rawurldecode($src);
  76          if (empty($src)) return '';
  77          return $this->setSourceFilename($src);
  78      }
  79  
  80      /**
  81       * Check to see if cached file already exists
  82       */
  83      public function checkForCachedFile() {
  84          $this->setCacheFilename();
  85          if (file_exists($this->cache_filename) && is_readable($this->cache_filename)) {
  86              return true;
  87          }
  88          return false;
  89      }
  90  
  91      /**
  92       * Load cached file
  93       */
  94      public function loadCache() {
  95          $this->RedirectToCachedFile();
  96      }
  97  
  98      /**
  99       * Cache the generated thumbnail.
 100       */
 101      public function cache() {
 102          phpthumb_functions::EnsureDirectoryExists(dirname($this->cache_filename));
 103          if ((file_exists($this->cache_filename) && is_writable($this->cache_filename)) || is_writable(dirname($this->cache_filename))) {
 104              $this->CleanUpCacheDirectory();
 105              if ($this->RenderToFile($this->cache_filename) && is_readable($this->cache_filename)) {
 106                  chmod($this->cache_filename, 0644);
 107                  $this->RedirectToCachedFile();
 108              }
 109          }
 110      }
 111  
 112      /**
 113       * Generate a thumbnail
 114       */
 115      public function generate() {
 116          if (!$this->GenerateThumbnail()) {
 117              $this->modx->log(modX::LOG_LEVEL_ERROR,'phpThumb was unable to generate a thumbnail for: '.$this->cache_filename);
 118              return false;
 119          }
 120          return true;
 121      }
 122  
 123      /**
 124       * Output a thumbnail.
 125       */
 126      public function output() {
 127          $output = $this->OutputThumbnail();
 128          if (!$output) {
 129              $this->modx->log(modx::LOG_LEVEL_ERROR,'Error outputting thumbnail:'."\n".$this->debugmessages[(count($this->debugmessages) - 1)]);
 130          }
 131          return $output;
 132      }
 133  
 134  
 135      /** PHPTHUMB HELPER METHODS **/
 136  
 137      public function RedirectToCachedFile() {
 138  
 139          $nice_cachefile = str_replace(DIRECTORY_SEPARATOR, '/', $this->cache_filename);
 140          $nice_docroot   = str_replace(DIRECTORY_SEPARATOR, '/', rtrim($this->config_document_root, '/\\'));
 141  
 142          $parsed_url = phpthumb_functions::ParseURLbetter(@$_SERVER['HTTP_REFERER']);
 143  
 144          $nModified  = filemtime($this->cache_filename);
 145  
 146          if ($this->config_nooffsitelink_enabled && @$_SERVER['HTTP_REFERER'] && !in_array(@$parsed_url['host'], $this->config_nooffsitelink_valid_domains)) {
 147  
 148              $this->DebugMessage('Would have used cached (image/'.$this->thumbnailFormat.') file "'.$this->cache_filename.'" (Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT), but skipping because $_SERVER[HTTP_REFERER] ('.@$_SERVER['HTTP_REFERER'].') is not in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__);
 149  
 150          } elseif ($this->phpThumbDebug) {
 151  
 152              $this->DebugTimingMessage('skipped using cached image', __FILE__, __LINE__);
 153              $this->DebugMessage('Would have used cached file, but skipping due to phpThumbDebug', __FILE__, __LINE__);
 154              $this->DebugMessage('* Would have sent headers (1): Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT', __FILE__, __LINE__);
 155              $getimagesize = @GetImageSize($this->cache_filename);
 156              if ($getimagesize) {
 157                  $this->DebugMessage('* Would have sent headers (2): Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2]), __FILE__, __LINE__);
 158              }
 159              if (ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) {
 160                  $this->DebugMessage('* Would have sent headers (3): Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1])), __FILE__, __LINE__);
 161              } else {
 162                  $this->DebugMessage('* Would have sent data: readfile('.$this->cache_filename.')', __FILE__, __LINE__);
 163              }
 164  
 165          } else {
 166  /*
 167              if (headers_sent()) {
 168                  $this->ErrorImage('Headers already sent ('.basename(__FILE__).' line '.__LINE__.')');
 169                  exit;
 170              }*/
 171              $this->SendSaveAsFileHeaderIfNeeded();
 172  
 173              header('Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT');
 174              if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] && ($nModified == strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) && @$_SERVER['SERVER_PROTOCOL']) {
 175                  header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');
 176                  exit;
 177              }
 178  
 179              $getimagesize = @GetImageSize($this->cache_filename);
 180              if ($getimagesize) {
 181                  header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2]));
 182              } elseif (eregi('\.ico$', $this->cache_filename)) {
 183                  header('Content-Type: image/x-icon');
 184              }
 185              if (!$this->config_cache_force_passthru && ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) {
 186                  header('Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1])));
 187              } else {
 188                  @readfile($this->cache_filename);
 189              }
 190              session_write_close();
 191              exit;
 192  
 193          }
 194          return true;
 195      }
 196      public function SendSaveAsFileHeaderIfNeeded() {
 197          if (headers_sent()) {
 198              return false;
 199          }
 200          $downloadfilename = phpthumb_functions::SanitizeFilename(@$_GET['sia'] ? $_GET['sia'] : (@$_GET['down'] ? $_GET['down'] : 'phpThumb_generated_thumbnail'.(@$_GET['f'] ? $_GET['f'] : 'jpg')));
 201          if (@$downloadfilename) {
 202              $this->DebugMessage('SendSaveAsFileHeaderIfNeeded() sending header: Content-Disposition: '.(@$_GET['down'] ? 'attachment' : 'inline').'; filename="'.$downloadfilename.'"', __FILE__, __LINE__);
 203              header('Content-Disposition: '.(@$_GET['down'] ? 'attachment' : 'inline').'; filename="'.$downloadfilename.'"');
 204          }
 205          return true;
 206      }
 207  
 208      function ResolveFilenameToAbsolute($filename) {
 209          if (empty($filename)) {
 210              return false;
 211          }
 212  
 213          if (preg_match('#^[a-z0-9]+\:/{1,2}#i', $filename)) {
 214              // eg: http://host/path/file.jpg (HTTP URL)
 215              // eg: ftp://host/path/file.jpg  (FTP URL)
 216              // eg: data1:/path/file.jpg      (Netware path)
 217  
 218              //$AbsoluteFilename = $filename;
 219              return $filename;
 220  
 221          } elseif ($this->iswindows && isset($filename{1}) && ($filename{1} == ':')) {
 222  
 223              // absolute pathname (Windows)
 224              $AbsoluteFilename = $filename;
 225  
 226          } elseif ($this->iswindows && ((substr($filename, 0, 2) == '//') || (substr($filename, 0, 2) == '\\\\'))) {
 227  
 228              // absolute pathname (Windows)
 229              $AbsoluteFilename = $filename;
 230  
 231          } elseif ($filename{0} == '/') {
 232  
 233              if (@is_readable($filename) && !@is_readable($this->config_document_root.$filename)) {
 234  
 235                  // absolute filename (*nix)
 236                  $AbsoluteFilename = $filename;
 237  
 238              } elseif (isset($filename{1}) && ($filename{1} == '~')) {
 239  
 240                  // /~user/path
 241                  if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray($filename)) {
 242                      $AbsoluteFilename = $ApacheLookupURIarray['filename'];
 243                  } else {
 244                      $AbsoluteFilename = realpath($filename);
 245                      if (@is_readable($AbsoluteFilename)) {
 246                          $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath($filename)', __FILE__, __LINE__);
 247                      } elseif (is_dir(dirname($AbsoluteFilename))) {
 248                          $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname($filename).'", but the correct directory ('.dirname($AbsoluteFilename).') seems to have been resolved with realpath(.)', __FILE__, __LINE__);
 249                      } else {
 250                          return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'". This has been known to fail on Apache2 - try using the absolute filename for the source image (ex: "/home/user/httpdocs/image.jpg" instead of "/~user/image.jpg")');
 251                      }
 252                  }
 253  
 254              } else {
 255  
 256                  // relative filename (any OS)
 257                  if (preg_match('#^'.preg_quote($this->config_document_root).'#', $filename)) {
 258                      $AbsoluteFilename = $filename;
 259                      $this->DebugMessage('ResolveFilenameToAbsolute() NOT prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__);
 260                  } else {
 261                      $AbsoluteFilename = $this->config_document_root.$filename;
 262                      $this->DebugMessage('ResolveFilenameToAbsolute() prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__);
 263                  }
 264  
 265              }
 266  
 267          } else {
 268  
 269              // relative to current directory (any OS)
 270              $AbsoluteFilename = $this->config_document_root.preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, dirname(@$_SERVER['PHP_SELF'])).DIRECTORY_SEPARATOR.preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, $filename);
 271  //            $AbsoluteFilename = dirname(__FILE__).DIRECTORY_SEPARATOR.preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, $filename);
 272  
 273              $AbsoluteFilename = preg_replace('~[\/]+~', DIRECTORY_SEPARATOR, $AbsoluteFilename);
 274  
 275              //if (!@file_exists($AbsoluteFilename) && @file_exists(realpath($this->DotPadRelativeDirectoryPath($filename)))) {
 276              //    $AbsoluteFilename = realpath($this->DotPadRelativeDirectoryPath($filename));
 277              //}
 278  
 279              if (substr(dirname(@$_SERVER['PHP_SELF']), 0, 2) == '/~') {
 280                  if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) {
 281                      $AbsoluteFilename = $ApacheLookupURIarray['filename'].DIRECTORY_SEPARATOR.$filename;
 282                  } else {
 283                      $AbsoluteFilename = realpath('.').DIRECTORY_SEPARATOR.$filename;
 284                      if (@is_readable($AbsoluteFilename)) {
 285                          $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath(.)/$filename', __FILE__, __LINE__);
 286                      } elseif (is_dir(dirname($AbsoluteFilename))) {
 287                          $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct directory ('.dirname($AbsoluteFilename).') seems to have been resolved with realpath(.)', __FILE__, __LINE__);
 288                      } else {
 289                          return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'". This has been known to fail on Apache2 - try using the absolute filename for the source image');
 290                      }
 291                  }
 292              }
 293  
 294          }
 295          if (is_link($AbsoluteFilename)) {
 296              $this->DebugMessage('is_link()==true, changing "'.$AbsoluteFilename.'" to "'.readlink($AbsoluteFilename).'"', __FILE__, __LINE__);
 297              $AbsoluteFilename = readlink($AbsoluteFilename);
 298          }
 299          if (realpath($AbsoluteFilename)) {
 300              $AbsoluteFilename = realpath($AbsoluteFilename);
 301          }
 302          if ($this->iswindows) {
 303              $AbsoluteFilename = preg_replace('#^'.preg_quote(realpath($this->config_document_root)).'#i', realpath($this->config_document_root), $AbsoluteFilename);
 304              $AbsoluteFilename = str_replace(DIRECTORY_SEPARATOR, '/', $AbsoluteFilename);
 305          }
 306          if (!$this->config_allow_src_above_docroot && !preg_match('#^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', realpath($this->config_document_root))).'#', $AbsoluteFilename)) {
 307              $this->DebugMessage('!$this->config_allow_src_above_docroot therefore setting "'.$AbsoluteFilename.'" (outside "'.realpath($this->config_document_root).'") to null', __FILE__, __LINE__);
 308              return false;
 309          }
 310          if (!$this->config_allow_src_above_phpthumb && !preg_match('#^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__))).'#', $AbsoluteFilename)) {
 311              $this->DebugMessage('!$this->config_allow_src_above_phpthumb therefore setting "'.$AbsoluteFilename.'" (outside "'.dirname(__FILE__).'") to null', __FILE__, __LINE__);
 312              return false;
 313          }
 314          return $AbsoluteFilename;
 315      }
 316  
 317  }

title

Description

title

Description

title

Description

title

title

Body