[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/kcfinder/core/ -> uploader.php (source)

   1  <?php
   2  
   3  /** This file is part of KCFinder project
   4    *
   5    *      @desc Uploader class
   6    *   @package KCFinder
   7    *   @version 2.21
   8    *    @author Pavel Tzonkov <[email protected]>
   9    * @copyright 2010 KCFinder Project
  10    *   @license http://www.opensource.org/licenses/gpl-2.0.php GPLv2
  11    *   @license http://www.opensource.org/licenses/lgpl-2.1.php LGPLv2
  12    *      @link http://kcfinder.sunhater.com
  13    */
  14  
  15  class uploader {
  16      protected $config = array();
  17      protected $opener = array();
  18      protected $type;
  19      protected $typeDir;
  20      protected $typeURL;
  21      protected $types = array();
  22      protected $typeSettings = array('disabled', 'theme', 'dirPerms', 'filePerms', 'denyZipDownload', 'maxImageWidth', 'maxImageHeight', 'thumbWidth', 'thumbHeight', 'jpegQuality');
  23      protected $charset;
  24      protected $lang = 'en';
  25      protected $langInputNames = array('lang', 'langCode', 'lng', 'language', 'lang_code');
  26      protected $file;
  27      protected $dateTimeFull;   // Currently not used
  28      protected $dateTimeMid;    // Currently not used
  29      protected $dateTimeSmall;
  30      protected $labels = array();
  31      protected $get;
  32      protected $post;
  33      protected $cookie;
  34      protected $session;
  35  
  36      public function __get($property) {
  37          return property_exists($this, $property) ? $this->$property : null;
  38      }
  39  
  40      public function __construct() {
  41  
  42          // DISABLE MAGIC QUOTES
  43          if (function_exists('set_magic_quotes_runtime'))
  44              @set_magic_quotes_runtime(false);
  45  
  46          // INPUT INIT
  47          $input = new input();
  48          $this->get = &$input->get;
  49          $this->post = &$input->post;
  50          $this->cookie = &$input->cookie;
  51  
  52          // LINKING UPLOADED FILE
  53          if (count($_FILES))
  54              $this->file = &$_FILES[key($_FILES)];
  55  
  56          // LOAD DEFAULT CONFIGURATION
  57          require  "config.php";
  58  
  59          // SETTING UP SESSION
  60          if (isset($_CONFIG['_sessionLifetime']))
  61              ini_set('session.gc_maxlifetime', $_CONFIG['_sessionLifetime'] * 60);
  62          if (isset($_CONFIG['_sessionDir']))
  63              ini_set('session.save_path', $_CONFIG['_sessionDir']);
  64          if (isset($_CONFIG['_sessionDomain']))
  65              ini_set('session.cookie_domain', $_CONFIG['_sessionDomain']);
  66          session_start();
  67  
  68          // RELOAD DEFAULT CONFIGURATION
  69          require  "config.php";
  70          $this->config = $_CONFIG;
  71  
  72          // LOAD SESSION CONFIGURATION IF EXISTS
  73          if (isset($_CONFIG['_sessionVar']) &&
  74              is_array($_CONFIG['_sessionVar'])
  75          ) {
  76              foreach ($_CONFIG['_sessionVar'] as $key => $val)
  77                  if ((substr($key, 0, 1) != "_") && isset($_CONFIG[$key]))
  78                      $this->config[$key] = $val;
  79              if (!isset($this->config['_sessionVar']['self']))
  80                  $this->config['_sessionVar']['self'] = array();
  81              $this->session = &$this->config['_sessionVar']['self'];
  82          } else
  83              $this->session = &$_SESSION;
  84  
  85          // GET TYPE DIRECTORY
  86          $this->types = &$this->config['types'];
  87          $firstType = array_keys($this->types);
  88          $firstType = $firstType[0];
  89          $this->type = (
  90              isset($this->get['type']) &&
  91              isset($this->types[$this->get['type']])
  92          )
  93              ? $this->get['type'] : $firstType;
  94  
  95          // LOAD DIRECTORY TYPE SPECIFIC CONFIGURATION IF EXISTS
  96          if (is_array($this->types[$this->type])) {
  97              foreach ($this->types[$this->type] as $key => $val)
  98                  if (in_array($key, $this->typeSettings))
  99                      $this->config[$key] = $val;
 100              $this->types[$this->type] = isset($this->types[$this->type]['type'])
 101                  ? $this->types[$this->type]['type'] : "";
 102          }
 103  
 104          // COOKIES INIT
 105          if (!strlen($this->config['cookieDomain']))
 106              $this->config['cookieDomain'] = $_SERVER['HTTP_HOST'];
 107          if (!strlen($this->config['cookiePath']))
 108              $this->config['cookiePath'] = "/";
 109  
 110          // UPLOAD FOLDER INIT
 111          if ($this->config['uploadURL'] == "/") {
 112              $this->config['uploadDir'] = strlen($this->config['uploadDir'])
 113                  ? path::normalize($this->config['uploadDir'])
 114                  : path::normalize($_SERVER['DOCUMENT_ROOT']);
 115              $this->typeDir = "{$this->config['uploadDir']}/{$this->type}";
 116              $this->typeURL = "/{$this->type}";
 117          } else {
 118              $this->config['uploadURL'] = (substr($this->config['uploadURL'], 0, 1) === "/")
 119                  ? path::normalize($this->config['uploadURL'])
 120                  : path::rel2abs_url($this->config['uploadURL']);
 121              $this->config['uploadDir'] = strlen($this->config['uploadDir'])
 122                  ? path::normalize($this->config['uploadDir'])
 123                  : path::url2fullPath($this->config['uploadURL']);
 124              $this->typeDir = "{$this->config['uploadDir']}/{$this->type}";
 125              $this->typeURL = "{$this->config['uploadURL']}/{$this->type}";
 126          }
 127          if (!is_dir($this->config['uploadDir']))
 128              @mkdir($this->config['uploadDir'], $this->config['dirPerms']);
 129  
 130          // HOST APPLICATIONS INIT
 131          if (isset($this->get['CKEditorFuncNum']))
 132              $this->opener['CKEditor']['funcNum'] = $this->get['CKEditorFuncNum'];
 133          if (isset($this->get['opener']) &&
 134              (strtolower($this->get['opener']) == "tinymce") &&
 135              isset($this->config['_tinyMCEPath']) &&
 136              strlen($this->config['_tinyMCEPath'])
 137          )
 138              $this->opener['TinyMCE'] = true;
 139  
 140          // LOCALIZATION
 141          foreach ($this->langInputNames as $key)
 142              if (isset($this->get[$key]) &&
 143                  preg_match('/^[a-z][a-z\._\-]*$/i', $this->get[$key]) &&
 144                  file_exists("lang/" . strtolower($this->get[$key]) . ".php")
 145              ) {
 146                  $this->lang = $this->get[$key];
 147                  break;
 148              }
 149          $this->localize($this->lang);
 150  
 151          // CHECK & MAKE DEFAULT .htaccess
 152          $htaccess = "{$this->config['uploadDir']}/.htaccess";
 153          if (isset($this->config['_check4htaccess']) &&
 154              $this->config['_check4htaccess']
 155          ) {
 156              if (!file_exists($htaccess)) {
 157                  if (!@file_put_contents($htaccess, $this->get_htaccess()))
 158                      $this->backMsg("Cannot write to upload folder.");
 159              } else {
 160                  if (false === ($data = @file_get_contents($htaccess)))
 161                      $this->backMsg("Cannot read .htaccess");
 162                  if (($data != $this->get_htaccess()) && !@file_put_contents($htaccess, $data))
 163                      $this->backMsg("Incorrect .htaccess file. Cannot rewrite it!");
 164              }
 165          }
 166  
 167          // CHECK & CREATE UPLOAD FOLDER
 168          if (!is_dir($this->typeDir)) {
 169              if (!mkdir($this->typeDir, $this->config['dirPerms']))
 170                  $this->backMsg("Cannot create {dir} folder.", array('dir' => $this->type));
 171          } elseif (!is_readable($this->typeDir))
 172              $this->backMsg("Cannot read upload folder.");
 173      }
 174  
 175      public function upload() {
 176          $config = &$this->config;
 177          $file = &$this->file;
 178          $url = $message = "";
 179  
 180          if ($config['disabled'] || $config['readonly']) {
 181              if (isset($file['tmp_name'])) @unlink($file['tmp_name']);
 182              $message = $this->label("You don't have permissions to upload files.");
 183  
 184          } elseif (true === ($message = $this->checkUploadedFile())) {
 185              $message = "";
 186  
 187              $dir = "{$this->typeDir}/";
 188              if (isset($this->get['dir']) &&
 189                  (false !== ($gdir = $this->checkInputDir($this->get['dir'])))
 190              ) {
 191                  $udir = path::normalize("$dir$gdir");
 192                  if (substr($udir, 0, strlen($dir)) !== $dir)
 193                      $message = $this->label("Unknown error.");
 194                  else {
 195                      $l = strlen($dir);
 196                      $dir = "$udir/";
 197                      $udir = substr($udir, $l);
 198                  }
 199              }
 200  
 201              if (!strlen($message)) {
 202                  if (!is_dir(path::normalize($dir)))
 203                      @mkdir(path::normalize($dir), $this->config['dirPerms'], true);
 204  
 205                  $target = file::getInexistantFilename("$dir{$file['name']}");
 206  
 207                  if (!@move_uploaded_file($file['tmp_name'], $target) &&
 208                      !@rename($file['tmp_name'], $target) &&
 209                      !@copy($file['tmp_name'], $target)
 210                  )
 211                      $message = $this->label("Cannot move uploaded file to target folder.");
 212                  else {
 213                      if (function_exists('chmod'))
 214                          @chmod($target, $this->config['filePerms']);
 215                      $this->makeThumb($target);
 216                      $url = $this->typeURL;
 217                      if (isset($udir)) $url .= "/$udir";
 218                      $url .= "/" . path::urlPathEncode(basename($target));
 219                  }
 220              }
 221          }
 222  
 223          if (strlen($message) &&
 224              isset($this->file['tmp_name']) &&
 225              file_exists($this->file['tmp_name'])
 226          )
 227              @unlink($this->file['tmp_name']);
 228  
 229          if (strlen($message) && method_exists($this, 'errorMsg'))
 230              $this->errorMsg($message);
 231          $this->callBack($url, $message);
 232      }
 233  
 234      protected function checkUploadedFile() {
 235          $config = &$this->config;
 236          $file = &$this->file;
 237  
 238          if (!is_array($file) || !isset($file['name']))
 239              return $this->label("Unknown error");
 240  
 241          $extension = file::getExtension($file['name']);
 242          $typePatt = strtolower(text::clearWhitespaces($this->types[$this->type]));
 243  
 244          // CHECK FOR UPLOAD ERRORS
 245          if ($file['error'])
 246              return
 247                  ($file['error'] == UPLOAD_ERR_INI_SIZE) ?
 248                      $this->label("The uploaded file exceeds {size} bytes.",
 249                          array('size' => ini_get('upload_max_filesize'))) : (
 250                  ($file['error'] == UPLOAD_ERR_FORM_SIZE) ?
 251                      $this->label("The uploaded file exceeds {size} bytes.",
 252                          array('size' => $this->get['MAX_FILE_SIZE'])) : (
 253                  ($file['error'] == UPLOAD_ERR_PARTIAL) ?
 254                      $this->label("The uploaded file was only partially uploaded.") : (
 255                  ($file['error'] == UPLOAD_ERR_NO_FILE) ?
 256                      $this->label("No file was uploaded.") : (
 257                  ($file['error'] == UPLOAD_ERR_NO_TMP_DIR) ?
 258                      $this->label("Missing a temporary folder.") : (
 259                  ($file['error'] == UPLOAD_ERR_CANT_WRITE) ?
 260                      $this->label("Failed to write file.") :
 261                      $this->label("Unknown error.")
 262              )))));
 263  
 264          // HIDDEN FILENAMES CHECK
 265          elseif (substr($file['name'], 0, 1) == ".")
 266              return $this->label("File name shouldn't begins with '.'");
 267  
 268          // EXTENSION CHECK
 269          elseif (!$this->validateExtension($extension, $this->type))
 270              return $this->label("Denied file extension.");
 271  
 272          // SPECIAL DIRECTORY TYPES CHECK (e.g. *img)
 273          elseif (preg_match('/^\*([^ ]+)(.*)?$/s', $typePatt, $patt)) {
 274              list($typePatt, $type, $params) = $patt;
 275              if (class_exists("type_$type")) {
 276                  $class = "type_$type";
 277                  $type = new $class();
 278                  $cfg = $config;
 279                  if (strlen($params))
 280                      $cfg['params'] = trim($params);
 281                  $response = $type->checkFile($file['tmp_name'], $cfg);
 282                  if ($response !== true)
 283                      return $this->label($response);
 284              } else
 285                  return $this->label("Non-existing directory type.");
 286          }
 287  
 288          // IMAGE RESIZE
 289          $gd = new gd($file['tmp_name']);
 290          if (!$gd->init_error && !$this->imageResize($gd, $file['tmp_name']))
 291              return $this->label("The image is too big and/or cannot be resized.");
 292  
 293          return true;
 294      }
 295  
 296      protected function checkInputDir($dir, $inclType=true, $existing=true) {
 297          $dir = path::normalize($dir);
 298          if (substr($dir, 0, 1) == "/")
 299              $dir = substr($dir, 1);
 300  
 301          if ((substr($dir, 0, 1) == ".") || (substr(basename($dir), 0, 1) == "."))
 302              return false;
 303  
 304          if ($inclType) {
 305              $first = explode("/", $dir);
 306              $first = $first[0];
 307              if ($first != $this->type)
 308                  return false;
 309              $return = $this->removeTypeFromPath($dir);
 310          } else {
 311              $return = $dir;
 312              $dir = "{$this->type}/$dir";
 313          }
 314  
 315          if (!$existing)
 316              return $return;
 317  
 318          $path = "{$this->config['uploadDir']}/$dir";
 319          return (is_dir($path) && is_readable($path)) ? $return : false;
 320      }
 321  
 322      protected function validateExtension($ext, $type) {
 323          $ext = trim(strtolower($ext));
 324          if (!isset($this->types[$type]))
 325              return false;
 326  
 327          $exts = strtolower(text::clearWhitespaces($this->config['deniedExts']));
 328          if (strlen($exts)) {
 329              $exts = explode(" ", $exts);
 330              if (in_array($ext, $exts))
 331                  return false;
 332          }
 333  
 334          $exts = trim($this->types[$type]);
 335          if (!strlen($exts) || substr($exts, 0, 1) == "*")
 336              return true;
 337  
 338          if (substr($exts, 0, 1) == "!") {
 339              $exts = explode(" ", trim(strtolower(substr($exts, 1))));
 340              return !in_array($ext, $exts);
 341          }
 342  
 343          $exts = explode(" ", trim(strtolower($exts)));
 344          return in_array($ext, $exts);
 345      }
 346  
 347      protected function getTypeFromPath($path) {
 348          return preg_match('/^([^\/]*)\/.*$/', $path, $patt)
 349              ? $patt[1] : $path;
 350      }
 351  
 352      protected function removeTypeFromPath($path) {
 353          return preg_match('/^[^\/]*\/(.*)$/', $path, $patt)
 354              ? $patt[1] : "";
 355      }
 356  
 357      protected function imageResize($image, $file=null) {
 358          if (!($image instanceof gd)) {
 359              $gd = new gd($image);
 360              if ($gd->init_error) return false;
 361              $file = $image;
 362          } elseif ($file === null)
 363              return false;
 364          else
 365              $gd = $image;
 366  
 367          if ((!$this->config['maxImageWidth'] && !$this->config['maxImageHeight']) ||
 368              (
 369                  ($gd->get_width() <= $this->config['maxImageWidth']) &&
 370                  ($gd->get_height() <= $this->config['maxImageHeight'])
 371              )
 372          )
 373              return true;
 374  
 375          return (
 376              $gd->resize_fit($this->config['maxImageWidth'], $this->config['maxImageHeight']) &&
 377              $gd->imagejpeg($file, $this->config['jpegQuality'])
 378          );
 379      }
 380  
 381      protected function makeThumb($file, $overwrite=true) {
 382          $gd = new gd($file);
 383  
 384          // Drop files which are not GD handled images
 385          if ($gd->init_error)
 386              return true;
 387  
 388          $thumb = substr($file, strlen($this->config['uploadDir']));
 389          $thumb = $this->config['uploadDir'] . "/" . $this->config['thumbsDir'] . "/" . $thumb;
 390          $thumb = path::normalize($thumb);
 391          $thumbDir = dirname($thumb);
 392          if (!is_dir($thumbDir) && !@mkdir($thumbDir, $this->config['dirPerms'], true))
 393              return false;
 394  
 395          if (!$overwrite && is_file($thumb))
 396              return true;
 397  
 398          // Images with smaller resolutions than thumbnails
 399          if (($gd->get_width() <= $this->config['thumbWidth']) &&
 400              ($gd->get_height() <= $this->config['thumbHeight'])
 401          ) {
 402              $browsable = array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_JPEG2000, IMAGETYPE_PNG);
 403              // Drop only browsable types
 404              if (in_array($gd->type, $browsable))
 405                  return true;
 406  
 407          // Resize image
 408          } elseif (!$gd->resize_fit($this->config['thumbWidth'], $this->config['thumbHeight']))
 409              return false;
 410  
 411          // Save thumbnail
 412          return $gd->imagejpeg($thumb, $this->config['jpegQuality']);
 413      }
 414  
 415      protected function localize($langCode) {
 416          require "lang/{$langCode}.php";
 417          setlocale(LC_ALL, $lang['_locale']);
 418          $this->charset = $lang['_charset'];
 419          $this->dateTimeFull = $lang['_dateTimeFull'];
 420          $this->dateTimeMid = $lang['_dateTimeMid'];
 421          $this->dateTimeSmall = $lang['_dateTimeSmall'];
 422          unset($lang['_locale']);
 423          unset($lang['_charset']);
 424          unset($lang['_dateTimeFull']);
 425          unset($lang['_dateTimeMid']);
 426          unset($lang['_dateTimeSmall']);
 427          $this->labels = $lang;
 428      }
 429  
 430      protected function label($string, array $data=null) {
 431          $return = isset($this->labels[$string]) ? $this->labels[$string] : $string;
 432          if (is_array($data))
 433              foreach ($data as $key => $val)
 434                  $return = str_replace("{{$key}}", $val, $return);
 435          return $return;
 436      }
 437  
 438      protected function backMsg($message, array $data=null) {
 439          $message = $this->label($message, $data);
 440          if (isset($this->file['tmp_name']) && file_exists($this->file['tmp_name']))
 441              @unlink($this->file['tmp_name']);
 442          $this->callBack("", $message);
 443          die;
 444      }
 445  
 446      protected function callBack($url, $message="") {
 447          $message = text::jsValue($message);
 448          $CKfuncNum = isset($this->opener['CKEditor']['funcNum'])
 449              ? $this->opener['CKEditor']['funcNum'] : 0;
 450          if (!$CKfuncNum) $CKfuncNum = 0;
 451          header("Content-Type: text/html; charset={$this->charset}");
 452  
 453  ?><html>
 454  <body>
 455  <script type='text/javascript'>
 456  var kc_CKEditor = (window.parent && window.parent.CKEDITOR)
 457      ? window.parent.CKEDITOR.tools.callFunction
 458      : ((window.opener && window.opener.CKEDITOR)
 459          ? window.opener.CKEDITOR.tools.callFunction
 460          : false);
 461  var kc_FCKeditor = (window.opener && window.opener.OnUploadCompleted)
 462      ? window.opener.OnUploadCompleted
 463      : ((window.parent && window.parent.OnUploadCompleted)
 464          ? window.parent.OnUploadCompleted
 465          : false);
 466  var kc_Custom = (window.parent && window.parent.KCFinder)
 467      ? window.parent.KCFinder.callBack
 468      : ((window.opener && window.opener.KCFinder)
 469          ? window.opener.KCFinder.callBack
 470          : false);
 471  if (kc_CKEditor)
 472      kc_CKEditor(<?php echo $CKfuncNum ?>, '<?php echo $url ?>', '<?php echo $message ?>');
 473  if (kc_FCKeditor)
 474      kc_FCKeditor(<?php echo strlen($message) ? 1 : 0 ?>, '<?php echo $url ?>', '', '<?php echo $message ?>');
 475  if (kc_Custom) {
 476      if (<?php echo strlen($message) ?>) alert('<?php echo $message ?>');
 477      kc_Custom('<?php echo $url ?>');
 478  }
 479  if (!kc_CKEditor && !kc_FCKeditor && !kc_Custom)
 480      alert("<?php echo $message ?>");
 481  </script>
 482  </body>
 483  </html><?php
 484  
 485      }
 486  
 487      protected function get_htaccess() {
 488          return "<IfModule mod_php4.c>
 489    php_value engine off
 490  </IfModule>
 491  <IfModule mod_php5.c>
 492    php_value engine off
 493  </IfModule>
 494  ";
 495      }
 496  }
 497  
 498  ?>


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1