Version Description
(released: 24 jun 2019)
- Tidied up code
Download this release
Release Info
Developer | rosell.dk |
Plugin | WebP Express |
Version | 0.14.11 |
Comparing to | |
See all releases |
Code changes from version 0.14.10 to 0.14.11
- README.txt +9 -1
- lib/classes/CachePurge.php +1 -1
- lib/classes/Convert.php +74 -18
- lib/classes/ConvertHelperIndependent.php +265 -144
- lib/classes/HandleUploadHooks.php +18 -4
- lib/classes/SanityCheck.php +24 -0
- lib/options/enqueue_scripts.php +1 -1
- lib/options/page-messages.php +0 -5
- webp-express.php +1 -1
- wod/webp-on-demand.php +5 -4
- wod/webp-realizer-old.php +0 -278
- wod/webp-realizer.php +4 -4
README.txt
CHANGED
@@ -4,7 +4,7 @@ Donate link: https://ko-fi.com/rosell
|
|
4 |
Tags: webp, images, performance
|
5 |
Requires at least: 4.0
|
6 |
Tested up to: 5.2
|
7 |
-
Stable tag: 0.14.
|
8 |
Requires PHP: 5.6
|
9 |
License: GPLv3
|
10 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
@@ -605,6 +605,11 @@ Easy enough! - [Go here!](https://ko-fi.com/rosell). Or [here](https://buymeacof
|
|
605 |
|
606 |
== Changelog ==
|
607 |
|
|
|
|
|
|
|
|
|
|
|
608 |
= 0.14.10 =
|
609 |
*(released: 24 jun 2019)*
|
610 |
|
@@ -849,6 +854,9 @@ For older releases, check out changelog.txt
|
|
849 |
|
850 |
== Upgrade Notice ==
|
851 |
|
|
|
|
|
|
|
852 |
= 0.14.10 =
|
853 |
Tidied up code
|
854 |
|
4 |
Tags: webp, images, performance
|
5 |
Requires at least: 4.0
|
6 |
Tested up to: 5.2
|
7 |
+
Stable tag: 0.14.11
|
8 |
Requires PHP: 5.6
|
9 |
License: GPLv3
|
10 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
605 |
|
606 |
== Changelog ==
|
607 |
|
608 |
+
= 0.14.11 =
|
609 |
+
*(released: 24 jun 2019)*
|
610 |
+
|
611 |
+
* Tidied up code
|
612 |
+
|
613 |
= 0.14.10 =
|
614 |
*(released: 24 jun 2019)*
|
615 |
|
854 |
|
855 |
== Upgrade Notice ==
|
856 |
|
857 |
+
= 0.14.11 =
|
858 |
+
Tidied up code
|
859 |
+
|
860 |
= 0.14.10 =
|
861 |
Tidied up code
|
862 |
|
lib/classes/CachePurge.php
CHANGED
@@ -55,7 +55,7 @@ class CachePurge
|
|
55 |
*
|
56 |
* @return [num files deleted, num files failed to delete]
|
57 |
*/
|
58 |
-
|
59 |
{
|
60 |
if (!@file_exists($dir) || !@is_dir($dir)) {
|
61 |
return [0, 0];
|
55 |
*
|
56 |
* @return [num files deleted, num files failed to delete]
|
57 |
*/
|
58 |
+
private static function purgeWebPFilesInDir($dir, &$filter, &$config)
|
59 |
{
|
60 |
if (!@file_exists($dir) || !@is_dir($dir)) {
|
61 |
return [0, 0];
|
lib/classes/Convert.php
CHANGED
@@ -29,28 +29,62 @@ class Convert
|
|
29 |
|
30 |
public static function convertFile($source, $config = null, $convertOptions = null, $converter = null)
|
31 |
{
|
32 |
-
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
-
if (is_null($config)) {
|
36 |
-
$config = Config::loadConfigAndFix();
|
37 |
-
}
|
38 |
-
if (is_null($convertOptions)) {
|
39 |
-
$convertOptions = Config::generateWodOptionsFromConfigObj($config)['webp-convert']['convert'];
|
40 |
-
}
|
41 |
-
/*
|
42 |
-
if (isset($config['converter'])) {
|
43 |
-
$options['convert']['converter'] = $config['converter'];
|
44 |
-
}*/
|
45 |
|
46 |
-
|
47 |
-
|
|
|
|
|
48 |
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
$result = ConvertHelperIndependent::convert($source, $destination, $convertOptions, $logDir, $converter);
|
52 |
|
53 |
-
//$result['destination'] = $destination;
|
54 |
if ($result['success'] === true) {
|
55 |
$result['filesize-original'] = @filesize($source);
|
56 |
$result['filesize-webp'] = @filesize($destination);
|
@@ -58,12 +92,33 @@ class Convert
|
|
58 |
return $result;
|
59 |
}
|
60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
public static function findSource($destination, &$config = null)
|
62 |
{
|
63 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
if (is_null($config)) {
|
65 |
$config = Config::loadConfigAndFix();
|
66 |
}
|
|
|
67 |
return ConvertHelperIndependent::findSource(
|
68 |
$destination,
|
69 |
$config['destination-folder'],
|
@@ -87,7 +142,8 @@ class Convert
|
|
87 |
$checking = '"filename" argument';
|
88 |
Validate::postHasKey('filename');
|
89 |
$filename = sanitize_text_field($_POST['filename']);
|
90 |
-
$filename = SanityCheck::
|
|
|
91 |
|
92 |
|
93 |
// Check converter id
|
29 |
|
30 |
public static function convertFile($source, $config = null, $convertOptions = null, $converter = null)
|
31 |
{
|
32 |
+
try {
|
33 |
+
// Check source
|
34 |
+
// ---------------
|
35 |
+
$checking = 'filename';
|
36 |
+
$filename = SanityCheck::absPathExistsAndIsFileInDocRoot($source);
|
37 |
+
// PS: No need to check mime type as the WebPConvert library does that (it only accepts image/jpeg and image/png)
|
38 |
+
|
39 |
+
|
40 |
+
// Check config
|
41 |
+
// --------------
|
42 |
+
$checking = 'configuration file';
|
43 |
+
if (is_null($config)) {
|
44 |
+
$config = Config::loadConfigAndFix(); // ps: if this fails to load, default config is returned.
|
45 |
+
}
|
46 |
+
if (!is_array($config)) {
|
47 |
+
throw new SanityException('file is corrupt');
|
48 |
+
}
|
49 |
+
|
50 |
+
// Check convert options
|
51 |
+
// -------------------------------
|
52 |
+
if (is_null($convertOptions)) {
|
53 |
+
$wodOptions = Config::generateWodOptionsFromConfigObj($config);
|
54 |
+
if (!isset($wodOptions['webp-convert']['convert'])) {
|
55 |
+
throw new SanityException('conversion options are missing');
|
56 |
+
}
|
57 |
+
$convertOptions = $wodOptions['webp-convert']['convert'];
|
58 |
+
}
|
59 |
+
if (!is_array($convertOptions)) {
|
60 |
+
throw new SanityException('conversion options are missing');
|
61 |
+
}
|
62 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
|
64 |
+
// Check destination
|
65 |
+
// -------------------------------
|
66 |
+
$destination = self::getDestination($source, $config);
|
67 |
+
$destination = SanityCheck::absPathIsInDocRoot($destination);
|
68 |
|
69 |
+
|
70 |
+
// Check log dir
|
71 |
+
// -------------------------------
|
72 |
+
$logDir = SanityCheck::absPathIsInDocRoot(Paths::getWebPExpressContentDirAbs() . '/log');
|
73 |
+
|
74 |
+
|
75 |
+
} catch (SanityException $e) {
|
76 |
+
return [
|
77 |
+
'success' => false,
|
78 |
+
'msg' => 'Sanitation check failed for ' . $checking . ': '. $e->getMessage(),
|
79 |
+
'log' => '',
|
80 |
+
];
|
81 |
+
}
|
82 |
+
|
83 |
+
// Done with sanitizing, lets get to work!
|
84 |
+
// ---------------------------------------
|
85 |
|
86 |
$result = ConvertHelperIndependent::convert($source, $destination, $convertOptions, $logDir, $converter);
|
87 |
|
|
|
88 |
if ($result['success'] === true) {
|
89 |
$result['filesize-original'] = @filesize($source);
|
90 |
$result['filesize-webp'] = @filesize($destination);
|
92 |
return $result;
|
93 |
}
|
94 |
|
95 |
+
/**
|
96 |
+
* Determine the location of a source from the location of a destination.
|
97 |
+
*
|
98 |
+
* If for example Operation mode is set to "mingled" and extension is set to "Append .webp",
|
99 |
+
* the result of looking passing "/path/to/logo.jpg.webp" will be "/path/to/logo.jpg".
|
100 |
+
*
|
101 |
+
* Additionally, it is tested if the source exists. If not, false is returned.
|
102 |
+
* The destination does not have to exist.
|
103 |
+
*
|
104 |
+
* @return string|null The source path corresponding to a destination path
|
105 |
+
* - or false on failure (if the source does not exist or $destination is not sane)
|
106 |
+
*
|
107 |
+
*/
|
108 |
public static function findSource($destination, &$config = null)
|
109 |
{
|
110 |
+
try {
|
111 |
+
// Check that destination path is sane and inside document root
|
112 |
+
$destination = SanityCheck::absPathIsInDocRoot($destination);
|
113 |
+
} catch (SanityException $e) {
|
114 |
+
return false;
|
115 |
+
}
|
116 |
+
|
117 |
+
// Load config if not already loaded
|
118 |
if (is_null($config)) {
|
119 |
$config = Config::loadConfigAndFix();
|
120 |
}
|
121 |
+
|
122 |
return ConvertHelperIndependent::findSource(
|
123 |
$destination,
|
124 |
$config['destination-folder'],
|
142 |
$checking = '"filename" argument';
|
143 |
Validate::postHasKey('filename');
|
144 |
$filename = sanitize_text_field($_POST['filename']);
|
145 |
+
$filename = SanityCheck::absPathExistsAndIsFileInDocRoot($filename);
|
146 |
+
// PS: No need to check mime version as webp-convert does that.
|
147 |
|
148 |
|
149 |
// Check converter id
|
lib/classes/ConvertHelperIndependent.php
CHANGED
@@ -1,22 +1,27 @@
|
|
1 |
<?php
|
2 |
|
3 |
/*
|
4 |
-
This class is made to be
|
5 |
It is used by webp-on-demand.php, which does not register an auto loader. It is also used for bulk conversion.
|
6 |
*/
|
7 |
namespace WebPExpress;
|
8 |
|
9 |
use \WebPConvert\WebPConvert;
|
10 |
use \WebPConvert\Convert\ConverterFactory;
|
|
|
11 |
use \WebPConvert\Loggers\BufferLogger;
|
12 |
use \WebPExpress\FileHelper;
|
13 |
-
use
|
14 |
-
|
15 |
|
16 |
class ConvertHelperIndependent
|
17 |
{
|
18 |
|
19 |
-
|
|
|
|
|
|
|
|
|
20 |
{
|
21 |
if ($destinationFolder != 'mingled') {
|
22 |
return false;
|
@@ -42,169 +47,175 @@ class ConvertHelperIndependent
|
|
42 |
return strpos($normalizedSource, $normalizedDocRoot) === 0;
|
43 |
}
|
44 |
|
45 |
-
/*
|
46 |
-
public static function getDestinationFolder($sourceDir, $destinationFolder, $destinationExt, $webExpressContentDirAbs, $uploadDirAbs)
|
47 |
-
{
|
48 |
-
if (self::storeMingledOrNot($sourceDir, $destinationFolder, $uploadDirAbs)) {
|
49 |
-
return $sourceDir;
|
50 |
-
} else {
|
51 |
-
|
52 |
-
$docRoot = rtrim(realpath($_SERVER["DOCUMENT_ROOT"]), '/');
|
53 |
-
$imageRoot = $webExpressContentDirAbs . '/webp-images';
|
54 |
-
|
55 |
-
// Check if source dir is residing inside document root.
|
56 |
-
// (it is, if path starts with document root + '/')
|
57 |
-
if (substr($sourceDir, 0, strlen($docRoot) + 1) === $docRoot . '/') {
|
58 |
-
|
59 |
-
// We store relative to document root.
|
60 |
-
// "Eat" the left part off the source parameter which contains the document root.
|
61 |
-
// and also eat the slash (+1)
|
62 |
-
$sourceDirRel = substr($sourceDir, strlen($docRoot) + 1);
|
63 |
-
return $imageRoot . '/doc-root/' . $sourceDirRel;
|
64 |
-
} else {
|
65 |
-
// Source file is residing outside document root.
|
66 |
-
// we must add complete path to structure
|
67 |
-
return $imageRoot . '/abs' . $sourceDir;
|
68 |
-
}
|
69 |
-
}
|
70 |
-
}*/
|
71 |
|
72 |
/**
|
73 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
*/
|
75 |
-
|
76 |
{
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
} else {
|
81 |
-
return preg_replace('/\\.(jpe?g|png)$/', '', $source) . '.webp';
|
82 |
-
}
|
83 |
-
} else {
|
84 |
-
|
85 |
-
$docRoot = rtrim(realpath($_SERVER["DOCUMENT_ROOT"]), '/');
|
86 |
-
$imageRoot = $webExpressContentDirAbs . '/webp-images';
|
87 |
|
88 |
-
|
89 |
-
//
|
90 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
|
92 |
-
// We store relative to document root.
|
93 |
-
// "Eat" the left part off the source parameter which contains the document root.
|
94 |
-
// and also eat the slash (+1)
|
95 |
$sourceRel = substr($source, strlen($docRoot) + 1);
|
96 |
-
|
97 |
-
|
98 |
-
// Source file is residing outside document root.
|
99 |
-
// we must add complete path to structure
|
100 |
-
return $imageRoot . '/abs' . $source . '.webp';
|
101 |
}
|
|
|
|
|
|
|
102 |
}
|
|
|
|
|
103 |
}
|
104 |
|
|
|
105 |
/**
|
106 |
-
*
|
107 |
*
|
108 |
-
*
|
109 |
-
*
|
110 |
-
*
|
111 |
-
* https://www.php.net/manual/en/wrappers.phar.php
|
112 |
*
|
113 |
-
*
|
|
|
114 |
*
|
115 |
-
* @
|
116 |
-
* @return string sanitized file path
|
117 |
*/
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
|
122 |
-
|
123 |
-
|
|
|
124 |
|
125 |
-
// remove "phar://", "php://" and the like from the beginning of the string
|
126 |
-
// important that this is done after removing "../" - otherwise one could send "../phar://"
|
127 |
-
$absFilePath = preg_replace('#^\\w+://#', '', $absFilePath);
|
128 |
|
129 |
-
|
130 |
-
|
|
|
131 |
|
132 |
-
/**
|
133 |
-
* Get destination from source (and some configurations)
|
134 |
-
*/
|
135 |
-
public static function getDestination($source, $destinationFolder, $destinationExt, $webExpressContentDirAbs, $uploadDirAbs)
|
136 |
-
{
|
137 |
-
return self::sanitizeAbsFilePath(
|
138 |
-
self::getDestinationUnsanitized($source, $destinationFolder, $destinationExt, $webExpressContentDirAbs, $uploadDirAbs)
|
139 |
-
);
|
140 |
-
}
|
141 |
|
142 |
-
|
143 |
-
|
144 |
-
* We can rely on destinationExt being "append" for separate
|
145 |
-
* Returns false if not found. Otherwise returns path to source
|
146 |
-
*/
|
147 |
-
private static function findSourceSeparate($destination, $webExpressContentDirAbs)
|
148 |
-
{
|
149 |
-
$imageRoot = $webExpressContentDirAbs . '/webp-images';
|
150 |
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
if (strpos($destination, $imageRoot . '/doc-root/') === 0) {
|
156 |
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
$sourceRel = substr($destination, strlen($imageRoot) + 1);
|
162 |
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
$
|
168 |
-
|
169 |
-
|
170 |
-
$source = preg_replace('/\\.(webp)$/', '', $source);
|
171 |
-
}
|
172 |
-
$source = self::sanitizeAbsFilePath($source);
|
173 |
-
if (!@file_exists($source)) {
|
174 |
return false;
|
175 |
}
|
|
|
176 |
return $source;
|
177 |
}
|
178 |
|
179 |
/**
|
180 |
-
*
|
181 |
-
*
|
|
|
|
|
|
|
|
|
|
|
182 |
*/
|
183 |
private static function findSourceMingled($destination, $destinationExt)
|
184 |
{
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
}
|
195 |
-
|
196 |
-
|
|
|
|
|
197 |
return false;
|
198 |
}
|
|
|
199 |
return $source;
|
200 |
}
|
201 |
|
202 |
/**
|
203 |
-
*
|
204 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
205 |
*/
|
206 |
public static function findSource($destination, $destinationFolder, $destinationExt, $webExpressContentDirAbs)
|
207 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
208 |
if ($destinationFolder == 'mingled') {
|
209 |
$result = self::findSourceMingled($destination, $destinationExt);
|
210 |
if ($result === false) {
|
@@ -216,31 +227,58 @@ class ConvertHelperIndependent
|
|
216 |
}
|
217 |
}
|
218 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
219 |
public static function getLogFilename($source, $logDir)
|
220 |
{
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
|
|
|
|
225 |
|
226 |
-
|
227 |
-
|
228 |
-
|
|
|
|
|
|
|
|
|
|
|
229 |
|
230 |
// We store relative to document root.
|
231 |
// "Eat" the left part off the source parameter which contains the document root.
|
232 |
// and also eat the slash (+1)
|
|
|
|
|
233 |
$sourceRel = substr($source, strlen($docRoot) + 1);
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
return
|
239 |
}
|
|
|
240 |
|
241 |
}
|
242 |
|
243 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
244 |
{
|
245 |
if (!is_dir($logDir)) {
|
246 |
@mkdir($logDir, 0775, true);
|
@@ -260,18 +298,33 @@ APACHE
|
|
260 |
return is_dir($logDir);
|
261 |
}
|
262 |
|
263 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
{
|
|
|
265 |
if (!file_exists($logDir)) {
|
266 |
self::createLogDir($logDir);
|
267 |
}
|
268 |
|
269 |
$text = preg_replace('#' . preg_quote($_SERVER["DOCUMENT_ROOT"]) . '#', '[doc-root]', $text);
|
270 |
|
271 |
-
$text = 'WebP Express 0.14.
|
272 |
|
273 |
$logFile = self::getLogFilename($source, $logDir);
|
274 |
|
|
|
|
|
|
|
|
|
275 |
$logFolder = @dirname($logFile);
|
276 |
if (!@file_exists($logFolder)) {
|
277 |
mkdir($logFolder, 0777, true);
|
@@ -282,11 +335,50 @@ APACHE
|
|
282 |
}
|
283 |
|
284 |
/**
|
285 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
286 |
*/
|
287 |
public static function convert($source, $destination, $convertOptions, $logDir, $converter = null) {
|
288 |
include_once __DIR__ . '/../../vendor/autoload.php';
|
289 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
290 |
$success = false;
|
291 |
$msg = '';
|
292 |
$logger = new BufferLogger();
|
@@ -322,15 +414,44 @@ APACHE
|
|
322 |
|
323 |
}
|
324 |
|
|
|
|
|
|
|
|
|
325 |
public static function serveConverted($source, $destination, $serveOptions, $logDir, $logMsgTop = '')
|
326 |
{
|
327 |
include_once __DIR__ . '/../../vendor/autoload.php';
|
328 |
|
329 |
-
//
|
330 |
-
//
|
331 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
332 |
|
333 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
334 |
|
335 |
$convertLogger = new BufferLogger();
|
336 |
WebPConvert::serveConverted($source, $destination, $serveOptions, null, $convertLogger);
|
1 |
<?php
|
2 |
|
3 |
/*
|
4 |
+
This class is made to be dependent only on a few WebPExpress classes, and must be kept like that.
|
5 |
It is used by webp-on-demand.php, which does not register an auto loader. It is also used for bulk conversion.
|
6 |
*/
|
7 |
namespace WebPExpress;
|
8 |
|
9 |
use \WebPConvert\WebPConvert;
|
10 |
use \WebPConvert\Convert\ConverterFactory;
|
11 |
+
use \WebPConvert\Exceptions\WebPConvertException;
|
12 |
use \WebPConvert\Loggers\BufferLogger;
|
13 |
use \WebPExpress\FileHelper;
|
14 |
+
use \WebPExpress\SanityCheck;
|
15 |
+
use \WebPExpress\SanityException;
|
16 |
|
17 |
class ConvertHelperIndependent
|
18 |
{
|
19 |
|
20 |
+
/**
|
21 |
+
*
|
22 |
+
* @return boolean Whether or not the destination corresponding to a given source should be stored in the same folder or the separate (in wp-content/webp-express)
|
23 |
+
*/
|
24 |
+
private static function storeMingledOrNot($source, $destinationFolder, $uploadDirAbs)
|
25 |
{
|
26 |
if ($destinationFolder != 'mingled') {
|
27 |
return false;
|
47 |
return strpos($normalizedSource, $normalizedDocRoot) === 0;
|
48 |
}
|
49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
/**
|
52 |
+
* Get destination path corresponding to the source path given (and some configurations)
|
53 |
+
*
|
54 |
+
* If for example Operation mode is set to "mingled" and extension is set to "Append .webp",
|
55 |
+
* the result of finding the destination path that corresponds to "/path/to/logo.jpg" will be "/path/to/logo.jpg.webp".
|
56 |
+
*
|
57 |
+
* @param string $source Path to source file
|
58 |
+
* @param string $destinationFolder 'mingled' or 'separate'
|
59 |
+
* @param string $destinationExt Extension ('append' or 'set')
|
60 |
+
* @param string $webExpressContentDirAbs
|
61 |
+
* @param string $uploadDirAbs
|
62 |
+
*
|
63 |
+
* @return string|false Returns path to destination corresponding to source, or false on failure
|
64 |
*/
|
65 |
+
public static function getDestination($source, $destinationFolder, $destinationExt, $webExpressContentDirAbs, $uploadDirAbs)
|
66 |
{
|
67 |
+
// At this point, everything has already been checked for sanity. But for good meassure, lets
|
68 |
+
// check the most important parts again. This is after all a public method.
|
69 |
+
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
71 |
+
try {
|
72 |
+
// Check source
|
73 |
+
// --------------
|
74 |
+
$source = SanityCheck::absPathExistsAndIsFileInDocRoot($source);
|
75 |
+
|
76 |
+
// Calculate destination and check that the result is sane
|
77 |
+
// -------------------------------------------------------
|
78 |
+
if (self::storeMingledOrNot($source, $destinationFolder, $uploadDirAbs)) {
|
79 |
+
if ($destinationExt == 'append') {
|
80 |
+
$destination = SanityCheck::absPathIsInDocRoot($source . '.webp');
|
81 |
+
} else {
|
82 |
+
$destination = preg_replace('/\\.(jpe?g|png)$/', '', $source) . '.webp';
|
83 |
+
$destination = SanityCheck::absPathIsInDocRoot($source . '.webp');
|
84 |
+
}
|
85 |
+
} else {
|
86 |
+
$docRoot = rtrim(realpath($_SERVER["DOCUMENT_ROOT"]), '/');
|
87 |
+
$imageRoot = $webExpressContentDirAbs . '/webp-images';
|
88 |
+
SanityCheck::absPathIsInDocRoot($imageRoot);
|
89 |
|
|
|
|
|
|
|
90 |
$sourceRel = substr($source, strlen($docRoot) + 1);
|
91 |
+
$destination = $imageRoot . '/doc-root/' . $sourceRel . '.webp';
|
92 |
+
$destination = SanityCheck::absPathIsInDocRoot($destination);
|
|
|
|
|
|
|
93 |
}
|
94 |
+
|
95 |
+
} catch (SanityException $e) {
|
96 |
+
return false;
|
97 |
}
|
98 |
+
|
99 |
+
return $destination;
|
100 |
}
|
101 |
|
102 |
+
|
103 |
/**
|
104 |
+
* Find source corresponding to destination, separate.
|
105 |
*
|
106 |
+
* We can rely on destinationExt being "append" for separate.
|
107 |
+
* Returns false if source file is not found or if a path is not sane. Otherwise returns path to source
|
108 |
+
* destination does not have to exist.
|
|
|
109 |
*
|
110 |
+
* @param string $destination Path to destination file (does not have to exist)
|
111 |
+
* @param string $webExpressContentDirAbs
|
112 |
*
|
113 |
+
* @return string|false Returns path to source, if found. If not - or a path is not sane, false is returned
|
|
|
114 |
*/
|
115 |
+
private static function findSourceSeparate($destination, $webExpressContentDirAbs)
|
116 |
+
{
|
117 |
+
try {
|
118 |
|
119 |
+
// Check that destination path is sane and inside document root
|
120 |
+
// --------------------------
|
121 |
+
$destination = SanityCheck::absPathIsInDocRoot($destination);
|
122 |
|
|
|
|
|
|
|
123 |
|
124 |
+
// Check that calculated image root is sane and inside document root
|
125 |
+
// --------------------------
|
126 |
+
$imageRoot = SanityCheck::absPathIsInDocRoot($webExpressContentDirAbs . '/webp-images/doc-root');
|
127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
|
129 |
+
// Calculate source and check that it is sane and exists
|
130 |
+
// -----------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
|
132 |
+
// TODO: This does not work on Windows yet.
|
133 |
+
// NOTE: WE CANNOT DO AS WITH sourceIsInsideDocRoot, because it relies on realpath, which only translates EXISTING paths.
|
134 |
+
// $destination does not exist yet, when this method is called from webp-realizer.php
|
135 |
+
if (strpos($destination, $imageRoot . '/doc-root/') === 0) {
|
|
|
136 |
|
137 |
+
// "Eat" the left part off the $destination parameter. $destination is for example:
|
138 |
+
// "/var/www/webp-express-tests/we0/wp-content-moved/webp-express/webp-images/doc-root/wordpress/uploads-moved/2018/12/tegning5-300x265.jpg.webp"
|
139 |
+
// We also eat the slash (+1)
|
140 |
+
$sourceRel = substr($destination, strlen($imageRoot) + 1);
|
|
|
141 |
|
142 |
+
$docRoot = rtrim(realpath($_SERVER["DOCUMENT_ROOT"]), '/');
|
143 |
+
$source = $docRoot . '/' . $sourceRel;
|
144 |
+
$source = preg_replace('/\\.(webp)$/', '', $source);
|
145 |
+
}
|
146 |
+
$source = SanityCheck::absPathExistsAndIsFileInDocRoot($source);
|
147 |
+
|
148 |
+
} catch (SanityException $e) {
|
|
|
|
|
|
|
|
|
149 |
return false;
|
150 |
}
|
151 |
+
|
152 |
return $source;
|
153 |
}
|
154 |
|
155 |
/**
|
156 |
+
* Find source corresponding to destination (mingled)
|
157 |
+
* Returns false if not found. Otherwise returns path to source
|
158 |
+
*
|
159 |
+
* @param string $destination Path to destination file (does not have to exist)
|
160 |
+
* @param string $destinationExt Extension ('append' or 'set')
|
161 |
+
*
|
162 |
+
* @return string|false Returns path to source, if found. If not - or a path is not sane, false is returned
|
163 |
*/
|
164 |
private static function findSourceMingled($destination, $destinationExt)
|
165 |
{
|
166 |
+
try {
|
167 |
+
|
168 |
+
// Check that destination path is sane and inside document root
|
169 |
+
// --------------------------
|
170 |
+
$destination = SanityCheck::absPathIsInDocRoot($destination);
|
171 |
+
|
172 |
+
|
173 |
+
// Calculate source and check that it is sane and exists
|
174 |
+
// -----------------------------------------------------
|
175 |
+
if ($destinationExt == 'append') {
|
176 |
+
$source = preg_replace('/\\.(webp)$/', '', $destination);
|
177 |
+
} else {
|
178 |
+
$source = preg_replace('#\\.webp$#', '.jpg', $destination);
|
179 |
+
if (!@file_exists($source)) {
|
180 |
+
$source = preg_replace('/\\.webp$/', '.jpeg', $destination);
|
181 |
+
}
|
182 |
+
if (!@file_exists($source)) {
|
183 |
+
$source = preg_replace('/\\.webp$/', '.png', $destination);
|
184 |
+
}
|
185 |
}
|
186 |
+
$source = SanityCheck::absPathExistsAndIsFileInDocRoot($source);
|
187 |
+
|
188 |
+
|
189 |
+
} catch (SanityException $e) {
|
190 |
return false;
|
191 |
}
|
192 |
+
|
193 |
return $source;
|
194 |
}
|
195 |
|
196 |
/**
|
197 |
+
* Get source from destination (and some configurations)
|
198 |
+
* Returns false if not found. Otherwise returns path to source
|
199 |
+
*
|
200 |
+
* @param string $destination Path to destination file (does not have to exist)
|
201 |
+
* @param string $destinationFolder 'mingled' or 'separate'
|
202 |
+
* @param string $destinationExt Extension ('append' or 'set')
|
203 |
+
* @param string $webExpressContentDirAbs
|
204 |
+
*
|
205 |
+
* @return string|false Returns path to source, if found. If not - or a path is not sane, false is returned
|
206 |
*/
|
207 |
public static function findSource($destination, $destinationFolder, $destinationExt, $webExpressContentDirAbs)
|
208 |
{
|
209 |
+
try {
|
210 |
+
|
211 |
+
// Check that destination path is sane and inside document root
|
212 |
+
// --------------------------
|
213 |
+
$destination = SanityCheck::absPathIsInDocRoot($destination);
|
214 |
+
|
215 |
+
} catch (SanityException $e) {
|
216 |
+
return false;
|
217 |
+
}
|
218 |
+
|
219 |
if ($destinationFolder == 'mingled') {
|
220 |
$result = self::findSourceMingled($destination, $destinationExt);
|
221 |
if ($result === false) {
|
227 |
}
|
228 |
}
|
229 |
|
230 |
+
/**
|
231 |
+
*
|
232 |
+
* @param string $source Path to source file
|
233 |
+
* @param string $logDir The folder where log files are kept
|
234 |
+
*
|
235 |
+
* @return string|false Returns computed filename of log - or false if a path is not sane
|
236 |
+
*
|
237 |
+
*/
|
238 |
public static function getLogFilename($source, $logDir)
|
239 |
{
|
240 |
+
try {
|
241 |
+
|
242 |
+
// Check that source path is sane and inside document root
|
243 |
+
// -------------------------------------------------------
|
244 |
+
$source = SanityCheck::absPathIsInDocRoot($source);
|
245 |
+
|
246 |
|
247 |
+
// Check that log path is sane and inside document root
|
248 |
+
// -------------------------------------------------------
|
249 |
+
$logDir = SanityCheck::absPathIsInDocRoot($logDir);
|
250 |
+
|
251 |
+
|
252 |
+
// Compute and check log path
|
253 |
+
// --------------------------
|
254 |
+
$logDirForConversions = $logDir .= '/conversions';
|
255 |
|
256 |
// We store relative to document root.
|
257 |
// "Eat" the left part off the source parameter which contains the document root.
|
258 |
// and also eat the slash (+1)
|
259 |
+
|
260 |
+
$docRoot = rtrim(realpath($_SERVER["DOCUMENT_ROOT"]), '/');
|
261 |
$sourceRel = substr($source, strlen($docRoot) + 1);
|
262 |
+
$logFileName = $logDir . '/doc-root/' . $sourceRel . '.md';
|
263 |
+
SanityCheck::absPathIsInDocRoot($logFileName);
|
264 |
+
|
265 |
+
} catch (SanityException $e) {
|
266 |
+
return false;
|
267 |
}
|
268 |
+
return $logFileName;
|
269 |
|
270 |
}
|
271 |
|
272 |
+
/**
|
273 |
+
* Create the directory for log files and put a .htaccess file into it, which prevents
|
274 |
+
* it to be viewed from the outside (not that it contains any sensitive information btw, but for good measure).
|
275 |
+
*
|
276 |
+
* @param string $logDir The folder where log files are kept
|
277 |
+
*
|
278 |
+
* @return boolean Whether it was created successfully or not.
|
279 |
+
*
|
280 |
+
*/
|
281 |
+
private static function createLogDir($logDir)
|
282 |
{
|
283 |
if (!is_dir($logDir)) {
|
284 |
@mkdir($logDir, 0775, true);
|
298 |
return is_dir($logDir);
|
299 |
}
|
300 |
|
301 |
+
/**
|
302 |
+
* Saves the log file corresponding to a conversion.
|
303 |
+
*
|
304 |
+
* @param string $source Path to the source file that was converted
|
305 |
+
* @param string $logDir The folder where log files are kept
|
306 |
+
* @param string $text Content of the log file
|
307 |
+
* @param string $msgTop A message that is printed before the conversion log (containing version info)
|
308 |
+
*
|
309 |
+
*
|
310 |
+
*/
|
311 |
+
private static function saveLog($source, $logDir, $text, $msgTop)
|
312 |
{
|
313 |
+
|
314 |
if (!file_exists($logDir)) {
|
315 |
self::createLogDir($logDir);
|
316 |
}
|
317 |
|
318 |
$text = preg_replace('#' . preg_quote($_SERVER["DOCUMENT_ROOT"]) . '#', '[doc-root]', $text);
|
319 |
|
320 |
+
$text = 'WebP Express 0.14.11. ' . $msgTop . ', ' . date("Y-m-d H:i:s") . "\n\r\n\r" . $text;
|
321 |
|
322 |
$logFile = self::getLogFilename($source, $logDir);
|
323 |
|
324 |
+
if ($logFile === false) {
|
325 |
+
return;
|
326 |
+
}
|
327 |
+
|
328 |
$logFolder = @dirname($logFile);
|
329 |
if (!@file_exists($logFolder)) {
|
330 |
mkdir($logFolder, 0777, true);
|
335 |
}
|
336 |
|
337 |
/**
|
338 |
+
* Trigger an actual conversion with webp-convert.
|
339 |
+
*
|
340 |
+
* PS: To convert with a specific converter, set it in the $converter param.
|
341 |
+
*
|
342 |
+
* @param string $source Path to the source file that was converted.
|
343 |
+
* @param string $destination Path to the destination file (may exist or not).
|
344 |
+
* @param array $convertOptions Conversion options.
|
345 |
+
* @param string $logDir The folder where log files are kept.
|
346 |
+
* @param string $converter (optional) Set it to convert with a specific converter.
|
347 |
*/
|
348 |
public static function convert($source, $destination, $convertOptions, $logDir, $converter = null) {
|
349 |
include_once __DIR__ . '/../../vendor/autoload.php';
|
350 |
|
351 |
+
// At this point, everything has already been checked for sanity. But for good meassure, lets
|
352 |
+
// check the most important parts again. This is after all a public method.
|
353 |
+
// ------------------------------------------------------------------
|
354 |
+
try {
|
355 |
+
|
356 |
+
// Check that source path is sane, exists, is a file and is inside document root
|
357 |
+
// -------------------------------------------------------
|
358 |
+
$source = SanityCheck::absPathExistsAndIsFileInDocRoot($source);
|
359 |
+
|
360 |
+
|
361 |
+
// Check that destination path is sane and is inside document root
|
362 |
+
// -------------------------------------------------------
|
363 |
+
$destination = SanityCheck::absPathIsInDocRoot($destination);
|
364 |
+
$destination = SanityCheck::pregMatch('#\.webp$#', $destination, 'Destination does not end with .webp');
|
365 |
+
|
366 |
+
|
367 |
+
// Check that log path is sane and inside document root
|
368 |
+
// -------------------------------------------------------
|
369 |
+
$logDir = SanityCheck::absPathIsInDocRoot($logDir);
|
370 |
+
|
371 |
+
|
372 |
+
// PS: No need to check $logMsgTop. Log files are markdown and stored as ".md". They can do no harm.
|
373 |
+
|
374 |
+
} catch (SanityException $e) {
|
375 |
+
return [
|
376 |
+
'success' => false,
|
377 |
+
'msg' => $e->getMessage(),
|
378 |
+
'log' => '',
|
379 |
+
];
|
380 |
+
}
|
381 |
+
|
382 |
$success = false;
|
383 |
$msg = '';
|
384 |
$logger = new BufferLogger();
|
414 |
|
415 |
}
|
416 |
|
417 |
+
/**
|
418 |
+
* Serve a converted file (if it does not already exist, a conversion is triggered - all handled in webp-convert).
|
419 |
+
*
|
420 |
+
*/
|
421 |
public static function serveConverted($source, $destination, $serveOptions, $logDir, $logMsgTop = '')
|
422 |
{
|
423 |
include_once __DIR__ . '/../../vendor/autoload.php';
|
424 |
|
425 |
+
// At this point, everything has already been checked for sanity. But for good meassure, lets
|
426 |
+
// check again. This is after all a public method.
|
427 |
+
// ---------------------------------------------
|
428 |
+
try {
|
429 |
+
|
430 |
+
// Check that source path is sane, exists, is a file and is inside document root
|
431 |
+
// -------------------------------------------------------
|
432 |
+
$source = SanityCheck::absPathExistsAndIsFileInDocRoot($source);
|
433 |
+
|
434 |
|
435 |
+
// Check that destination path is sane and is inside document root
|
436 |
+
// -------------------------------------------------------
|
437 |
+
$destination = SanityCheck::absPathIsInDocRoot($destination);
|
438 |
+
$destination = SanityCheck::pregMatch('#\.webp$#', $destination, 'Destination does not end with .webp');
|
439 |
+
|
440 |
+
|
441 |
+
// Check that log path is sane and inside document root
|
442 |
+
// -------------------------------------------------------
|
443 |
+
$logDir = SanityCheck::absPathIsInDocRoot($logDir);
|
444 |
+
|
445 |
+
|
446 |
+
// PS: No need to check $logMsgTop. Log files are markdown and stored as ".md". They can do no harm.
|
447 |
+
|
448 |
+
} catch (SanityException $e) {
|
449 |
+
$msg = $e->getMessage();
|
450 |
+
echo $msg;
|
451 |
+
header('X-WebP-Express-Error: ' . $msg, true);
|
452 |
+
// TODO: error_log() ?
|
453 |
+
exit;
|
454 |
+
}
|
455 |
|
456 |
$convertLogger = new BufferLogger();
|
457 |
WebPConvert::serveConverted($source, $destination, $serveOptions, null, $convertLogger);
|
lib/classes/HandleUploadHooks.php
CHANGED
@@ -5,6 +5,8 @@ namespace WebPExpress;
|
|
5 |
use \WebPExpress\Config;
|
6 |
use \WebPExpress\Convert;
|
7 |
use \WebPExpress\Mime;
|
|
|
|
|
8 |
|
9 |
class HandleUploadHooks
|
10 |
{
|
@@ -58,9 +60,14 @@ class HandleUploadHooks
|
|
58 |
*/
|
59 |
public static function handleUpload($filearray, $overrides = false, $ignore = false)
|
60 |
{
|
61 |
-
|
62 |
-
|
63 |
-
|
|
|
|
|
|
|
|
|
|
|
64 |
return $filearray;
|
65 |
}
|
66 |
|
@@ -70,7 +77,14 @@ class HandleUploadHooks
|
|
70 |
*/
|
71 |
public static function handleMakeIntermediateSize($filename)
|
72 |
{
|
73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
return $filename;
|
75 |
}
|
76 |
}
|
5 |
use \WebPExpress\Config;
|
6 |
use \WebPExpress\Convert;
|
7 |
use \WebPExpress\Mime;
|
8 |
+
use \WebPExpress\SanityCheck;
|
9 |
+
use \WebPExpress\SanityException;
|
10 |
|
11 |
class HandleUploadHooks
|
12 |
{
|
60 |
*/
|
61 |
public static function handleUpload($filearray, $overrides = false, $ignore = false)
|
62 |
{
|
63 |
+
if (isset($filearray['file'])) {
|
64 |
+
try {
|
65 |
+
$filename = SanityCheck::absPathExistsAndIsFileInDocRoot($filearray['file']);
|
66 |
+
self::convertIf($filename);
|
67 |
+
} catch (SanityException $e) {
|
68 |
+
// fail silently. (maybe we should write to debug log instead?)
|
69 |
+
}
|
70 |
+
}
|
71 |
return $filearray;
|
72 |
}
|
73 |
|
77 |
*/
|
78 |
public static function handleMakeIntermediateSize($filename)
|
79 |
{
|
80 |
+
if (!is_null($filename)) {
|
81 |
+
try {
|
82 |
+
$filenameToConvert = SanityCheck::absPathExistsAndIsFileInDocRoot($filearray['file']);
|
83 |
+
self::convertIf($filenameToConvert);
|
84 |
+
} catch (SanityException $e) {
|
85 |
+
// fail silently. (maybe we should write to debug log instead?)
|
86 |
+
}
|
87 |
+
}
|
88 |
return $filename;
|
89 |
}
|
90 |
}
|
lib/classes/SanityCheck.php
CHANGED
@@ -115,6 +115,23 @@ class SanityCheck
|
|
115 |
return $input;
|
116 |
}
|
117 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
public static function absPath($input)
|
119 |
{
|
120 |
return self::path($input);
|
@@ -151,6 +168,13 @@ class SanityCheck
|
|
151 |
return $input;
|
152 |
}
|
153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
public static function absPathExistsAndIsNotDir(
|
155 |
$input,
|
156 |
$errorMsg = 'Path points to a directory (it should point to a file)'
|
115 |
return $input;
|
116 |
}
|
117 |
|
118 |
+
public static function absPathIsInDocRoot($input, $errorMsg = 'Path is outside allowed path')
|
119 |
+
{
|
120 |
+
$docRoot = self::absPath($_SERVER["DOCUMENT_ROOT"]);
|
121 |
+
|
122 |
+
// Use realpath to expand symbolic links and check if it exists
|
123 |
+
$docRoot = realpath($docRoot);
|
124 |
+
if ($docRoot === false) {
|
125 |
+
throw new SanityException('Cannot find document root');
|
126 |
+
}
|
127 |
+
$docRoot = rtrim($docRoot, '/');
|
128 |
+
$docRoot = self::absPathExists($docRoot, 'Document root does not exist!');
|
129 |
+
$docRoot = self::absPathExistsAndIsDir($docRoot, 'Document root is not a directory!');
|
130 |
+
|
131 |
+
self::pathBeginsWith($input, $docRoot . '/', $errorMsg);
|
132 |
+
return $input;
|
133 |
+
}
|
134 |
+
|
135 |
public static function absPath($input)
|
136 |
{
|
137 |
return self::path($input);
|
168 |
return $input;
|
169 |
}
|
170 |
|
171 |
+
public static function absPathExistsAndIsFileInDocRoot($input)
|
172 |
+
{
|
173 |
+
self::absPathExistsAndIsFile($input);
|
174 |
+
self::absPathIsInDocRoot($input);
|
175 |
+
return $input;
|
176 |
+
}
|
177 |
+
|
178 |
public static function absPathExistsAndIsNotDir(
|
179 |
$input,
|
180 |
$errorMsg = 'Path points to a directory (it should point to a file)'
|
lib/options/enqueue_scripts.php
CHANGED
@@ -8,7 +8,7 @@ use \WebPExpress\Paths;
|
|
8 |
include_once __DIR__ . '/../classes/Config.php';
|
9 |
use \WebPExpress\Config;
|
10 |
|
11 |
-
$ver = '
|
12 |
$jsDir = 'js/0.14.9'; // We change dir when it is critical that no-one gets the cached version (there is a plugin that strips version strings out there...)
|
13 |
|
14 |
if (!function_exists('webp_express_add_inline_script')) {
|
8 |
include_once __DIR__ . '/../classes/Config.php';
|
9 |
use \WebPExpress\Config;
|
10 |
|
11 |
+
$ver = '2'; // note: Minimum 1
|
12 |
$jsDir = 'js/0.14.9'; // We change dir when it is critical that no-one gets the cached version (there is a plugin that strips version strings out there...)
|
13 |
|
14 |
if (!function_exists('webp_express_add_inline_script')) {
|
lib/options/page-messages.php
CHANGED
@@ -13,15 +13,10 @@ use \WebPExpress\Paths;
|
|
13 |
use \WebPExpress\PlatformInfo;
|
14 |
use \WebPExpress\State;
|
15 |
|
16 |
-
//use \WebPExpress\BulkConvert;
|
17 |
-
//echo '<pre>' . print_r(BulkConvert::getList($config), true) . "</pre>";
|
18 |
-
//echo '<pre>' . print_r(BulkConvert::convertFile('/var/www/webp-express-tests/we0/wordpress/uploads-moved/space in name.jpg'), true) . "</pre>";
|
19 |
-
|
20 |
if ((!State::getState('configured', false))) {
|
21 |
include __DIR__ . "/page-welcome.php";
|
22 |
}
|
23 |
|
24 |
-
|
25 |
/*
|
26 |
if (CapabilityTest::modRewriteWorking()) {
|
27 |
echo 'mod rewrite works. that is nice';
|
13 |
use \WebPExpress\PlatformInfo;
|
14 |
use \WebPExpress\State;
|
15 |
|
|
|
|
|
|
|
|
|
16 |
if ((!State::getState('configured', false))) {
|
17 |
include __DIR__ . "/page-welcome.php";
|
18 |
}
|
19 |
|
|
|
20 |
/*
|
21 |
if (CapabilityTest::modRewriteWorking()) {
|
22 |
echo 'mod rewrite works. that is nice';
|
webp-express.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
* Plugin Name: WebP Express
|
4 |
* Plugin URI: https://github.com/rosell-dk/webp-express
|
5 |
* Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
|
6 |
-
* Version: 0.14.
|
7 |
* Author: Bjørn Rosell
|
8 |
* Author URI: https://www.bitwise-it.dk
|
9 |
* License: GPL2
|
3 |
* Plugin Name: WebP Express
|
4 |
* Plugin URI: https://github.com/rosell-dk/webp-express
|
5 |
* Description: Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP. Works on anything (media library images, galleries, theme images etc).
|
6 |
+
* Version: 0.14.11
|
7 |
* Author: Bjørn Rosell
|
8 |
* Author URI: https://www.bitwise-it.dk
|
9 |
* License: GPL2
|
wod/webp-on-demand.php
CHANGED
@@ -121,7 +121,8 @@ class WebPOnDempand
|
|
121 |
// Check if it is in an environment variable
|
122 |
$source = self::getEnvPassedInRewriteRule('REQFN');
|
123 |
if ($source !== false) {
|
124 |
-
$source = SanityCheck::
|
|
|
125 |
} else {
|
126 |
// Check if it is in header (but only if .htaccess was configured to send in header)
|
127 |
if (isset($wodOptions['base-htaccess-on-these-capability-tests'])) {
|
@@ -134,7 +135,7 @@ class WebPOnDempand
|
|
134 |
}
|
135 |
if ((!$passThrougEnvVarDefinitelyAvailable) && (!$passThroughHeaderDefinitelyUnavailable)) {
|
136 |
if (isset($_SERVER['HTTP_REQFN'])) {
|
137 |
-
$source = SanityCheck::
|
138 |
}
|
139 |
} else {
|
140 |
// Check querystring (relative path)
|
@@ -151,10 +152,10 @@ class WebPOnDempand
|
|
151 |
(isset($_GET['source']) || isset($_GET['xsource']))
|
152 |
) {
|
153 |
if (isset($_GET['source'])) {
|
154 |
-
$source = SanityCheck::
|
155 |
} else {
|
156 |
$xsrc = SanityCheck::noControlChars($_GET['xsource']);
|
157 |
-
$source = SanityCheck::
|
158 |
}
|
159 |
} else {
|
160 |
// Last resort is to use $_SERVER['REQUEST_URI'], well knowing that it does not give the
|
121 |
// Check if it is in an environment variable
|
122 |
$source = self::getEnvPassedInRewriteRule('REQFN');
|
123 |
if ($source !== false) {
|
124 |
+
$source = SanityCheck::absPathExistsAndIsFileInDocRoot($source);
|
125 |
+
echo $source; exit;
|
126 |
} else {
|
127 |
// Check if it is in header (but only if .htaccess was configured to send in header)
|
128 |
if (isset($wodOptions['base-htaccess-on-these-capability-tests'])) {
|
135 |
}
|
136 |
if ((!$passThrougEnvVarDefinitelyAvailable) && (!$passThroughHeaderDefinitelyUnavailable)) {
|
137 |
if (isset($_SERVER['HTTP_REQFN'])) {
|
138 |
+
$source = SanityCheck::absPathExistsAndIsFileInDocRoot($_SERVER['HTTP_REQFN']);
|
139 |
}
|
140 |
} else {
|
141 |
// Check querystring (relative path)
|
152 |
(isset($_GET['source']) || isset($_GET['xsource']))
|
153 |
) {
|
154 |
if (isset($_GET['source'])) {
|
155 |
+
$source = SanityCheck::absPathExistsAndIsFileInDocRoot($_GET['source']);
|
156 |
} else {
|
157 |
$xsrc = SanityCheck::noControlChars($_GET['xsource']);
|
158 |
+
$source = SanityCheck::absPathExistsAndIsFileInDocRoot(substr($xsrc, 1));
|
159 |
}
|
160 |
} else {
|
161 |
// Last resort is to use $_SERVER['REQUEST_URI'], well knowing that it does not give the
|
wod/webp-realizer-old.php
DELETED
@@ -1,278 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
namespace WebPExpress;
|
3 |
-
|
4 |
-
use \WebPConvert\WebPConvert;
|
5 |
-
use \WebPConvert\Serve\ServeConvertedWebP;
|
6 |
-
use \WebPExpress\ConvertHelperIndependent;
|
7 |
-
use \WebPExpress\Sanitize;
|
8 |
-
use \WebPExpress\ValidateException;
|
9 |
-
|
10 |
-
class WebPRealizer
|
11 |
-
{
|
12 |
-
|
13 |
-
private static $docRoot;
|
14 |
-
|
15 |
-
public static function exitWithError($msg) {
|
16 |
-
header('X-WebP-Express-Error: ' . $msg, true);
|
17 |
-
echo $msg;
|
18 |
-
exit;
|
19 |
-
}
|
20 |
-
|
21 |
-
//echo $_SERVER["SERVER_SOFTWARE"]; exit;
|
22 |
-
//stripos($_SERVER["SERVER_SOFTWARE"], 'nginx') !== false
|
23 |
-
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Get environment variable set with mod_rewrite module
|
27 |
-
* Return false if the environment variable isn't found
|
28 |
-
*/
|
29 |
-
static function getEnvPassedInRewriteRule($envName) {
|
30 |
-
// Envirenment variables passed through the REWRITE module have "REWRITE_" as a prefix (in Apache, not Litespeed, if I recall correctly)
|
31 |
-
// Multiple iterations causes multiple REWRITE_ prefixes, and we get many environment variables set.
|
32 |
-
// Multiple iterations causes multiple REWRITE_ prefixes, and we get many environment variables set.
|
33 |
-
// We simply look for an environment variable that ends with what we are looking for.
|
34 |
-
// (so make sure to make it unique)
|
35 |
-
$len = strlen($envName);
|
36 |
-
foreach ($_SERVER as $key => $item) {
|
37 |
-
if (substr($key, -$len) == $envName) {
|
38 |
-
return $item;
|
39 |
-
}
|
40 |
-
}
|
41 |
-
return false;
|
42 |
-
}
|
43 |
-
|
44 |
-
/**
|
45 |
-
* Get absolute path to destination file.
|
46 |
-
*
|
47 |
-
* The path can be passed to this file from the .htaccess file / nginx config in various ways.
|
48 |
-
*
|
49 |
-
* @return string Absolute path to destination (unsanitized! - call sanitizeAbsFilePath immidiately after calling this method)
|
50 |
-
*/
|
51 |
-
static function getDestinationUnsanitized($docRoot) {
|
52 |
-
|
53 |
-
// First check if it is in an environment variable - thats the safest way
|
54 |
-
$destinationRel = self::getEnvPassedInRewriteRule('DESTINATIONREL');
|
55 |
-
if ($destinationRel !== false) {
|
56 |
-
return $docRoot . '/' . $destinationRel;
|
57 |
-
}
|
58 |
-
|
59 |
-
// Next, check querystring (relative path)
|
60 |
-
$destinationRel = '';
|
61 |
-
if (isset($_GET['xdestination-rel'])) {
|
62 |
-
$destinationRel = substr(Sanitize::removeNUL($_GET['xdestination-rel']), 1);
|
63 |
-
} elseif (isset($_GET['destination-rel'])) {
|
64 |
-
$destinationRel = Sanitize::removeNUL($_GET['destination-rel']);
|
65 |
-
}
|
66 |
-
if ($destinationRel != '') {
|
67 |
-
/*
|
68 |
-
if (isset($_GET['source-rel-filter'])) {
|
69 |
-
if (Sanitize::removeNUL($_GET['source-rel-filter']) == 'discard-parts-before-wp-content') {
|
70 |
-
$parts = explode('/', $destinationRel);
|
71 |
-
$wp_content = isset($_GET['wp-content']) ? Sanitize::removeNUL($_GET['wp-content']) : 'wp-content';
|
72 |
-
|
73 |
-
if (in_array($wp_content, $parts)) {
|
74 |
-
foreach($parts as $index => $part) {
|
75 |
-
if($part !== $wp_content) {
|
76 |
-
unset($parts[$index]);
|
77 |
-
} else {
|
78 |
-
break;
|
79 |
-
}
|
80 |
-
}
|
81 |
-
$destinationRel = implode('/', $parts);
|
82 |
-
}
|
83 |
-
}
|
84 |
-
}*/
|
85 |
-
return $docRoot . '/' . $destinationRel;
|
86 |
-
}
|
87 |
-
|
88 |
-
// Then querystring (full path) - But only on Nginx (our Apache .htaccess rules never passes absolute url)
|
89 |
-
if (stripos($_SERVER["SERVER_SOFTWARE"], 'nginx') !== false) {
|
90 |
-
if (isset($_GET['xdestination'])) {
|
91 |
-
return substr($_GET['xdestination'], 1); // No url decoding needed as $_GET is already decoded
|
92 |
-
} elseif (isset($_GET['destination'])) {
|
93 |
-
return $_GET['destination'];
|
94 |
-
}
|
95 |
-
}
|
96 |
-
|
97 |
-
// Last resort is to use $_SERVER['REQUEST_URI'], well knowing that it does not give the
|
98 |
-
// correct result in all setups (ie "folder method 1")
|
99 |
-
$requestUriNoQS = explode('?', $_SERVER['REQUEST_URI'])[0];
|
100 |
-
$docRoot = rtrim(realpath($_SERVER["DOCUMENT_ROOT"]), '/');
|
101 |
-
$dest = $docRoot . urldecode($requestUriNoQS);
|
102 |
-
return $dest;
|
103 |
-
}
|
104 |
-
|
105 |
-
|
106 |
-
static function getWpContentRelUnsanitized() {
|
107 |
-
// Passed in env variable?
|
108 |
-
$wpContentDirRel = self::getEnvPassedInRewriteRule('WPCONTENT');
|
109 |
-
if ($wpContentDirRel !== false) {
|
110 |
-
return $wpContentDirRel;
|
111 |
-
}
|
112 |
-
|
113 |
-
// Passed in QS?
|
114 |
-
if (isset($_GET['wp-content'])) {
|
115 |
-
return $_GET['wp-content'];
|
116 |
-
}
|
117 |
-
|
118 |
-
// In case above fails, fall back to standard location
|
119 |
-
return 'wp-content';
|
120 |
-
}
|
121 |
-
|
122 |
-
/*
|
123 |
-
static function registerAutoload()
|
124 |
-
{
|
125 |
-
define('WEBPEXPRESS_PLUGIN_DIR', __DIR__);
|
126 |
-
|
127 |
-
// Autoload WebPExpress classes
|
128 |
-
spl_autoload_register('webpexpress_autoload');
|
129 |
-
function webpexpress_autoload($class) {
|
130 |
-
if (strpos($class, 'WebPExpress\\') === 0) {
|
131 |
-
require_once WEBPEXPRESS_PLUGIN_DIR . '/lib/classes/' . substr($class, 12) . '.php';
|
132 |
-
}
|
133 |
-
}
|
134 |
-
}*/
|
135 |
-
|
136 |
-
static function process() {
|
137 |
-
|
138 |
-
include_once "../lib/classes/ConvertHelperIndependent.php";
|
139 |
-
include_once __DIR__ . '/../lib/classes/Sanitize.php';
|
140 |
-
include_once __DIR__ . '/../lib/classes/Validate.php';
|
141 |
-
include_once __DIR__ . '/../lib/classes/ValidateException.php';
|
142 |
-
|
143 |
-
// Validate!
|
144 |
-
// ----------
|
145 |
-
|
146 |
-
try {
|
147 |
-
|
148 |
-
// Validate DOCUMENT_ROOT
|
149 |
-
// ----------------------
|
150 |
-
$validating = 'DOCUMENT_ROOT';
|
151 |
-
$realPathResult = realpath(Sanitize::removeNUL($_SERVER["DOCUMENT_ROOT"]));
|
152 |
-
if ($realPathResult === false) {
|
153 |
-
throw new ValidateException('Cannot find document root');
|
154 |
-
}
|
155 |
-
$docRoot = rtrim($realPathResult, '/');
|
156 |
-
SanityCheck::absPathExistsAndIsDir($docRoot);
|
157 |
-
$docRoot = $docRoot;
|
158 |
-
|
159 |
-
|
160 |
-
// Validate WebP Express content dir
|
161 |
-
// ---------------------------------
|
162 |
-
$validating = 'WebP Express content dir';
|
163 |
-
$webExpressContentDirAbs = ConvertHelperIndependent::sanitizeAbsFilePath(
|
164 |
-
$docRoot . '/' . self::getWpContentRelUnsanitized() . '/webp-express'
|
165 |
-
);
|
166 |
-
SanityCheck::absPathExistsAndIsDir($webExpressContentDirAbs);
|
167 |
-
|
168 |
-
|
169 |
-
// Validate config file name
|
170 |
-
// ---------------------------------
|
171 |
-
$validating = 'config file';
|
172 |
-
$configFilename = $webExpressContentDirAbs . '/config/wod-options.json';
|
173 |
-
SanityCheck::absPathExistsAndIsFile($configFilename);
|
174 |
-
|
175 |
-
|
176 |
-
// Validate config file
|
177 |
-
// --------------------
|
178 |
-
$configLoadResult = file_get_contents($configFilename);
|
179 |
-
if ($configLoadResult === false) {
|
180 |
-
throw new ValidateException('Cannot open config file');
|
181 |
-
}
|
182 |
-
SanityCheck::isJSONObject($configLoadResult);
|
183 |
-
$json = $configLoadResult;
|
184 |
-
$options = json_decode($json, true);
|
185 |
-
$wodOptions = $options['wod'];
|
186 |
-
$serveOptions = $options['webp-convert'];
|
187 |
-
$convertOptions = &$serveOptions['convert'];
|
188 |
-
//echo '<pre>' . print_r($wodOptions, true) . '</pre>'; exit;
|
189 |
-
|
190 |
-
|
191 |
-
// Validate that WebPExpress was configured to redirect to this conversion script
|
192 |
-
// ------------------------------------------------------------------------------
|
193 |
-
$validating = 'settings';
|
194 |
-
if (!isset($wodOptions['enable-redirection-to-webp-realizer']) || ($wodOptions['enable-redirection-to-webp-realizer'] === false)) {
|
195 |
-
throw new ValidateException('Redirection to conversion script is not enabled');
|
196 |
-
}
|
197 |
-
|
198 |
-
|
199 |
-
// Validate destination (the image that was requested, but has not been converted yet)
|
200 |
-
// ------------------------------------------------------------------------------------
|
201 |
-
$validating = 'destination path';
|
202 |
-
$destination = Sanitize::removeNUL(self::getDestinationUnsanitized($docRoot));
|
203 |
-
SanityCheck::absPath($destination);
|
204 |
-
//echo $destination; exit;
|
205 |
-
|
206 |
-
|
207 |
-
// Validate source path
|
208 |
-
// --------------------------------------------
|
209 |
-
$validating = 'source path';
|
210 |
-
$source = ConvertHelperIndependent::findSource(
|
211 |
-
$destination,
|
212 |
-
$wodOptions['destination-folder'],
|
213 |
-
$wodOptions['destination-extension'],
|
214 |
-
$webExpressContentDirAbs
|
215 |
-
);
|
216 |
-
|
217 |
-
if ($source === false) {
|
218 |
-
header('X-WebP-Express-Error: webp-realizer.php could not find an existing jpg or png that corresponds to the webp requested', true);
|
219 |
-
|
220 |
-
$protocol = isset($_SERVER["SERVER_PROTOCOL"]) ? $_SERVER["SERVER_PROTOCOL"] : 'HTTP/1.0';
|
221 |
-
header($protocol . " 404 Not Found");
|
222 |
-
die();
|
223 |
-
//echo 'destination requested:<br><i>' . $destination . '</i>';
|
224 |
-
}
|
225 |
-
SanityCheck::absPathExistsAndIsFile($source);
|
226 |
-
//echo $source; exit;
|
227 |
-
|
228 |
-
} catch (ValidateException $e) {
|
229 |
-
self::exitWithError('failed validating ' . $validating . ': '. $e->getMessage());
|
230 |
-
}
|
231 |
-
|
232 |
-
/*
|
233 |
-
if ($wodOptions['forward-query-string']) {
|
234 |
-
if (isset($_GET['debug'])) {
|
235 |
-
$serveOptions['show-report'] = true;
|
236 |
-
}
|
237 |
-
if (isset($_GET['reconvert'])) {
|
238 |
-
$serveOptions['reconvert'] = true;
|
239 |
-
}
|
240 |
-
}*/
|
241 |
-
|
242 |
-
$serveOptions['add-vary-header'] = false;
|
243 |
-
$serveOptions['fail'] = '404';
|
244 |
-
$serveOptions['fail-when-fail-fails'] = '404';
|
245 |
-
$serveOptions['serve-image']['headers']['vary-accept'] = false;
|
246 |
-
|
247 |
-
/*
|
248 |
-
function aboutToServeImageCallBack($servingWhat, $whyServingThis, $obj) {
|
249 |
-
// Redirect to same location.
|
250 |
-
header('Location: ?fresh' , 302);
|
251 |
-
return false; // tell webp-convert not to serve!
|
252 |
-
}
|
253 |
-
*/
|
254 |
-
|
255 |
-
//echo '<pre>' . print_r($serveOptions, true) . '</pre>'; exit;
|
256 |
-
//$serveOptions['show-report'] = true;
|
257 |
-
|
258 |
-
ConvertHelperIndependent::serveConverted(
|
259 |
-
$source,
|
260 |
-
$destination,
|
261 |
-
$serveOptions,
|
262 |
-
$webExpressContentDirAbs . '/log',
|
263 |
-
'Conversion triggered with the conversion script (wod/webp-realizer.php)'
|
264 |
-
);
|
265 |
-
|
266 |
-
}
|
267 |
-
}
|
268 |
-
|
269 |
-
// Protect against directly accessing webp-on-demand.php
|
270 |
-
// Only protect on Apache. We know for sure that the method is not reliable on nginx. We have not tested on litespeed yet, so we dare not.
|
271 |
-
if (stripos($_SERVER["SERVER_SOFTWARE"], 'apache') !== false && stripos($_SERVER["SERVER_SOFTWARE"], 'nginx') === false) {
|
272 |
-
if (strpos($_SERVER['REQUEST_URI'], 'webp-realizer.php') !== false) {
|
273 |
-
WebPRealizer::exitWithError('It seems you are visiting this file (plugins/webp-express/wod/webp-realizer.php) directly. We do not allow this.');
|
274 |
-
exit;
|
275 |
-
}
|
276 |
-
}
|
277 |
-
|
278 |
-
WebPRealizer::process();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wod/webp-realizer.php
CHANGED
@@ -88,7 +88,7 @@ class WebPRealizer
|
|
88 |
// Check config file name
|
89 |
// ---------------------------------
|
90 |
$checking = 'config file';
|
91 |
-
$configFilename = SanityCheck::
|
92 |
|
93 |
|
94 |
// Check config file
|
@@ -137,10 +137,10 @@ class WebPRealizer
|
|
137 |
(isset($_GET['destination']) || isset($_GET['xdestination']))
|
138 |
) {
|
139 |
if (isset($_GET['destination'])) {
|
140 |
-
$destination = SanityCheck::
|
141 |
} else {
|
142 |
$xdest = SanityCheck::noControlChars($_GET['xdestination']);
|
143 |
-
$destination = SanityCheck::
|
144 |
}
|
145 |
} else {
|
146 |
// Last resort is to use $_SERVER['REQUEST_URI'], well knowing that it does not give the
|
@@ -152,7 +152,7 @@ class WebPRealizer
|
|
152 |
}
|
153 |
|
154 |
$destination = SanityCheck::pregMatch('#\.webp$#', $destination, 'Does not end with .webp');
|
155 |
-
$destination = SanityCheck::
|
156 |
|
157 |
|
158 |
// Validate source path
|
88 |
// Check config file name
|
89 |
// ---------------------------------
|
90 |
$checking = 'config file';
|
91 |
+
$configFilename = SanityCheck::absPathExistsAndIsFileInDocRoot($webExpressContentDirAbs . '/config/wod-options.json');
|
92 |
|
93 |
|
94 |
// Check config file
|
137 |
(isset($_GET['destination']) || isset($_GET['xdestination']))
|
138 |
) {
|
139 |
if (isset($_GET['destination'])) {
|
140 |
+
$destination = SanityCheck::absPathIsInDocRoot($_GET['destination']);
|
141 |
} else {
|
142 |
$xdest = SanityCheck::noControlChars($_GET['xdestination']);
|
143 |
+
$destination = SanityCheck::absPathIsInDocRoot(substr($xdest, 1));
|
144 |
}
|
145 |
} else {
|
146 |
// Last resort is to use $_SERVER['REQUEST_URI'], well knowing that it does not give the
|
152 |
}
|
153 |
|
154 |
$destination = SanityCheck::pregMatch('#\.webp$#', $destination, 'Does not end with .webp');
|
155 |
+
$destination = SanityCheck::absPathIsInDocRoot($destination);
|
156 |
|
157 |
|
158 |
// Validate source path
|