WebP Express - Version 0.14.5

Version Description

(released: 20 jun 2019)

  • Various fixes
Download this release

Release Info

Developer rosell.dk
Plugin Icon 128x128 WebP Express
Version 0.14.5
Comparing to
See all releases

Code changes from version 0.14.4 to 0.14.5

Files changed (61) hide show
  1. README.txt +10 -2
  2. composer.json +1 -1
  3. composer.lock +5 -5
  4. lib/classes/AlterHtmlInit.php +1 -1
  5. lib/classes/Convert.php +4 -0
  6. lib/classes/ConvertHelperIndependent.php +40 -2
  7. lib/classes/ConvertersHelper.php +1 -1
  8. lib/options/enqueue_scripts.php +2 -2
  9. lib/options/js/0.14.2/whitelist_old.js +0 -189
  10. lib/options/js/{0.14.2 → 0.14.5}/authorized_sites_bak.js +0 -0
  11. lib/options/js/{0.14.2 → 0.14.5}/bulk-convert.js +0 -0
  12. lib/options/js/{0.14.2 → 0.14.5}/converters.js +0 -0
  13. lib/options/js/{0.14.2 → 0.14.5}/das-popup.js +0 -0
  14. lib/options/js/{0.14.2 → 0.14.5}/image-comparison-slider.js +0 -0
  15. lib/options/js/{0.14.2 → 0.14.5}/page.js +0 -0
  16. lib/options/js/{0.14.2 → 0.14.5}/purge-cache.js +0 -0
  17. lib/options/js/{0.14.2 → 0.14.5}/sortable.min.js +0 -0
  18. lib/options/js/{0.14.2 → 0.14.5}/test-convert.js +0 -0
  19. lib/options/js/{0.14.2 → 0.14.5}/whitelist.js +9 -1
  20. lib/options/options/conversion-options/jpeg.inc +2 -2
  21. lib/options/options/conversion-options/png.inc +3 -2
  22. lib/options/options/general/image-types.inc +1 -3
  23. lib/options/page-messages.php +7 -6
  24. lib/options/submit.php +10 -2
  25. vendor/composer/installed.json +6 -6
  26. vendor/rosell-dk/webp-convert/build-scripts/PHPMerger.php +7 -3
  27. vendor/rosell-dk/webp-convert/build-scripts/build.php +20 -4
  28. vendor/rosell-dk/webp-convert/build-tests-webp-convert/WebPConvertBuildTest.php +11 -1
  29. vendor/rosell-dk/webp-convert/build-tests-wod/WodBuildTest.php +13 -2
  30. vendor/rosell-dk/webp-convert/src-build/webp-convert.inc +268 -106
  31. vendor/rosell-dk/webp-convert/src-build/webp-on-demand-1.inc +793 -16
  32. vendor/rosell-dk/webp-convert/src-build/webp-on-demand-2.inc +53 -668
  33. vendor/rosell-dk/webp-convert/src/Convert/Converters/AbstractConverter.php +7 -22
  34. vendor/rosell-dk/webp-convert/src/Convert/Converters/BaseTraits/SourceValidationTrait.php +0 -64
  35. vendor/rosell-dk/webp-convert/src/Exceptions/InvalidInput/InvalidImageTypeException.php +10 -0
  36. vendor/rosell-dk/webp-convert/src/Exceptions/InvalidInput/TargetNotFoundException.php +10 -0
  37. vendor/rosell-dk/webp-convert/src/Exceptions/InvalidInputException.php +10 -0
  38. vendor/rosell-dk/webp-convert/src/Helpers/InputValidator.php +61 -0
  39. vendor/rosell-dk/webp-convert/src/Helpers/MimeType.php +40 -0
  40. vendor/rosell-dk/webp-convert/src/Helpers/PathChecker.php +97 -0
  41. vendor/rosell-dk/webp-convert/src/Serve/Report.php +5 -3
  42. vendor/rosell-dk/webp-convert/src/Serve/ServeConvertedWebP.php +8 -13
  43. vendor/rosell-dk/webp-convert/src/Serve/ServeConvertedWebPWithErrorHandling.php +3 -2
  44. vendor/rosell-dk/webp-convert/src/Serve/ServeFile.php +11 -1
  45. vendor/rosell-dk/webp-convert/tests/Convert/Converters/AbstractConverterTest.php +27 -10
  46. vendor/rosell-dk/webp-convert/tests/Convert/Converters/BaseTraits/AutoQualityTraitTest.php +20 -12
  47. vendor/rosell-dk/webp-convert/tests/Convert/Converters/ConverterTestHelper.php +21 -5
  48. vendor/rosell-dk/webp-convert/tests/Convert/Converters/CwebpTest.php +16 -8
  49. vendor/rosell-dk/webp-convert/tests/Convert/Converters/EwwwTest.php +12 -4
  50. vendor/rosell-dk/webp-convert/tests/Convert/Converters/GdTest.php +12 -4
  51. vendor/rosell-dk/webp-convert/tests/Convert/Converters/GraphicsMagickTest.php +10 -2
  52. vendor/rosell-dk/webp-convert/tests/Convert/Converters/ImageMagickTest.php +10 -2
  53. vendor/rosell-dk/webp-convert/tests/Convert/Converters/StackTest.php +14 -4
  54. vendor/rosell-dk/webp-convert/tests/Convert/Converters/VipsTest.php +12 -3
  55. vendor/rosell-dk/webp-convert/tests/Convert/Converters/WPCTest.php +36 -16
  56. vendor/rosell-dk/webp-convert/tests/Serve/ServeConvertedWebPTest.php +34 -22
  57. vendor/rosell-dk/webp-convert/tests/Serve/ServeFileTest.php +21 -8
  58. vendor/rosell-dk/webp-convert/tests/WebPConvertTest.php +2 -1
  59. webp-express.php +1 -1
  60. wod/webp-on-demand.php +25 -3
  61. wod/webp-realizer.php +7 -1
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.4
8
Requires PHP: 5.6
9
License: GPLv3
10
License URI: https://www.gnu.org/licenses/gpl-3.0.html
@@ -12,7 +12,7 @@ License URI: https://www.gnu.org/licenses/gpl-3.0.html
12
Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP.
13
14
== Description ==
15
- [](http://coderisk.com/wp/plugin/webp-express/RIPS-NAA8tMia3z)
16
Almost 4 out of 5 mobile users use a browser that is able to display webp images. Yet, on most websites, they are served jpeg images, which are typically double the size of webp images for a given quality. What a waste of bandwidth! This plugin was created to help remedy that situation. With little effort, Wordpress admins can have their site serving autogenerated webp images to browsers that supports it, while still serving jpeg and png files to browsers that does not support webp.
17
18
### The image converter
@@ -605,6 +605,11 @@ Easy enough! - [Go here!](https://ko-fi.com/rosell). Or [here](https://buymeacof
605
606
== Changelog ==
607
608
= 0.14.4 =
609
*(released: 18 jun 2019)*
610
@@ -819,6 +824,9 @@ For older releases, check out changelog.txt
819
820
== Upgrade Notice ==
821
822
= 0.14.4 =
823
Now bundles with multiple cwebp binaries for linux for systems where 1.0.2 fails.
824
4
Tags: webp, images, performance
5
Requires at least: 4.0
6
Tested up to: 5.2
7
+ Stable tag: 0.14.5
8
Requires PHP: 5.6
9
License: GPLv3
10
License URI: https://www.gnu.org/licenses/gpl-3.0.html
12
Serve autogenerated WebP images instead of jpeg/png to browsers that supports WebP.
13
14
== Description ==
15
+
16
Almost 4 out of 5 mobile users use a browser that is able to display webp images. Yet, on most websites, they are served jpeg images, which are typically double the size of webp images for a given quality. What a waste of bandwidth! This plugin was created to help remedy that situation. With little effort, Wordpress admins can have their site serving autogenerated webp images to browsers that supports it, while still serving jpeg and png files to browsers that does not support webp.
17
18
### The image converter
605
606
== Changelog ==
607
608
+ = 0.14.5 =
609
+ *(released: 20 jun 2019)*
610
+
611
+ * Various fixes
612
+
613
= 0.14.4 =
614
*(released: 18 jun 2019)*
615
824
825
== Upgrade Notice ==
826
827
+ = 0.14.5 =
828
+ Various fixes
829
+
830
= 0.14.4 =
831
Now bundles with multiple cwebp binaries for linux for systems where 1.0.2 fails.
832
composer.json CHANGED
@@ -4,7 +4,7 @@
4
"type": "project",
5
"license": "MIT",
6
"require": {
7
- "rosell-dk/webp-convert": "^2.0.5",
8
"rosell-dk/webp-convert-cloud-service": "^2.0.0",
9
"rosell-dk/dom-util-for-webp": "^0.3.0"
10
},
4
"type": "project",
5
"license": "MIT",
6
"require": {
7
+ "rosell-dk/webp-convert": "^2.1.0",
8
"rosell-dk/webp-convert-cloud-service": "^2.0.0",
9
"rosell-dk/dom-util-for-webp": "^0.3.0"
10
},
composer.lock CHANGED
@@ -118,16 +118,16 @@
118
},
119
{
120
"name": "rosell-dk/webp-convert",
121
- "version": "2.0.5",
122
"source": {
123
"type": "git",
124
"url": "https://github.com/rosell-dk/webp-convert.git",
125
- "reference": "5d69bbb048334badffca2983511800604d650da3"
126
},
127
"dist": {
128
"type": "zip",
129
- "url": "https://api.github.com/repos/rosell-dk/webp-convert/zipball/5d69bbb048334badffca2983511800604d650da3",
130
- "reference": "5d69bbb048334badffca2983511800604d650da3",
131
"shasum": ""
132
},
133
"require": {
@@ -190,7 +190,7 @@
190
"png",
191
"png2webp"
192
],
193
- "time": "2019-06-18T12:27:33+00:00"
194
},
195
{
196
"name": "rosell-dk/webp-convert-cloud-service",
118
},
119
{
120
"name": "rosell-dk/webp-convert",
121
+ "version": "2.1.0",
122
"source": {
123
"type": "git",
124
"url": "https://github.com/rosell-dk/webp-convert.git",
125
+ "reference": "b142cfc2b2b8a1930b3b394c40f0923871ef2abd"
126
},
127
"dist": {
128
"type": "zip",
129
+ "url": "https://api.github.com/repos/rosell-dk/webp-convert/zipball/b142cfc2b2b8a1930b3b394c40f0923871ef2abd",
130
+ "reference": "b142cfc2b2b8a1930b3b394c40f0923871ef2abd",
131
"shasum": ""
132
},
133
"require": {
190
"png",
191
"png2webp"
192
],
193
+ "time": "2019-06-20T12:12:13+00:00"
194
},
195
{
196
"name": "rosell-dk/webp-convert-cloud-service",
lib/classes/AlterHtmlInit.php CHANGED
@@ -110,7 +110,7 @@ class AlterHtmlInit
110
111
/*
112
TODO:
113
- check out these hooks (used by Jecpack, in class.photon.php)
114
115
// Images in post content and galleries
116
add_filter( 'the_content', array( __CLASS__, 'filter_the_content' ), 999999 );
110
111
/*
112
TODO:
113
+ check out these hooks (used by Jetpack, in class.photon.php)
114
115
// Images in post content and galleries
116
add_filter( 'the_content', array( __CLASS__, 'filter_the_content' ), 999999 );
lib/classes/Convert.php CHANGED
@@ -29,6 +29,8 @@ class Convert
29
30
public static function convertFile($source, $config = null, $convertOptions = null, $converter = null)
31
{
32
if (is_null($config)) {
33
$config = Config::loadConfigAndFix();
34
}
@@ -41,6 +43,7 @@ class Convert
41
}*/
42
43
$destination = self::getDestination($source, $config);
44
45
$logDir = Paths::getWebPExpressContentDirAbs() . '/log';
46
@@ -56,6 +59,7 @@ class Convert
56
57
public static function findSource($destination, &$config = null)
58
{
59
if (is_null($config)) {
60
$config = Config::loadConfigAndFix();
61
}
29
30
public static function convertFile($source, $config = null, $convertOptions = null, $converter = null)
31
{
32
+ $source = ConvertHelperIndependent::sanitizeAbsFilePath($source);
33
+
34
if (is_null($config)) {
35
$config = Config::loadConfigAndFix();
36
}
43
}*/
44
45
$destination = self::getDestination($source, $config);
46
+ $destination = ConvertHelperIndependent::sanitizeAbsFilePath($destination);
47
48
$logDir = Paths::getWebPExpressContentDirAbs() . '/log';
49
59
60
public static function findSource($destination, &$config = null)
61
{
62
+ $destination = ConvertHelperIndependent::sanitizeAbsFilePath($destination);
63
if (is_null($config)) {
64
$config = Config::loadConfigAndFix();
65
}
lib/classes/ConvertHelperIndependent.php CHANGED
@@ -72,7 +72,7 @@ class ConvertHelperIndependent
72
/**
73
* Get destination from source (and some configurations)
74
*/
75
- public static function getDestination($source, $destinationFolder, $destinationExt, $webExpressContentDirAbs, $uploadDirAbs)
76
{
77
if (self::storeMingledOrNot($source, $destinationFolder, $uploadDirAbs)) {
78
if ($destinationExt == 'append') {
@@ -102,6 +102,43 @@ class ConvertHelperIndependent
102
}
103
}
104
105
/**
106
* Find source corresponding to destination, separate
107
* We can rely on destinationExt being "append" for separate
@@ -132,6 +169,7 @@ class ConvertHelperIndependent
132
$source = $sourceRel;
133
$source = preg_replace('/\\.(webp)#x2F;', '', $source);
134
}
135
if (!@file_exists($source)) {
136
return false;
137
}
@@ -234,7 +272,7 @@ APACHE
234
235
$text = preg_replace('#' . preg_quote($_SERVER["DOCUMENT_ROOT"]) . '#', '[doc-root]', $text);
236
237
- $text = 'WebP Express 0.14.4. ' . $msgTop . ', ' . date("Y-m-d H:i:s") . "\n\r\n\r" . $text;
238
239
$logFile = self::getLogFilename($source, $logDir);
240
72
/**
73
* Get destination from source (and some configurations)
74
*/
75
+ private static function getDestinationUnsanitized($source, $destinationFolder, $destinationExt, $webExpressContentDirAbs, $uploadDirAbs)
76
{
77
if (self::storeMingledOrNot($source, $destinationFolder, $uploadDirAbs)) {
78
if ($destinationExt == 'append') {
102
}
103
}
104
105
+ /**
106
+ * Sanitize absolute file path.
107
+ *
108
+ * Make sure that file path is not a stream wrapper.
109
+ * This protects against Phar Deserialization and possibly other nasty tricks
110
+ * https://blog.ripstech.com/2018/new-php-exploitation-technique/
111
+ * https://www.php.net/manual/en/wrappers.phar.php
112
+ *
113
+ * We also prevent directory traversal, as we do not expect any traversal in our absolute paths.
114
+ *
115
+ * @param string $absFilePath
116
+ * @return string sanitized file path
117
+ */
118
+ public static function sanitizeAbsFilePath($absFilePath) {
119
+ // Remove NUL characters (https://st-g.de/2011/04/doing-filename-checks-securely-in-PHP)
120
+ $absFilePath = str_replace(chr(0), '', $absFilePath);
121
+
122
+ // remove "../"
123
+ $absFilePath = preg_replace('#\.\.\/#', '', $absFilePath);
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
+ return $absFilePath;
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
* Find source corresponding to destination, separate
144
* We can rely on destinationExt being "append" for separate
169
$source = $sourceRel;
170
$source = preg_replace('/\\.(webp)#x2F;', '', $source);
171
}
172
+ $source = self::sanitizeAbsFilePath($source);
173
if (!@file_exists($source)) {
174
return false;
175
}
272
273
$text = preg_replace('#' . preg_quote($_SERVER["DOCUMENT_ROOT"]) . '#', '[doc-root]', $text);
274
275
+ $text = 'WebP Express 0.14.5. ' . $msgTop . ', ' . date("Y-m-d H:i:s") . "\n\r\n\r" . $text;
276
277
$logFile = self::getLogFilename($source, $logDir);
278
lib/classes/ConvertersHelper.php CHANGED
@@ -156,7 +156,7 @@ class ConvertersHelper
156
* Get working and active converters.
157
*
158
* @param object $config
159
- * @return array
160
*/
161
public static function getWorkingAndActiveConverters($config)
162
{
156
* Get working and active converters.
157
*
158
* @param object $config
159
+ * @return array Array of converter objects
160
*/
161
public static function getWorkingAndActiveConverters($config)
162
{
lib/options/enqueue_scripts.php CHANGED
@@ -8,8 +8,8 @@ use \WebPExpress\Paths;
8
include_once __DIR__ . '/../classes/Config.php';
9
use \WebPExpress\Config;
10
11
- $ver = '1';
12
- $jsDir = 'js/0.14.2';
13
14
if (!function_exists('webp_express_add_inline_script')) {
15
function webp_express_add_inline_script($id, $script, $position) {
8
include_once __DIR__ . '/../classes/Config.php';
9
use \WebPExpress\Config;
10
11
+ $ver = '1'; // note: Minimum 1
12
+ $jsDir = 'js/0.14.5';
13
14
if (!function_exists('webp_express_add_inline_script')) {
15
function webp_express_add_inline_script($id, $script, $position) {
lib/options/js/0.14.2/whitelist_old.js DELETED
@@ -1,189 +0,0 @@
1
- function updateWhitelistInputValue() {
2
- //var val = [];
3
-
4
- document.getElementsByName('whitelist')[0].value = JSON.stringify(window.whitelist);
5
- }
6
-
7
- function openPasswordPopup(i) {
8
- window.currentWhitelistPassword = i;
9
- document.getElementById('whitelist_enter_password').value = '';
10
- document.getElementById('whitelist_hash_password').checked = false;
11
-
12
- var options = '#TB_inline?inlineId=whitelist_enter_password_popup&width=400&height=300';
13
- tb_show("Enter password", options);
14
-
15
- }
16
- function setPassword() {
17
-
18
- var i = window.currentWhitelistPassword;
19
- var password = document.getElementById('whitelist_enter_password').value;
20
- var hashPassword = document.getElementById('whitelist_hash_password').checked;
21
-
22
- //var password = window.prompt('Enter password');
23
-
24
- window.whitelist[i]['password'] = '';
25
- window.whitelist[i]['new_password'] = password;
26
- window.whitelist[i]['hash_new_password'] = hashPassword;
27
-
28
- setWhitelistHTML();
29
- tb_remove();
30
- }
31
-
32
- function setWhitelistHTML() {
33
- var s = '';
34
- s+='<table class="whitelist" id="whitelist_table">';
35
- s+='<tr>';
36
- s+='<th>Site<span id="whitelist_site_helptext2"></span></th>'
37
- s+='<th>Password<span id="password_helptext2"></span></th>'
38
- //s+='<th>Salt<span id="salt_helptext2"></span></th>'
39
- //s+='<th>Limit<span id="whitelist_quota_helptext2"></span></th>'
40
- s+='</tr>';
41
- s=='</th></tr>';
42
- if (window.whitelist) {
43
- for (var i=0; i<window.whitelist.length; i++) {
44
- s+='<tr>';
45
- s+='<td><input type="text" size="15" id="whitelist-site-' + i + '" placeholder="hostname or IP"></input></td>';
46
- //s+='<td><input type="text" size="10" id="whitelist-password-' + i + '"></input></td>';
47
-
48
- s+='<td><a href="javascript:openPasswordPopup(' + i + ')">Click to ' +
49
- ((window.whitelist[i]['password'] || window.whitelist[i]['new_password']) ? 'change' : 'set')
50
- + '</td>';
51
- //s+='<td>' + (window.whitelist[i]['salt'] || '') + '</td>';
52
-
53
- //s+='<td class="quota"><nobr><input type="text" size="3" id="whitelist-quota-' + i + '"></input><i> per hour</i></nobr></td>';
54
- //s+='<td class="buttons"><button type="button" class="button button-secondary" onclick="whitelistRemoveRow(' + i + ')">remove</button></td>';
55
- s+='<td class="remove"><a href="javascript:whitelistRemoveRow(' + i + ')">remove row</a></td>';
56
- s+='</tr>';
57
- }
58
- }
59
- s+='<tr><td colspan="3" class="whitelist-add-site">';
60
- s+='<button type="button" class="button button-secondary" id="whitelist_add" onclick="whitelistAddSite()">+ Add site</button>';
61
- s+='</td></tr>';
62
- s+='</table>';
63
-
64
- document.getElementById('whitelist_div').innerHTML = s;
65
-
66
- if (window.whitelist) {
67
- for (var i=0; i<window.whitelist.length; i++) {
68
- document.getElementById('whitelist-site-' + i).value = window.whitelist[i]['site'];
69
- //document.getElementById('whitelist-password-hashed' + i).value = window.whitelist[i]['password_hashed'];
70
- //document.getElementById('whitelist-quota-' + i).value = window.whitelist[i]['quota'];
71
- }
72
- }
73
- updateWhitelistInputValue();
74
-
75
- document.getElementById('password_helptext2').innerHTML = document.getElementById('password_helptext').innerHTML;
76
- document.getElementById('whitelist_site_helptext2').innerHTML = document.getElementById('whitelist_site_helptext').innerHTML;
77
- //document.getElementById('whitelist_quota_helptext2').innerHTML = document.getElementById('whitelist_quota_helptext').innerHTML;
78
-
79
- }
80
-
81
- function whitelistStartPolling() {
82
-
83
- jQuery.post(window.ajaxurl, {
84
- 'action': 'webpexpress_start_listening',
85
- }, function(response) {
86
- window.whitelistTid = window.setInterval(function() {
87
- jQuery.post(window.ajaxurl, {
88
- 'action': 'webpexpress_get_request',
89
- }, function(response) {
90
- if (response && (response.substr(0,1) == '{')) {
91
- var r = JSON.parse(response);
92
- window.webpexpress_incoming_request = r;
93
- //console.log(r);
94
- window.clearInterval(window.whitelistTid);
95
- closeDasPopup();
96
-
97
- // Show request
98
- openDasPopup('whitelist_accept_request', 300, 200);
99
-
100
- var s = '';
101
- s += 'Website: ' + r['website'] + '<br>';
102
- s += 'IP: ' + r['ip'] + '<br>';
103
-
104
- document.getElementById('request_details').innerHTML = s;
105
- } else {
106
- console.log('Got this from the server: ' + response);
107
- }
108
- }
109
- );
110
- }, 2000);
111
- }
112
- );
113
- }
114
-
115
- function whitelistCancelListening() {
116
- jQuery.post(window.ajaxurl, {
117
- 'action': 'webpexpress_stop_listening',
118
- }, function(response) {}
119
- );
120
- closeDasPopup();
121
- }
122
-
123
- function whitelistAcceptRequest() {
124
- whitelistCancelListening();
125
-
126
- var r = window.webpexpress_incoming_request;
127
- window.whitelist.push({
128
- id: r['website'],
129
- new_password: r['password'],
130
- // new_password: '',
131
- //quota: 60
132
- });
133
- setWhitelistHTML();
134
- }
135
-
136
- function whitelistDenyRequest() {
137
- whitelistCancelListening();
138
- }
139
-
140
- function whitelistAddSite() {
141
- whitelistStartPolling();
142
- openDasPopup('whitelist_listen_popup', 400, 300);
143
- }
144
-
145
- function whitelistAdd() {
146
- }
147
-
148
- function whitelistRemoveRow(i) {
149
- window.whitelist.splice(i, 1);
150
- setWhitelistHTML();
151
- }
152
-
153
- document.addEventListener('DOMContentLoaded', function() {
154
-
155
- window.setInterval(function() {
156
- var el = document.getElementById('animated_dots');
157
- if (el.innerText == '....') {
158
- el.innerText = '';
159
- } else {
160
- el.innerText += '.';
161
- }
162
- }, 500);
163
-
164
- setWhitelistHTML();
165
-
166
- document.getElementById('whitelist_div').addEventListener("input", function(e){
167
- console.log(e);
168
- for (var i=0; i<window.whitelist.length; i++) {
169
- window.whitelist[i]['site'] = document.getElementById('whitelist-site-' + i).value;
170
- //window.whitelist[i]['password_hashed'] = document.getElementById('whitelist-password-hashed' + i).value;
171
- //window.whitelist[i]['quota'] = document.getElementById('whitelist-quota-' + i).value;
172
- }
173
- updateWhitelistInputValue();
174
- });
175
-
176
- document.getElementById('whitelist_table').addEventListener("change", function(e){
177
- // Clean up
178
- for (var i=0; i<window.whitelist.length; i++) {
179
- var s = document.getElementById('whitelist-site-' + i).value;
180
- var s2 = s.replace(/^https?:\/\//, '');
181
- if (s2 != s) {
182
- e.target.value = s2;
183
- window.whitelist[i][0] = s2;
184
- updateWhitelistInputValue();
185
- }
186
- }
187
- });
188
-
189
- });
lib/options/js/{0.14.2 → 0.14.5}/authorized_sites_bak.js RENAMED
File without changes
lib/options/js/{0.14.2 → 0.14.5}/bulk-convert.js RENAMED
File without changes
lib/options/js/{0.14.2 → 0.14.5}/converters.js RENAMED
File without changes
lib/options/js/{0.14.2 → 0.14.5}/das-popup.js RENAMED
File without changes
lib/options/js/{0.14.2 → 0.14.5}/image-comparison-slider.js RENAMED
File without changes
lib/options/js/{0.14.2 → 0.14.5}/page.js RENAMED
File without changes
lib/options/js/{0.14.2 → 0.14.5}/purge-cache.js RENAMED
File without changes
lib/options/js/{0.14.2 → 0.14.5}/sortable.min.js RENAMED
File without changes
lib/options/js/{0.14.2 → 0.14.5}/test-convert.js RENAMED
File without changes
lib/options/js/{0.14.2 → 0.14.5}/whitelist.js RENAMED
@@ -87,6 +87,14 @@ function whitelistRemoveEntry(i) {
87
window.whitelist.splice(i, 1);
88
whitelistSetHTML();
89
}
90
function whitelistSetHTML() {
91
updateWhitelistInputValue();
92
var s = '';
@@ -96,7 +104,7 @@ function whitelistSetHTML() {
96
s+='<ul>';
97
for (var i=0; i<window.whitelist.length; i++) {
98
s+='<li>';
99
- s+=window.whitelist[i]['label'];
100
s+='<div class="whitelist-links">'
101
s+='<a href="javascript:whitelistEditEntry(' + i + ')">edit</a>';
102
s+='<a href="javascript:whitelistRemoveEntry(' + i + ')">remove</a>';
87
window.whitelist.splice(i, 1);
88
whitelistSetHTML();
89
}
90
+
91
+ function whitelistEncodeHTMLEntities(s)
92
+ {
93
+ return s.replace(/./gm, function(s) {
94
+ return "&#" + s.charCodeAt(0) + ";";
95
+ });
96
+ }
97
+
98
function whitelistSetHTML() {
99
updateWhitelistInputValue();
100
var s = '';
104
s+='<ul>';
105
for (var i=0; i<window.whitelist.length; i++) {
106
s+='<li>';
107
+ s+= whitelistEncodeHTMLEntities(window.whitelist[i]['label']);
108
s+='<div class="whitelist-links">'
109
s+='<a href="javascript:whitelistEditEntry(' + i + ')">edit</a>';
110
s+='<a href="javascript:whitelistRemoveEntry(' + i + ')">remove</a>';
lib/options/options/conversion-options/jpeg.inc CHANGED
@@ -64,7 +64,7 @@ png
64
'<p>If you select the "Same as the jpeg" option, WebP Express will try to determine the quality of ' .
65
'the jpeg and use that for the webp - unless the quality is higher than the limit entered, in which ' .
66
'case the limit is used.</p>' .
67
- '<p>Ouality detection requires imagick or gmagick (not neccessarily compiled with webp). ' .
68
'In case quality detection is not available, the fallback quality is used.</p>' .
69
(
70
$canDetectQuality ?
@@ -110,7 +110,7 @@ png
110
echo helpIcon(
111
'Fallback quality in case quality detection is not available or should fail for some reason (which has yet to be seen). ' .
112
(
113
- !$canDetectQuality ?
114
'You have quality detection working, btw, so this setting will probably never be used' :
115
'<i>You do not have quality detection working, btw</i> - which means that all conversions will have the fixed quality entered here'
116
)
64
'<p>If you select the "Same as the jpeg" option, WebP Express will try to determine the quality of ' .
65
'the jpeg and use that for the webp - unless the quality is higher than the limit entered, in which ' .
66
'case the limit is used.</p>' .
67
+ '<p>Ouality detection requires imagick, imagemagick or gmagick (not neccessarily compiled with webp). ' .
68
'In case quality detection is not available, the fallback quality is used.</p>' .
69
(
70
$canDetectQuality ?
110
echo helpIcon(
111
'Fallback quality in case quality detection is not available or should fail for some reason (which has yet to be seen). ' .
112
(
113
+ $canDetectQuality ?
114
'You have quality detection working, btw, so this setting will probably never be used' :
115
'<i>You do not have quality detection working, btw</i> - which means that all conversions will have the fixed quality entered here'
116
)
lib/options/options/conversion-options/png.inc CHANGED
@@ -41,8 +41,9 @@
41
<input type="text" size=3 name="png-quality" value="<?php echo $config['png-quality'] ?>" style="text-align:right; padding-left:0px; padding-right:4px; width:34px">
42
<?php
43
echo helpIcon(
44
- 'You probably want to set this value a bit higher than the quality for JPEGs. PNGs are often used for icons and graphics, ' .
45
- 'which perhaps demands a bit more quality than photos, which jpegs often are used for.'
46
);
47
?>
48
<label style="margin-left:10px">
41
<input type="text" size=3 name="png-quality" value="<?php echo $config['png-quality'] ?>" style="text-align:right; padding-left:0px; padding-right:4px; width:34px">
42
<?php
43
echo helpIcon(
44
+ '<p>You probably want to set this value a bit higher than the quality for JPEGs. PNGs are often used for icons and graphics, ' .
45
+ 'which perhaps demands a bit more quality than photos, which jpegs often are used for.</p>' .
46
+ '<p>Note that there is no "Same as PNG" option available here as PNGs are lossless</p>'
47
);
48
?>
49
<label style="margin-left:10px">
lib/options/options/general/image-types.inc CHANGED
@@ -18,10 +18,8 @@ switch ($config['operation-mode']) {
18
}
19
if ($config['operation-mode'] == 'no-conversion') {
20
echo helpIcon('<p>Select which types of images you would like to redirect and/or have altered in the HTML</p>');
21
-
22
} else {
23
- echo helpIcon('<p>Beware that the Gd conversion method cannot handle transparency for PNGs. PNG conversions havent been tested much yet. Please report any problems with PNG images <a target="_blank" href="https://github.com/rosell-dk/webp-convert/issues/42">here</a></p><p>The term "send" means an internal redirect on the server (not to be confused with an external redirect, such as a 301 or 302 response)</p>');
24
-
25
}
26
echo '</th><td>';
27
18
}
19
if ($config['operation-mode'] == 'no-conversion') {
20
echo helpIcon('<p>Select which types of images you would like to redirect and/or have altered in the HTML</p>');
21
} else {
22
+ echo helpIcon('<p>Beware that some has reported problems with Gd and PNG, but it has not been pinned down when it happens. It is probably on older versions of Gd. Please report any problems with Gd!</p>');
23
}
24
echo '</th><td>';
25
lib/options/page-messages.php CHANGED
@@ -17,7 +17,6 @@ use \WebPExpress\State;
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
-
21
if ((!State::getState('configured', false))) {
22
include __DIR__ . "/page-welcome.php";
23
}
@@ -236,11 +235,13 @@ if ($config['image-types'] == 3) {
236
$workingConverters = ConvertersHelper::getWorkingAndActiveConverters($config);
237
if (count($workingConverters) == 1) {
238
if (ConvertersHelper::getConverterId($workingConverters[0]) == 'gd') {
239
- Messenger::printMessage(
240
- 'warning',
241
- 'You have enabled PNGs, but configured Gd to skip PNGs, and Gd is your only active working converter. ' .
242
- 'This is a bad combination!'
243
- );
244
}
245
}
246
}
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
}
235
$workingConverters = ConvertersHelper::getWorkingAndActiveConverters($config);
236
if (count($workingConverters) == 1) {
237
if (ConvertersHelper::getConverterId($workingConverters[0]) == 'gd') {
238
+ if (isset($workingConverters[0]['options']['skip-pngs']) && $workingConverters[0]['options']['skip-pngs']) {
239
+ Messenger::printMessage(
240
+ 'warning',
241
+ 'You have enabled PNGs, but configured Gd to skip PNGs, and Gd is your only active working converter. ' .
242
+ 'This is a bad combination!'
243
+ );
244
+ }
245
}
246
}
247
}
lib/options/submit.php CHANGED
@@ -10,7 +10,6 @@ use \WebPExpress\HTAccess;
10
use \WebPExpress\Messenger;
11
use \WebPExpress\Paths;
12
13
-
14
check_admin_referer('webpexpress-save-settings-nonce');
15
16
DismissableMessages::dismissMessage('0.14.0/say-hello-to-vips');
@@ -133,9 +132,18 @@ if ($_POST['operation-mode'] != 'no-conversion') {
133
// Web Service
134
// -------------
135
136
$config['web-service'] = [
137
'enabled' => isset($_POST['web-service-enabled']),
138
- 'whitelist' => json_decode(wp_unslash($_POST['whitelist']), true)
139
];
140
141
// Set existing api keys in web service (we removed them from the json array, for security purposes)
10
use \WebPExpress\Messenger;
11
use \WebPExpress\Paths;
12
13
check_admin_referer('webpexpress-save-settings-nonce');
14
15
DismissableMessages::dismissMessage('0.14.0/say-hello-to-vips');
132
// Web Service
133
// -------------
134
135
+ $whitelistPosted = json_decode(wp_unslash($_POST['whitelist']), true);
136
+
137
+ // Sanitize whitelist
138
+ foreach ($whitelistPosted as &$whitelist) {
139
+ $whitelist['label'] = sanitize_text_field($whitelist['label']);
140
+ $whitelist['ip'] = sanitize_text_field($whitelist['ip']);
141
+ $whitelist['api-key'] = sanitize_text_field($whitelist['api-key']);
142
+ }
143
+
144
$config['web-service'] = [
145
'enabled' => isset($_POST['web-service-enabled']),
146
+ 'whitelist' => $whitelistPosted
147
];
148
149
// Set existing api keys in web service (we removed them from the json array, for security purposes)
vendor/composer/installed.json CHANGED
@@ -115,17 +115,17 @@
115
},
116
{
117
"name": "rosell-dk/webp-convert",
118
- "version": "2.0.5",
119
- "version_normalized": "2.0.5.0",
120
"source": {
121
"type": "git",
122
"url": "https://github.com/rosell-dk/webp-convert.git",
123
- "reference": "5d69bbb048334badffca2983511800604d650da3"
124
},
125
"dist": {
126
"type": "zip",
127
- "url": "https://api.github.com/repos/rosell-dk/webp-convert/zipball/5d69bbb048334badffca2983511800604d650da3",
128
- "reference": "5d69bbb048334badffca2983511800604d650da3",
129
"shasum": ""
130
},
131
"require": {
@@ -143,7 +143,7 @@
143
"ext-vips": "to use Vips extension for converting.",
144
"php-stan/php-stan": "Suggested for dev, in order to analyse code before committing"
145
},
146
- "time": "2019-06-18T12:27:33+00:00",
147
"type": "library",
148
"extra": {
149
"scripts-descriptions": {
115
},
116
{
117
"name": "rosell-dk/webp-convert",
118
+ "version": "2.1.0",
119
+ "version_normalized": "2.1.0.0",
120
"source": {
121
"type": "git",
122
"url": "https://github.com/rosell-dk/webp-convert.git",
123
+ "reference": "b142cfc2b2b8a1930b3b394c40f0923871ef2abd"
124
},
125
"dist": {
126
"type": "zip",
127
+ "url": "https://api.github.com/repos/rosell-dk/webp-convert/zipball/b142cfc2b2b8a1930b3b394c40f0923871ef2abd",
128
+ "reference": "b142cfc2b2b8a1930b3b394c40f0923871ef2abd",
129
"shasum": ""
130
},
131
"require": {
143
"ext-vips": "to use Vips extension for converting.",
144
"php-stan/php-stan": "Suggested for dev, in order to analyse code before committing"
145
},
146
+ "time": "2019-06-20T12:12:13+00:00",
147
"type": "library",
148
"extra": {
149
"scripts-descriptions": {
vendor/rosell-dk/webp-convert/build-scripts/PHPMerger.php CHANGED
@@ -28,16 +28,20 @@ class PhpMerger
28
29
// load dirs in defined order. No recursion.
30
foreach ($def['dirs'] as $dir) {
31
- $dirAbs = __DIR__ . '/' . $def['root'] . '/' . $dir;
32
$files = glob($dirAbs . '/*.php');
33
foreach ($files as $file) {
34
// only require files that begins with uppercase (A-Z)
35
if (preg_match('/\/[A-Z][a-zA-Z]*\.php/', $file)) {
36
- $file = str_replace(__DIR__ . '/' . $def['root'], '', $file);
37
$file = str_replace('./', '', $file);
38
39
//echo $file . "\n";
40
- self::add_to_queue($def['root'] . $file);
41
}
42
}
43
}
28
29
// load dirs in defined order. No recursion.
30
foreach ($def['dirs'] as $dir) {
31
+ $dirAbs = __DIR__ . '/' . $def['dir-root'] . '/' . $dir;
32
+ if (!is_dir($dirAbs)) {
33
+ echo 'Dir not found: ' . $dirAbs;
34
+ return false;
35
+ }
36
$files = glob($dirAbs . '/*.php');
37
foreach ($files as $file) {
38
// only require files that begins with uppercase (A-Z)
39
if (preg_match('/\/[A-Z][a-zA-Z]*\.php/', $file)) {
40
+ $file = str_replace(__DIR__ . '/' . $def['dir-root'], '', $file);
41
$file = str_replace('./', '', $file);
42
43
//echo $file . "\n";
44
+ self::add_to_queue($def['dir-root'] . $file);
45
}
46
}
47
}
vendor/rosell-dk/webp-convert/build-scripts/build.php CHANGED
@@ -16,8 +16,15 @@ $filesInWod1 = [
16
'/Serve/ServeConvertedWebP.php',
17
'/Serve/ServeConvertedWebPWithErrorHandling.php',
18
'/Serve/ServeFile.php',
19
'/Serve/Header.php',
20
- '/WebPConvert.php'
21
];
22
23
// Build "webp-on-demand-1.php" (for non-composer projects)
@@ -29,8 +36,11 @@ $success = PhpMerger::generate([
29
[
30
'root' => '../src/',
31
'files' => $filesInWod1,
32
'dirs' => [
33
// dirs will be required in specified order. There is no recursion, so you need to specify subdirs as well.
34
//'.',
35
]
36
]
@@ -39,11 +49,11 @@ $success = PhpMerger::generate([
39
if (!$success) {
40
exit(255);
41
}
42
-
43
$jobsEverything = [
44
[
45
'root' => '../src/',
46
-
47
'files' => [
48
// put base classes here
49
'Options/Option.php',
@@ -63,8 +73,9 @@ $jobsEverything = [
63
'Options',
64
'Convert/Converters/BaseTraits',
65
'Convert/Converters/ConverterTraits',
66
- 'Convert/BaseConverters',
67
'Convert/Converters',
68
'Convert/Exceptions',
69
'Convert/Exceptions/ConversionFailed',
70
'Convert/Exceptions/ConversionFailed/ConverterNotOperational',
@@ -73,6 +84,7 @@ $jobsEverything = [
73
'Convert/Helpers',
74
'Convert',
75
'Exceptions',
76
'Helpers',
77
'Loggers',
78
'Serve',
@@ -83,6 +95,7 @@ $jobsEverything = [
83
],
84
[
85
'root' => '../vendor/rosell-dk/image-mime-type-guesser/src/',
86
87
'files' => [
88
// put base classes here
@@ -111,6 +124,9 @@ if (!$success) {
111
$jobsWod2 = $jobsEverything;
112
$jobsWod2[0]['exclude'] = $filesInWod1;
113
114
// Build "webp-on-demand-2.inc"
115
// It must contain everything EXCEPT those classes that were included in 'webp-on-demand-1.inc'
116
$success = PhpMerger::generate([
16
'/Serve/ServeConvertedWebP.php',
17
'/Serve/ServeConvertedWebPWithErrorHandling.php',
18
'/Serve/ServeFile.php',
19
+ '/Exceptions/WebPConvertException.php',
20
+ '/Exceptions/InvalidInputException.php',
21
+ '/Exceptions/InvalidInput/InvalidImageTypeException.php',
22
+ '/Exceptions/InvalidInput/TargetNotFoundException.php',
23
+ '/Helpers/PathChecker.php',
24
+ '/Helpers/InputValidator.php',
25
'/Serve/Header.php',
26
+ '/WebPConvert.php',
27
+ //'../vendor/rosell-dk/image-mime-type-guesser/src/Detectors/AbstractDetector.php',
28
];
29
30
// Build "webp-on-demand-1.php" (for non-composer projects)
36
[
37
'root' => '../src/',
38
'files' => $filesInWod1,
39
+ 'dir-root' => '..',
40
'dirs' => [
41
// dirs will be required in specified order. There is no recursion, so you need to specify subdirs as well.
42
+ 'vendor/rosell-dk/image-mime-type-guesser/src',
43
+ 'vendor/rosell-dk/image-mime-type-guesser/src/Detectors',
44
//'.',
45
]
46
]
49
if (!$success) {
50
exit(255);
51
}
52
+ //exit(0);
53
$jobsEverything = [
54
[
55
'root' => '../src/',
56
+ 'dir-root' => '../src',
57
'files' => [
58
// put base classes here
59
'Options/Option.php',
73
'Options',
74
'Convert/Converters/BaseTraits',
75
'Convert/Converters/ConverterTraits',
76
'Convert/Converters',
77
+ 'Convert/Converters/BaseTraits',
78
+ 'Convert/Converters/ConverterTraits',
79
'Convert/Exceptions',
80
'Convert/Exceptions/ConversionFailed',
81
'Convert/Exceptions/ConversionFailed/ConverterNotOperational',
84
'Convert/Helpers',
85
'Convert',
86
'Exceptions',
87
+ 'Exceptions/InvalidInput',
88
'Helpers',
89
'Loggers',
90
'Serve',
95
],
96
[
97
'root' => '../vendor/rosell-dk/image-mime-type-guesser/src/',
98
+ 'dir-root' => '../vendor/rosell-dk/image-mime-type-guesser/src',
99
100
'files' => [
101
// put base classes here
124
$jobsWod2 = $jobsEverything;
125
$jobsWod2[0]['exclude'] = $filesInWod1;
126
127
+ // remove second job (ImageMimeTypeGuesser is included in wod-1)
128
+ unset($jobsWod2[1]);
129
+
130
// Build "webp-on-demand-2.inc"
131
// It must contain everything EXCEPT those classes that were included in 'webp-on-demand-1.inc'
132
$success = PhpMerger::generate([
vendor/rosell-dk/webp-convert/build-tests-webp-convert/WebPConvertBuildTest.php CHANGED
@@ -15,11 +15,21 @@ use PHPUnit\Framework\TestCase;
15
class WebPConvertBuildTest extends TestCase
16
{
17
18
public function testWebPConvertBuildNotCompletelyBroken()
19
{
20
require __DIR__ . '/../src-build/webp-convert.inc';
21
22
- $source = __DIR__ . '/../tests/images/png-without-extension';
23
$this->assertTrue(file_exists($source));
24
25
ob_start();
15
class WebPConvertBuildTest extends TestCase
16
{
17
18
+ public static function getImageFolder()
19
+ {
20
+ return realpath(__DIR__ . '/../tests/images');
21
+ }
22
+
23
+ public static function getImagePath($image)
24
+ {
25
+ return self::getImageFolder() . '/' . $image;
26
+ }
27
+
28
public function testWebPConvertBuildNotCompletelyBroken()
29
{
30
require __DIR__ . '/../src-build/webp-convert.inc';
31
32
+ $source = self::getImagePath('png-without-extension');
33
$this->assertTrue(file_exists($source));
34
35
ob_start();
vendor/rosell-dk/webp-convert/build-tests-wod/WodBuildTest.php CHANGED
@@ -14,6 +14,17 @@ class WodBuildTest extends TestCase
14
15
private static $buildDir = __DIR__ . '/../src-build';
16
17
public function autoloadingDisallowed($class) {
18
throw new \Exception('no autoloading expected! ' . $class);
19
}
@@ -38,7 +49,7 @@ class WodBuildTest extends TestCase
38
39
spl_autoload_register([self::class, 'autoloaderLoad'], true, true);
40
41
- $source = __DIR__ . '/../tests/images/png-without-extension';
42
$this->assertTrue(file_exists($source));
43
44
ob_start();
@@ -101,7 +112,7 @@ class WodBuildTest extends TestCase
101
require_once $wod1;
102
103
104
- $source = __DIR__ . '/../tests/images/png-without-extension';
105
$this->assertTrue(file_exists($source));
106
107
/*
14
15
private static $buildDir = __DIR__ . '/../src-build';
16
17
+ public static function getImageFolder()
18
+ {
19
+ return realpath(__DIR__ . '/../tests/images');
20
+ }
21
+
22
+ public static function getImagePath($image)
23
+ {
24
+ return self::getImageFolder() . '/' . $image;
25
+ }
26
+
27
+
28
public function autoloadingDisallowed($class) {
29
throw new \Exception('no autoloading expected! ' . $class);
30
}
49
50
spl_autoload_register([self::class, 'autoloaderLoad'], true, true);
51
52
+ $source = self::getImagePath('png-without-extension');
53
$this->assertTrue(file_exists($source));
54
55
ob_start();
112
require_once $wod1;
113
114
115
+ $source = self::getImagePath('png-without-extension');
116
$this->assertTrue(file_exists($source));
117
118
/*
vendor/rosell-dk/webp-convert/src-build/webp-convert.inc CHANGED
@@ -142,18 +142,17 @@ class Option
142
143
namespace WebPConvert\Convert\Converters;
144
145
use WebPConvert\Convert\Exceptions\ConversionFailedException;
146
- use WebPConvert\Exceptions\WebPConvertException;
147
use WebPConvert\Convert\Converters\BaseTraits\AutoQualityTrait;
148
use WebPConvert\Convert\Converters\BaseTraits\DestinationPreparationTrait;
149
use WebPConvert\Convert\Converters\BaseTraits\LoggerTrait;
150
use WebPConvert\Convert\Converters\BaseTraits\OptionsTrait;
151
- use WebPConvert\Convert\Converters\BaseTraits\SourceValidationTrait;
152
use WebPConvert\Convert\Converters\BaseTraits\WarningLoggerTrait;
153
use WebPConvert\Loggers\BaseLogger;
154
155
- use ImageMimeTypeGuesser\ImageMimeTypeGuesser;
156
-
157
/**
158
* Base for all converter classes.
159
*
@@ -167,7 +166,6 @@ abstract class AbstractConverter
167
use OptionsTrait;
168
use WarningLoggerTrait;
169
use DestinationPreparationTrait;
170
- use SourceValidationTrait;
171
use LoggerTrait;
172
173
/**
@@ -205,9 +203,6 @@ abstract class AbstractConverter
205
/** @var string Where to save the webp (complete path) */
206
protected $destination;
207
208
- /** @var string|false|null Where to save the webp (complete path) */
209
- private $sourceMimeType;
210
-
211
/**
212
* Check basis operationality
213
*
@@ -250,6 +245,8 @@ abstract class AbstractConverter
250
*/
251
public function __construct($source, $destination, $options = [], $logger = null)
252
{
253
$this->source = $source;
254
$this->destination = $destination;
255
@@ -257,7 +254,7 @@ abstract class AbstractConverter
257
$this->setProvidedOptions($options);
258
259
if (!isset($this->options['_skip_input_check'])) {
260
- $this->log('WebP Convert 2.0.0', 'italic');
261
$this->logLn(' ignited.');
262
$this->logLn('- PHP version: ' . phpversion());
263
if (isset($_SERVER['SERVER_SOFTWARE'])) {
@@ -266,9 +263,6 @@ abstract class AbstractConverter
266
$this->logLn('');
267
$this->logLn(self::getConverterDisplayName() . ' converter ignited');
268
}
269
-
270
- $this->checkSourceExists();
271
- $this->checkSourceMimeType();
272
}
273
274
/**
@@ -376,10 +370,6 @@ abstract class AbstractConverter
376
$this->removeExistingDestinationIfExists();
377
378
if (!isset($this->options['_skip_input_check'])) {
379
- // Run basic input validations (if source exists and if file extension is valid)
380
- $this->checkSourceExists();
381
- $this->checkSourceMimeType();
382
-
383
// Check that a file can be written to destination
384
$this->checkDestinationWritable();
385
}
@@ -517,12 +507,7 @@ abstract class AbstractConverter
517
*/
518
public function getMimeTypeOfSource()
519
{
520
- if (!isset($this->sourceMimeType)) {
521
- // PS: Scrutinizer complains that ImageMimeTypeGuesser::lenientGuess could also return a boolean
522
- // but this is not true! - it returns string|false|null, just as this method does.
523
- $this->sourceMimeType = ImageMimeTypeGuesser::lenientGuess($this->source);
524
- }
525
- return $this->sourceMimeType;
526
}
527
}
528
@@ -1816,71 +1801,6 @@ trait OptionsTrait
1816
1817
namespace WebPConvert\Convert\Converters\BaseTraits;
1818
1819
- use WebPConvert\Convert\Exceptions\ConversionFailed\InvalidInput\TargetNotFoundException;
1820
- use WebPConvert\Convert\Exceptions\ConversionFailed\InvalidInput\InvalidImageTypeException;
1821
-
1822
- /**
1823
- * Trait for handling options
1824
- *
1825
- * This trait is currently only used in the AbstractConverter class. It has been extracted into a
1826
- * trait in order to bundle the methods concerning options.
1827
- *
1828
- * @package WebPConvert
1829
- * @author Bjørn Rosell <it@rosell.dk>
1830
- * @since Class available since Release 2.0.0
1831
- */
1832
- trait SourceValidationTrait
1833
- {
1834
-
1835
- abstract protected function getMimeTypeOfSource();
1836
- abstract public function getSource();
1837
-
1838
- /** @var array Array of allowed mime types for source. */
1839
- public static $allowedMimeTypes = ['image/jpeg', 'image/png'];
1840
-
1841
- /**
1842
- * Check that source file exists.
1843
- *
1844
- * Note: As the input validations are only run one time in a stack,
1845
- * this method is not overridable
1846
- *
1847
- * @throws TargetNotFoundException
1848
- * @return void
1849
- */
1850
- private function checkSourceExists()
1851
- {
1852
- // Check if source exists
1853
- if (!@file_exists($this->getSource())) {
1854
- throw new TargetNotFoundException('File or directory not found: ' . $this->getSource());
1855
- }
1856
- }
1857
-
1858
- /**
1859
- * Check that source has a valid mime type.
1860
- *
1861
- * Note: As the input validations are only run one time in a stack,
1862
- * this method is not overridable
1863
- *
1864
- * @throws InvalidImageTypeException If mime type could not be detected or is unsupported
1865
- * @return void
1866
- */
1867
- private function checkSourceMimeType()
1868
- {
1869
- $fileMimeType = $this->getMimeTypeOfSource();
1870
- if (is_null($fileMimeType)) {
1871
- throw new InvalidImageTypeException('Image type could not be detected');
1872
- } elseif ($fileMimeType === false) {
1873
- throw new InvalidImageTypeException('File seems not to be an image.');
1874
- } elseif (!in_array($fileMimeType, self::$allowedMimeTypes)) {
1875
- throw new InvalidImageTypeException('Unsupported mime type: ' . $fileMimeType);
1876
- }
1877
- }
1878
- }
1879
-
1880
- ?><?php
1881
-
1882
- namespace WebPConvert\Convert\Converters\BaseTraits;
1883
-
1884
/**
1885
* Trait for handling warnings (by logging them)
1886
*
@@ -5668,6 +5588,240 @@ class ConverterFactory
5668
5669
?><?php
5670
5671
namespace WebPConvert\Loggers;
5672
5673
/**
@@ -5924,8 +6078,9 @@ class Header
5924
?><?php
5925
namespace WebPConvert\Serve;
5926
5927
- use WebPConvert\WebPConvert;
5928
use WebPConvert\Loggers\EchoLogger;
5929
5930
/**
5931
* Class for generating a HTML report of converting an image.
@@ -5938,6 +6093,7 @@ class Report
5938
{
5939
public static function convertAndReport($source, $destination, $options)
5940
{
5941
?>
5942
<html>
5943
<head>
@@ -5951,8 +6107,8 @@ class Report
5951
</head>
5952
<body>
5953
<table>
5954
- <tr><td><i>source:</i></td><td><?php echo $source ?></td></tr>
5955
- <tr><td><i>destination:</i></td><td><?php echo $destination ?><td></tr>
5956
</table>
5957
<br>
5958
<?php
@@ -5977,9 +6133,9 @@ class Report
5977
?><?php
5978
namespace WebPConvert\Serve;
5979
5980
- use ImageMimeTypeGuesser\ImageMimeTypeGuesser;
5981
-
5982
use WebPConvert\Convert\Exceptions\ConversionFailedException;
5983
use WebPConvert\Serve\Exceptions\ServeFailedException;
5984
use WebPConvert\Serve\Header;
5985
use WebPConvert\Serve\Report;
@@ -6047,7 +6203,8 @@ class ServeConvertedWebP
6047
*/
6048
public static function serveOriginal($source, $serveImageOptions = [])
6049
{
6050
- $contentType = ImageMimeTypeGuesser::lenientGuess($source);
6051
if (is_null($contentType)) {
6052
throw new ServeFailedException('Rejecting to serve original (mime type cannot be determined)');
6053
} elseif ($contentType === false) {
@@ -6060,6 +6217,8 @@ class ServeConvertedWebP
6060
/**
6061
* Serve destination file.
6062
*
6063
* @param string $destination path to destination file
6064
* @param array $serveImageOptions (optional) options for serving (such as which headers to add)
6065
* Supported options:
@@ -6068,6 +6227,7 @@ class ServeConvertedWebP
6068
*/
6069
public static function serveDestination($destination, $serveImageOptions = [])
6070
{
6071
ServeFile::serve($destination, 'image/webp', $serveImageOptions);
6072
}
6073
@@ -6103,16 +6263,7 @@ class ServeConvertedWebP
6103
*/
6104
public static function serve($source, $destination, $options = [], $serveLogger = null, $convertLogger = null)
6105
{
6106
-
6107
- if (empty($source)) {
6108
- throw new ServeFailedException('Source argument missing');
6109
- }
6110
- if (empty($destination)) {
6111
- throw new ServeFailedException('Destination argument missing');
6112
- }
6113
- if (@!file_exists($source)) {
6114
- throw new ServeFailedException('Source file was not found');
6115
- }
6116
6117
$options = self::processOptions($options);
6118
@@ -6178,6 +6329,7 @@ class ServeConvertedWebP
6178
?><?php
6179
namespace WebPConvert\Serve;
6180
6181
use WebPConvert\Options\Options;
6182
use WebPConvert\Options\StringOption;
6183
use WebPConvert\Serve\Header;
@@ -6245,7 +6397,6 @@ class ServeConvertedWebPWithErrorHandling
6245
{
6246
self::addHeadersPreventingCaching();
6247
6248
- //Header::addLogHeader('Failure');
6249
Header::addLogHeader('Performing fail action: ' . $fail);
6250
6251
switch ($fail) {
@@ -6312,9 +6463,10 @@ class ServeConvertedWebPWithErrorHandling
6312
$convertLogger = null,
6313
$serveClass = '\\WebPConvert\\Serve\\ServeConvertedWebP'
6314
) {
6315
- $options = self::processOptions($options);
6316
6317
try {
6318
//ServeConvertedWebP::serve($source, $destination, $options, $serveLogger);
6319
call_user_func($serveClass . '::serve', $source, $destination, $options, $serveLogger, $convertLogger);
6320
} catch (\Exception $e) {
@@ -6339,6 +6491,7 @@ class ServeConvertedWebPWithErrorHandling
6339
namespace WebPConvert\Serve;
6340
6341
//use WebPConvert\Serve\Report;
6342
use WebPConvert\Options\ArrayOption;
6343
use WebPConvert\Options\BooleanOption;
6344
use WebPConvert\Options\Options;
@@ -6415,10 +6568,19 @@ class ServeFile
6415
*/
6416
public static function serve($filename, $contentType, $options = [])
6417
{
6418
if (!file_exists($filename)) {
6419
Header::addHeader('X-WebP-Convert-Error: Could not read file');
6420
throw new ServeFailedException('Could not read file');
6421
- }
6422
6423
$options = self::processOptions($options);
6424
142
143
namespace WebPConvert\Convert\Converters;
144
145
+ use WebPConvert\Helpers\InputValidator;
146
+ use WebPConvert\Helpers\MimeType;
147
use WebPConvert\Convert\Exceptions\ConversionFailedException;
148
use WebPConvert\Convert\Converters\BaseTraits\AutoQualityTrait;
149
use WebPConvert\Convert\Converters\BaseTraits\DestinationPreparationTrait;
150
use WebPConvert\Convert\Converters\BaseTraits\LoggerTrait;
151
use WebPConvert\Convert\Converters\BaseTraits\OptionsTrait;
152
use WebPConvert\Convert\Converters\BaseTraits\WarningLoggerTrait;
153
+ use WebPConvert\Exceptions\WebPConvertException;
154
use WebPConvert\Loggers\BaseLogger;
155
156
/**
157
* Base for all converter classes.
158
*
166
use OptionsTrait;
167
use WarningLoggerTrait;
168
use DestinationPreparationTrait;
169
use LoggerTrait;
170
171
/**
203
/** @var string Where to save the webp (complete path) */
204
protected $destination;
205
206
/**
207
* Check basis operationality
208
*
245
*/
246
public function __construct($source, $destination, $options = [], $logger = null)
247
{
248
+ InputValidator::checkSourceAndDestination($source, $destination);
249
+
250
$this->source = $source;
251
$this->destination = $destination;
252
254
$this->setProvidedOptions($options);
255
256
if (!isset($this->options['_skip_input_check'])) {
257
+ $this->log('WebP Convert 2.0.5', 'italic');
258
$this->logLn(' ignited.');
259
$this->logLn('- PHP version: ' . phpversion());
260
if (isset($_SERVER['SERVER_SOFTWARE'])) {
263
$this->logLn('');
264
$this->logLn(self::getConverterDisplayName() . ' converter ignited');
265
}
266
}
267
268
/**
370
$this->removeExistingDestinationIfExists();
371
372
if (!isset($this->options['_skip_input_check'])) {
373
// Check that a file can be written to destination
374
$this->checkDestinationWritable();
375
}
507
*/
508
public function getMimeTypeOfSource()
509
{
510
+ return MimeType::getMimeTypeDetectionResult($this->source);
511
}
512
}
513
1801
1802
namespace WebPConvert\Convert\Converters\BaseTraits;
1803
1804
/**
1805
* Trait for handling warnings (by logging them)
1806
*
5588
5589
?><?php
5590
5591
+ namespace WebPConvert\Exceptions;
5592
+
5593
+ use WebPConvert\Exceptions\WebPConvertException;
5594
+
5595
+ class InvalidInputException extends WebPConvertException
5596
+ {
5597
+ public $description = 'Invalid input';
5598
+ }
5599
+
5600
+ ?><?php
5601
+
5602
+ namespace WebPConvert\Exceptions\InvalidInput;
5603
+
5604
+ use WebPConvert\Exceptions\InvalidInputException;
5605
+
5606
+ class InvalidImageTypeException extends InvalidInputException
5607
+ {
5608
+ public $description = 'The converter does not handle the supplied image type';
5609
+ }
5610
+
5611
+ ?><?php
5612
+
5613
+ namespace WebPConvert\Exceptions\InvalidInput;
5614
+
5615
+ use WebPConvert\Exceptions\InvalidInputException;
5616
+
5617
+ class TargetNotFoundException extends InvalidInputException
5618
+ {
5619
+ public $description = 'The converter could not locate source file';
5620
+ }
5621
+
5622
+ ?><?php
5623
+
5624
+ namespace WebPConvert\Helpers;
5625
+
5626
+ use WebPConvert\Helpers\MimeType;
5627
+ use WebPConvert\Helpers\PathChecker;
5628
+ use WebPConvert\Exceptions\InvalidInputException;
5629
+ use WebPConvert\Exceptions\InvalidInput\InvalidImageTypeException;
5630
+
5631
+ /**
5632
+ * Functions for sanitizing.
5633
+ *
5634
+ * @package WebPConvert
5635
+ * @author Bjørn Rosell <it@rosell.dk>
5636
+ * @since Class available since Release 2.0.6
5637
+ */
5638
+ class InputValidator
5639
+ {
5640
+
5641
+ private static $allowedMimeTypes = [
5642
+ 'image/jpeg',
5643
+ 'image/png'
5644
+ ];
5645
+
5646
+ /**
5647
+ * Check mimetype and if file path is ok and exists
5648
+ */
5649
+ public static function checkMimeType($filePath, $allowedMimeTypes = null)
5650
+ {
5651
+ if (is_null($allowedMimeTypes)) {
5652
+ $allowedMimeTypes = self::$allowedMimeTypes;
5653
+ }
5654
+ // the following also tests that file path is ok and file exists
5655
+ $fileMimeType = MimeType::getMimeTypeDetectionResult($filePath);
5656
+
5657
+ if (is_null($fileMimeType)) {
5658
+ throw new InvalidImageTypeException('Image type could not be detected');
5659
+ } elseif ($fileMimeType === false) {
5660
+ throw new InvalidImageTypeException('File seems not to be an image.');
5661
+ } elseif (!in_array($fileMimeType, $allowedMimeTypes)) {
5662
+ throw new InvalidImageTypeException('Unsupported mime type: ' . $fileMimeType);
5663
+ }
5664
+ }
5665
+
5666
+ public static function checkSource($source)
5667
+ {
5668
+ PathChecker::checkSourcePath($source);
5669
+ self::checkMimeType($source);
5670
+ }
5671
+
5672
+ public static function checkDestination($destination)
5673
+ {
5674
+ PathChecker::checkDestinationPath($destination);
5675
+ }
5676
+
5677
+ public static function checkSourceAndDestination($source, $destination)
5678
+ {
5679
+ self::checkSource($source);
5680
+ self::checkDestination($destination);
5681
+ }
5682
+ }
5683
+
5684
+ ?><?php
5685
+
5686
+ namespace WebPConvert\Helpers;
5687
+
5688
+ use ImageMimeTypeGuesser\ImageMimeTypeGuesser;
5689
+
5690
+ use WebPConvert\Exceptions\InvalidInputException;
5691
+ use WebPConvert\Exceptions\InvalidInput\TargetNotFoundException;
5692
+
5693
+ /**
5694
+ * Get MimeType, results cached by path.
5695
+ *
5696
+ * @package WebPConvert
5697
+ * @author Bjørn Rosell <it@rosell.dk>
5698
+ * @since Class available since Release 2.0.6
5699
+ */
5700
+ class MimeType
5701
+ {
5702
+ private static $cachedDetections = [];
5703
+
5704
+ /**
5705
+ * Get mime type for image (best guess).
5706
+ *
5707
+ * It falls back to using file extension. If that fails too, false is returned
5708
+ *
5709
+ * @return string|false|null mimetype (if it is an image, and type could be determined / guessed),
5710
+ * false (if it is not an image type that the server knowns about)
5711
+ * or null (if nothing can be determined)
5712
+ */
5713
+ public static function getMimeTypeDetectionResult($absFilePath)
5714
+ {
5715
+ PathChecker::checkAbsolutePathAndExists($absFilePath);
5716
+
5717
+ if (isset(self::$cachedDetections[$absFilePath])) {
5718
+ return self::$cachedDetections[$absFilePath];
5719
+ }
5720
+ $cachedDetections[$absFilePath] = ImageMimeTypeGuesser::lenientGuess($absFilePath);
5721
+ return $cachedDetections[$absFilePath];
5722
+ }
5723
+ }
5724
+
5725
+ ?><?php
5726
+
5727
+ namespace WebPConvert\Helpers;
5728
+
5729
+ use WebPConvert\Exceptions\InvalidInputException;
5730
+ use WebPConvert\Exceptions\InvalidInput\TargetNotFoundException;
5731
+
5732
+ /**
5733
+ * Functions for sanitizing.
5734
+ *
5735
+ * @package WebPConvert
5736
+ * @author Bjørn Rosell <it@rosell.dk>
5737
+ * @since Class available since Release 2.0.6
5738
+ */
5739
+ class PathChecker
5740
+ {
5741
+
5742
+ /**
5743
+ * Check absolute file path to prevent attacks.
5744
+ *
5745
+ * - Prevents non printable characters
5746
+ * - Prevents stream wrappers
5747
+ * - Prevents directory traversal
5748
+ *
5749
+ * Preventing non printable characters is especially done to prevent the NUL character, which can be used
5750
+ * to bypass other tests. See https://st-g.de/2011/04/doing-filename-checks-securely-in-PHP.
5751
+ *
5752
+ * Preventeng stream wrappers is especially done to protect against Phar Deserialization.
5753
+ * See https://blog.ripstech.com/2018/new-php-exploitation-technique/
5754
+ *
5755
+ * @param string $absFilePath
5756
+ * @return string sanitized file path
5757
+ */
5758
+ public static function checkAbsolutePath($absFilePath, $text = 'file')
5759
+ {
5760
+ if (empty($absFilePath)) {
5761
+ throw new InvalidInputException('Empty filepath for ' . $text);
5762
+ }
5763
+
5764
+ // Prevent non printable characters
5765
+ if (!ctype_print($absFilePath)) {
5766
+ throw new InvalidInputException('Non-printable characters are not allowed in ' . $text);
5767
+ }
5768
+
5769
+ // Prevent directory traversal
5770
+ if (preg_match('#\.\.\/#', $absFilePath)) {
5771
+ throw new InvalidInputException('Directory traversal is not allowed in ' . $text . ' path');
5772
+ }
5773
+
5774
+ // Prevent stream wrappers ("phar://", "php://" and the like)
5775
+ // https://www.php.net/manual/en/wrappers.phar.php
5776
+ if (preg_match('#^\\w+://#', $absFilePath)) {
5777
+ throw new InvalidInputException('Stream wrappers are not allowed in ' . $text . ' path');
5778
+ }
5779
+ }
5780
+
5781
+ public static function checkAbsolutePathAndExists($absFilePath, $text = 'file')
5782
+ {
5783
+ if (empty($absFilePath)) {
5784
+ throw new TargetNotFoundException($text . ' argument missing');
5785
+ }
5786
+ self::checkAbsolutePath($absFilePath, $text);
5787
+ if (@!file_exists($absFilePath)) {
5788
+ throw new TargetNotFoundException($text . ' file was not found');
5789
+ }
5790
+ if (@is_dir($absFilePath)) {
5791
+ throw new InvalidInputException($text . ' is a directory');
5792
+ }
5793
+ }
5794
+
5795
+ /**
5796
+ * Checks that source path is secure, file exists and it is not a dir.
5797
+ *
5798
+ * To also check mime type, use InputValidator::checkSource
5799
+ */
5800
+ public static function checkSourcePath($source)
5801
+ {
5802
+ self::checkAbsolutePathAndExists($source, 'source');
5803
+ }
5804
+
5805
+ public static function checkDestinationPath($destination)
5806
+ {
5807
+ if (empty($destination)) {
5808
+ throw new InvalidInputException('Destination argument missing');
5809
+ }
5810
+ self::checkAbsolutePath($destination, 'destination');
5811
+ if (@is_dir($destination)) {
5812
+ throw new InvalidInputException('Destination is a directory');
5813
+ }
5814
+ }
5815
+
5816
+ public static function checkSourceAndDestinationPaths($source, $destination)
5817
+ {
5818
+ self::checkSourcePath($source);
5819
+ self::checkDestinationPath($destination);
5820
+ }
5821
+ }
5822
+
5823
+ ?><?php
5824
+
5825
namespace WebPConvert\Loggers;
5826
5827
/**
6078
?><?php
6079
namespace WebPConvert\Serve;
6080
6081
+ use WebPConvert\Helpers\InputValidator;
6082
use WebPConvert\Loggers\EchoLogger;
6083
+ use WebPConvert\WebPConvert;
6084
6085
/**
6086
* Class for generating a HTML report of converting an image.
6093
{
6094
public static function convertAndReport($source, $destination, $options)
6095
{
6096
+ InputValidator::checkSourceAndDestination($source, $destination);
6097
?>
6098
<html>
6099
<head>
6107
</head>
6108
<body>
6109
<table>
6110
+ <tr><td><i>source:</i></td><td><?php echo htmlentities($source) ?></td></tr>
6111
+ <tr><td><i>destination:</i></td><td><?php echo htmlentities($destination) ?><td></tr>
6112
</table>
6113
<br>
6114
<?php
6133
?><?php
6134
namespace WebPConvert\Serve;
6135
6136
use WebPConvert\Convert\Exceptions\ConversionFailedException;
6137
+ use WebPConvert\Helpers\InputValidator;
6138
+ use WebPConvert\Helpers\MimeType;
6139
use WebPConvert\Serve\Exceptions\ServeFailedException;
6140
use WebPConvert\Serve\Header;
6141
use WebPConvert\Serve\Report;
6203
*/
6204
public static function serveOriginal($source, $serveImageOptions = [])
6205
{
6206
+ InputValidator::checkSource($source);
6207
+ $contentType = MimeType::getMimeTypeDetectionResult($source);
6208
if (is_null($contentType)) {
6209
throw new ServeFailedException('Rejecting to serve original (mime type cannot be determined)');
6210
} elseif ($contentType === false) {
6217
/**
6218
* Serve destination file.
6219
*
6220
+ * TODO: SHould this really be public?
6221
+ *
6222
* @param string $destination path to destination file
6223
* @param array $serveImageOptions (optional) options for serving (such as which headers to add)
6224
* Supported options:
6227
*/
6228
public static function serveDestination($destination, $serveImageOptions = [])
6229
{
6230
+ InputValidator::checkDestination($destination);
6231
ServeFile::serve($destination, 'image/webp', $serveImageOptions);
6232
}
6233
6263
*/
6264
public static function serve($source, $destination, $options = [], $serveLogger = null, $convertLogger = null)
6265
{
6266
+ InputValidator::checkSourceAndDestination($source, $destination);
6267
6268
$options = self::processOptions($options);
6269
6329
?><?php
6330
namespace WebPConvert\Serve;
6331
6332
+ use WebPConvert\Helpers\InputValidator;
6333
use WebPConvert\Options\Options;
6334
use WebPConvert\Options\StringOption;
6335
use WebPConvert\Serve\Header;
6397
{
6398
self::addHeadersPreventingCaching();
6399
6400
Header::addLogHeader('Performing fail action: ' . $fail);
6401
6402
switch ($fail) {
6463
$convertLogger = null,
6464
$serveClass = '\\WebPConvert\\Serve\\ServeConvertedWebP'
6465
) {
6466
6467
+ $options = self::processOptions($options);
6468
try {
6469
+ InputValidator::checkSourceAndDestination($source, $destination);
6470
//ServeConvertedWebP::serve($source, $destination, $options, $serveLogger);
6471
call_user_func($serveClass . '::serve', $source, $destination, $options, $serveLogger, $convertLogger);
6472
} catch (\Exception $e) {
6491
namespace WebPConvert\Serve;
6492
6493
//use WebPConvert\Serve\Report;
6494
+ use WebPConvert\Helpers\InputValidator;
6495
use WebPConvert\Options\ArrayOption;
6496
use WebPConvert\Options\BooleanOption;
6497
use WebPConvert\Options\Options;
6568
*/
6569
public static function serve($filename, $contentType, $options = [])
6570
{
6571
+ // Check mimetype - this also checks that path is secure and file exists
6572
+ InputValidator::checkMimeType($filename, [
6573
+ 'image/jpeg',
6574
+ 'image/png',
6575
+ 'image/webp',
6576
+ 'image/gif'
6577
+ ]);
6578
+
6579
+ /*
6580
if (!file_exists($filename)) {
6581
Header::addHeader('X-WebP-Convert-Error: Could not read file');
6582
throw new ServeFailedException('Could not read file');
6583
+ }*/
6584
6585
$options = self::processOptions($options);
6586
vendor/rosell-dk/webp-convert/src-build/webp-on-demand-1.inc CHANGED
@@ -2,9 +2,9 @@
2
?><?php
3
namespace WebPConvert\Serve;
4
5
- use ImageMimeTypeGuesser\ImageMimeTypeGuesser;
6
-
7
use WebPConvert\Convert\Exceptions\ConversionFailedException;
8
use WebPConvert\Serve\Exceptions\ServeFailedException;
9
use WebPConvert\Serve\Header;
10
use WebPConvert\Serve\Report;
@@ -72,7 +72,8 @@ class ServeConvertedWebP
72
*/
73
public static function serveOriginal($source, $serveImageOptions = [])
74
{
75
- $contentType = ImageMimeTypeGuesser::lenientGuess($source);
76
if (is_null($contentType)) {
77
throw new ServeFailedException('Rejecting to serve original (mime type cannot be determined)');
78
} elseif ($contentType === false) {
@@ -85,6 +86,8 @@ class ServeConvertedWebP
85
/**
86
* Serve destination file.
87
*
88
* @param string $destination path to destination file
89
* @param array $serveImageOptions (optional) options for serving (such as which headers to add)
90
* Supported options:
@@ -93,6 +96,7 @@ class ServeConvertedWebP
93
*/
94
public static function serveDestination($destination, $serveImageOptions = [])
95
{
96
ServeFile::serve($destination, 'image/webp', $serveImageOptions);
97
}
98
@@ -128,16 +132,7 @@ class ServeConvertedWebP
128
*/
129
public static function serve($source, $destination, $options = [], $serveLogger = null, $convertLogger = null)
130
{
131
-
132
- if (empty($source)) {
133
- throw new ServeFailedException('Source argument missing');
134
- }
135
- if (empty($destination)) {
136
- throw new ServeFailedException('Destination argument missing');
137
- }
138
- if (@!file_exists($source)) {
139
- throw new ServeFailedException('Source file was not found');
140
- }
141
142
$options = self::processOptions($options);
143
@@ -203,6 +198,7 @@ class ServeConvertedWebP
203
?><?php
204
namespace WebPConvert\Serve;
205
206
use WebPConvert\Options\Options;
207
use WebPConvert\Options\StringOption;
208
use WebPConvert\Serve\Header;
@@ -270,7 +266,6 @@ class ServeConvertedWebPWithErrorHandling
270
{
271
self::addHeadersPreventingCaching();
272
273
- //Header::addLogHeader('Failure');
274
Header::addLogHeader('Performing fail action: ' . $fail);
275
276
switch ($fail) {
@@ -337,9 +332,10 @@ class ServeConvertedWebPWithErrorHandling
337
$convertLogger = null,
338
$serveClass = '\\WebPConvert\\Serve\\ServeConvertedWebP'
339
) {
340
- $options = self::processOptions($options);
341
342
try {
343
//ServeConvertedWebP::serve($source, $destination, $options, $serveLogger);
344
call_user_func($serveClass . '::serve', $source, $destination, $options, $serveLogger, $convertLogger);
345
} catch (\Exception $e) {
@@ -364,6 +360,7 @@ class ServeConvertedWebPWithErrorHandling
364
namespace WebPConvert\Serve;
365
366
//use WebPConvert\Serve\Report;
367
use WebPConvert\Options\ArrayOption;
368
use WebPConvert\Options\BooleanOption;
369
use WebPConvert\Options\Options;
@@ -440,10 +437,19 @@ class ServeFile
440
*/
441
public static function serve($filename, $contentType, $options = [])
442
{
443
if (!file_exists($filename)) {
444
Header::addHeader('X-WebP-Convert-Error: Could not read file');
445
throw new ServeFailedException('Could not read file');
446
- }
447
448
$options = self::processOptions($options);
449
@@ -484,6 +490,244 @@ class ServeFile
484
}
485
}
486
487
?><?php
488
namespace WebPConvert\Serve;
489
@@ -614,3 +858,536 @@ class WebPConvert
614
}
615
}
616
2
?><?php
3
namespace WebPConvert\Serve;
4
5
use WebPConvert\Convert\Exceptions\ConversionFailedException;
6
+ use WebPConvert\Helpers\InputValidator;
7
+ use WebPConvert\Helpers\MimeType;
8
use WebPConvert\Serve\Exceptions\ServeFailedException;
9
use WebPConvert\Serve\Header;
10
use WebPConvert\Serve\Report;
72
*/
73
public static function serveOriginal($source, $serveImageOptions = [])
74
{
75
+ InputValidator::checkSource($source);
76
+ $contentType = MimeType::getMimeTypeDetectionResult($source);
77
if (is_null($contentType)) {
78
throw new ServeFailedException('Rejecting to serve original (mime type cannot be determined)');
79
} elseif ($contentType === false) {
86
/**
87
* Serve destination file.
88
*
89
+ * TODO: SHould this really be public?
90
+ *
91
* @param string $destination path to destination file
92
* @param array $serveImageOptions (optional) options for serving (such as which headers to add)
93
* Supported options:
96
*/
97
public static function serveDestination($destination, $serveImageOptions = [])
98
{
99
+ InputValidator::checkDestination($destination);
100
ServeFile::serve($destination, 'image/webp', $serveImageOptions);
101
}
102
132
*/
133
public static function serve($source, $destination, $options = [], $serveLogger = null, $convertLogger = null)
134
{
135
+ InputValidator::checkSourceAndDestination($source, $destination);
136
137
$options = self::processOptions($options);
138
198
?><?php
199
namespace WebPConvert\Serve;
200
201
+ use WebPConvert\Helpers\InputValidator;
202
use WebPConvert\Options\Options;
203
use WebPConvert\Options\StringOption;
204
use WebPConvert\Serve\Header;
266
{
267
self::addHeadersPreventingCaching();
268
269
Header::addLogHeader('Performing fail action: ' . $fail);
270
271
switch ($fail) {
332
$convertLogger = null,
333
$serveClass = '\\WebPConvert\\Serve\\ServeConvertedWebP'
334
) {
335
336
+ $options = self::processOptions($options);
337
try {
338
+ InputValidator::checkSourceAndDestination($source, $destination);
339
//ServeConvertedWebP::serve($source, $destination, $options, $serveLogger);
340
call_user_func($serveClass . '::serve', $source, $destination, $options, $serveLogger, $convertLogger);
341
} catch (\Exception $e) {
360
namespace WebPConvert\Serve;
361
362
//use WebPConvert\Serve\Report;
363
+ use WebPConvert\Helpers\InputValidator;
364
use WebPConvert\Options\ArrayOption;
365
use WebPConvert\Options\BooleanOption;
366
use WebPConvert\Options\Options;
437
*/
438
public static function serve($filename, $contentType, $options = [])
439
{
440
+ // Check mimetype - this also checks that path is secure and file exists
441
+ InputValidator::checkMimeType($filename, [
442
+ 'image/jpeg',
443
+ 'image/png',
444
+ 'image/webp',
445
+ 'image/gif'
446
+ ]);
447
+
448
+ /*
449
if (!file_exists($filename)) {
450
Header::addHeader('X-WebP-Convert-Error: Could not read file');
451
throw new ServeFailedException('Could not read file');
452
+ }*/
453
454
$options = self::processOptions($options);
455
490
}
491
}
492
493
+ ?><?php
494
+
495
+ namespace WebPConvert\Exceptions;
496
+
497
+ /**
498
+ * WebPConvertException is the base exception for all exceptions in this library.
499
+ *
500
+ * Note that the parameters for the constructor differs from that of the Exception class.
501
+ * We do not use exception code here, but are instead allowing two version of the error message:
502
+ * a short version and a long version.
503
+ * The short version may not contain special characters or dynamic content.
504
+ * The detailed version may.
505
+ * If the detailed version isn't provided, getDetailedMessage will return the short version.
506
+ *
507
+ */
508
+ class WebPConvertException extends \Exception
509
+ {
510
+ public $description = '';
511
+ protected $detailedMessage;
512
+ protected $shortMessage;
513
+
514
+ public function getDetailedMessage()
515
+ {
516
+ return $this->detailedMessage;
517
+ }
518
+
519
+ public function getShortMessage()
520
+ {
521
+ return $this->shortMessage;
522
+ }
523
+
524
+ public function __construct($shortMessage = "", $detailedMessage = "", $previous = null)
525
+ {
526
+ $detailedMessage = ($detailedMessage != '') ? $detailedMessage : $shortMessage;
527
+ $this->detailedMessage = $detailedMessage;
528
+ $this->shortMessage = $shortMessage;
529
+
530
+ parent::__construct(
531
+ $detailedMessage,
532
+ 0,
533
+ $previous
534
+ );
535
+ }
536
+ }
537
+
538
+ ?><?php
539
+
540
+ namespace WebPConvert\Exceptions;
541
+
542
+ use WebPConvert\Exceptions\WebPConvertException;
543
+
544
+ class InvalidInputException extends WebPConvertException
545
+ {
546
+ public $description = 'Invalid input';
547
+ }
548
+
549
+ ?><?php
550
+
551
+ namespace WebPConvert\Exceptions\InvalidInput;
552
+
553
+ use WebPConvert\Exceptions\InvalidInputException;
554
+
555
+ class InvalidImageTypeException extends InvalidInputException
556
+ {
557
+ public $description = 'The converter does not handle the supplied image type';
558
+ }
559
+
560
+ ?><?php
561
+
562
+ namespace WebPConvert\Exceptions\InvalidInput;
563
+
564
+ use WebPConvert\Exceptions\InvalidInputException;
565
+
566
+ class TargetNotFoundException extends InvalidInputException
567
+ {
568
+ public $description = 'The converter could not locate source file';
569
+ }
570
+
571
+ ?><?php
572
+
573
+ namespace WebPConvert\Helpers;
574
+
575
+ use WebPConvert\Exceptions\InvalidInputException;
576
+ use WebPConvert\Exceptions\InvalidInput\TargetNotFoundException;
577
+
578
+ /**
579
+ * Functions for sanitizing.
580
+ *
581
+ * @package WebPConvert
582
+ * @author Bjørn Rosell <it@rosell.dk>
583
+ * @since Class available since Release 2.0.6
584
+ */
585
+ class PathChecker
586
+ {
587
+
588
+ /**
589
+ * Check absolute file path to prevent attacks.
590
+ *
591
+ * - Prevents non printable characters
592
+ * - Prevents stream wrappers
593
+ * - Prevents directory traversal
594
+ *
595
+ * Preventing non printable characters is especially done to prevent the NUL character, which can be used
596
+ * to bypass other tests. See https://st-g.de/2011/04/doing-filename-checks-securely-in-PHP.
597
+ *
598
+ * Preventeng stream wrappers is especially done to protect against Phar Deserialization.
599
+ * See https://blog.ripstech.com/2018/new-php-exploitation-technique/
600
+ *
601
+ * @param string $absFilePath
602
+ * @return string sanitized file path
603
+ */
604
+ public static function checkAbsolutePath($absFilePath, $text = 'file')
605
+ {
606
+ if (empty($absFilePath)) {
607
+ throw new InvalidInputException('Empty filepath for ' . $text);
608
+ }
609
+
610
+ // Prevent non printable characters
611
+ if (!ctype_print($absFilePath)) {
612
+ throw new InvalidInputException('Non-printable characters are not allowed in ' . $text);
613
+ }
614
+
615
+ // Prevent directory traversal
616
+ if (preg_match('#\.\.\/#', $absFilePath)) {
617
+ throw new InvalidInputException('Directory traversal is not allowed in ' . $text . ' path');
618
+ }
619
+
620
+ // Prevent stream wrappers ("phar://", "php://" and the like)
621
+ // https://www.php.net/manual/en/wrappers.phar.php
622
+ if (preg_match('#^\\w+://#', $absFilePath)) {
623
+ throw new InvalidInputException('Stream wrappers are not allowed in ' . $text . ' path');
624
+ }
625
+ }
626
+
627
+ public static function checkAbsolutePathAndExists($absFilePath, $text = 'file')
628
+ {
629
+ if (empty($absFilePath)) {
630
+ throw new TargetNotFoundException($text . ' argument missing');
631
+ }
632
+ self::checkAbsolutePath($absFilePath, $text);
633
+ if (@!file_exists($absFilePath)) {
634
+ throw new TargetNotFoundException($text . ' file was not found');
635
+ }
636
+ if (@is_dir($absFilePath)) {
637
+ throw new InvalidInputException($text . ' is a directory');
638
+ }
639
+ }
640
+
641
+ /**
642
+ * Checks that source path is secure, file exists and it is not a dir.
643
+ *
644
+ * To also check mime type, use InputValidator::checkSource
645
+ */
646
+ public static function checkSourcePath($source)
647
+ {
648
+ self::checkAbsolutePathAndExists($source, 'source');
649
+ }
650
+
651
+ public static function checkDestinationPath($destination)
652
+ {
653
+ if (empty($destination)) {
654
+ throw new InvalidInputException('Destination argument missing');
655
+ }
656
+ self::checkAbsolutePath($destination, 'destination');
657
+ if (@is_dir($destination)) {
658
+ throw new InvalidInputException('Destination is a directory');
659
+ }
660
+ }
661
+
662
+ public static function checkSourceAndDestinationPaths($source, $destination)
663
+ {
664
+ self::checkSourcePath($source);
665
+ self::checkDestinationPath($destination);
666
+ }
667
+ }
668
+
669
+ ?><?php
670
+
671
+ namespace WebPConvert\Helpers;
672
+
673
+ use WebPConvert\Helpers\MimeType;
674
+ use WebPConvert\Helpers\PathChecker;
675
+ use WebPConvert\Exceptions\InvalidInputException;
676
+ use WebPConvert\Exceptions\InvalidInput\InvalidImageTypeException;
677
+
678
+ /**
679
+ * Functions for sanitizing.
680
+ *
681
+ * @package WebPConvert
682
+ * @author Bjørn Rosell <it@rosell.dk>
683
+ * @since Class available since Release 2.0.6
684
+ */
685
+ class InputValidator
686
+ {
687
+
688
+ private static $allowedMimeTypes = [
689
+ 'image/jpeg',
690
+ 'image/png'
691
+ ];
692
+
693
+ /**
694
+ * Check mimetype and if file path is ok and exists
695