mirror of
https://gitlab.com/signalytic/client-external/streamline/streamline-emr.git
synced 2026-09-12 11:11:31 +00:00
Build modified streamline images
The official image from streamline does not currently work for the arm64 platform. As a temporary measure, the source code and docker build scripts have been lifted from the official images and are used to build locally. Some additional modifications are made to reduce overall image size, these are documented in docker/README.md
This commit is contained in:
+20
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Contracts;
|
||||
|
||||
interface Serializable
|
||||
{
|
||||
/**
|
||||
* Resolve the closure with the given arguments.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke();
|
||||
|
||||
/**
|
||||
* Gets the closure that got serialized/unserialized.
|
||||
*
|
||||
* @return \Closure
|
||||
*/
|
||||
public function getClosure();
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Contracts;
|
||||
|
||||
interface Signer
|
||||
{
|
||||
/**
|
||||
* Sign the given serializable.
|
||||
*
|
||||
* @param string $serializable
|
||||
* @return array
|
||||
*/
|
||||
public function sign($serializable);
|
||||
|
||||
/**
|
||||
* Verify the given signature.
|
||||
*
|
||||
* @param array $signature
|
||||
* @return bool
|
||||
*/
|
||||
public function verify($signature);
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class InvalidSignatureException extends Exception
|
||||
{
|
||||
/**
|
||||
* Create a new exception instance.
|
||||
*
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($message = 'Your serialized closure might have been modified or it\'s unsafe to be unserialized.')
|
||||
{
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class MissingSecretKeyException extends Exception
|
||||
{
|
||||
/**
|
||||
* Create a new exception instance.
|
||||
*
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($message = 'No serializable closure secret key has been specified.')
|
||||
{
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class PhpVersionNotSupportedException extends Exception
|
||||
{
|
||||
/**
|
||||
* Create a new exception instance.
|
||||
*
|
||||
* @param string $message
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($message = 'PHP 7.3 is not supported.')
|
||||
{
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure;
|
||||
|
||||
use Closure;
|
||||
use Laravel\SerializableClosure\Exceptions\InvalidSignatureException;
|
||||
use Laravel\SerializableClosure\Exceptions\PhpVersionNotSupportedException;
|
||||
use Laravel\SerializableClosure\Serializers\Signed;
|
||||
use Laravel\SerializableClosure\Signers\Hmac;
|
||||
|
||||
class SerializableClosure
|
||||
{
|
||||
/**
|
||||
* The closure's serializable.
|
||||
*
|
||||
* @var \Laravel\SerializableClosure\Contracts\Serializable
|
||||
*/
|
||||
protected $serializable;
|
||||
|
||||
/**
|
||||
* Creates a new serializable closure instance.
|
||||
*
|
||||
* @param \Closure $closure
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Closure $closure)
|
||||
{
|
||||
if (\PHP_VERSION_ID < 70400) {
|
||||
throw new PhpVersionNotSupportedException();
|
||||
}
|
||||
|
||||
$this->serializable = Serializers\Signed::$signer
|
||||
? new Serializers\Signed($closure)
|
||||
: new Serializers\Native($closure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the closure with the given arguments.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
if (\PHP_VERSION_ID < 70400) {
|
||||
throw new PhpVersionNotSupportedException();
|
||||
}
|
||||
|
||||
return call_user_func_array($this->serializable, func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the closure.
|
||||
*
|
||||
* @return \Closure
|
||||
*/
|
||||
public function getClosure()
|
||||
{
|
||||
if (\PHP_VERSION_ID < 70400) {
|
||||
throw new PhpVersionNotSupportedException();
|
||||
}
|
||||
|
||||
return $this->serializable->getClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new unsigned serializable closure instance.
|
||||
*
|
||||
* @param Closure $closure
|
||||
* @return \Laravel\SerializableClosure\UnsignedSerializableClosure
|
||||
*/
|
||||
public static function unsigned(Closure $closure)
|
||||
{
|
||||
return new UnsignedSerializableClosure($closure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the serializable closure secret key.
|
||||
*
|
||||
* @param string|null $secret
|
||||
* @return void
|
||||
*/
|
||||
public static function setSecretKey($secret)
|
||||
{
|
||||
Serializers\Signed::$signer = $secret
|
||||
? new Hmac($secret)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the serializable closure secret key.
|
||||
*
|
||||
* @param \Closure|null $transformer
|
||||
* @return void
|
||||
*/
|
||||
public static function transformUseVariablesUsing($transformer)
|
||||
{
|
||||
Serializers\Native::$transformUseVariables = $transformer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the serializable closure secret key.
|
||||
*
|
||||
* @param \Closure|null $resolver
|
||||
* @return void
|
||||
*/
|
||||
public static function resolveUseVariablesUsing($resolver)
|
||||
{
|
||||
Serializers\Native::$resolveUseVariables = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the serializable representation of the closure.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return [
|
||||
'serializable' => $this->serializable,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the closure after serialization.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*
|
||||
* @throws \Laravel\SerializableClosure\Exceptions\InvalidSignatureException
|
||||
*/
|
||||
public function __unserialize($data)
|
||||
{
|
||||
if (Signed::$signer && ! $data['serializable'] instanceof Signed) {
|
||||
throw new InvalidSignatureException();
|
||||
}
|
||||
|
||||
$this->serializable = $data['serializable'];
|
||||
}
|
||||
}
|
||||
+514
@@ -0,0 +1,514 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Serializers;
|
||||
|
||||
use Closure;
|
||||
use DateTimeInterface;
|
||||
use Laravel\SerializableClosure\Contracts\Serializable;
|
||||
use Laravel\SerializableClosure\SerializableClosure;
|
||||
use Laravel\SerializableClosure\Support\ClosureScope;
|
||||
use Laravel\SerializableClosure\Support\ClosureStream;
|
||||
use Laravel\SerializableClosure\Support\ReflectionClosure;
|
||||
use Laravel\SerializableClosure\Support\SelfReference;
|
||||
use Laravel\SerializableClosure\UnsignedSerializableClosure;
|
||||
use ReflectionObject;
|
||||
use UnitEnum;
|
||||
|
||||
class Native implements Serializable
|
||||
{
|
||||
/**
|
||||
* Transform the use variables before serialization.
|
||||
*
|
||||
* @var \Closure|null
|
||||
*/
|
||||
public static $transformUseVariables;
|
||||
|
||||
/**
|
||||
* Resolve the use variables after unserialization.
|
||||
*
|
||||
* @var \Closure|null
|
||||
*/
|
||||
public static $resolveUseVariables;
|
||||
|
||||
/**
|
||||
* The closure to be serialized/unserialized.
|
||||
*
|
||||
* @var \Closure
|
||||
*/
|
||||
protected $closure;
|
||||
|
||||
/**
|
||||
* The closure's reflection.
|
||||
*
|
||||
* @var \Laravel\SerializableClosure\Support\ReflectionClosure|null
|
||||
*/
|
||||
protected $reflector;
|
||||
|
||||
/**
|
||||
* The closure's code.
|
||||
*
|
||||
* @var array|null
|
||||
*/
|
||||
protected $code;
|
||||
|
||||
/**
|
||||
* The closure's reference.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $reference;
|
||||
|
||||
/**
|
||||
* The closure's scope.
|
||||
*
|
||||
* @var \Laravel\SerializableClosure\Support\ClosureScope|null
|
||||
*/
|
||||
protected $scope;
|
||||
|
||||
/**
|
||||
* The "key" that marks an array as recursive.
|
||||
*/
|
||||
const ARRAY_RECURSIVE_KEY = 'LARAVEL_SERIALIZABLE_RECURSIVE_KEY';
|
||||
|
||||
/**
|
||||
* Creates a new serializable closure instance.
|
||||
*
|
||||
* @param \Closure $closure
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Closure $closure)
|
||||
{
|
||||
$this->closure = $closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the closure with the given arguments.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
return call_user_func_array($this->closure, func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the closure.
|
||||
*
|
||||
* @return \Closure
|
||||
*/
|
||||
public function getClosure()
|
||||
{
|
||||
return $this->closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the serializable representation of the closure.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
if ($this->scope === null) {
|
||||
$this->scope = new ClosureScope();
|
||||
$this->scope->toSerialize++;
|
||||
}
|
||||
|
||||
$this->scope->serializations++;
|
||||
|
||||
$scope = $object = null;
|
||||
$reflector = $this->getReflector();
|
||||
|
||||
if ($reflector->isBindingRequired()) {
|
||||
$object = $reflector->getClosureThis();
|
||||
|
||||
static::wrapClosures($object, $this->scope);
|
||||
}
|
||||
|
||||
if ($scope = $reflector->getClosureScopeClass()) {
|
||||
$scope = $scope->name;
|
||||
}
|
||||
|
||||
$this->reference = spl_object_hash($this->closure);
|
||||
|
||||
$this->scope[$this->closure] = $this;
|
||||
|
||||
$use = $reflector->getUseVariables();
|
||||
|
||||
if (static::$transformUseVariables) {
|
||||
$use = call_user_func(static::$transformUseVariables, $reflector->getUseVariables());
|
||||
}
|
||||
|
||||
$code = $reflector->getCode();
|
||||
|
||||
$this->mapByReference($use);
|
||||
|
||||
$data = [
|
||||
'use' => $use,
|
||||
'function' => $code,
|
||||
'scope' => $scope,
|
||||
'this' => $object,
|
||||
'self' => $this->reference,
|
||||
];
|
||||
|
||||
if (! --$this->scope->serializations && ! --$this->scope->toSerialize) {
|
||||
$this->scope = null;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the closure after serialization.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function __unserialize($data)
|
||||
{
|
||||
ClosureStream::register();
|
||||
|
||||
$this->code = $data;
|
||||
unset($data);
|
||||
|
||||
$this->code['objects'] = [];
|
||||
|
||||
if ($this->code['use']) {
|
||||
$this->scope = new ClosureScope();
|
||||
|
||||
if (static::$resolveUseVariables) {
|
||||
$this->code['use'] = call_user_func(static::$resolveUseVariables, $this->code['use']);
|
||||
}
|
||||
|
||||
$this->mapPointers($this->code['use']);
|
||||
|
||||
extract($this->code['use'], EXTR_OVERWRITE | EXTR_REFS);
|
||||
|
||||
$this->scope = null;
|
||||
}
|
||||
|
||||
$this->closure = include ClosureStream::STREAM_PROTO.'://'.$this->code['function'];
|
||||
|
||||
if ($this->code['this'] === $this) {
|
||||
$this->code['this'] = null;
|
||||
}
|
||||
|
||||
$this->closure = $this->closure->bindTo($this->code['this'], $this->code['scope']);
|
||||
|
||||
if (! empty($this->code['objects'])) {
|
||||
foreach ($this->code['objects'] as $item) {
|
||||
$item['property']->setValue($item['instance'], $item['object']->getClosure());
|
||||
}
|
||||
}
|
||||
|
||||
$this->code = $this->code['function'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the given closures are serializable.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @param \Laravel\SerializableClosure\Support\ClosureScope $storage
|
||||
* @return void
|
||||
*/
|
||||
public static function wrapClosures(&$data, $storage)
|
||||
{
|
||||
if ($data instanceof Closure) {
|
||||
$data = new static($data);
|
||||
} elseif (is_array($data)) {
|
||||
if (isset($data[self::ARRAY_RECURSIVE_KEY])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data[self::ARRAY_RECURSIVE_KEY] = true;
|
||||
|
||||
foreach ($data as $key => &$value) {
|
||||
if ($key === self::ARRAY_RECURSIVE_KEY) {
|
||||
continue;
|
||||
}
|
||||
static::wrapClosures($value, $storage);
|
||||
}
|
||||
|
||||
unset($value);
|
||||
unset($data[self::ARRAY_RECURSIVE_KEY]);
|
||||
} elseif ($data instanceof \stdClass) {
|
||||
if (isset($storage[$data])) {
|
||||
$data = $storage[$data];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$data = $storage[$data] = clone $data;
|
||||
|
||||
foreach ($data as &$value) {
|
||||
static::wrapClosures($value, $storage);
|
||||
}
|
||||
|
||||
unset($value);
|
||||
} elseif (is_object($data) && ! $data instanceof static && ! $data instanceof UnitEnum) {
|
||||
if (isset($storage[$data])) {
|
||||
$data = $storage[$data];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = $data;
|
||||
$reflection = new ReflectionObject($instance);
|
||||
|
||||
if (! $reflection->isUserDefined()) {
|
||||
$storage[$instance] = $data;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$storage[$instance] = $data = $reflection->newInstanceWithoutConstructor();
|
||||
|
||||
do {
|
||||
if (! $reflection->isUserDefined()) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($reflection->getProperties() as $property) {
|
||||
if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$property->setAccessible(true);
|
||||
|
||||
if (PHP_VERSION >= 7.4 && ! $property->isInitialized($instance)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = $property->getValue($instance);
|
||||
|
||||
if (is_array($value) || is_object($value)) {
|
||||
static::wrapClosures($value, $storage);
|
||||
}
|
||||
|
||||
$property->setValue($data, $value);
|
||||
}
|
||||
} while ($reflection = $reflection->getParentClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the closure's reflector.
|
||||
*
|
||||
* @return \Laravel\SerializableClosure\Support\ReflectionClosure
|
||||
*/
|
||||
public function getReflector()
|
||||
{
|
||||
if ($this->reflector === null) {
|
||||
$this->code = null;
|
||||
$this->reflector = new ReflectionClosure($this->closure);
|
||||
}
|
||||
|
||||
return $this->reflector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method used to map closure pointers.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @return void
|
||||
*/
|
||||
protected function mapPointers(&$data)
|
||||
{
|
||||
$scope = $this->scope;
|
||||
|
||||
if ($data instanceof static) {
|
||||
$data = &$data->closure;
|
||||
} elseif (is_array($data)) {
|
||||
if (isset($data[self::ARRAY_RECURSIVE_KEY])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data[self::ARRAY_RECURSIVE_KEY] = true;
|
||||
|
||||
foreach ($data as $key => &$value) {
|
||||
if ($key === self::ARRAY_RECURSIVE_KEY) {
|
||||
continue;
|
||||
} elseif ($value instanceof static) {
|
||||
$data[$key] = &$value->closure;
|
||||
} elseif ($value instanceof SelfReference && $value->hash === $this->code['self']) {
|
||||
$data[$key] = &$this->closure;
|
||||
} else {
|
||||
$this->mapPointers($value);
|
||||
}
|
||||
}
|
||||
|
||||
unset($value);
|
||||
unset($data[self::ARRAY_RECURSIVE_KEY]);
|
||||
} elseif ($data instanceof \stdClass) {
|
||||
if (isset($scope[$data])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scope[$data] = true;
|
||||
|
||||
foreach ($data as $key => &$value) {
|
||||
if ($value instanceof SelfReference && $value->hash === $this->code['self']) {
|
||||
$data->{$key} = &$this->closure;
|
||||
} elseif (is_array($value) || is_object($value)) {
|
||||
$this->mapPointers($value);
|
||||
}
|
||||
}
|
||||
|
||||
unset($value);
|
||||
} elseif (is_object($data) && ! ($data instanceof Closure)) {
|
||||
if (isset($scope[$data])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$scope[$data] = true;
|
||||
$reflection = new ReflectionObject($data);
|
||||
|
||||
do {
|
||||
if (! $reflection->isUserDefined()) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($reflection->getProperties() as $property) {
|
||||
if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$property->setAccessible(true);
|
||||
|
||||
if (PHP_VERSION >= 7.4 && ! $property->isInitialized($data)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$item = $property->getValue($data);
|
||||
|
||||
if ($item instanceof SerializableClosure || $item instanceof UnsignedSerializableClosure || ($item instanceof SelfReference && $item->hash === $this->code['self'])) {
|
||||
$this->code['objects'][] = [
|
||||
'instance' => $data,
|
||||
'property' => $property,
|
||||
'object' => $item instanceof SelfReference ? $this : $item,
|
||||
];
|
||||
} elseif (is_array($item) || is_object($item)) {
|
||||
$this->mapPointers($item);
|
||||
$property->setValue($data, $item);
|
||||
}
|
||||
}
|
||||
} while ($reflection = $reflection->getParentClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method used to map closures by reference.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @return void
|
||||
*/
|
||||
protected function mapByReference(&$data)
|
||||
{
|
||||
if ($data instanceof Closure) {
|
||||
if ($data === $this->closure) {
|
||||
$data = new SelfReference($this->reference);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($this->scope[$data])) {
|
||||
$data = $this->scope[$data];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = new static($data);
|
||||
|
||||
$instance->scope = $this->scope;
|
||||
|
||||
$data = $this->scope[$data] = $instance;
|
||||
} elseif (is_array($data)) {
|
||||
if (isset($data[self::ARRAY_RECURSIVE_KEY])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data[self::ARRAY_RECURSIVE_KEY] = true;
|
||||
|
||||
foreach ($data as $key => &$value) {
|
||||
if ($key === self::ARRAY_RECURSIVE_KEY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->mapByReference($value);
|
||||
}
|
||||
|
||||
unset($value);
|
||||
unset($data[self::ARRAY_RECURSIVE_KEY]);
|
||||
} elseif ($data instanceof \stdClass) {
|
||||
if (isset($this->scope[$data])) {
|
||||
$data = $this->scope[$data];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = $data;
|
||||
$this->scope[$instance] = $data = clone $data;
|
||||
|
||||
foreach ($data as &$value) {
|
||||
$this->mapByReference($value);
|
||||
}
|
||||
|
||||
unset($value);
|
||||
} elseif (is_object($data) && ! $data instanceof SerializableClosure && ! $data instanceof UnsignedSerializableClosure) {
|
||||
if (isset($this->scope[$data])) {
|
||||
$data = $this->scope[$data];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = $data;
|
||||
|
||||
if ($data instanceof DateTimeInterface) {
|
||||
$this->scope[$instance] = $data;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($data instanceof UnitEnum) {
|
||||
$this->scope[$instance] = $data;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$reflection = new ReflectionObject($data);
|
||||
|
||||
if (! $reflection->isUserDefined()) {
|
||||
$this->scope[$instance] = $data;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->scope[$instance] = $data = $reflection->newInstanceWithoutConstructor();
|
||||
|
||||
do {
|
||||
if (! $reflection->isUserDefined()) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($reflection->getProperties() as $property) {
|
||||
if ($property->isStatic() || ! $property->getDeclaringClass()->isUserDefined()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$property->setAccessible(true);
|
||||
|
||||
if (PHP_VERSION >= 7.4 && ! $property->isInitialized($instance)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = $property->getValue($instance);
|
||||
|
||||
if (is_array($value) || is_object($value)) {
|
||||
$this->mapByReference($value);
|
||||
}
|
||||
|
||||
$property->setValue($data, $value);
|
||||
}
|
||||
} while ($reflection = $reflection->getParentClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Serializers;
|
||||
|
||||
use Laravel\SerializableClosure\Contracts\Serializable;
|
||||
use Laravel\SerializableClosure\Exceptions\InvalidSignatureException;
|
||||
use Laravel\SerializableClosure\Exceptions\MissingSecretKeyException;
|
||||
|
||||
class Signed implements Serializable
|
||||
{
|
||||
/**
|
||||
* The signer that will sign and verify the closure's signature.
|
||||
*
|
||||
* @var \Laravel\SerializableClosure\Contracts\Signer|null
|
||||
*/
|
||||
public static $signer;
|
||||
|
||||
/**
|
||||
* The closure to be serialized/unserialized.
|
||||
*
|
||||
* @var \Closure
|
||||
*/
|
||||
protected $closure;
|
||||
|
||||
/**
|
||||
* Creates a new serializable closure instance.
|
||||
*
|
||||
* @param \Closure $closure
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($closure)
|
||||
{
|
||||
$this->closure = $closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the closure with the given arguments.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
return call_user_func_array($this->closure, func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the closure.
|
||||
*
|
||||
* @return \Closure
|
||||
*/
|
||||
public function getClosure()
|
||||
{
|
||||
return $this->closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the serializable representation of the closure.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
if (! static::$signer) {
|
||||
throw new MissingSecretKeyException();
|
||||
}
|
||||
|
||||
return static::$signer->sign(
|
||||
serialize(new Native($this->closure))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the closure after serialization.
|
||||
*
|
||||
* @param array $signature
|
||||
* @return void
|
||||
*
|
||||
* @throws \Laravel\SerializableClosure\Exceptions\InvalidSignatureException
|
||||
*/
|
||||
public function __unserialize($signature)
|
||||
{
|
||||
if (static::$signer && ! static::$signer->verify($signature)) {
|
||||
throw new InvalidSignatureException();
|
||||
}
|
||||
|
||||
/** @var \Laravel\SerializableClosure\Contracts\Serializable $serializable */
|
||||
$serializable = unserialize($signature['serializable']);
|
||||
|
||||
$this->closure = $serializable->getClosure();
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Signers;
|
||||
|
||||
use Laravel\SerializableClosure\Contracts\Signer;
|
||||
|
||||
class Hmac implements Signer
|
||||
{
|
||||
/**
|
||||
* The secret key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $secret;
|
||||
|
||||
/**
|
||||
* Creates a new signer instance.
|
||||
*
|
||||
* @param string $secret
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($secret)
|
||||
{
|
||||
$this->secret = $secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign the given serializable.
|
||||
*
|
||||
* @param string $serialized
|
||||
* @return array
|
||||
*/
|
||||
public function sign($serialized)
|
||||
{
|
||||
return [
|
||||
'serializable' => $serialized,
|
||||
'hash' => base64_encode(hash_hmac('sha256', $serialized, $this->secret, true)),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the given signature.
|
||||
*
|
||||
* @param array $signature
|
||||
* @return bool
|
||||
*/
|
||||
public function verify($signature)
|
||||
{
|
||||
return hash_equals(base64_encode(
|
||||
hash_hmac('sha256', $signature['serializable'], $this->secret, true)
|
||||
), $signature['hash']);
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Support;
|
||||
|
||||
use SplObjectStorage;
|
||||
|
||||
class ClosureScope extends SplObjectStorage
|
||||
{
|
||||
/**
|
||||
* The number of serializations in current scope.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $serializations = 0;
|
||||
|
||||
/**
|
||||
* The number of closures that have to be serialized.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $toSerialize = 0;
|
||||
}
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Support;
|
||||
|
||||
#[\AllowDynamicProperties]
|
||||
class ClosureStream
|
||||
{
|
||||
/**
|
||||
* The stream protocol.
|
||||
*/
|
||||
const STREAM_PROTO = 'laravel-serializable-closure';
|
||||
|
||||
/**
|
||||
* Checks if this stream is registered.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $isRegistered = false;
|
||||
|
||||
/**
|
||||
* The stream content.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $content;
|
||||
|
||||
/**
|
||||
* The stream content.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $length;
|
||||
|
||||
/**
|
||||
* The stream pointer.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $pointer = 0;
|
||||
|
||||
/**
|
||||
* Opens file or URL.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $mode
|
||||
* @param string $options
|
||||
* @param string|null $opened_path
|
||||
* @return bool
|
||||
*/
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
$this->content = "<?php\nreturn ".substr($path, strlen(static::STREAM_PROTO.'://')).';';
|
||||
$this->length = strlen($this->content);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from stream.
|
||||
*
|
||||
* @param int $count
|
||||
* @return string
|
||||
*/
|
||||
public function stream_read($count)
|
||||
{
|
||||
$value = substr($this->content, $this->pointer, $count);
|
||||
|
||||
$this->pointer += $count;
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for end-of-file on a file pointer.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function stream_eof()
|
||||
{
|
||||
return $this->pointer >= $this->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change stream options.
|
||||
*
|
||||
* @param int $option
|
||||
* @param int $arg1
|
||||
* @param int $arg2
|
||||
* @return bool
|
||||
*/
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve information about a file resource.
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function stream_stat()
|
||||
{
|
||||
$stat = stat(__FILE__);
|
||||
// @phpstan-ignore-next-line
|
||||
$stat[7] = $stat['size'] = $this->length;
|
||||
|
||||
return $stat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve information about a file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $flags
|
||||
* @return array|bool
|
||||
*/
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$stat = stat(__FILE__);
|
||||
// @phpstan-ignore-next-line
|
||||
$stat[7] = $stat['size'] = $this->length;
|
||||
|
||||
return $stat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seeks to specific location in a stream.
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int $whence
|
||||
* @return bool
|
||||
*/
|
||||
public function stream_seek($offset, $whence = SEEK_SET)
|
||||
{
|
||||
$crt = $this->pointer;
|
||||
|
||||
switch ($whence) {
|
||||
case SEEK_SET:
|
||||
$this->pointer = $offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
$this->pointer += $offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
$this->pointer = $this->length + $offset;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->pointer < 0 || $this->pointer >= $this->length) {
|
||||
$this->pointer = $crt;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current position of a stream.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the stream.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function register()
|
||||
{
|
||||
if (! static::$isRegistered) {
|
||||
static::$isRegistered = stream_wrapper_register(static::STREAM_PROTO, __CLASS__);
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+1198
File diff suppressed because it is too large
Load Diff
+24
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure\Support;
|
||||
|
||||
class SelfReference
|
||||
{
|
||||
/**
|
||||
* The unique hash representing the object.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $hash;
|
||||
|
||||
/**
|
||||
* Creates a new self reference instance.
|
||||
*
|
||||
* @param string $hash
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($hash)
|
||||
{
|
||||
$this->hash = $hash;
|
||||
}
|
||||
}
|
||||
Vendored
+82
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\SerializableClosure;
|
||||
|
||||
use Closure;
|
||||
use Laravel\SerializableClosure\Exceptions\PhpVersionNotSupportedException;
|
||||
|
||||
class UnsignedSerializableClosure
|
||||
{
|
||||
/**
|
||||
* The closure's serializable.
|
||||
*
|
||||
* @var \Laravel\SerializableClosure\Contracts\Serializable
|
||||
*/
|
||||
protected $serializable;
|
||||
|
||||
/**
|
||||
* Creates a new serializable closure instance.
|
||||
*
|
||||
* @param \Closure $closure
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Closure $closure)
|
||||
{
|
||||
if (\PHP_VERSION_ID < 70400) {
|
||||
throw new PhpVersionNotSupportedException();
|
||||
}
|
||||
|
||||
$this->serializable = new Serializers\Native($closure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the closure with the given arguments.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
if (\PHP_VERSION_ID < 70400) {
|
||||
throw new PhpVersionNotSupportedException();
|
||||
}
|
||||
|
||||
return call_user_func_array($this->serializable, func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the closure.
|
||||
*
|
||||
* @return \Closure
|
||||
*/
|
||||
public function getClosure()
|
||||
{
|
||||
if (\PHP_VERSION_ID < 70400) {
|
||||
throw new PhpVersionNotSupportedException();
|
||||
}
|
||||
|
||||
return $this->serializable->getClosure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the serializable representation of the closure.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
return [
|
||||
'serializable' => $this->serializable,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the closure after serialization.
|
||||
*
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function __unserialize($data)
|
||||
{
|
||||
$this->serializable = $data['serializable'];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user