Skip to content

Commit dfa8b51

Browse files
authored
Release version 4.1.3 (#97)
Merge pull request #97 from short-pixel-optimizer/updates
2 parents b290930 + df8aa5f commit dfa8b51

File tree

13 files changed

+458
-18
lines changed

13 files changed

+458
-18
lines changed

build/shortpixel/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"name":"EnableMediaReplace\/shortpixelmodules","description":"ShortPixel submodules","type":"function","autoload":{"psr-4":{"EnableMediaReplace\\ShortPixelLogger":"log\/src","EnableMediaReplace\\Notices":"notices\/src","EnableMediaReplace\\Replacer":"replacer\/src","EnableMediaReplace\\FileSystem":"filesystem\/src"}}}
1+
{"name":"EnableMediaReplace\/shortpixelmodules","description":"ShortPixel submodules","type":"function","autoload":{"psr-4":{"EnableMediaReplace\\Notices":"notices\/src","EnableMediaReplace\\ShortPixelLogger":"log\/src","EnableMediaReplace\\FileSystem":"filesystem\/src","EnableMediaReplace\\Replacer":"replacer\/src"}}}

build/shortpixel/notices/src/NoticeModel.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,16 @@ public function getForDisplay()
219219
return false;
220220
}
221221

222-
$return = call_user_func($this->callback, $this);
223-
if ($return === false) // don't display is callback returns false explicitly.
224-
return;
222+
if (! is_callable($this->callback))
223+
{
224+
return;
225+
}
226+
else {
227+
$return = call_user_func($this->callback, $this);
228+
if ($return === false) // don't display is callback returns false explicitly.
229+
return;
230+
231+
}
225232
}
226233

227234
switch($this->messageType)
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
<?php
2+
namespace EnableMediaReplace\Replacer\Libraries\Unserialize;
3+
4+
5+
/**
6+
* Worker implementation for identifying and skipping false-positives
7+
* not to be substituted - like nested serializations in string literals.
8+
*
9+
* @internal This class should only be used by \Brumann\Polyfill\Unserialize
10+
*/
11+
final class DisallowedClassesSubstitutor
12+
{
13+
const PATTERN_STRING = '#s:(\d+):(")#';
14+
const PATTERN_OBJECT = '#(^|;)O:\d+:"([^"]*)":(\d+):\{#';
15+
16+
/**
17+
* @var string
18+
*/
19+
private $serialized;
20+
21+
/**
22+
* @var string[]
23+
*/
24+
private $allowedClasses;
25+
26+
/**
27+
* Each array item consists of `[<offset-start>, <offset-end>]` and
28+
* marks start and end positions of items to be ignored.
29+
*
30+
* @var array[]
31+
*/
32+
private $ignoreItems = array();
33+
34+
/**
35+
* @param string $serialized
36+
* @param string[] $allowedClasses
37+
*/
38+
public function __construct($serialized, array $allowedClasses)
39+
{
40+
$this->serialized = $serialized;
41+
$this->allowedClasses = $allowedClasses;
42+
43+
$this->buildIgnoreItems();
44+
$this->substituteObjects();
45+
}
46+
47+
/**
48+
* @return string
49+
*/
50+
public function getSubstitutedSerialized()
51+
{
52+
return $this->serialized;
53+
}
54+
55+
/**
56+
* Identifies items to be ignored - like nested serializations in string literals.
57+
*/
58+
private function buildIgnoreItems()
59+
{
60+
$offset = 0;
61+
while (preg_match(self::PATTERN_STRING, $this->serialized, $matches, PREG_OFFSET_CAPTURE, $offset)) {
62+
$length = (int)$matches[1][0]; // given length in serialized data (e.g. `s:123:"` --> 123)
63+
$start = $matches[2][1]; // offset position of quote character
64+
$end = $start + $length + 1;
65+
$offset = $end + 1;
66+
67+
// serialized string nested in outer serialized string
68+
if ($this->ignore($start, $end)) {
69+
continue;
70+
}
71+
72+
$this->ignoreItems[] = array($start, $end);
73+
}
74+
}
75+
76+
/**
77+
* Substitutes disallowed object class names and respects items to be ignored.
78+
*/
79+
private function substituteObjects()
80+
{
81+
$offset = 0;
82+
while (preg_match(self::PATTERN_OBJECT, $this->serialized, $matches, PREG_OFFSET_CAPTURE, $offset)) {
83+
$completeMatch = (string)$matches[0][0];
84+
$completeLength = strlen($completeMatch);
85+
$start = $matches[0][1];
86+
$end = $start + $completeLength;
87+
$leftBorder = (string)$matches[1][0];
88+
$className = (string)$matches[2][0];
89+
$objectSize = (int)$matches[3][0];
90+
$offset = $end + 1;
91+
92+
// class name is actually allowed - skip this item
93+
if (in_array($className, $this->allowedClasses, true)) {
94+
continue;
95+
}
96+
// serialized object nested in outer serialized string
97+
if ($this->ignore($start, $end)) {
98+
continue;
99+
}
100+
101+
$incompleteItem = $this->sanitizeItem($className, $leftBorder, $objectSize);
102+
$incompleteItemLength = strlen($incompleteItem);
103+
$offset = $start + $incompleteItemLength + 1;
104+
105+
$this->replace($incompleteItem, $start, $end);
106+
$this->shift($end, $incompleteItemLength - $completeLength);
107+
}
108+
}
109+
110+
/**
111+
* Replaces sanitized object class names in serialized data.
112+
*
113+
* @param string $replacement Sanitized object data
114+
* @param int $start Start offset in serialized data
115+
* @param int $end End offset in serialized data
116+
*/
117+
private function replace($replacement, $start, $end)
118+
{
119+
$this->serialized = substr($this->serialized, 0, $start)
120+
. $replacement . substr($this->serialized, $end);
121+
}
122+
123+
/**
124+
* Whether given offset positions should be ignored.
125+
*
126+
* @param int $start
127+
* @param int $end
128+
* @return bool
129+
*/
130+
private function ignore($start, $end)
131+
{
132+
foreach ($this->ignoreItems as $ignoreItem) {
133+
if ($ignoreItem[0] <= $start && $ignoreItem[1] >= $end) {
134+
return true;
135+
}
136+
}
137+
138+
return false;
139+
}
140+
141+
/**
142+
* Shifts offset positions of ignore items by `$size`.
143+
* This is necessary whenever object class names have been
144+
* substituted which have a different length than before.
145+
*
146+
* @param int $offset
147+
* @param int $size
148+
*/
149+
private function shift($offset, $size)
150+
{
151+
foreach ($this->ignoreItems as &$ignoreItem) {
152+
// only focus on items starting after given offset
153+
if ($ignoreItem[0] < $offset) {
154+
continue;
155+
}
156+
$ignoreItem[0] += $size;
157+
$ignoreItem[1] += $size;
158+
}
159+
}
160+
161+
/**
162+
* Sanitizes object class item.
163+
*
164+
* @param string $className
165+
* @param int $leftBorder
166+
* @param int $objectSize
167+
* @return string
168+
*/
169+
private function sanitizeItem($className, $leftBorder, $objectSize)
170+
{
171+
return sprintf(
172+
'%sO:22:"__PHP_Incomplete_Class":%d:{s:27:"__PHP_Incomplete_Class_Name";%s',
173+
$leftBorder,
174+
$objectSize + 1, // size of object + 1 for added string
175+
\serialize($className)
176+
);
177+
}
178+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2016-2019 Denis Brumann
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
Polyfill unserialize [![Build Status](https://travis-ci.org/dbrumann/polyfill-unserialize.svg?branch=master)](https://travis-ci.org/dbrumann/polyfill-unserialize)
2+
===
3+
4+
Backports unserialize options introduced in PHP 7.0 to older PHP versions.
5+
This was originally designed as a Proof of Concept for Symfony Issue
6+
[#21090](https://github.com/symfony/symfony/pull/21090).
7+
8+
You can use this package in projects that rely on PHP versions older than
9+
PHP 7.0. In case you are using PHP 7.0+ the original `unserialize()` will be
10+
used instead.
11+
12+
From the [documentation](https://secure.php.net/manual/en/function.unserialize.php):
13+
14+
> **Warning**
15+
>
16+
> Do not pass untrusted user input to unserialize() regardless of the options
17+
> value of allowed_classes. Unserialization can result in code being loaded and
18+
> executed due to object instantiation and autoloading, and a malicious user
19+
> may be able to exploit this. Use a safe, standard data interchange format
20+
> such as JSON (via json_decode() and json_encode()) if you need to pass
21+
> serialized data to the user.
22+
23+
Requirements
24+
------------
25+
26+
- PHP 5.3+
27+
28+
Installation
29+
------------
30+
31+
You can install this package via composer:
32+
33+
```bash
34+
composer require brumann/polyfill-unserialize "^2.0"
35+
```
36+
37+
Older versions
38+
--------------
39+
40+
You can find the most recent 1.x versions in the branch with the same name:
41+
42+
* [dbrumann/polyfill-unserialize/tree/1.x](https://github.com/dbrumann/polyfill-unserialize/tree/1.x)
43+
44+
Upgrading
45+
---------
46+
47+
Upgrading from 1.x to 2.0 should be seamless and require no changes to code
48+
using the library. There are no changes to the public API, i.e. the names for
49+
classes, methods and arguments as well as argument order and types remain the
50+
same. Version 2.x uses a completely different approach for substituting
51+
disallowed classes, which is why we chose to use a new major release to prevent
52+
issues from unknown side effects in existing installations.
53+
54+
Known Issues
55+
------------
56+
57+
There is a mismatch in behavior when `allowed_classes` in `$options` is not
58+
of the correct type (array or boolean). PHP 7.0 will not issue a warning that
59+
an invalid type was provided. This library will trigger a warning, similar to
60+
the one PHP 7.1+ will raise and then continue, assuming `false` to make sure
61+
no classes are deserialized by accident.
62+
63+
Tests
64+
-----
65+
66+
You can run the test suite using PHPUnit. It is intentionally not bundled as
67+
dev dependency to make sure this package has the lowest restrictions on the
68+
implementing system as possible.
69+
70+
Please read the [PHPUnit Manual](https://phpunit.de/manual/current/en/installation.html)
71+
for information how to install it on your system.
72+
73+
Please make sure to pick a compatible version. If you use PHP 5.6 you should
74+
use PHPUnit 5.7.27 and for older PHP versions you should use PHPUnit 4.8.36.
75+
Older versions of PHPUnit might not support namespaces, meaning they will not
76+
work with the tests. Newer versions only support PHP 7.0+, where this library
77+
is not needed anymore.
78+
79+
You can run the test suite as follows:
80+
81+
```bash
82+
phpunit -c phpunit.xml.dist tests/
83+
```
84+
85+
Contributing
86+
------------
87+
88+
This package is considered feature complete. As such I will likely not update
89+
it unless there are security issues.
90+
91+
Should you find any bugs or have questions, feel free to submit an Issue or a
92+
Pull Request on GitHub.
93+
94+
Development setup
95+
-----------------
96+
97+
This library contains a docker setup for development purposes. This allows
98+
running the code on an older PHP version without having to install it locally.
99+
100+
You can use the setup as follows:
101+
102+
1. Go into the project directory
103+
104+
1. Build the docker image
105+
106+
```
107+
docker build -t polyfill-unserialize .
108+
```
109+
110+
This will download a debian/jessie container with PHP 5.6 installed. Then
111+
it will download an appropriate version of phpunit for this PHP version.
112+
It will also download composer. It will set the working directory to `/opt/app`.
113+
The resulting image is tagged as `polyfill-unserialize`, which is the name
114+
we will refer to, when running the container.
115+
116+
1. You can then run a container based on the image, which will run your tests
117+
118+
```
119+
docker run -it --rm --name polyfill-unserialize-dev -v "$PWD":/opt/app polyfill-unserialize
120+
```
121+
122+
This will run a docker container based on our previously built image.
123+
The container will automatically be removed after phpunit finishes.
124+
We name the image `polyfill-unserialize-dev`. This makes sure only one
125+
instance is running and that we can easily identify a running container by
126+
its name, e.g. in order to remove it manually.
127+
We mount our current directory into the container's working directory.
128+
This ensures that tests run on our current project's state.
129+
130+
You can repeat the final step as often as you like in order to run the tests.
131+
The output should look something like this:
132+
133+
```bash
134+
dbr:polyfill-unserialize/ (improvement/dev_setup*) $ docker run -it --rm --name polyfill-unserialize-dev -v "$PWD":/opt/app polyfill-unserialize
135+
Loading composer repositories with package information
136+
Installing dependencies (including require-dev) from lock file
137+
Nothing to install or update
138+
Generating autoload files
139+
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
140+
141+
...................... 22 / 22 (100%)
142+
143+
Time: 167 ms, Memory: 13.25MB
144+
145+
OK (22 tests, 31 assertions)
146+
```
147+
148+
When you are done working on the project you can free up disk space by removing
149+
the initially built image:
150+
151+
```
152+
docker image rm polyfill-unserialize
153+
```

0 commit comments

Comments
 (0)