One Hat Cyber Team
Your IP:
216.73.216.102
Server IP:
198.54.114.155
Server:
Linux server71.web-hosting.com 4.18.0-513.18.1.lve.el8.x86_64 #1 SMP Thu Feb 22 12:55:50 UTC 2024 x86_64
Server Software:
LiteSpeed
PHP Version:
5.6.40
Create File
|
Create Folder
Execute
Dir :
~
/
home
/
fluxyjvi
/
www
/
assets
/
images
/
Edit File:
serializable-closure.tar
src/Contracts/Signer.php 0000644 00000000604 15107461606 0011241 0 ustar 00 <?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); } src/Contracts/Serializable.php 0000644 00000000541 15107461606 0012420 0 ustar 00 <?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(); } src/Exceptions/PhpVersionNotSupportedException.php 0000644 00000000564 15107461606 0016543 0 ustar 00 <?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); } } src/Exceptions/InvalidSignatureException.php 0000644 00000000651 15107461606 0015324 0 ustar 00 <?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); } } src/Exceptions/MissingSecretKeyException.php 0000644 00000000613 15107461606 0015302 0 ustar 00 <?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); } } src/Signers/Hmac.php 0000644 00000002061 15107461606 0010333 0 ustar 00 <?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']); } } src/Support/ReflectionClosure.php 0000644 00000131005 15107461606 0013155 0 ustar 00 <?php namespace Laravel\SerializableClosure\Support; defined('T_NAME_QUALIFIED') || define('T_NAME_QUALIFIED', -4); defined('T_NAME_FULLY_QUALIFIED') || define('T_NAME_FULLY_QUALIFIED', -5); defined('T_FN') || define('T_FN', -6); defined('T_NULLSAFE_OBJECT_OPERATOR') || define('T_NULLSAFE_OBJECT_OPERATOR', -7); use Closure; use ReflectionFunction; class ReflectionClosure extends ReflectionFunction { protected $code; protected $tokens; protected $hashedName; protected $useVariables; protected $isStaticClosure; protected $isScopeRequired; protected $isBindingRequired; protected $isShortClosure; protected static $files = []; protected static $classes = []; protected static $functions = []; protected static $constants = []; protected static $structures = []; /** * Creates a new reflection closure instance. * * @param \Closure $closure * @param string|null $code * @return void */ public function __construct(Closure $closure, $code = null) { parent::__construct($closure); } /** * Checks if the closure is "static". * * @return bool */ public function isStatic(): bool { if ($this->isStaticClosure === null) { $this->isStaticClosure = strtolower(substr($this->getCode(), 0, 6)) === 'static'; } return $this->isStaticClosure; } /** * Checks if the closure is a "short closure". * * @return bool */ public function isShortClosure() { if ($this->isShortClosure === null) { $code = $this->getCode(); if ($this->isStatic()) { $code = substr($code, 6); } $this->isShortClosure = strtolower(substr(trim($code), 0, 2)) === 'fn'; } return $this->isShortClosure; } /** * Get the closure's code. * * @return string */ public function getCode() { if ($this->code !== null) { return $this->code; } $fileName = $this->getFileName(); $line = $this->getStartLine() - 1; $className = null; if (null !== $className = $this->getClosureScopeClass()) { $className = '\\'.trim($className->getName(), '\\'); } $builtin_types = self::getBuiltinTypes(); $class_keywords = ['self', 'static', 'parent']; $ns = $this->getClosureNamespaceName(); $nsf = $ns == '' ? '' : ($ns[0] == '\\' ? $ns : '\\'.$ns); $_file = var_export($fileName, true); $_dir = var_export(dirname($fileName), true); $_namespace = var_export($ns, true); $_class = var_export(trim($className ?: '', '\\'), true); $_function = $ns.($ns == '' ? '' : '\\').'{closure}'; $_method = ($className == '' ? '' : trim($className, '\\').'::').$_function; $_function = var_export($_function, true); $_method = var_export($_method, true); $_trait = null; $tokens = $this->getTokens(); $state = $lastState = 'start'; $inside_structure = false; $isFirstClassCallable = false; $isShortClosure = false; $inside_structure_mark = 0; $open = 0; $code = ''; $id_start = $id_start_ci = $id_name = $context = ''; $classes = $functions = $constants = null; $use = []; $lineAdd = 0; $isUsingScope = false; $isUsingThisObject = false; for ($i = 0, $l = count($tokens); $i < $l; $i++) { $token = $tokens[$i]; switch ($state) { case 'start': if ($token[0] === T_FUNCTION || $token[0] === T_STATIC) { $code .= $token[1]; $state = $token[0] === T_FUNCTION ? 'function' : 'static'; } elseif ($token[0] === T_FN) { $isShortClosure = true; $code .= $token[1]; $state = 'closure_args'; } elseif ($token[0] === T_PUBLIC || $token[0] === T_PROTECTED || $token[0] === T_PRIVATE) { $code = ''; $isFirstClassCallable = true; } break; case 'static': if ($token[0] === T_WHITESPACE || $token[0] === T_COMMENT || $token[0] === T_FUNCTION) { $code .= $token[1]; if ($token[0] === T_FUNCTION) { $state = 'function'; } } elseif ($token[0] === T_FN) { $isShortClosure = true; $code .= $token[1]; $state = 'closure_args'; } else { $code = ''; $state = 'start'; } break; case 'function': switch ($token[0]) { case T_STRING: if ($isFirstClassCallable) { $state = 'closure_args'; break; } $code = ''; $state = 'named_function'; break; case '(': $code .= '('; $state = 'closure_args'; break; default: $code .= is_array($token) ? $token[1] : $token; } break; case 'named_function': if ($token[0] === T_FUNCTION || $token[0] === T_STATIC) { $code = $token[1]; $state = $token[0] === T_FUNCTION ? 'function' : 'static'; } elseif ($token[0] === T_FN) { $isShortClosure = true; $code .= $token[1]; $state = 'closure_args'; } break; case 'closure_args': switch ($token[0]) { case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $context = 'args'; $state = 'id_name'; $lastState = 'closure_args'; break; case T_NS_SEPARATOR: case T_STRING: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $context = 'args'; $state = 'id_name'; $lastState = 'closure_args'; break; case T_USE: $code .= $token[1]; $state = 'use'; break; case T_DOUBLE_ARROW: $code .= $token[1]; if ($isShortClosure) { $state = 'closure'; } break; case ':': $code .= ':'; $state = 'return'; break; case '{': $code .= '{'; $state = 'closure'; $open++; break; default: $code .= is_array($token) ? $token[1] : $token; } break; case 'use': switch ($token[0]) { case T_VARIABLE: $use[] = substr($token[1], 1); $code .= $token[1]; break; case '{': $code .= '{'; $state = 'closure'; $open++; break; case ':': $code .= ':'; $state = 'return'; break; default: $code .= is_array($token) ? $token[1] : $token; break; } break; case 'return': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: $code .= $token[1]; break; case T_NS_SEPARATOR: case T_STRING: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $context = 'return_type'; $state = 'id_name'; $lastState = 'return'; break 2; case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $context = 'return_type'; $state = 'id_name'; $lastState = 'return'; break 2; case T_DOUBLE_ARROW: $code .= $token[1]; if ($isShortClosure) { $state = 'closure'; } break; case '{': $code .= '{'; $state = 'closure'; $open++; break; default: $code .= is_array($token) ? $token[1] : $token; break; } break; case 'closure': switch ($token[0]) { case T_CURLY_OPEN: case T_DOLLAR_OPEN_CURLY_BRACES: case '{': $code .= is_array($token) ? $token[1] : $token; $open++; break; case '}': $code .= '}'; if (--$open === 0 && ! $isShortClosure) { break 3; } elseif ($inside_structure) { $inside_structure = ! ($open === $inside_structure_mark); } break; case '(': case '[': $code .= $token[0]; if ($isShortClosure) { $open++; } break; case ')': case ']': if ($isShortClosure) { if ($open === 0) { break 3; } $open--; } $code .= $token[0]; break; case ',': case ';': if ($isShortClosure && $open === 0) { break 3; } $code .= $token[0]; break; case T_LINE: $code .= $token[2] - $line + $lineAdd; break; case T_FILE: $code .= $_file; break; case T_DIR: $code .= $_dir; break; case T_NS_C: $code .= $_namespace; break; case T_CLASS_C: $code .= $inside_structure ? $token[1] : $_class; break; case T_FUNC_C: $code .= $inside_structure ? $token[1] : $_function; break; case T_METHOD_C: $code .= $inside_structure ? $token[1] : $_method; break; case T_COMMENT: if (substr($token[1], 0, 8) === '#trackme') { $timestamp = time(); $code .= '/**'.PHP_EOL; $code .= '* Date : '.date(DATE_W3C, $timestamp).PHP_EOL; $code .= '* Timestamp : '.$timestamp.PHP_EOL; $code .= '* Line : '.($line + 1).PHP_EOL; $code .= '* File : '.$_file.PHP_EOL.'*/'.PHP_EOL; $lineAdd += 5; } else { $code .= $token[1]; } break; case T_VARIABLE: if ($token[1] == '$this' && ! $inside_structure) { $isUsingThisObject = true; } $code .= $token[1]; break; case T_STATIC: case T_NS_SEPARATOR: case T_STRING: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $context = 'root'; $state = 'id_name'; $lastState = 'closure'; break 2; case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $context = 'root'; $state = 'id_name'; $lastState = 'closure'; break 2; case T_NEW: $code .= $token[1]; $context = 'new'; $state = 'id_start'; $lastState = 'closure'; break 2; case T_USE: $code .= $token[1]; $context = 'use'; $state = 'id_start'; $lastState = 'closure'; break; case T_INSTANCEOF: case T_INSTEADOF: $code .= $token[1]; $context = 'instanceof'; $state = 'id_start'; $lastState = 'closure'; break; case T_OBJECT_OPERATOR: case T_NULLSAFE_OBJECT_OPERATOR: case T_DOUBLE_COLON: $code .= $token[1]; $lastState = 'closure'; $state = 'ignore_next'; break; case T_FUNCTION: $code .= $token[1]; $state = 'closure_args'; if (! $inside_structure) { $inside_structure = true; $inside_structure_mark = $open; } break; case T_TRAIT_C: if ($_trait === null) { $startLine = $this->getStartLine(); $endLine = $this->getEndLine(); $structures = $this->getStructures(); $_trait = ''; foreach ($structures as &$struct) { if ($struct['type'] === 'trait' && $struct['start'] <= $startLine && $struct['end'] >= $endLine ) { $_trait = ($ns == '' ? '' : $ns.'\\').$struct['name']; break; } } $_trait = var_export($_trait, true); } $code .= $_trait; break; default: $code .= is_array($token) ? $token[1] : $token; } break; case 'ignore_next': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: $code .= $token[1]; break; case T_CLASS: case T_NEW: case T_STATIC: case T_VARIABLE: case T_STRING: case T_CLASS_C: case T_FILE: case T_DIR: case T_METHOD_C: case T_FUNC_C: case T_FUNCTION: case T_INSTANCEOF: case T_LINE: case T_NS_C: case T_TRAIT_C: case T_USE: $code .= $token[1]; $state = $lastState; break; default: $state = $lastState; $i--; } break; case 'id_start': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: $code .= $token[1]; break; case T_NS_SEPARATOR: case T_NAME_FULLY_QUALIFIED: case T_STRING: case T_STATIC: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $state = 'id_name'; break 2; case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $state = 'id_name'; break 2; case T_VARIABLE: $code .= $token[1]; $state = $lastState; break; case T_CLASS: $code .= $token[1]; $state = 'anonymous'; break; default: $i--; //reprocess last $state = 'id_name'; } break; case 'id_name': switch ($token[0]) { // named arguments... case ':': if ($lastState === 'closure' && $context === 'root') { $state = 'closure'; $code .= $id_start.$token; } break; case T_NAME_QUALIFIED: case T_NS_SEPARATOR: case T_STRING: case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: $id_name .= $token[1]; break; case '(': if ($isShortClosure) { $open++; } if ($context === 'new' || false !== strpos($id_name, '\\')) { if ($id_start_ci === 'self' || $id_start_ci === 'static') { if (! $inside_structure) { $isUsingScope = true; } } elseif ($id_start !== '\\' && ! in_array($id_start_ci, $class_keywords)) { if ($classes === null) { $classes = $this->getClasses(); } if (isset($classes[$id_start_ci])) { $id_start = $classes[$id_start_ci]; } if ($id_start[0] !== '\\') { $id_start = $nsf.'\\'.$id_start; } } } else { if ($id_start !== '\\') { if ($functions === null) { $functions = $this->getFunctions(); } if (isset($functions[$id_start_ci])) { $id_start = $functions[$id_start_ci]; } elseif ($nsf !== '\\' && function_exists($nsf.'\\'.$id_start)) { $id_start = $nsf.'\\'.$id_start; // Cache it to functions array $functions[$id_start_ci] = $id_start; } } } $code .= $id_start.$id_name.'('; $state = $lastState; break; case T_VARIABLE: case T_DOUBLE_COLON: if ($id_start !== '\\') { if ($id_start_ci === 'self' || $id_start_ci === 'parent') { if (! $inside_structure) { $isUsingScope = true; } } elseif ($id_start_ci === 'static') { if (! $inside_structure) { $isUsingScope = $token[0] === T_DOUBLE_COLON; } } elseif (! (\PHP_MAJOR_VERSION >= 7 && in_array($id_start_ci, $builtin_types))) { if ($classes === null) { $classes = $this->getClasses(); } if (isset($classes[$id_start_ci])) { $id_start = $classes[$id_start_ci]; } if ($id_start[0] !== '\\') { $id_start = $nsf.'\\'.$id_start; } } } $code .= $id_start.$id_name.$token[1]; $state = $token[0] === T_DOUBLE_COLON ? 'ignore_next' : $lastState; break; default: if ($id_start !== '\\' && ! defined($id_start)) { if ($constants === null) { $constants = $this->getConstants(); } if (isset($constants[$id_start])) { $id_start = $constants[$id_start]; } elseif ($context === 'new') { if (in_array($id_start_ci, $class_keywords)) { if (! $inside_structure) { $isUsingScope = true; } } else { if ($classes === null) { $classes = $this->getClasses(); } if (isset($classes[$id_start_ci])) { $id_start = $classes[$id_start_ci]; } if ($id_start[0] !== '\\') { $id_start = $nsf.'\\'.$id_start; } } } elseif ($context === 'use' || $context === 'instanceof' || $context === 'args' || $context === 'return_type' || $context === 'extends' || $context === 'root' ) { if (in_array($id_start_ci, $class_keywords)) { if (! $inside_structure && ! $id_start_ci === 'static') { $isUsingScope = true; } } elseif (! (\PHP_MAJOR_VERSION >= 7 && in_array($id_start_ci, $builtin_types))) { if ($classes === null) { $classes = $this->getClasses(); } if (isset($classes[$id_start_ci])) { $id_start = $classes[$id_start_ci]; } if ($id_start[0] !== '\\') { $id_start = $nsf.'\\'.$id_start; } } } } $code .= $id_start.$id_name; $state = $lastState; $i--; //reprocess last token } break; case 'anonymous': switch ($token[0]) { case T_NAME_QUALIFIED: [$id_start, $id_start_ci, $id_name] = $this->parseNameQualified($token[1]); $state = 'id_name'; $lastState = 'anonymous'; break 2; case T_NS_SEPARATOR: case T_STRING: $id_start = $token[1]; $id_start_ci = strtolower($id_start); $id_name = ''; $state = 'id_name'; $context = 'extends'; $lastState = 'anonymous'; break; case '{': $state = 'closure'; if (! $inside_structure) { $inside_structure = true; $inside_structure_mark = $open; } $i--; break; default: $code .= is_array($token) ? $token[1] : $token; } break; } } if ($isShortClosure) { $this->useVariables = $this->getStaticVariables(); } else { $this->useVariables = empty($use) ? $use : array_intersect_key($this->getStaticVariables(), array_flip($use)); } $this->isShortClosure = $isShortClosure; $this->isBindingRequired = $isUsingThisObject; $this->isScopeRequired = $isUsingScope; if (PHP_VERSION_ID >= 80100) { $attributesCode = array_map(function ($attribute) { $arguments = $attribute->getArguments(); $name = $attribute->getName(); $arguments = implode(', ', array_map(function ($argument, $key) { $argument = sprintf("'%s'", str_replace("'", "\\'", $argument)); if (is_string($key)) { $argument = sprintf('%s: %s', $key, $argument); } return $argument; }, $arguments, array_keys($arguments))); return "#[$name($arguments)]"; }, $this->getAttributes()); if (! empty($attributesCode)) { $code = implode("\n", array_merge($attributesCode, [$code])); } } $this->code = $code; return $this->code; } /** * Get PHP native built in types. * * @return array */ protected static function getBuiltinTypes() { // PHP 8.1 if (PHP_VERSION_ID >= 80100) { return ['array', 'callable', 'string', 'int', 'bool', 'float', 'iterable', 'void', 'object', 'mixed', 'false', 'null', 'never']; } // PHP 8 if (\PHP_MAJOR_VERSION === 8) { return ['array', 'callable', 'string', 'int', 'bool', 'float', 'iterable', 'void', 'object', 'mixed', 'false', 'null']; } // PHP 7 switch (\PHP_MINOR_VERSION) { case 0: return ['array', 'callable', 'string', 'int', 'bool', 'float']; case 1: return ['array', 'callable', 'string', 'int', 'bool', 'float', 'iterable', 'void']; default: return ['array', 'callable', 'string', 'int', 'bool', 'float', 'iterable', 'void', 'object']; } } /** * Gets the use variables by the closure. * * @return array */ public function getUseVariables() { if ($this->useVariables !== null) { return $this->useVariables; } $tokens = $this->getTokens(); $use = []; $state = 'start'; foreach ($tokens as &$token) { $is_array = is_array($token); switch ($state) { case 'start': if ($is_array && $token[0] === T_USE) { $state = 'use'; } break; case 'use': if ($is_array) { if ($token[0] === T_VARIABLE) { $use[] = substr($token[1], 1); } } elseif ($token == ')') { break 2; } break; } } $this->useVariables = empty($use) ? $use : array_intersect_key($this->getStaticVariables(), array_flip($use)); return $this->useVariables; } /** * Checks if binding is required. * * @return bool */ public function isBindingRequired() { if ($this->isBindingRequired === null) { $this->getCode(); } return $this->isBindingRequired; } /** * Checks if access to the scope is required. * * @return bool */ public function isScopeRequired() { if ($this->isScopeRequired === null) { $this->getCode(); } return $this->isScopeRequired; } /** * The the hash of the current file name. * * @return string */ protected function getHashedFileName() { if ($this->hashedName === null) { $this->hashedName = sha1($this->getFileName()); } return $this->hashedName; } /** * Get the file tokens. * * @return array */ protected function getFileTokens() { $key = $this->getHashedFileName(); if (! isset(static::$files[$key])) { static::$files[$key] = token_get_all(file_get_contents($this->getFileName())); } return static::$files[$key]; } /** * Get the tokens. * * @return array */ protected function getTokens() { if ($this->tokens === null) { $tokens = $this->getFileTokens(); $startLine = $this->getStartLine(); $endLine = $this->getEndLine(); $results = []; $start = false; foreach ($tokens as &$token) { if (! is_array($token)) { if ($start) { $results[] = $token; } continue; } $line = $token[2]; if ($line <= $endLine) { if ($line >= $startLine) { $start = true; $results[] = $token; } continue; } break; } $this->tokens = $results; } return $this->tokens; } /** * Get the classes. * * @return array */ protected function getClasses() { $key = $this->getHashedFileName(); if (! isset(static::$classes[$key])) { $this->fetchItems(); } return static::$classes[$key]; } /** * Get the functions. * * @return array */ protected function getFunctions() { $key = $this->getHashedFileName(); if (! isset(static::$functions[$key])) { $this->fetchItems(); } return static::$functions[$key]; } /** * Gets the constants. * * @return array */ protected function getConstants() { $key = $this->getHashedFileName(); if (! isset(static::$constants[$key])) { $this->fetchItems(); } return static::$constants[$key]; } /** * Get the structures. * * @return array */ protected function getStructures() { $key = $this->getHashedFileName(); if (! isset(static::$structures[$key])) { $this->fetchItems(); } return static::$structures[$key]; } /** * Fetch the items. * * @return void. */ protected function fetchItems() { $key = $this->getHashedFileName(); $classes = []; $functions = []; $constants = []; $structures = []; $tokens = $this->getFileTokens(); $open = 0; $state = 'start'; $lastState = ''; $prefix = ''; $name = ''; $alias = ''; $isFunc = $isConst = false; $startLine = $endLine = 0; $structType = $structName = ''; $structIgnore = false; foreach ($tokens as $token) { switch ($state) { case 'start': switch ($token[0]) { case T_CLASS: case T_INTERFACE: case T_TRAIT: $state = 'before_structure'; $startLine = $token[2]; $structType = $token[0] == T_CLASS ? 'class' : ($token[0] == T_INTERFACE ? 'interface' : 'trait'); break; case T_USE: $state = 'use'; $prefix = $name = $alias = ''; $isFunc = $isConst = false; break; case T_FUNCTION: $state = 'structure'; $structIgnore = true; break; case T_NEW: $state = 'new'; break; case T_OBJECT_OPERATOR: case T_DOUBLE_COLON: $state = 'invoke'; break; } break; case 'use': switch ($token[0]) { case T_FUNCTION: $isFunc = true; break; case T_CONST: $isConst = true; break; case T_NS_SEPARATOR: $name .= $token[1]; break; case T_STRING: $name .= $token[1]; $alias = $token[1]; break; case T_NAME_QUALIFIED: $name .= $token[1]; $pieces = explode('\\', $token[1]); $alias = end($pieces); break; case T_AS: $lastState = 'use'; $state = 'alias'; break; case '{': $prefix = $name; $name = $alias = ''; $state = 'use-group'; break; case ',': case ';': if ($name === '' || $name[0] !== '\\') { $name = '\\'.$name; } if ($alias !== '') { if ($isFunc) { $functions[strtolower($alias)] = $name; } elseif ($isConst) { $constants[$alias] = $name; } else { $classes[strtolower($alias)] = $name; } } $name = $alias = ''; $state = $token === ';' ? 'start' : 'use'; break; } break; case 'use-group': switch ($token[0]) { case T_NS_SEPARATOR: $name .= $token[1]; break; case T_NAME_QUALIFIED: $name .= $token[1]; $pieces = explode('\\', $token[1]); $alias = end($pieces); break; case T_STRING: $name .= $token[1]; $alias = $token[1]; break; case T_AS: $lastState = 'use-group'; $state = 'alias'; break; case ',': case '}': if ($prefix === '' || $prefix[0] !== '\\') { $prefix = '\\'.$prefix; } if ($alias !== '') { if ($isFunc) { $functions[strtolower($alias)] = $prefix.$name; } elseif ($isConst) { $constants[$alias] = $prefix.$name; } else { $classes[strtolower($alias)] = $prefix.$name; } } $name = $alias = ''; $state = $token === '}' ? 'use' : 'use-group'; break; } break; case 'alias': if ($token[0] === T_STRING) { $alias = $token[1]; $state = $lastState; } break; case 'new': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: break 2; case T_CLASS: $state = 'structure'; $structIgnore = true; break; default: $state = 'start'; } break; case 'invoke': switch ($token[0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: break 2; default: $state = 'start'; } break; case 'before_structure': if ($token[0] == T_STRING) { $structName = $token[1]; $state = 'structure'; } break; case 'structure': switch ($token[0]) { case '{': case T_CURLY_OPEN: case T_DOLLAR_OPEN_CURLY_BRACES: $open++; break; case '}': if (--$open == 0) { if (! $structIgnore) { $structures[] = [ 'type' => $structType, 'name' => $structName, 'start' => $startLine, 'end' => $endLine, ]; } $structIgnore = false; $state = 'start'; } break; default: if (is_array($token)) { $endLine = $token[2]; } } break; } } static::$classes[$key] = $classes; static::$functions[$key] = $functions; static::$constants[$key] = $constants; static::$structures[$key] = $structures; } /** * Returns the namespace associated to the closure. * * @return string */ protected function getClosureNamespaceName() { $ns = $this->getNamespaceName(); // First class callables... if ($this->getName() !== '{closure}' && empty($ns) && ! is_null($this->getClosureScopeClass())) { $ns = $this->getClosureScopeClass()->getNamespaceName(); } return $ns; } /** * Parse the given token. * * @param string $token * @return array */ protected function parseNameQualified($token) { $pieces = explode('\\', $token); $id_start = array_shift($pieces); $id_start_ci = strtolower($id_start); $id_name = '\\'.implode('\\', $pieces); return [$id_start, $id_start_ci, $id_name]; } } src/Support/ClosureStream.php 0000644 00000007007 15107461606 0012322 0 ustar 00 <?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__); } } } src/Support/SelfReference.php 0000644 00000000602 15107461606 0012234 0 ustar 00 <?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; } } src/Support/ClosureScope.php 0000644 00000000572 15107461606 0012140 0 ustar 00 <?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; } src/Serializers/Native.php 0000644 00000034020 15107461606 0011573 0 ustar 00 <?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()); } } } src/Serializers/Signed.php 0000644 00000004124 15107461606 0011560 0 ustar 00 <?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(); } } src/UnsignedSerializableClosure.php 0000644 00000003316 15107461606 0013515 0 ustar 00 <?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']; } } src/SerializableClosure.php 0000644 00000006453 15107461606 0012025 0 ustar 00 <?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']; } } README.md 0000644 00000005517 15107461606 0006041 0 ustar 00 # Serializable Closure <a href="https://github.com/laravel/serializable-closure/actions"> <img src="https://github.com/laravel/serializable-closure/workflows/tests/badge.svg" alt="Build Status"> </a> <a href="https://packagist.org/packages/laravel/serializable-closure"> <img src="https://img.shields.io/packagist/dt/laravel/serializable-closure" alt="Total Downloads"> </a> <a href="https://packagist.org/packages/laravel/serializable-closure"> <img src="https://img.shields.io/packagist/v/laravel/serializable-closure" alt="Latest Stable Version"> </a> <a href="https://packagist.org/packages/laravel/serializable-closure"> <img src="https://img.shields.io/packagist/l/laravel/serializable-closure" alt="License"> </a> ## Introduction > This project is a fork of the excellent [opis/closure: 3.x](https://github.com/opis/closure) package. At Laravel, we decided to fork this package as the upcoming version [4.x](https://github.com/opis/closure) is a complete rewrite on top of the [FFI extension](https://www.php.net/manual/en/book.ffi.php). As Laravel is a web framework, and FFI is not enabled by default in web requests, this fork allows us to keep using the `3.x` series while adding support for new PHP versions. Laravel Serializable Closure provides an easy and secure way to **serialize closures in PHP**. ## Official Documentation ### Installation > **Requires [PHP 7.4+](https://php.net/releases/)** First, install Laravel Serializable Closure via the [Composer](https://getcomposer.org/) package manager: ```bash composer require laravel/serializable-closure ``` ### Usage You may serialize a closure this way: ```php use Laravel\SerializableClosure\SerializableClosure; $closure = fn () => 'james'; // Recommended SerializableClosure::setSecretKey('secret'); $serialized = serialize(new SerializableClosure($closure)); $closure = unserialize($serialized)->getClosure(); echo $closure(); // james; ``` ### Caveats * Anonymous classes cannot be created within closures. * Attributes cannot be used within closures. * Serializing closures on REPL environments like Laravel Tinker is not supported. * Serializing closures that reference objects with readonly properties is not supported. ## Contributing Thank you for considering contributing to Serializable Closure! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). ## Code of Conduct In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). ## Security Vulnerabilities Please review [our security policy](https://github.com/laravel/serializable-closure/security/policy) on how to report security vulnerabilities. ## License Serializable Closure is open-sourced software licensed under the [MIT license](LICENSE.md). composer.json 0000644 00000002463 15107461606 0007301 0 ustar 00 { "name": "laravel/serializable-closure", "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", "keywords": ["laravel", "Serializable", "closure"], "license": "MIT", "support": { "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, "authors": [ { "name": "Taylor Otwell", "email": "taylor@laravel.com" }, { "name": "Nuno Maduro", "email": "nuno@laravel.com" } ], "require": { "php": "^7.3|^8.0" }, "require-dev": { "nesbot/carbon": "^2.61", "pestphp/pest": "^1.21.3", "phpstan/phpstan": "^1.8.2", "symfony/var-dumper": "^5.4.11" }, "autoload": { "psr-4": { "Laravel\\SerializableClosure\\": "src/" } }, "autoload-dev": { "psr-4": { "Tests\\": "tests/" } }, "extra": { "branch-alias": { "dev-master": "1.x-dev" } }, "config": { "sort-packages": true, "allow-plugins": { "pestphp/pest-plugin": true } }, "minimum-stability": "dev", "prefer-stable": true } LICENSE.md 0000644 00000002063 15107461606 0006157 0 ustar 00 The MIT License (MIT) Copyright (c) Taylor Otwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Simpan