PageRenderTime 27ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/min/lib/Minify/Controller/MinApp.php

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