PluginProbe
WP Super Minify • Minify, Compress and Cache HTML, CSS & JavaScript / trunk
WP Super Minify • Minify, Compress and Cache HTML, CSS & JavaScript vtrunk
trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.4 1.5 1.5.1 1.6 2.0 2.0.1
wp-super-minify / includes / min / lib / Minify / Controller / MinApp.php

MinApp.php in WP Super Minify • Minify, Compress and Cache HTML, CSS & JavaScript trunk, at includes/min/lib/Minify/Controller/MinApp.php

197 lines 7.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 /**
17 * Set up groups of files as sources
18 *
19 * @param array $options controller and Minify options
20 *
21 * @return array Minify options
22 */
23 public function createConfiguration(array $options)
24 {
25 // PHP insecure by default: realpath() and other FS functions can't handle null bytes.
26 $get = $this->env->get();
27 foreach (array('g', 'b', 'f') as $key) {
28 if (isset($get[$key])) {
29 $get[$key] = str_replace("\x00", '', (string)$get[$key]);
30 }
31 }
32
33 // filter controller options
34 $defaults = array(
35 'groupsOnly' => false,
36 'groups' => array(),
37 'symlinks' => array(),
38 );
39 $minApp = isset($options['minApp']) ? $options['minApp'] : array();
40 $localOptions = array_merge($defaults, $minApp);
41
42 unset($options['minApp']);
43
44 // normalize $symlinks in order to map to target
45 $symlinks = array();
46 foreach ($localOptions['symlinks'] as $link => $target) {
47 if (0 === strpos($link, '//')) {
48 $link = rtrim(substr($link, 1), '/') . '/';
49 $target = rtrim($target, '/\\');
50 $symlinks[$link] = $target;
51 }
52 }
53
54 $sources = array();
55 $selectionId = '';
56 $firstMissing = null;
57
58 if (isset($get['g'])) {
59 // add group(s)
60 $selectionId .= 'g=' . $get['g'];
61 $keys = explode(',', $get['g']);
62 if ($keys != array_unique($keys)) {
63 $this->logger->info("Duplicate group key found.");
64
65 return new Minify_ServeConfiguration($options);
66 }
67 foreach ($keys as $key) {
68 if (! isset($localOptions['groups'][$key])) {
69 $this->logger->info("A group configuration for \"{$key}\" was not found");
70
71 return new Minify_ServeConfiguration($options);
72 }
73 $files = $localOptions['groups'][$key];
74 // if $files is a single object, casting will break it
75 if (is_object($files)) {
76 $files = array($files);
77 } elseif (! is_array($files)) {
78 $files = (array)$files;
79 }
80 foreach ($files as $file) {
81 try {
82 $source = $this->sourceFactory->makeSource($file);
83 $sources[] = $source;
84 } catch (Minify_Source_FactoryException $e) {
85 $this->logger->error($e->getMessage());
86 if (null === $firstMissing) {
87 $firstMissing = basename($file);
88 continue;
89 } else {
90 $secondMissing = basename($file);
91 $this->logger->info("More than one file was missing: '$firstMissing', '$secondMissing'");
92
93 return new Minify_ServeConfiguration($options);
94 }
95 }
96 }
97 }
98 }
99 if (! $localOptions['groupsOnly'] && isset($get['f'])) {
100 // try user files
101 // The following restrictions are to limit the URLs that minify will
102 // respond to.
103
104 // verify at least one file, files are single comma separated, and are all same extension
105 $validPattern = preg_match('/^[^,]+\\.(css|less|scss|js)(?:,[^,]+\\.\\1)*$/', $get['f'], $m);
106 $hasComment = strpos($get['f'], '//') !== false;
107 $hasEscape = strpos($get['f'], '\\') !== false;
108
109 if (!$validPattern || $hasComment || $hasEscape) {
110 $this->logger->info("GET param 'f' was invalid");
111
112 return new Minify_ServeConfiguration($options);
113 }
114
115 $ext = ".{$m[1]}";
116 $files = explode(',', $get['f']);
117 if ($files != array_unique($files)) {
118 $this->logger->info("Duplicate files were specified");
119
120 return new Minify_ServeConfiguration($options);
121 }
122
123 if (isset($get['b'])) {
124 // check for validity
125 $isValidBase = preg_match('@^[^/]+(?:/[^/]+)*$@', $get['b']);
126 $hasDots = false !== strpos($get['b'], '..');
127 $isDot = $get['b'] === '.';
128
129 if ($isValidBase && !$hasDots && !$isDot) {
130 // valid base
131 $base = "/{$get['b']}/";
132 } else {
133 $this->logger->info("GET param 'b' was invalid");
134
135 return new Minify_ServeConfiguration($options);
136 }
137 } else {
138 $base = '/';
139 }
140
141 $basenames = array(); // just for cache id
142 foreach ($files as $file) {
143 $uri = $base . $file;
144 $path = $this->env->getDocRoot() . $uri;
145
146 // try to rewrite path
147 foreach ($symlinks as $link => $target) {
148 if (0 === strpos($uri, $link)) {
149 $path = $target . DIRECTORY_SEPARATOR . substr($uri, strlen($link));
150 break;
151 }
152 }
153
154 try {
155 $source = $this->sourceFactory->makeSource($path);
156 $sources[] = $source;
157 $basenames[] = basename($path, $ext);
158 } catch (Minify_Source_FactoryException $e) {
159 $this->logger->error($e->getMessage());
160 if (null === $firstMissing) {
161 $firstMissing = $uri;
162 continue;
163 } else {
164 $secondMissing = $uri;
165 $this->logger->info("More than one file was missing: '$firstMissing', '$secondMissing`'");
166
167 return new Minify_ServeConfiguration($options);
168 }
169 }
170 }
171 if ($selectionId) {
172 $selectionId .= '_f=';
173 }
174 $selectionId .= implode(',', $basenames) . $ext;
175 }
176
177 if (!$sources) {
178 $this->logger->info("No sources to serve");
179
180 return new Minify_ServeConfiguration($options);
181 }
182
183 if (null !== $firstMissing) {
184 array_unshift($sources, new Minify_Source(array(
185 'id' => 'missingFile',
186 // should not cause cache invalidation
187 'lastModified' => 0,
188 // due to caching, filename is unreliable.
189 'content' => "/* Minify: at least one missing file. See " . Minify::URL_DEBUG . " */\n",
190 'minifier' => 'Minify::nullMinifier',
191 )));
192 }
193
194 return new Minify_ServeConfiguration($options, $sources, $selectionId);
195 }
196 }
197