[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/minify/lib/Minify/Controller/ -> MinApp.php (source)

   1  <?php
   2  /**
   3   * Class Minify_Controller_MinApp  
   4   * @package Minify
   5   */
   6  
   7  /**
   8   * Controller class for requests to /min/index.php
   9   * 
  10   * @package Minify
  11   * @author Stephen Clay <steve@mrclay.org>
  12   */
  13  class Minify_Controller_MinApp extends Minify_Controller_Base {
  14      
  15      /**
  16       * Set up groups of files as sources
  17       * 
  18       * @param array $options controller and Minify options
  19       *
  20       * @return array Minify options
  21       */
  22      public function setupSources($options) {
  23          // PHP insecure by default: realpath() and other FS functions can't handle null bytes.
  24          foreach (array('g', 'b', 'f') as $key) {
  25              if (isset($_GET[$key])) {
  26                  $_GET[$key] = str_replace("\x00", '', (string)$_GET[$key]);
  27              }
  28          }
  29  
  30          // filter controller options
  31          $cOptions = array_merge(
  32              array(
  33                  'allowDirs' => '//'
  34                  ,'groupsOnly' => false
  35                  ,'groups' => array()
  36                  ,'noMinPattern' => '@[-\\.]min\\.(?:js|css)$@i' // matched against basename
  37              )
  38              ,(isset($options['minApp']) ? $options['minApp'] : array())
  39          );
  40          unset($options['minApp']);
  41          $sources = array();
  42          $this->selectionId = '';
  43          $firstMissingResource = null;
  44          if (isset($_GET['g'])) {
  45              // add group(s)
  46              $this->selectionId .= 'g=' . $_GET['g'];
  47              $keys = explode(',', $_GET['g']);
  48              if ($keys != array_unique($keys)) {
  49                  $this->log("Duplicate group key found.");
  50                  return $options;
  51              }
  52              foreach ($keys as $key) {
  53                  if (! isset($cOptions['groups'][$key])) {
  54                      $this->log("A group configuration for \"{$key}\" was not found");
  55                      return $options;
  56                  }
  57                  $files = $cOptions['groups'][$key];
  58                  // if $files is a single object, casting will break it
  59                  if (is_object($files)) {
  60                      $files = array($files);
  61                  } elseif (! is_array($files)) {
  62                      $files = (array)$files;
  63                  }
  64                  foreach ($files as $file) {
  65                      if ($file instanceof Minify_Source) {
  66                          $sources[] = $file;
  67                          continue;
  68                      }
  69                      if (0 === strpos($file, '//')) {
  70                          $file = $_SERVER['DOCUMENT_ROOT'] . substr($file, 1);
  71                      }
  72                      $realpath = realpath($file);
  73                      if ($realpath && is_file($realpath)) {
  74                          $sources[] = $this->_getFileSource($realpath, $cOptions);
  75                      } else {
  76                          $this->log("The path \"{$file}\" (realpath \"{$realpath}\") could not be found (or was not a file)");
  77                          if (null === $firstMissingResource) {
  78                              $firstMissingResource = basename($file);
  79                              continue;
  80                          } else {
  81                              $secondMissingResource = basename($file);
  82                              $this->log("More than one file was missing: '$firstMissingResource', '$secondMissingResource'");
  83                              return $options;
  84                          }
  85                      }
  86                  }
  87                  if ($sources) {
  88                      try {
  89                          $this->checkType($sources[0]);
  90                      } catch (Exception $e) {
  91                          $this->log($e->getMessage());
  92                          return $options;
  93                      }
  94                  }
  95              }
  96          }
  97          if (! $cOptions['groupsOnly'] && isset($_GET['f'])) {
  98              // try user files
  99              // The following restrictions are to limit the URLs that minify will
 100              // respond to.
 101              if (// verify at least one file, files are single comma separated, 
 102                  // and are all same extension
 103                  ! preg_match('/^[^,]+\\.(css|js)(?:,[^,]+\\.\\1)*$/', $_GET['f'], $m)
 104                  // no "//"
 105                  || strpos($_GET['f'], '//') !== false
 106                  // no "\"
 107                  || strpos($_GET['f'], '\\') !== false
 108              ) {
 109                  $this->log("GET param 'f' was invalid");
 110                  return $options;
 111              }
 112              $ext = ".{$m[1]}";
 113              try {
 114                  $this->checkType($m[1]);
 115              } catch (Exception $e) {
 116                  $this->log($e->getMessage());
 117                  return $options;
 118              }
 119              $files = explode(',', $_GET['f']);
 120              if ($files != array_unique($files)) {
 121                  $this->log("Duplicate files were specified");
 122                  return $options;
 123              }
 124              if (isset($_GET['b'])) {
 125                  // check for validity
 126                  if (preg_match('@^[^/]+(?:/[^/]+)*$@', $_GET['b'])
 127                      && false === strpos($_GET['b'], '..')
 128                      && $_GET['b'] !== '.') {
 129                      // valid base
 130                      $base = "/{$_GET['b']}/";       
 131                  } else {
 132                      $this->log("GET param 'b' was invalid");
 133                      return $options;
 134                  }
 135              } else {
 136                  $base = '/';
 137              }
 138              $allowDirs = array();
 139              foreach ((array)$cOptions['allowDirs'] as $allowDir) {
 140                  $allowDirs[] = realpath(str_replace('//', $_SERVER['DOCUMENT_ROOT'] . '/', $allowDir));
 141              }
 142              $basenames = array(); // just for cache id
 143              foreach ($files as $file) {
 144                  $uri = $base . $file;
 145                  $path = $_SERVER['DOCUMENT_ROOT'] . $uri;
 146                  $realpath = realpath($path);
 147                  if (false === $realpath || ! is_file($realpath)) {
 148                      $this->log("The path \"{$path}\" (realpath \"{$realpath}\") could not be found (or was not a file)");
 149                      if (null === $firstMissingResource) {
 150                          $firstMissingResource = $uri;
 151                          continue;
 152                      } else {
 153                          $secondMissingResource = $uri;
 154                          $this->log("More than one file was missing: '$firstMissingResource', '$secondMissingResource`'");
 155                          return $options;
 156                      }
 157                  }
 158                  try {
 159                      parent::checkNotHidden($realpath);
 160                      parent::checkAllowDirs($realpath, $allowDirs, $uri);
 161                  } catch (Exception $e) {
 162                      $this->log($e->getMessage());
 163                      return $options;
 164                  }
 165                  $sources[] = $this->_getFileSource($realpath, $cOptions);
 166                  $basenames[] = basename($realpath, $ext);
 167              }
 168              if ($this->selectionId) {
 169                  $this->selectionId .= '_f=';
 170              }
 171              $this->selectionId .= implode(',', $basenames) . $ext;
 172          }
 173          if ($sources) {
 174              if (null !== $firstMissingResource) {
 175                  array_unshift($sources, new Minify_Source(array(
 176                      'id' => 'missingFile'
 177                      // should not cause cache invalidation
 178                      ,'lastModified' => 0
 179                      // due to caching, filename is unreliable.
 180                      ,'content' => "/* Minify: at least one missing file. See " . Minify::URL_DEBUG . " */\n"
 181                      ,'minifier' => ''
 182                  )));
 183              }
 184              $this->sources = $sources;
 185          } else {
 186              $this->log("No sources to serve");
 187          }
 188          return $options;
 189      }
 190  
 191      /**
 192       * @param string $file
 193       *
 194       * @param array $cOptions
 195       *
 196       * @return Minify_Source
 197       */
 198      protected function _getFileSource($file, $cOptions)
 199      {
 200          $spec['filepath'] = $file;
 201          if ($cOptions['noMinPattern'] && preg_match($cOptions['noMinPattern'], basename($file))) {
 202              if (preg_match('~\.css$~i', $file)) {
 203                  $spec['minifyOptions']['compress'] = false;
 204              } else {
 205                  $spec['minifier'] = '';
 206              }
 207          }
 208          return new Minify_Source($spec);
 209      }
 210  
 211      protected $_type = null;
 212  
 213      /**
 214       * Make sure that only source files of a single type are registered
 215       *
 216       * @param string $sourceOrExt
 217       *
 218       * @throws Exception
 219       */
 220      public function checkType($sourceOrExt)
 221      {
 222          if ($sourceOrExt === 'js') {
 223              $type = Minify::TYPE_JS;
 224          } elseif ($sourceOrExt === 'css') {
 225              $type = Minify::TYPE_CSS;
 226          } elseif ($sourceOrExt->contentType !== null) {
 227              $type = $sourceOrExt->contentType;
 228          } else {
 229              return;
 230          }
 231          if ($this->_type === null) {
 232              $this->_type = $type;
 233          } elseif ($this->_type !== $type) {
 234              throw new Exception('Content-Type mismatch');
 235          }
 236      }
 237  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1