���� JFIF    �� �        "" $(4,$&1'-=-157:::#+?D?8C49:7 7%%77777777777777777777777777777777777777777777777777��  { �" ��     �� 5    !1AQa"q�2��BR��#b�������  ��  ��   ? ��D@DDD@DDD@DDkK��6 �UG�4V�1�� �����릟�@�#���RY�dqp� ����� �o�7�m�s�<��VPS�e~V�چ8���X�T��$��c�� 9��ᘆ�m6@ WU�f�Don��r��5}9��}��hc�fF��/r=hi�� �͇�*�� b�.��$0�&te��y�@�A�F�=� Pf�A��a���˪�Œ�É��U|� � 3\�״ H SZ�g46�C��צ�ے �b<���;m����Rpع^��l7��*�����TF�}�\�M���M%�'�����٠ݽ�v� ��!-�����?�N!La��A+[`#���M����'�~oR�?��v^)��=��h����A��X�.���˃����^Ə��ܯsO"B�c>; �e�4��5�k��/CB��.  �J?��;�҈�������������������~�<�VZ�ꭼ2/)Í”jC���ע�V�G�!���!�F������\�� Kj�R�oc�h���:Þ I��1"2�q×°8��Р@ז���_C0�ր��A��lQ��@纼�!7��F�� �]�sZ B�62r�v�z~�K�7�c��5�.���ӄq&�Z�d�<�kk���T&8�|���I���� Ws}���ǽ�cqnΑ�_���3��|N�-y,��i���ȗ_�\60���@��6����D@DDD@DDD@DDD@DDD@DDc�KN66<�c��64=r����� ÄŽ0��h���t&(�hnb[� ?��^��\��â|�,�/h�\��R��5�? �0�!צ܉-����G����٬��Q�zA���1�����V��� �:R���`�$��ik��H����D4�����#dk����� h�}����7���w%�������*o8wG�LycuT�.���ܯ7��I��u^���)��/c�,s�Nq�ۺ�;�ך�YH2���.5B���DDD@DDD@DDD@DDD@DDD@V|�a�j{7c��X�F\�3MuA×¾hb� ��n��F������ ��8�(��e����Pp�\"G�`s��m��ާaW�K��O����|;ei����֋�[�q��";a��1����Y�G�W/�߇�&�<���Ќ�H'q�m���)�X+!���=�m�ۚ丷~6a^X�)���,�>#&6G���Y��{����"" """ """ """ """ ""��at\/�a�8 �yp%�lhl�n����)���i�t��B�������������?��modskinlienminh.com - WSOX ENC PK!C4$3 "guzzlehttp/promises/src/Create.phpnu[then([$promise, 'resolve'], [$promise, 'reject']); return $promise; } return new \YoastSEO_Vendor\GuzzleHttp\Promise\FulfilledPromise($value); } /** * Creates a rejected promise for a reason if the reason is not a promise. * If the provided reason is a promise, then it is returned as-is. * * @param mixed $reason Promise or reason. */ public static function rejectionFor($reason) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { if ($reason instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface) { return $reason; } return new \YoastSEO_Vendor\GuzzleHttp\Promise\RejectedPromise($reason); } /** * Create an exception for a rejected promise value. * * @param mixed $reason */ public static function exceptionFor($reason) : \Throwable { if ($reason instanceof \Throwable) { return $reason; } return new \YoastSEO_Vendor\GuzzleHttp\Promise\RejectionException($reason); } /** * Returns an iterator for the given value. * * @param mixed $value */ public static function iterFor($value) : \Iterator { if ($value instanceof \Iterator) { return $value; } if (\is_array($value)) { return new \ArrayIterator($value); } return new \ArrayIterator([$value]); } } PK!Xa1guzzlehttp/promises/src/CancellationException.phpnu[ $onFulfilled, 'rejected' => $onRejected]))->promise(); } /** * Like of, but only allows a certain number of outstanding promises at any * given time. * * $concurrency may be an integer or a function that accepts the number of * pending promises and returns a numeric concurrency limit value to allow * for dynamic a concurrency size. * * @param mixed $iterable * @param int|callable $concurrency */ public static function ofLimit($iterable, $concurrency, callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return (new \YoastSEO_Vendor\GuzzleHttp\Promise\EachPromise($iterable, ['fulfilled' => $onFulfilled, 'rejected' => $onRejected, 'concurrency' => $concurrency]))->promise(); } /** * Like limit, but ensures that no promise in the given $iterable argument * is rejected. If any promise is rejected, then the aggregate promise is * rejected with the encountered rejection. * * @param mixed $iterable * @param int|callable $concurrency */ public static function ofLimitAll($iterable, $concurrency, callable $onFulfilled = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return self::ofLimit($iterable, $concurrency, $onFulfilled, function ($reason, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $aggregate) : void { $aggregate->reject($reason); }); } } PK!2 .guzzlehttp/promises/src/AggregateException.phpnu[run(); * * @final */ class TaskQueue implements \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface { private $enableShutdown = \true; private $queue = []; public function __construct(bool $withShutdown = \true) { if ($withShutdown) { \register_shutdown_function(function () : void { if ($this->enableShutdown) { // Only run the tasks if an E_ERROR didn't occur. $err = \error_get_last(); if (!$err || $err['type'] ^ \E_ERROR) { $this->run(); } } }); } } public function isEmpty() : bool { return !$this->queue; } public function add(callable $task) : void { $this->queue[] = $task; } public function run() : void { while ($task = \array_shift($this->queue)) { /** @var callable $task */ $task(); } } /** * The task queue will be run and exhausted by default when the process * exits IFF the exit is not the result of a PHP E_ERROR error. * * You can disable running the automatic shutdown of the queue by calling * this function. If you disable the task queue shutdown process, then you * MUST either run the task queue (as a result of running your event loop * or manually using the run() method) or wait on each outstanding promise. * * Note: This shutdown will occur before any destructors are triggered. */ public function disableShutdown() : void { $this->enableShutdown = \false; } } PK!1guzzlehttp/promises/src/Is.phpnu[getState() === \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::PENDING; } /** * Returns true if a promise is fulfilled or rejected. */ public static function settled(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : bool { return $promise->getState() !== \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::PENDING; } /** * Returns true if a promise is fulfilled. */ public static function fulfilled(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : bool { return $promise->getState() === \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED; } /** * Returns true if a promise is rejected. */ public static function rejected(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : bool { return $promise->getState() === \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED; } } PK!2).guzzlehttp/promises/src/RejectionException.phpnu[reason = $reason; $message = 'The promise was rejected'; if ($description) { $message .= ' with reason: ' . $description; } elseif (\is_string($reason) || \is_object($reason) && \method_exists($reason, '__toString')) { $message .= ' with reason: ' . $this->reason; } elseif ($reason instanceof \JsonSerializable) { $message .= ' with reason: ' . \json_encode($this->reason, \JSON_PRETTY_PRINT); } parent::__construct($message); } /** * Returns the rejection reason. * * @return mixed */ public function getReason() { return $this->reason; } } PK!FB""!guzzlehttp/promises/src/Utils.phpnu[ * while ($eventLoop->isRunning()) { * GuzzleHttp\Promise\Utils::queue()->run(); * } * * * @param TaskQueueInterface|null $assign Optionally specify a new queue instance. */ public static function queue(\YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface $assign = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueueInterface { static $queue; if ($assign) { $queue = $assign; } elseif (!$queue) { $queue = new \YoastSEO_Vendor\GuzzleHttp\Promise\TaskQueue(); } return $queue; } /** * Adds a function to run in the task queue when it is next `run()` and * returns a promise that is fulfilled or rejected with the result. * * @param callable $task Task function to run. */ public static function task(callable $task) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { $queue = self::queue(); $promise = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$queue, 'run']); $queue->add(function () use($task, $promise) : void { try { if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($promise)) { $promise->resolve($task()); } } catch (\Throwable $e) { $promise->reject($e); } }); return $promise; } /** * Synchronously waits on a promise to resolve and returns an inspection * state array. * * Returns a state associative array containing a "state" key mapping to a * valid promise state. If the state of the promise is "fulfilled", the * array will contain a "value" key mapping to the fulfilled value of the * promise. If the promise is rejected, the array will contain a "reason" * key mapping to the rejection reason of the promise. * * @param PromiseInterface $promise Promise or value. */ public static function inspect(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise) : array { try { return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED, 'value' => $promise->wait()]; } catch (\YoastSEO_Vendor\GuzzleHttp\Promise\RejectionException $e) { return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e->getReason()]; } catch (\Throwable $e) { return ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $e]; } } /** * Waits on all of the provided promises, but does not unwrap rejected * promises as thrown exception. * * Returns an array of inspection state arrays. * * @see inspect for the inspection state array format. * * @param PromiseInterface[] $promises Traversable of promises to wait upon. */ public static function inspectAll($promises) : array { $results = []; foreach ($promises as $key => $promise) { $results[$key] = self::inspect($promise); } return $results; } /** * Waits on all of the provided promises and returns the fulfilled values. * * Returns an array that contains the value of each promise (in the same * order the promises were provided). An exception is thrown if any of the * promises are rejected. * * @param iterable $promises Iterable of PromiseInterface objects to wait on. * * @throws \Throwable on error */ public static function unwrap($promises) : array { $results = []; foreach ($promises as $key => $promise) { $results[$key] = $promise->wait(); } return $results; } /** * Given an array of promises, return a promise that is fulfilled when all * the items in the array are fulfilled. * * The promise's fulfillment value is an array with fulfillment values at * respective positions to the original array. If any promise in the array * rejects, the returned promise is rejected with the rejection reason. * * @param mixed $promises Promises or values. * @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution. */ public static function all($promises, bool $recursive = \false) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { $results = []; $promise = \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx) use(&$results) : void { $results[$idx] = $value; }, function ($reason, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\Promise $aggregate) : void { $aggregate->reject($reason); })->then(function () use(&$results) { \ksort($results); return $results; }); if (\true === $recursive) { $promise = $promise->then(function ($results) use($recursive, &$promises) { foreach ($promises as $promise) { if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($promise)) { return self::all($promises, $recursive); } } return $results; }); } return $promise; } /** * Initiate a competitive race between multiple promises or values (values * will become immediately fulfilled promises). * * When count amount of promises have been fulfilled, the returned promise * is fulfilled with an array that contains the fulfillment values of the * winners in order of resolution. * * This promise is rejected with a {@see AggregateException} if the number * of fulfilled promises is less than the desired $count. * * @param int $count Total number of promises. * @param mixed $promises Promises or values. */ public static function some(int $count, $promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { $results = []; $rejections = []; return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx, \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $p) use(&$results, $count) : void { if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::settled($p)) { return; } $results[$idx] = $value; if (\count($results) >= $count) { $p->resolve(null); } }, function ($reason) use(&$rejections) : void { $rejections[] = $reason; })->then(function () use(&$results, &$rejections, $count) { if (\count($results) !== $count) { throw new \YoastSEO_Vendor\GuzzleHttp\Promise\AggregateException('Not enough promises to fulfill count', $rejections); } \ksort($results); return \array_values($results); }); } /** * Like some(), with 1 as count. However, if the promise fulfills, the * fulfillment value is not an array of 1 but the value directly. * * @param mixed $promises Promises or values. */ public static function any($promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return self::some(1, $promises)->then(function ($values) { return $values[0]; }); } /** * Returns a promise that is fulfilled when all of the provided promises have * been fulfilled or rejected. * * The returned promise is fulfilled with an array of inspection state arrays. * * @see inspect for the inspection state array format. * * @param mixed $promises Promises or values. */ public static function settle($promises) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { $results = []; return \YoastSEO_Vendor\GuzzleHttp\Promise\Each::of($promises, function ($value, $idx) use(&$results) : void { $results[$idx] = ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::FULFILLED, 'value' => $value]; }, function ($reason, $idx) use(&$results) : void { $results[$idx] = ['state' => \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface::REJECTED, 'reason' => $reason]; })->then(function () use(&$results) { \ksort($results); return $results; }); } } PK!(Q.guzzlehttp/promises/src/TaskQueueInterface.phpnu[value = $value; } public function then(callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { // Return itself if there is no onFulfilled function. if (!$onFulfilled) { return $this; } $queue = \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue(); $p = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$queue, 'run']); $value = $this->value; $queue->add(static function () use($p, $value, $onFulfilled) : void { if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($p)) { try { $p->resolve($onFulfilled($value)); } catch (\Throwable $e) { $p->reject($e); } } }); return $p; } public function otherwise(callable $onRejected) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return $this->then(null, $onRejected); } public function wait(bool $unwrap = \true) { return $unwrap ? $this->value : null; } public function getState() : string { return self::FULFILLED; } public function resolve($value) : void { if ($value !== $this->value) { throw new \LogicException('Cannot resolve a fulfilled promise'); } } public function reject($reason) : void { throw new \LogicException('Cannot reject a fulfilled promise'); } public function cancel() : void { // pass } } PK!zvv'guzzlehttp/promises/src/EachPromise.phpnu[iterable = \YoastSEO_Vendor\GuzzleHttp\Promise\Create::iterFor($iterable); if (isset($config['concurrency'])) { $this->concurrency = $config['concurrency']; } if (isset($config['fulfilled'])) { $this->onFulfilled = $config['fulfilled']; } if (isset($config['rejected'])) { $this->onRejected = $config['rejected']; } } /** @psalm-suppress InvalidNullableReturnType */ public function promise() : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { if ($this->aggregate) { return $this->aggregate; } try { $this->createPromise(); /** @psalm-assert Promise $this->aggregate */ $this->iterable->rewind(); $this->refillPending(); } catch (\Throwable $e) { $this->aggregate->reject($e); } /** * @psalm-suppress NullableReturnStatement */ return $this->aggregate; } private function createPromise() : void { $this->mutex = \false; $this->aggregate = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(function () : void { if ($this->checkIfFinished()) { return; } \reset($this->pending); // Consume a potentially fluctuating list of promises while // ensuring that indexes are maintained (precluding array_shift). while ($promise = \current($this->pending)) { \next($this->pending); $promise->wait(); if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::settled($this->aggregate)) { return; } } }); // Clear the references when the promise is resolved. $clearFn = function () : void { $this->iterable = $this->concurrency = $this->pending = null; $this->onFulfilled = $this->onRejected = null; $this->nextPendingIndex = 0; }; $this->aggregate->then($clearFn, $clearFn); } private function refillPending() : void { if (!$this->concurrency) { // Add all pending promises. while ($this->addPending() && $this->advanceIterator()) { } return; } // Add only up to N pending promises. $concurrency = \is_callable($this->concurrency) ? ($this->concurrency)(\count($this->pending)) : $this->concurrency; $concurrency = \max($concurrency - \count($this->pending), 0); // Concurrency may be set to 0 to disallow new promises. if (!$concurrency) { return; } // Add the first pending promise. $this->addPending(); // Note this is special handling for concurrency=1 so that we do // not advance the iterator after adding the first promise. This // helps work around issues with generators that might not have the // next value to yield until promise callbacks are called. while (--$concurrency && $this->advanceIterator() && $this->addPending()) { } } private function addPending() : bool { if (!$this->iterable || !$this->iterable->valid()) { return \false; } $promise = \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($this->iterable->current()); $key = $this->iterable->key(); // Iterable keys may not be unique, so we use a counter to // guarantee uniqueness $idx = $this->nextPendingIndex++; $this->pending[$idx] = $promise->then(function ($value) use($idx, $key) : void { if ($this->onFulfilled) { ($this->onFulfilled)($value, $key, $this->aggregate); } $this->step($idx); }, function ($reason) use($idx, $key) : void { if ($this->onRejected) { ($this->onRejected)($reason, $key, $this->aggregate); } $this->step($idx); }); return \true; } private function advanceIterator() : bool { // Place a lock on the iterator so that we ensure to not recurse, // preventing fatal generator errors. if ($this->mutex) { return \false; } $this->mutex = \true; try { $this->iterable->next(); $this->mutex = \false; return \true; } catch (\Throwable $e) { $this->aggregate->reject($e); $this->mutex = \false; return \false; } } private function step(int $idx) : void { // If the promise was already resolved, then ignore this step. if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::settled($this->aggregate)) { return; } unset($this->pending[$idx]); // Only refill pending promises if we are not locked, preventing the // EachPromise to recursively invoke the provided iterator, which // cause a fatal error: "Cannot resume an already running generator" if ($this->advanceIterator() && !$this->checkIfFinished()) { // Add more pending promises if possible. $this->refillPending(); } } private function checkIfFinished() : bool { if (!$this->pending && !$this->iterable->valid()) { // Resolve the promise if there's nothing left to do. $this->aggregate->resolve(null); return \true; } return \false; } } PK!.S-f +guzzlehttp/promises/src/RejectedPromise.phpnu[reason = $reason; } public function then(callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { // If there's no onRejected callback then just return self. if (!$onRejected) { return $this; } $queue = \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue(); $reason = $this->reason; $p = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$queue, 'run']); $queue->add(static function () use($p, $reason, $onRejected) : void { if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($p)) { try { // Return a resolved promise if onRejected does not throw. $p->resolve($onRejected($reason)); } catch (\Throwable $e) { // onRejected threw, so return a rejected promise. $p->reject($e); } } }); return $p; } public function otherwise(callable $onRejected) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return $this->then(null, $onRejected); } public function wait(bool $unwrap = \true) { if ($unwrap) { throw \YoastSEO_Vendor\GuzzleHttp\Promise\Create::exceptionFor($this->reason); } return null; } public function getState() : string { return self::REJECTED; } public function resolve($value) : void { throw new \LogicException('Cannot resolve a rejected promise'); } public function reject($reason) : void { if ($reason !== $this->reason) { throw new \LogicException('Cannot reject a rejected promise'); } } public function cancel() : void { // pass } } PK!..-guzzlehttp/promises/src/PromisorInterface.phpnu[waitFn = $waitFn; $this->cancelFn = $cancelFn; } public function then(callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { if ($this->state === self::PENDING) { $p = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(null, [$this, 'cancel']); $this->handlers[] = [$p, $onFulfilled, $onRejected]; $p->waitList = $this->waitList; $p->waitList[] = $this; return $p; } // Return a fulfilled promise and immediately invoke any callbacks. if ($this->state === self::FULFILLED) { $promise = \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($this->result); return $onFulfilled ? $promise->then($onFulfilled) : $promise; } // It's either cancelled or rejected, so return a rejected promise // and immediately invoke any callbacks. $rejection = \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($this->result); return $onRejected ? $rejection->then(null, $onRejected) : $rejection; } public function otherwise(callable $onRejected) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return $this->then(null, $onRejected); } public function wait(bool $unwrap = \true) { $this->waitIfPending(); if ($this->result instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface) { return $this->result->wait($unwrap); } if ($unwrap) { if ($this->state === self::FULFILLED) { return $this->result; } // It's rejected so "unwrap" and throw an exception. throw \YoastSEO_Vendor\GuzzleHttp\Promise\Create::exceptionFor($this->result); } } public function getState() : string { return $this->state; } public function cancel() : void { if ($this->state !== self::PENDING) { return; } $this->waitFn = $this->waitList = null; if ($this->cancelFn) { $fn = $this->cancelFn; $this->cancelFn = null; try { $fn(); } catch (\Throwable $e) { $this->reject($e); } } // Reject the promise only if it wasn't rejected in a then callback. /** @psalm-suppress RedundantCondition */ if ($this->state === self::PENDING) { $this->reject(new \YoastSEO_Vendor\GuzzleHttp\Promise\CancellationException('Promise has been cancelled')); } } public function resolve($value) : void { $this->settle(self::FULFILLED, $value); } public function reject($reason) : void { $this->settle(self::REJECTED, $reason); } private function settle(string $state, $value) : void { if ($this->state !== self::PENDING) { // Ignore calls with the same resolution. if ($state === $this->state && $value === $this->result) { return; } throw $this->state === $state ? new \LogicException("The promise is already {$state}.") : new \LogicException("Cannot change a {$this->state} promise to {$state}"); } if ($value === $this) { throw new \LogicException('Cannot fulfill or reject a promise with itself'); } // Clear out the state of the promise but stash the handlers. $this->state = $state; $this->result = $value; $handlers = $this->handlers; $this->handlers = null; $this->waitList = $this->waitFn = null; $this->cancelFn = null; if (!$handlers) { return; } // If the value was not a settled promise or a thenable, then resolve // it in the task queue using the correct ID. if (!\is_object($value) || !\method_exists($value, 'then')) { $id = $state === self::FULFILLED ? 1 : 2; // It's a success, so resolve the handlers in the queue. \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue()->add(static function () use($id, $value, $handlers) : void { foreach ($handlers as $handler) { self::callHandler($id, $value, $handler); } }); } elseif ($value instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\Promise && \YoastSEO_Vendor\GuzzleHttp\Promise\Is::pending($value)) { // We can just merge our handlers onto the next promise. $value->handlers = \array_merge($value->handlers, $handlers); } else { // Resolve the handlers when the forwarded promise is resolved. $value->then(static function ($value) use($handlers) : void { foreach ($handlers as $handler) { self::callHandler(1, $value, $handler); } }, static function ($reason) use($handlers) : void { foreach ($handlers as $handler) { self::callHandler(2, $reason, $handler); } }); } } /** * Call a stack of handlers using a specific callback index and value. * * @param int $index 1 (resolve) or 2 (reject). * @param mixed $value Value to pass to the callback. * @param array $handler Array of handler data (promise and callbacks). */ private static function callHandler(int $index, $value, array $handler) : void { /** @var PromiseInterface $promise */ $promise = $handler[0]; // The promise may have been cancelled or resolved before placing // this thunk in the queue. if (\YoastSEO_Vendor\GuzzleHttp\Promise\Is::settled($promise)) { return; } try { if (isset($handler[$index])) { /* * If $f throws an exception, then $handler will be in the exception * stack trace. Since $handler contains a reference to the callable * itself we get a circular reference. We clear the $handler * here to avoid that memory leak. */ $f = $handler[$index]; unset($handler); $promise->resolve($f($value)); } elseif ($index === 1) { // Forward resolution values as-is. $promise->resolve($value); } else { // Forward rejections down the chain. $promise->reject($value); } } catch (\Throwable $reason) { $promise->reject($reason); } } private function waitIfPending() : void { if ($this->state !== self::PENDING) { return; } elseif ($this->waitFn) { $this->invokeWaitFn(); } elseif ($this->waitList) { $this->invokeWaitList(); } else { // If there's no wait function, then reject the promise. $this->reject('Cannot wait on a promise that has ' . 'no internal wait function. You must provide a wait ' . 'function when constructing the promise to be able to ' . 'wait on a promise.'); } \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue()->run(); /** @psalm-suppress RedundantCondition */ if ($this->state === self::PENDING) { $this->reject('Invoking the wait callback did not resolve the promise'); } } private function invokeWaitFn() : void { try { $wfn = $this->waitFn; $this->waitFn = null; $wfn(\true); } catch (\Throwable $reason) { if ($this->state === self::PENDING) { // The promise has not been resolved yet, so reject the promise // with the exception. $this->reject($reason); } else { // The promise was already resolved, so there's a problem in // the application. throw $reason; } } } private function invokeWaitList() : void { $waitList = $this->waitList; $this->waitList = null; foreach ($waitList as $result) { do { $result->waitIfPending(); $result = $result->result; } while ($result instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\Promise); if ($result instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface) { $result->wait(\false); } } } } PK!,%  %guzzlehttp/promises/src/Coroutine.phpnu[then(function ($v) { echo $v; }); * * @param callable $generatorFn Generator function to wrap into a promise. * * @return Promise * * @see https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration */ final class Coroutine implements \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { /** * @var PromiseInterface|null */ private $currentPromise; /** * @var Generator */ private $generator; /** * @var Promise */ private $result; public function __construct(callable $generatorFn) { $this->generator = $generatorFn(); $this->result = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise(function () : void { while (isset($this->currentPromise)) { $this->currentPromise->wait(); } }); try { $this->nextCoroutine($this->generator->current()); } catch (\Throwable $throwable) { $this->result->reject($throwable); } } /** * Create a new coroutine. */ public static function of(callable $generatorFn) : self { return new self($generatorFn); } public function then(callable $onFulfilled = null, callable $onRejected = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return $this->result->then($onFulfilled, $onRejected); } public function otherwise(callable $onRejected) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return $this->result->otherwise($onRejected); } public function wait(bool $unwrap = \true) { return $this->result->wait($unwrap); } public function getState() : string { return $this->result->getState(); } public function resolve($value) : void { $this->result->resolve($value); } public function reject($reason) : void { $this->result->reject($reason); } public function cancel() : void { $this->currentPromise->cancel(); $this->result->cancel(); } private function nextCoroutine($yielded) : void { $this->currentPromise = \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($yielded)->then([$this, '_handleSuccess'], [$this, '_handleFailure']); } /** * @internal */ public function _handleSuccess($value) : void { unset($this->currentPromise); try { $next = $this->generator->send($value); if ($this->generator->valid()) { $this->nextCoroutine($next); } else { $this->result->resolve($value); } } catch (\Throwable $throwable) { $this->result->reject($throwable); } } /** * @internal */ public function _handleFailure($reason) : void { unset($this->currentPromise); try { $nextYield = $this->generator->throw(\YoastSEO_Vendor\GuzzleHttp\Promise\Create::exceptionFor($reason)); // The throw was caught, so keep iterating on the coroutine $this->nextCoroutine($nextYield); } catch (\Throwable $throwable) { $this->result->reject($throwable); } } } PK!#c /guzzlehttp/guzzle/src/PrepareBodyMiddleware.phpnu[nextHandler = $nextHandler; } public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { $fn = $this->nextHandler; // Don't do anything if the request has no body. if ($request->getBody()->getSize() === 0) { return $fn($request, $options); } $modify = []; // Add a default content-type if possible. if (!$request->hasHeader('Content-Type')) { if ($uri = $request->getBody()->getMetadata('uri')) { if (\is_string($uri) && ($type = \YoastSEO_Vendor\GuzzleHttp\Psr7\MimeType::fromFilename($uri))) { $modify['set_headers']['Content-Type'] = $type; } } } // Add a default content-length or transfer-encoding header. if (!$request->hasHeader('Content-Length') && !$request->hasHeader('Transfer-Encoding')) { $size = $request->getBody()->getSize(); if ($size !== null) { $modify['set_headers']['Content-Length'] = $size; } else { $modify['set_headers']['Transfer-Encoding'] = 'chunked'; } } // Add the expect header if needed. $this->addExpectHeader($request, $options, $modify); return $fn(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::modifyRequest($request, $modify), $options); } /** * Add expect header */ private function addExpectHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, array &$modify) : void { // Determine if the Expect header should be used if ($request->hasHeader('Expect')) { return; } $expect = $options['expect'] ?? null; // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0 if ($expect === \false || $request->getProtocolVersion() < 1.1) { return; } // The expect header is unconditionally enabled if ($expect === \true) { $modify['set_headers']['Expect'] = '100-Continue'; return; } // By default, send the expect header when the payload is > 1mb if ($expect === null) { $expect = 1048576; } // Always add if the body cannot be rewound, the size cannot be // determined, or the size is greater than the cutoff threshold $body = $request->getBody(); $size = $body->getSize(); if ($size === null || $size >= (int) $expect || !$body->isSeekable()) { $modify['set_headers']['Expect'] = '100-Continue'; } } } PK!Nh%h%%guzzlehttp/guzzle/src/ClientTrait.phpnu[request('GET', $uri, $options); } /** * Create and send an HTTP HEAD request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function head($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface { return $this->request('HEAD', $uri, $options); } /** * Create and send an HTTP PUT request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function put($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface { return $this->request('PUT', $uri, $options); } /** * Create and send an HTTP POST request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function post($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface { return $this->request('POST', $uri, $options); } /** * Create and send an HTTP PATCH request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function patch($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface { return $this->request('PATCH', $uri, $options); } /** * Create and send an HTTP DELETE request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. * * @throws GuzzleException */ public function delete($uri, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface { return $this->request('DELETE', $uri, $options); } /** * Create and send an asynchronous HTTP request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string $method HTTP method * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public abstract function requestAsync(string $method, $uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface; /** * Create and send an asynchronous HTTP GET request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function getAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return $this->requestAsync('GET', $uri, $options); } /** * Create and send an asynchronous HTTP HEAD request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function headAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return $this->requestAsync('HEAD', $uri, $options); } /** * Create and send an asynchronous HTTP PUT request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function putAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return $this->requestAsync('PUT', $uri, $options); } /** * Create and send an asynchronous HTTP POST request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function postAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return $this->requestAsync('POST', $uri, $options); } /** * Create and send an asynchronous HTTP PATCH request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function patchAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return $this->requestAsync('PATCH', $uri, $options); } /** * Create and send an asynchronous HTTP DELETE request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. */ public function deleteAsync($uri, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return $this->requestAsync('DELETE', $uri, $options); } } PK!z-)guzzlehttp/guzzle/src/RetryMiddleware.phpnu[decider = $decider; $this->nextHandler = $nextHandler; $this->delay = $delay ?: __CLASS__ . '::exponentialDelay'; } /** * Default exponential backoff delay function. * * @return int milliseconds. */ public static function exponentialDelay(int $retries) : int { return (int) 2 ** ($retries - 1) * 1000; } public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { if (!isset($options['retries'])) { $options['retries'] = 0; } $fn = $this->nextHandler; return $fn($request, $options)->then($this->onFulfilled($request, $options), $this->onRejected($request, $options)); } /** * Execute fulfilled closure */ private function onFulfilled(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : callable { return function ($value) use($request, $options) { if (!($this->decider)($options['retries'], $request, $value, null)) { return $value; } return $this->doRetry($request, $options, $value); }; } /** * Execute rejected closure */ private function onRejected(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $req, array $options) : callable { return function ($reason) use($req, $options) { if (!($this->decider)($options['retries'], $req, null, $reason)) { return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($reason); } return $this->doRetry($req, $options); }; } private function doRetry(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { $options['delay'] = ($this->delay)(++$options['retries'], $response, $request); return $this($request, $options); } } PK!ud++1guzzlehttp/guzzle/src/BodySummarizerInterface.phpnu[request = $request; $this->response = $response; $this->transferTime = $transferTime; $this->handlerErrorData = $handlerErrorData; $this->handlerStats = $handlerStats; } public function getRequest() : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface { return $this->request; } /** * Returns the response that was received (if any). */ public function getResponse() : ?\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface { return $this->response; } /** * Returns true if a response was received. */ public function hasResponse() : bool { return $this->response !== null; } /** * Gets handler specific error data. * * This might be an exception, a integer representing an error code, or * anything else. Relying on this value assumes that you know what handler * you are using. * * @return mixed */ public function getHandlerErrorData() { return $this->handlerErrorData; } /** * Get the effective URI the request was sent to. */ public function getEffectiveUri() : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { return $this->request->getUri(); } /** * Get the estimated time the request was being transferred by the handler. * * @return float|null Time in seconds. */ public function getTransferTime() : ?float { return $this->transferTime; } /** * Gets an array of all of the handler specific transfer data. */ public function getHandlerStats() : array { return $this->handlerStats; } /** * Get a specific handler statistic from the handler by name. * * @param string $stat Handler specific transfer stat to retrieve. * * @return mixed|null */ public function getHandlerStat(string $stat) { return $this->handlerStats[$stat] ?? null; } } PK!etvv*guzzlehttp/guzzle/src/MessageFormatter.phpnu[>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}"; public const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}'; /** * @var string Template used to format log messages */ private $template; /** * @param string $template Log message template */ public function __construct(?string $template = self::CLF) { $this->template = $template ?: self::CLF; } /** * Returns a formatted message string. * * @param RequestInterface $request Request that was sent * @param ResponseInterface|null $response Response that was received * @param \Throwable|null $error Exception that was received */ public function format(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Throwable $error = null) : string { $cache = []; /** @var string */ return \preg_replace_callback('/{\\s*([A-Za-z_\\-\\.0-9]+)\\s*}/', function (array $matches) use($request, $response, $error, &$cache) { if (isset($cache[$matches[1]])) { return $cache[$matches[1]]; } $result = ''; switch ($matches[1]) { case 'request': $result = \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::toString($request); break; case 'response': $result = $response ? \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::toString($response) : ''; break; case 'req_headers': $result = \trim($request->getMethod() . ' ' . $request->getRequestTarget()) . ' HTTP/' . $request->getProtocolVersion() . "\r\n" . $this->headers($request); break; case 'res_headers': $result = $response ? \sprintf('HTTP/%s %d %s', $response->getProtocolVersion(), $response->getStatusCode(), $response->getReasonPhrase()) . "\r\n" . $this->headers($response) : 'NULL'; break; case 'req_body': $result = $request->getBody()->__toString(); break; case 'res_body': if (!$response instanceof \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface) { $result = 'NULL'; break; } $body = $response->getBody(); if (!$body->isSeekable()) { $result = 'RESPONSE_NOT_LOGGEABLE'; break; } $result = $response->getBody()->__toString(); break; case 'ts': case 'date_iso_8601': $result = \gmdate('c'); break; case 'date_common_log': $result = \date('d/M/Y:H:i:s O'); break; case 'method': $result = $request->getMethod(); break; case 'version': $result = $request->getProtocolVersion(); break; case 'uri': case 'url': $result = $request->getUri()->__toString(); break; case 'target': $result = $request->getRequestTarget(); break; case 'req_version': $result = $request->getProtocolVersion(); break; case 'res_version': $result = $response ? $response->getProtocolVersion() : 'NULL'; break; case 'host': $result = $request->getHeaderLine('Host'); break; case 'hostname': $result = \gethostname(); break; case 'code': $result = $response ? $response->getStatusCode() : 'NULL'; break; case 'phrase': $result = $response ? $response->getReasonPhrase() : 'NULL'; break; case 'error': $result = $error ? $error->getMessage() : 'NULL'; break; default: // handle prefixed dynamic headers if (\strpos($matches[1], 'req_header_') === 0) { $result = $request->getHeaderLine(\substr($matches[1], 11)); } elseif (\strpos($matches[1], 'res_header_') === 0) { $result = $response ? $response->getHeaderLine(\substr($matches[1], 11)) : 'NULL'; } } $cache[$matches[1]] = $result; return $result; }, $this->template); } /** * Get headers from message as string */ private function headers(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message) : string { $result = ''; foreach ($message->getHeaders() as $name => $values) { $result .= $name . ': ' . \implode(', ', $values) . "\r\n"; } return \trim($result); } } PK!s``#guzzlehttp/guzzle/src/functions.phpnu[push(\YoastSEO_Vendor\GuzzleHttp\Middleware::httpErrors(), 'http_errors'); $stack->push(\YoastSEO_Vendor\GuzzleHttp\Middleware::redirect(), 'allow_redirects'); $stack->push(\YoastSEO_Vendor\GuzzleHttp\Middleware::cookies(), 'cookies'); $stack->push(\YoastSEO_Vendor\GuzzleHttp\Middleware::prepareBody(), 'prepare_body'); return $stack; } /** * @param (callable(RequestInterface, array): PromiseInterface)|null $handler Underlying HTTP handler. */ public function __construct(callable $handler = null) { $this->handler = $handler; } /** * Invokes the handler stack as a composed handler * * @return ResponseInterface|PromiseInterface */ public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) { $handler = $this->resolve(); return $handler($request, $options); } /** * Dumps a string representation of the stack. * * @return string */ public function __toString() { $depth = 0; $stack = []; if ($this->handler !== null) { $stack[] = '0) Handler: ' . $this->debugCallable($this->handler); } $result = ''; foreach (\array_reverse($this->stack) as $tuple) { ++$depth; $str = "{$depth}) Name: '{$tuple[1]}', "; $str .= 'Function: ' . $this->debugCallable($tuple[0]); $result = "> {$str}\n{$result}"; $stack[] = $str; } foreach (\array_keys($stack) as $k) { $result .= "< {$stack[$k]}\n"; } return $result; } /** * Set the HTTP handler that actually returns a promise. * * @param callable(RequestInterface, array): PromiseInterface $handler Accepts a request and array of options and * returns a Promise. */ public function setHandler(callable $handler) : void { $this->handler = $handler; $this->cached = null; } /** * Returns true if the builder has a handler. */ public function hasHandler() : bool { return $this->handler !== null; } /** * Unshift a middleware to the bottom of the stack. * * @param callable(callable): callable $middleware Middleware function * @param string $name Name to register for this middleware. */ public function unshift(callable $middleware, string $name = null) : void { \array_unshift($this->stack, [$middleware, $name]); $this->cached = null; } /** * Push a middleware to the top of the stack. * * @param callable(callable): callable $middleware Middleware function * @param string $name Name to register for this middleware. */ public function push(callable $middleware, string $name = '') : void { $this->stack[] = [$middleware, $name]; $this->cached = null; } /** * Add a middleware before another middleware by name. * * @param string $findName Middleware to find * @param callable(callable): callable $middleware Middleware function * @param string $withName Name to register for this middleware. */ public function before(string $findName, callable $middleware, string $withName = '') : void { $this->splice($findName, $withName, $middleware, \true); } /** * Add a middleware after another middleware by name. * * @param string $findName Middleware to find * @param callable(callable): callable $middleware Middleware function * @param string $withName Name to register for this middleware. */ public function after(string $findName, callable $middleware, string $withName = '') : void { $this->splice($findName, $withName, $middleware, \false); } /** * Remove a middleware by instance or name from the stack. * * @param callable|string $remove Middleware to remove by instance or name. */ public function remove($remove) : void { if (!\is_string($remove) && !\is_callable($remove)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a callable or string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->cached = null; $idx = \is_callable($remove) ? 0 : 1; $this->stack = \array_values(\array_filter($this->stack, static function ($tuple) use($idx, $remove) { return $tuple[$idx] !== $remove; })); } /** * Compose the middleware and handler into a single callable function. * * @return callable(RequestInterface, array): PromiseInterface */ public function resolve() : callable { if ($this->cached === null) { if (($prev = $this->handler) === null) { throw new \LogicException('No handler has been specified'); } foreach (\array_reverse($this->stack) as $fn) { /** @var callable(RequestInterface, array): PromiseInterface $prev */ $prev = $fn[0]($prev); } $this->cached = $prev; } return $this->cached; } private function findByName(string $name) : int { foreach ($this->stack as $k => $v) { if ($v[1] === $name) { return $k; } } throw new \InvalidArgumentException("Middleware not found: {$name}"); } /** * Splices a function into the middleware list at a specific position. */ private function splice(string $findName, string $withName, callable $middleware, bool $before) : void { $this->cached = null; $idx = $this->findByName($findName); $tuple = [$middleware, $withName]; if ($before) { if ($idx === 0) { \array_unshift($this->stack, $tuple); } else { $replacement = [$tuple, $this->stack[$idx]]; \array_splice($this->stack, $idx, 1, $replacement); } } elseif ($idx === \count($this->stack) - 1) { $this->stack[] = $tuple; } else { $replacement = [$this->stack[$idx], $tuple]; \array_splice($this->stack, $idx, 1, $replacement); } } /** * Provides a debug string for a given callable. * * @param callable|string $fn Function to write as a string. */ private function debugCallable($fn) : string { if (\is_string($fn)) { return "callable({$fn})"; } if (\is_array($fn)) { return \is_string($fn[0]) ? "callable({$fn[0]}::{$fn[1]})" : "callable(['" . \get_class($fn[0]) . "', '{$fn[1]}'])"; } /** @var object $fn */ return 'callable(' . \spl_object_hash($fn) . ')'; } } PK!0j55guzzlehttp/guzzle/src/Utils.phpnu[getHost()) { $asciiHost = self::idnToAsci($uri->getHost(), $options, $info); if ($asciiHost === \false) { $errorBitSet = $info['errors'] ?? 0; $errorConstants = \array_filter(\array_keys(\get_defined_constants()), static function (string $name) : bool { return \substr($name, 0, 11) === 'IDNA_ERROR_'; }); $errors = []; foreach ($errorConstants as $errorConstant) { if ($errorBitSet & \constant($errorConstant)) { $errors[] = $errorConstant; } } $errorMessage = 'IDN conversion failed'; if ($errors) { $errorMessage .= ' (errors: ' . \implode(', ', $errors) . ')'; } throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException($errorMessage); } if ($uri->getHost() !== $asciiHost) { // Replace URI only if the ASCII version is different $uri = $uri->withHost($asciiHost); } } return $uri; } /** * @internal */ public static function getenv(string $name) : ?string { if (isset($_SERVER[$name])) { return (string) $_SERVER[$name]; } if (\PHP_SAPI === 'cli' && ($value = \getenv($name)) !== \false && $value !== null) { return (string) $value; } return null; } /** * @return string|false */ private static function idnToAsci(string $domain, int $options, ?array &$info = []) { if (\function_exists('idn_to_ascii') && \defined('INTL_IDNA_VARIANT_UTS46')) { return \idn_to_ascii($domain, $options, \INTL_IDNA_VARIANT_UTS46, $info); } throw new \Error('ext-idn or symfony/polyfill-intl-idn not loaded or too old'); } } PK!}Mguzzlehttp/guzzle/src/Pool.phpnu[ $rfn) { if ($rfn instanceof \YoastSEO_Vendor\Psr\Http\Message\RequestInterface) { (yield $key => $client->sendAsync($rfn, $opts)); } elseif (\is_callable($rfn)) { (yield $key => $rfn($opts)); } else { throw new \InvalidArgumentException('Each value yielded by the iterator must be a Psr7\\Http\\Message\\RequestInterface or a callable that returns a promise that fulfills with a Psr7\\Message\\Http\\ResponseInterface object.'); } } }; $this->each = new \YoastSEO_Vendor\GuzzleHttp\Promise\EachPromise($requests(), $config); } /** * Get promise */ public function promise() : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return $this->each->promise(); } /** * Sends multiple requests concurrently and returns an array of responses * and exceptions that uses the same ordering as the provided requests. * * IMPORTANT: This method keeps every request and response in memory, and * as such, is NOT recommended when sending a large number or an * indeterminate number of requests concurrently. * * @param ClientInterface $client Client used to send the requests * @param array|\Iterator $requests Requests to send concurrently. * @param array $options Passes through the options available in * {@see \GuzzleHttp\Pool::__construct} * * @return array Returns an array containing the response or an exception * in the same order that the requests were sent. * * @throws \InvalidArgumentException if the event format is incorrect. */ public static function batch(\YoastSEO_Vendor\GuzzleHttp\ClientInterface $client, $requests, array $options = []) : array { $res = []; self::cmpCallback($options, 'fulfilled', $res); self::cmpCallback($options, 'rejected', $res); $pool = new static($client, $requests, $options); $pool->promise()->wait(); \ksort($res); return $res; } /** * Execute callback(s) */ private static function cmpCallback(array &$options, string $name, array &$results) : void { if (!isset($options[$name])) { $options[$name] = static function ($v, $k) use(&$results) { $results[$k] = $v; }; } else { $currentFn = $options[$name]; $options[$name] = static function ($v, $k) use(&$results, $currentFn) { $currentFn($v, $k); $results[$k] = $v; }; } } } PK!(guzzlehttp/guzzle/src/BodySummarizer.phpnu[truncateAt = $truncateAt; } /** * Returns a summarized message body. */ public function summarize(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message) : ?string { return $this->truncateAt === null ? \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::bodySummary($message) : \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::bodySummary($message, $this->truncateAt); } } PK! | )guzzlehttp/guzzle/src/ClientInterface.phpnu[filename = $cookieFile; $this->storeSessionCookies = $storeSessionCookies; if (\file_exists($cookieFile)) { $this->load($cookieFile); } } /** * Saves the file when shutting down */ public function __destruct() { $this->save($this->filename); } /** * Saves the cookies to a file. * * @param string $filename File to save * * @throws \RuntimeException if the file cannot be found or created */ public function save(string $filename) : void { $json = []; /** @var SetCookie $cookie */ foreach ($this as $cookie) { if (\YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { $json[] = $cookie->toArray(); } } $jsonStr = \YoastSEO_Vendor\GuzzleHttp\Utils::jsonEncode($json); if (\false === \file_put_contents($filename, $jsonStr, \LOCK_EX)) { throw new \RuntimeException("Unable to save file {$filename}"); } } /** * Load cookies from a JSON formatted file. * * Old cookies are kept unless overwritten by newly loaded ones. * * @param string $filename Cookie file to load. * * @throws \RuntimeException if the file cannot be loaded. */ public function load(string $filename) : void { $json = \file_get_contents($filename); if (\false === $json) { throw new \RuntimeException("Unable to load file {$filename}"); } if ($json === '') { return; } $data = \YoastSEO_Vendor\GuzzleHttp\Utils::jsonDecode($json, \true); if (\is_array($data)) { foreach ($data as $cookie) { $this->setCookie(new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie($cookie)); } } elseif (\is_scalar($data) && !empty($data)) { throw new \RuntimeException("Invalid cookie file: {$filename}"); } } } PK!^4747*guzzlehttp/guzzle/src/Cookie/SetCookie.phpnu[ null, 'Value' => null, 'Domain' => null, 'Path' => '/', 'Max-Age' => null, 'Expires' => null, 'Secure' => \false, 'Discard' => \false, 'HttpOnly' => \false]; /** * @var array Cookie data */ private $data; /** * Create a new SetCookie object from a string. * * @param string $cookie Set-Cookie header string */ public static function fromString(string $cookie) : self { // Create the default return array $data = self::$defaults; // Explode the cookie string using a series of semicolons $pieces = \array_filter(\array_map('trim', \explode(';', $cookie))); // The name of the cookie (first kvp) must exist and include an equal sign. if (!isset($pieces[0]) || \strpos($pieces[0], '=') === \false) { return new self($data); } // Add the cookie pieces into the parsed data array foreach ($pieces as $part) { $cookieParts = \explode('=', $part, 2); $key = \trim($cookieParts[0]); $value = isset($cookieParts[1]) ? \trim($cookieParts[1], " \n\r\t\x00\v") : \true; // Only check for non-cookies when cookies have been found if (!isset($data['Name'])) { $data['Name'] = $key; $data['Value'] = $value; } else { foreach (\array_keys(self::$defaults) as $search) { if (!\strcasecmp($search, $key)) { if ($search === 'Max-Age') { if (\is_numeric($value)) { $data[$search] = (int) $value; } } else { $data[$search] = $value; } continue 2; } } $data[$key] = $value; } } return new self($data); } /** * @param array $data Array of cookie data provided by a Cookie parser */ public function __construct(array $data = []) { $this->data = self::$defaults; if (isset($data['Name'])) { $this->setName($data['Name']); } if (isset($data['Value'])) { $this->setValue($data['Value']); } if (isset($data['Domain'])) { $this->setDomain($data['Domain']); } if (isset($data['Path'])) { $this->setPath($data['Path']); } if (isset($data['Max-Age'])) { $this->setMaxAge($data['Max-Age']); } if (isset($data['Expires'])) { $this->setExpires($data['Expires']); } if (isset($data['Secure'])) { $this->setSecure($data['Secure']); } if (isset($data['Discard'])) { $this->setDiscard($data['Discard']); } if (isset($data['HttpOnly'])) { $this->setHttpOnly($data['HttpOnly']); } // Set the remaining values that don't have extra validation logic foreach (\array_diff(\array_keys($data), \array_keys(self::$defaults)) as $key) { $this->data[$key] = $data[$key]; } // Extract the Expires value and turn it into a UNIX timestamp if needed if (!$this->getExpires() && $this->getMaxAge()) { // Calculate the Expires date $this->setExpires(\time() + $this->getMaxAge()); } elseif (null !== ($expires = $this->getExpires()) && !\is_numeric($expires)) { $this->setExpires($expires); } } public function __toString() { $str = $this->data['Name'] . '=' . ($this->data['Value'] ?? '') . '; '; foreach ($this->data as $k => $v) { if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== \false) { if ($k === 'Expires') { $str .= 'Expires=' . \gmdate('D, d M Y H:i:s \\G\\M\\T', $v) . '; '; } else { $str .= ($v === \true ? $k : "{$k}={$v}") . '; '; } } } return \rtrim($str, '; '); } public function toArray() : array { return $this->data; } /** * Get the cookie name. * * @return string */ public function getName() { return $this->data['Name']; } /** * Set the cookie name. * * @param string $name Cookie name */ public function setName($name) : void { if (!\is_string($name)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Name'] = (string) $name; } /** * Get the cookie value. * * @return string|null */ public function getValue() { return $this->data['Value']; } /** * Set the cookie value. * * @param string $value Cookie value */ public function setValue($value) : void { if (!\is_string($value)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Value'] = (string) $value; } /** * Get the domain. * * @return string|null */ public function getDomain() { return $this->data['Domain']; } /** * Set the domain of the cookie. * * @param string|null $domain */ public function setDomain($domain) : void { if (!\is_string($domain) && null !== $domain) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Domain'] = null === $domain ? null : (string) $domain; } /** * Get the path. * * @return string */ public function getPath() { return $this->data['Path']; } /** * Set the path of the cookie. * * @param string $path Path of the cookie */ public function setPath($path) : void { if (!\is_string($path)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a string to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Path'] = (string) $path; } /** * Maximum lifetime of the cookie in seconds. * * @return int|null */ public function getMaxAge() { return null === $this->data['Max-Age'] ? null : (int) $this->data['Max-Age']; } /** * Set the max-age of the cookie. * * @param int|null $maxAge Max age of the cookie in seconds */ public function setMaxAge($maxAge) : void { if (!\is_int($maxAge) && null !== $maxAge) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Max-Age'] = $maxAge === null ? null : (int) $maxAge; } /** * The UNIX timestamp when the cookie Expires. * * @return string|int|null */ public function getExpires() { return $this->data['Expires']; } /** * Set the unix timestamp for which the cookie will expire. * * @param int|string|null $timestamp Unix timestamp or any English textual datetime description. */ public function setExpires($timestamp) : void { if (!\is_int($timestamp) && !\is_string($timestamp) && null !== $timestamp) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an int, string or null to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Expires'] = null === $timestamp ? null : (\is_numeric($timestamp) ? (int) $timestamp : \strtotime((string) $timestamp)); } /** * Get whether or not this is a secure cookie. * * @return bool */ public function getSecure() { return $this->data['Secure']; } /** * Set whether or not the cookie is secure. * * @param bool $secure Set to true or false if secure */ public function setSecure($secure) : void { if (!\is_bool($secure)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Secure'] = (bool) $secure; } /** * Get whether or not this is a session cookie. * * @return bool|null */ public function getDiscard() { return $this->data['Discard']; } /** * Set whether or not this is a session cookie. * * @param bool $discard Set to true or false if this is a session cookie */ public function setDiscard($discard) : void { if (!\is_bool($discard)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['Discard'] = (bool) $discard; } /** * Get whether or not this is an HTTP only cookie. * * @return bool */ public function getHttpOnly() { return $this->data['HttpOnly']; } /** * Set whether or not this is an HTTP only cookie. * * @param bool $httpOnly Set to true or false if this is HTTP only */ public function setHttpOnly($httpOnly) : void { if (!\is_bool($httpOnly)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing a bool to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } $this->data['HttpOnly'] = (bool) $httpOnly; } /** * Check if the cookie matches a path value. * * A request-path path-matches a given cookie-path if at least one of * the following conditions holds: * * - The cookie-path and the request-path are identical. * - The cookie-path is a prefix of the request-path, and the last * character of the cookie-path is %x2F ("/"). * - The cookie-path is a prefix of the request-path, and the first * character of the request-path that is not included in the cookie- * path is a %x2F ("/") character. * * @param string $requestPath Path to check against */ public function matchesPath(string $requestPath) : bool { $cookiePath = $this->getPath(); // Match on exact matches or when path is the default empty "/" if ($cookiePath === '/' || $cookiePath == $requestPath) { return \true; } // Ensure that the cookie-path is a prefix of the request path. if (0 !== \strpos($requestPath, $cookiePath)) { return \false; } // Match if the last character of the cookie-path is "/" if (\substr($cookiePath, -1, 1) === '/') { return \true; } // Match if the first character not included in cookie path is "/" return \substr($requestPath, \strlen($cookiePath), 1) === '/'; } /** * Check if the cookie matches a domain value. * * @param string $domain Domain to check against */ public function matchesDomain(string $domain) : bool { $cookieDomain = $this->getDomain(); if (null === $cookieDomain) { return \true; } // Remove the leading '.' as per spec in RFC 6265. // https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3 $cookieDomain = \ltrim(\strtolower($cookieDomain), '.'); $domain = \strtolower($domain); // Domain not set or exact match. if ('' === $cookieDomain || $domain === $cookieDomain) { return \true; } // Matching the subdomain according to RFC 6265. // https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.3 if (\filter_var($domain, \FILTER_VALIDATE_IP)) { return \false; } return (bool) \preg_match('/\\.' . \preg_quote($cookieDomain, '/') . '$/', $domain); } /** * Check if the cookie is expired. */ public function isExpired() : bool { return $this->getExpires() !== null && \time() > $this->getExpires(); } /** * Check if the cookie is valid according to RFC 6265. * * @return bool|string Returns true if valid or an error message if invalid */ public function validate() { $name = $this->getName(); if ($name === '') { return 'The cookie name must not be empty'; } // Check if any of the invalid characters are present in the cookie name if (\preg_match('/[\\x00-\\x20\\x22\\x28-\\x29\\x2c\\x2f\\x3a-\\x40\\x5c\\x7b\\x7d\\x7f]/', $name)) { return 'Cookie name must not contain invalid characters: ASCII ' . 'Control characters (0-31;127), space, tab and the ' . 'following characters: ()<>@,;:\\"/?={}'; } // Value must not be null. 0 and empty string are valid. Empty strings // are technically against RFC 6265, but known to happen in the wild. $value = $this->getValue(); if ($value === null) { return 'The cookie value must not be empty'; } // Domains must not be empty, but can be 0. "0" is not a valid internet // domain, but may be used as server name in a private network. $domain = $this->getDomain(); if ($domain === null || $domain === '') { return 'The cookie domain must not be empty'; } return \true; } } PK!B·]%%*guzzlehttp/guzzle/src/Cookie/CookieJar.phpnu[strictMode = $strictMode; foreach ($cookieArray as $cookie) { if (!$cookie instanceof \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie) { $cookie = new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie($cookie); } $this->setCookie($cookie); } } /** * Create a new Cookie jar from an associative array and domain. * * @param array $cookies Cookies to create the jar from * @param string $domain Domain to set the cookies to */ public static function fromArray(array $cookies, string $domain) : self { $cookieJar = new self(); foreach ($cookies as $name => $value) { $cookieJar->setCookie(new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie(['Domain' => $domain, 'Name' => $name, 'Value' => $value, 'Discard' => \true])); } return $cookieJar; } /** * Evaluate if this cookie should be persisted to storage * that survives between requests. * * @param SetCookie $cookie Being evaluated. * @param bool $allowSessionCookies If we should persist session cookies */ public static function shouldPersist(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie, bool $allowSessionCookies = \false) : bool { if ($cookie->getExpires() || $allowSessionCookies) { if (!$cookie->getDiscard()) { return \true; } } return \false; } /** * Finds and returns the cookie based on the name * * @param string $name cookie name to search for * * @return SetCookie|null cookie that was found or null if not found */ public function getCookieByName(string $name) : ?\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie { foreach ($this->cookies as $cookie) { if ($cookie->getName() !== null && \strcasecmp($cookie->getName(), $name) === 0) { return $cookie; } } return null; } public function toArray() : array { return \array_map(static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : array { return $cookie->toArray(); }, $this->getIterator()->getArrayCopy()); } public function clear(string $domain = null, string $path = null, string $name = null) : void { if (!$domain) { $this->cookies = []; return; } elseif (!$path) { $this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($domain) : bool { return !$cookie->matchesDomain($domain); }); } elseif (!$name) { $this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($path, $domain) : bool { return !($cookie->matchesPath($path) && $cookie->matchesDomain($domain)); }); } else { $this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) use($path, $domain, $name) { return !($cookie->getName() == $name && $cookie->matchesPath($path) && $cookie->matchesDomain($domain)); }); } } public function clearSessionCookies() : void { $this->cookies = \array_filter($this->cookies, static function (\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : bool { return !$cookie->getDiscard() && $cookie->getExpires(); }); } public function setCookie(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : bool { // If the name string is empty (but not 0), ignore the set-cookie // string entirely. $name = $cookie->getName(); if (!$name && $name !== '0') { return \false; } // Only allow cookies with set and valid domain, name, value $result = $cookie->validate(); if ($result !== \true) { if ($this->strictMode) { throw new \RuntimeException('Invalid cookie: ' . $result); } $this->removeCookieIfEmpty($cookie); return \false; } // Resolve conflicts with previously set cookies foreach ($this->cookies as $i => $c) { // Two cookies are identical, when their path, and domain are // identical. if ($c->getPath() != $cookie->getPath() || $c->getDomain() != $cookie->getDomain() || $c->getName() != $cookie->getName()) { continue; } // The previously set cookie is a discard cookie and this one is // not so allow the new cookie to be set if (!$cookie->getDiscard() && $c->getDiscard()) { unset($this->cookies[$i]); continue; } // If the new cookie's expiration is further into the future, then // replace the old cookie if ($cookie->getExpires() > $c->getExpires()) { unset($this->cookies[$i]); continue; } // If the value has changed, we better change it if ($cookie->getValue() !== $c->getValue()) { unset($this->cookies[$i]); continue; } // The cookie exists, so no need to continue return \false; } $this->cookies[] = $cookie; return \true; } public function count() : int { return \count($this->cookies); } /** * @return \ArrayIterator */ public function getIterator() : \ArrayIterator { return new \ArrayIterator(\array_values($this->cookies)); } public function extractCookies(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) : void { if ($cookieHeader = $response->getHeader('Set-Cookie')) { foreach ($cookieHeader as $cookie) { $sc = \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie::fromString($cookie); if (!$sc->getDomain()) { $sc->setDomain($request->getUri()->getHost()); } if (0 !== \strpos($sc->getPath(), '/')) { $sc->setPath($this->getCookiePathFromRequest($request)); } if (!$sc->matchesDomain($request->getUri()->getHost())) { continue; } // Note: At this point `$sc->getDomain()` being a public suffix should // be rejected, but we don't want to pull in the full PSL dependency. $this->setCookie($sc); } } } /** * Computes cookie path following RFC 6265 section 5.1.4 * * @see https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4 */ private function getCookiePathFromRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : string { $uriPath = $request->getUri()->getPath(); if ('' === $uriPath) { return '/'; } if (0 !== \strpos($uriPath, '/')) { return '/'; } if ('/' === $uriPath) { return '/'; } $lastSlashPos = \strrpos($uriPath, '/'); if (0 === $lastSlashPos || \false === $lastSlashPos) { return '/'; } return \substr($uriPath, 0, $lastSlashPos); } public function withCookieHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface { $values = []; $uri = $request->getUri(); $scheme = $uri->getScheme(); $host = $uri->getHost(); $path = $uri->getPath() ?: '/'; foreach ($this->cookies as $cookie) { if ($cookie->matchesPath($path) && $cookie->matchesDomain($host) && !$cookie->isExpired() && (!$cookie->getSecure() || $scheme === 'https')) { $values[] = $cookie->getName() . '=' . $cookie->getValue(); } } return $values ? $request->withHeader('Cookie', \implode('; ', $values)) : $request; } /** * If a cookie already exists and the server asks to set it again with a * null value, the cookie must be deleted. */ private function removeCookieIfEmpty(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : void { $cookieValue = $cookie->getValue(); if ($cookieValue === null || $cookieValue === '') { $this->clear($cookie->getDomain(), $cookie->getPath(), $cookie->getName()); } } } PK!9cJJ1guzzlehttp/guzzle/src/Cookie/SessionCookieJar.phpnu[sessionKey = $sessionKey; $this->storeSessionCookies = $storeSessionCookies; $this->load(); } /** * Saves cookies to session when shutting down */ public function __destruct() { $this->save(); } /** * Save cookies to the client session */ public function save() : void { $json = []; /** @var SetCookie $cookie */ foreach ($this as $cookie) { if (\YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) { $json[] = $cookie->toArray(); } } $_SESSION[$this->sessionKey] = \json_encode($json); } /** * Load the contents of the client session into the data array */ protected function load() : void { if (!isset($_SESSION[$this->sessionKey])) { return; } $data = \json_decode($_SESSION[$this->sessionKey], \true); if (\is_array($data)) { foreach ($data as $cookie) { $this->setCookie(new \YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie($cookie)); } } elseif (\strlen($data)) { throw new \RuntimeException('Invalid cookie data'); } } } PK!_| 3guzzlehttp/guzzle/src/Cookie/CookieJarInterface.phpnu[ */ interface CookieJarInterface extends \Countable, \IteratorAggregate { /** * Create a request with added cookie headers. * * If no matching cookies are found in the cookie jar, then no Cookie * header is added to the request and the same request is returned. * * @param RequestInterface $request Request object to modify. * * @return RequestInterface returns the modified request. */ public function withCookieHeader(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface; /** * Extract cookies from an HTTP response and store them in the CookieJar. * * @param RequestInterface $request Request that was sent * @param ResponseInterface $response Response that was received */ public function extractCookies(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) : void; /** * Sets a cookie in the cookie jar. * * @param SetCookie $cookie Cookie to set. * * @return bool Returns true on success or false on failure */ public function setCookie(\YoastSEO_Vendor\GuzzleHttp\Cookie\SetCookie $cookie) : bool; /** * Remove cookies currently held in the cookie jar. * * Invoking this method without arguments will empty the whole cookie jar. * If given a $domain argument only cookies belonging to that domain will * be removed. If given a $domain and $path argument, cookies belonging to * the specified path within that domain are removed. If given all three * arguments, then the cookie with the specified name, path and domain is * removed. * * @param string|null $domain Clears cookies matching a domain * @param string|null $path Clears cookies matching a domain and path * @param string|null $name Clears cookies matching a domain, path, and name */ public function clear(string $domain = null, string $path = null, string $name = null) : void; /** * Discard all sessions cookies. * * Removes cookies that don't have an expire field or a have a discard * field set to true. To be called when the user agent shuts down according * to RFC 2965. */ public function clearSessionCookies() : void; /** * Converts the cookie jar to an array. */ public function toArray() : array; } PK!Aj!j!,guzzlehttp/guzzle/src/RedirectMiddleware.phpnu[ 5, 'protocols' => ['http', 'https'], 'strict' => \false, 'referer' => \false, 'track_redirects' => \false]; /** * @var callable(RequestInterface, array): PromiseInterface */ private $nextHandler; /** * @param callable(RequestInterface, array): PromiseInterface $nextHandler Next handler to invoke. */ public function __construct(callable $nextHandler) { $this->nextHandler = $nextHandler; } public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { $fn = $this->nextHandler; if (empty($options['allow_redirects'])) { return $fn($request, $options); } if ($options['allow_redirects'] === \true) { $options['allow_redirects'] = self::$defaultSettings; } elseif (!\is_array($options['allow_redirects'])) { throw new \InvalidArgumentException('allow_redirects must be true, false, or array'); } else { // Merge the default settings with the provided settings $options['allow_redirects'] += self::$defaultSettings; } if (empty($options['allow_redirects']['max'])) { return $fn($request, $options); } return $fn($request, $options)->then(function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($request, $options) { return $this->checkRedirect($request, $options, $response); }); } /** * @return ResponseInterface|PromiseInterface */ public function checkRedirect(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) { if (\strpos((string) $response->getStatusCode(), '3') !== 0 || !$response->hasHeader('Location')) { return $response; } $this->guardMax($request, $response, $options); $nextRequest = $this->modifyRequest($request, $options, $response); // If authorization is handled by curl, unset it if URI is cross-origin. if (\YoastSEO_Vendor\GuzzleHttp\Psr7\UriComparator::isCrossOrigin($request->getUri(), $nextRequest->getUri()) && \defined('\\CURLOPT_HTTPAUTH')) { unset($options['curl'][\CURLOPT_HTTPAUTH], $options['curl'][\CURLOPT_USERPWD]); } if (isset($options['allow_redirects']['on_redirect'])) { $options['allow_redirects']['on_redirect']($request, $response, $nextRequest->getUri()); } $promise = $this($nextRequest, $options); // Add headers to be able to track history of redirects. if (!empty($options['allow_redirects']['track_redirects'])) { return $this->withTracking($promise, (string) $nextRequest->getUri(), $response->getStatusCode()); } return $promise; } /** * Enable tracking on promise. */ private function withTracking(\YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface $promise, string $uri, int $statusCode) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { return $promise->then(static function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($uri, $statusCode) { // Note that we are pushing to the front of the list as this // would be an earlier response than what is currently present // in the history header. $historyHeader = $response->getHeader(self::HISTORY_HEADER); $statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER); \array_unshift($historyHeader, $uri); \array_unshift($statusHeader, (string) $statusCode); return $response->withHeader(self::HISTORY_HEADER, $historyHeader)->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader); }); } /** * Check for too many redirects. * * @throws TooManyRedirectsException Too many redirects. */ private function guardMax(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, array &$options) : void { $current = $options['__redirect_count'] ?? 0; $options['__redirect_count'] = $current + 1; $max = $options['allow_redirects']['max']; if ($options['__redirect_count'] > $max) { throw new \YoastSEO_Vendor\GuzzleHttp\Exception\TooManyRedirectsException("Will not follow more than {$max} redirects", $request, $response); } } public function modifyRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface { // Request modifications to apply. $modify = []; $protocols = $options['allow_redirects']['protocols']; // Use a GET request if this is an entity enclosing request and we are // not forcing RFC compliance, but rather emulating what all browsers // would do. $statusCode = $response->getStatusCode(); if ($statusCode == 303 || $statusCode <= 302 && !$options['allow_redirects']['strict']) { $safeMethods = ['GET', 'HEAD', 'OPTIONS']; $requestMethod = $request->getMethod(); $modify['method'] = \in_array($requestMethod, $safeMethods) ? $requestMethod : 'GET'; $modify['body'] = ''; } $uri = self::redirectUri($request, $response, $protocols); if (isset($options['idn_conversion']) && $options['idn_conversion'] !== \false) { $idnOptions = $options['idn_conversion'] === \true ? \IDNA_DEFAULT : $options['idn_conversion']; $uri = \YoastSEO_Vendor\GuzzleHttp\Utils::idnUriConvert($uri, $idnOptions); } $modify['uri'] = $uri; \YoastSEO_Vendor\GuzzleHttp\Psr7\Message::rewindBody($request); // Add the Referer header if it is told to do so and only // add the header if we are not redirecting from https to http. if ($options['allow_redirects']['referer'] && $modify['uri']->getScheme() === $request->getUri()->getScheme()) { $uri = $request->getUri()->withUserInfo(''); $modify['set_headers']['Referer'] = (string) $uri; } else { $modify['remove_headers'][] = 'Referer'; } // Remove Authorization and Cookie headers if URI is cross-origin. if (\YoastSEO_Vendor\GuzzleHttp\Psr7\UriComparator::isCrossOrigin($request->getUri(), $modify['uri'])) { $modify['remove_headers'][] = 'Authorization'; $modify['remove_headers'][] = 'Cookie'; } return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::modifyRequest($request, $modify); } /** * Set the appropriate URL on the request based on the location header. */ private static function redirectUri(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, array $protocols) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $location = \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve($request->getUri(), new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($response->getHeaderLine('Location'))); // Ensure that the redirect URI is allowed based on the protocols. if (!\in_array($location->getScheme(), $protocols)) { throw new \YoastSEO_Vendor\GuzzleHttp\Exception\BadResponseException(\sprintf('Redirect URI, %s, does not use one of the allowed redirect protocols: %s', $location, \implode(', ', $protocols)), $request, $response); } return $location; } } PK!pI6guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.phpnu[maxHandles = $maxHandles; } public function create(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle { if (isset($options['curl']['body_as_string'])) { $options['_body_as_string'] = $options['curl']['body_as_string']; unset($options['curl']['body_as_string']); } $easy = new \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle(); $easy->request = $request; $easy->options = $options; $conf = $this->getDefaultConf($easy); $this->applyMethod($easy, $conf); $this->applyHandlerOptions($easy, $conf); $this->applyHeaders($easy, $conf); unset($conf['_headers']); // Add handler options from the request configuration options if (isset($options['curl'])) { $conf = \array_replace($conf, $options['curl']); } $conf[\CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy); $easy->handle = $this->handles ? \array_pop($this->handles) : \curl_init(); \curl_setopt_array($easy->handle, $conf); return $easy; } public function release(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) : void { $resource = $easy->handle; unset($easy->handle); if (\count($this->handles) >= $this->maxHandles) { \curl_close($resource); } else { // Remove all callback functions as they can hold onto references // and are not cleaned up by curl_reset. Using curl_setopt_array // does not work for some reason, so removing each one // individually. \curl_setopt($resource, \CURLOPT_HEADERFUNCTION, null); \curl_setopt($resource, \CURLOPT_READFUNCTION, null); \curl_setopt($resource, \CURLOPT_WRITEFUNCTION, null); \curl_setopt($resource, \CURLOPT_PROGRESSFUNCTION, null); \curl_reset($resource); $this->handles[] = $resource; } } /** * Completes a cURL transaction, either returning a response promise or a * rejected promise. * * @param callable(RequestInterface, array): PromiseInterface $handler * @param CurlFactoryInterface $factory Dictates how the handle is released */ public static function finish(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInterface $factory) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { if (isset($easy->options['on_stats'])) { self::invokeStats($easy); } if (!$easy->response || $easy->errno) { return self::finishError($handler, $easy, $factory); } // Return the response if it is present and there is no error. $factory->release($easy); // Rewind the body of the response if possible. $body = $easy->response->getBody(); if ($body->isSeekable()) { $body->rewind(); } return new \YoastSEO_Vendor\GuzzleHttp\Promise\FulfilledPromise($easy->response); } private static function invokeStats(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) : void { $curlStats = \curl_getinfo($easy->handle); $curlStats['appconnect_time'] = \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME); $stats = new \YoastSEO_Vendor\GuzzleHttp\TransferStats($easy->request, $easy->response, $curlStats['total_time'], $easy->errno, $curlStats); $easy->options['on_stats']($stats); } /** * @param callable(RequestInterface, array): PromiseInterface $handler */ private static function finishError(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactoryInterface $factory) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { // Get error information and release the handle to the factory. $ctx = ['errno' => $easy->errno, 'error' => \curl_error($easy->handle), 'appconnect_time' => \curl_getinfo($easy->handle, \CURLINFO_APPCONNECT_TIME)] + \curl_getinfo($easy->handle); $ctx[self::CURL_VERSION_STR] = \curl_version()['version']; $factory->release($easy); // Retry when nothing is present or when curl failed to rewind. if (empty($easy->options['_err_message']) && (!$easy->errno || $easy->errno == 65)) { return self::retryFailedRewind($handler, $easy, $ctx); } return self::createRejection($easy, $ctx); } private static function createRejection(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array $ctx) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { static $connectionErrors = [\CURLE_OPERATION_TIMEOUTED => \true, \CURLE_COULDNT_RESOLVE_HOST => \true, \CURLE_COULDNT_CONNECT => \true, \CURLE_SSL_CONNECT_ERROR => \true, \CURLE_GOT_NOTHING => \true]; if ($easy->createResponseException) { return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered while creating the response', $easy->request, $easy->response, $easy->createResponseException, $ctx)); } // If an exception was encountered during the onHeaders event, then // return a rejected promise that wraps that exception. if ($easy->onHeadersException) { return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered during the on_headers event', $easy->request, $easy->response, $easy->onHeadersException, $ctx)); } $message = \sprintf('cURL error %s: %s (%s)', $ctx['errno'], $ctx['error'], 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'); $uriString = (string) $easy->request->getUri(); if ($uriString !== '' && \false === \strpos($ctx['error'], $uriString)) { $message .= \sprintf(' for %s', $uriString); } // Create a connection exception if it was a specific error code. $error = isset($connectionErrors[$easy->errno]) ? new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException($message, $easy->request, null, $ctx) : new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException($message, $easy->request, $easy->response, null, $ctx); return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($error); } /** * @return array */ private function getDefaultConf(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) : array { $conf = ['_headers' => $easy->request->getHeaders(), \CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(), \CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''), \CURLOPT_RETURNTRANSFER => \false, \CURLOPT_HEADER => \false, \CURLOPT_CONNECTTIMEOUT => 300]; if (\defined('CURLOPT_PROTOCOLS')) { $conf[\CURLOPT_PROTOCOLS] = \CURLPROTO_HTTP | \CURLPROTO_HTTPS; } $version = $easy->request->getProtocolVersion(); if ($version == 1.1) { $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_1; } elseif ($version == 2.0) { $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_2_0; } else { $conf[\CURLOPT_HTTP_VERSION] = \CURL_HTTP_VERSION_1_0; } return $conf; } private function applyMethod(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf) : void { $body = $easy->request->getBody(); $size = $body->getSize(); if ($size === null || $size > 0) { $this->applyBody($easy->request, $easy->options, $conf); return; } $method = $easy->request->getMethod(); if ($method === 'PUT' || $method === 'POST') { // See https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2 if (!$easy->request->hasHeader('Content-Length')) { $conf[\CURLOPT_HTTPHEADER][] = 'Content-Length: 0'; } } elseif ($method === 'HEAD') { $conf[\CURLOPT_NOBODY] = \true; unset($conf[\CURLOPT_WRITEFUNCTION], $conf[\CURLOPT_READFUNCTION], $conf[\CURLOPT_FILE], $conf[\CURLOPT_INFILE]); } } private function applyBody(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, array &$conf) : void { $size = $request->hasHeader('Content-Length') ? (int) $request->getHeaderLine('Content-Length') : null; // Send the body as a string if the size is less than 1MB OR if the // [curl][body_as_string] request value is set. if ($size !== null && $size < 1000000 || !empty($options['_body_as_string'])) { $conf[\CURLOPT_POSTFIELDS] = (string) $request->getBody(); // Don't duplicate the Content-Length header $this->removeHeader('Content-Length', $conf); $this->removeHeader('Transfer-Encoding', $conf); } else { $conf[\CURLOPT_UPLOAD] = \true; if ($size !== null) { $conf[\CURLOPT_INFILESIZE] = $size; $this->removeHeader('Content-Length', $conf); } $body = $request->getBody(); if ($body->isSeekable()) { $body->rewind(); } $conf[\CURLOPT_READFUNCTION] = static function ($ch, $fd, $length) use($body) { return $body->read($length); }; } // If the Expect header is not present, prevent curl from adding it if (!$request->hasHeader('Expect')) { $conf[\CURLOPT_HTTPHEADER][] = 'Expect:'; } // cURL sometimes adds a content-type by default. Prevent this. if (!$request->hasHeader('Content-Type')) { $conf[\CURLOPT_HTTPHEADER][] = 'Content-Type:'; } } private function applyHeaders(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf) : void { foreach ($conf['_headers'] as $name => $values) { foreach ($values as $value) { $value = (string) $value; if ($value === '') { // cURL requires a special format for empty headers. // See https://github.com/guzzle/guzzle/issues/1882 for more details. $conf[\CURLOPT_HTTPHEADER][] = "{$name};"; } else { $conf[\CURLOPT_HTTPHEADER][] = "{$name}: {$value}"; } } } // Remove the Accept header if one was not set if (!$easy->request->hasHeader('Accept')) { $conf[\CURLOPT_HTTPHEADER][] = 'Accept:'; } } /** * Remove a header from the options array. * * @param string $name Case-insensitive header to remove * @param array $options Array of options to modify */ private function removeHeader(string $name, array &$options) : void { foreach (\array_keys($options['_headers']) as $key) { if (!\strcasecmp($key, $name)) { unset($options['_headers'][$key]); return; } } } private function applyHandlerOptions(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array &$conf) : void { $options = $easy->options; if (isset($options['verify'])) { if ($options['verify'] === \false) { unset($conf[\CURLOPT_CAINFO]); $conf[\CURLOPT_SSL_VERIFYHOST] = 0; $conf[\CURLOPT_SSL_VERIFYPEER] = \false; } else { $conf[\CURLOPT_SSL_VERIFYHOST] = 2; $conf[\CURLOPT_SSL_VERIFYPEER] = \true; if (\is_string($options['verify'])) { // Throw an error if the file/folder/link path is not valid or doesn't exist. if (!\file_exists($options['verify'])) { throw new \InvalidArgumentException("SSL CA bundle not found: {$options['verify']}"); } // If it's a directory or a link to a directory use CURLOPT_CAPATH. // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO. if (\is_dir($options['verify']) || \is_link($options['verify']) === \true && ($verifyLink = \readlink($options['verify'])) !== \false && \is_dir($verifyLink)) { $conf[\CURLOPT_CAPATH] = $options['verify']; } else { $conf[\CURLOPT_CAINFO] = $options['verify']; } } } } if (!isset($options['curl'][\CURLOPT_ENCODING]) && !empty($options['decode_content'])) { $accept = $easy->request->getHeaderLine('Accept-Encoding'); if ($accept) { $conf[\CURLOPT_ENCODING] = $accept; } else { // The empty string enables all available decoders and implicitly // sets a matching 'Accept-Encoding' header. $conf[\CURLOPT_ENCODING] = ''; // But as the user did not specify any acceptable encodings we need // to overwrite this implicit header with an empty one. $conf[\CURLOPT_HTTPHEADER][] = 'Accept-Encoding:'; } } if (!isset($options['sink'])) { // Use a default temp stream if no sink was set. $options['sink'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'w+'); } $sink = $options['sink']; if (!\is_string($sink)) { $sink = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($sink); } elseif (!\is_dir(\dirname($sink))) { // Ensure that the directory exists before failing in curl. throw new \RuntimeException(\sprintf('Directory %s does not exist for sink value of %s', \dirname($sink), $sink)); } else { $sink = new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($sink, 'w+'); } $easy->sink = $sink; $conf[\CURLOPT_WRITEFUNCTION] = static function ($ch, $write) use($sink) : int { return $sink->write($write); }; $timeoutRequiresNoSignal = \false; if (isset($options['timeout'])) { $timeoutRequiresNoSignal |= $options['timeout'] < 1; $conf[\CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000; } // CURL default value is CURL_IPRESOLVE_WHATEVER if (isset($options['force_ip_resolve'])) { if ('v4' === $options['force_ip_resolve']) { $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V4; } elseif ('v6' === $options['force_ip_resolve']) { $conf[\CURLOPT_IPRESOLVE] = \CURL_IPRESOLVE_V6; } } if (isset($options['connect_timeout'])) { $timeoutRequiresNoSignal |= $options['connect_timeout'] < 1; $conf[\CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000; } if ($timeoutRequiresNoSignal && \strtoupper(\substr(\PHP_OS, 0, 3)) !== 'WIN') { $conf[\CURLOPT_NOSIGNAL] = \true; } if (isset($options['proxy'])) { if (!\is_array($options['proxy'])) { $conf[\CURLOPT_PROXY] = $options['proxy']; } else { $scheme = $easy->request->getUri()->getScheme(); if (isset($options['proxy'][$scheme])) { $host = $easy->request->getUri()->getHost(); if (isset($options['proxy']['no']) && \YoastSEO_Vendor\GuzzleHttp\Utils::isHostInNoProxy($host, $options['proxy']['no'])) { unset($conf[\CURLOPT_PROXY]); } else { $conf[\CURLOPT_PROXY] = $options['proxy'][$scheme]; } } } } if (isset($options['crypto_method'])) { if (\STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT === $options['crypto_method']) { if (!\defined('CURL_SSLVERSION_TLSv1_0')) { throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.0 not supported by your version of cURL'); } $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_0; } elseif (\STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT === $options['crypto_method']) { if (!\defined('CURL_SSLVERSION_TLSv1_1')) { throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.1 not supported by your version of cURL'); } $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_1; } elseif (\STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT === $options['crypto_method']) { if (!\defined('CURL_SSLVERSION_TLSv1_2')) { throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.2 not supported by your version of cURL'); } $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_2; } elseif (\defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT === $options['crypto_method']) { if (!\defined('CURL_SSLVERSION_TLSv1_3')) { throw new \InvalidArgumentException('Invalid crypto_method request option: TLS 1.3 not supported by your version of cURL'); } $conf[\CURLOPT_SSLVERSION] = \CURL_SSLVERSION_TLSv1_3; } else { throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided'); } } if (isset($options['cert'])) { $cert = $options['cert']; if (\is_array($cert)) { $conf[\CURLOPT_SSLCERTPASSWD] = $cert[1]; $cert = $cert[0]; } if (!\file_exists($cert)) { throw new \InvalidArgumentException("SSL certificate not found: {$cert}"); } // OpenSSL (versions 0.9.3 and later) also support "P12" for PKCS#12-encoded files. // see https://curl.se/libcurl/c/CURLOPT_SSLCERTTYPE.html $ext = \pathinfo($cert, \PATHINFO_EXTENSION); if (\preg_match('#^(der|p12)$#i', $ext)) { $conf[\CURLOPT_SSLCERTTYPE] = \strtoupper($ext); } $conf[\CURLOPT_SSLCERT] = $cert; } if (isset($options['ssl_key'])) { if (\is_array($options['ssl_key'])) { if (\count($options['ssl_key']) === 2) { [$sslKey, $conf[\CURLOPT_SSLKEYPASSWD]] = $options['ssl_key']; } else { [$sslKey] = $options['ssl_key']; } } $sslKey = $sslKey ?? $options['ssl_key']; if (!\file_exists($sslKey)) { throw new \InvalidArgumentException("SSL private key not found: {$sslKey}"); } $conf[\CURLOPT_SSLKEY] = $sslKey; } if (isset($options['progress'])) { $progress = $options['progress']; if (!\is_callable($progress)) { throw new \InvalidArgumentException('progress client option must be callable'); } $conf[\CURLOPT_NOPROGRESS] = \false; $conf[\CURLOPT_PROGRESSFUNCTION] = static function ($resource, int $downloadSize, int $downloaded, int $uploadSize, int $uploaded) use($progress) { $progress($downloadSize, $downloaded, $uploadSize, $uploaded); }; } if (!empty($options['debug'])) { $conf[\CURLOPT_STDERR] = \YoastSEO_Vendor\GuzzleHttp\Utils::debugResource($options['debug']); $conf[\CURLOPT_VERBOSE] = \true; } } /** * This function ensures that a response was set on a transaction. If one * was not set, then the request is retried if possible. This error * typically means you are sending a payload, curl encountered a * "Connection died, retrying a fresh connect" error, tried to rewind the * stream, and then encountered a "necessary data rewind wasn't possible" * error, causing the request to be sent through curl_multi_info_read() * without an error status. * * @param callable(RequestInterface, array): PromiseInterface $handler */ private static function retryFailedRewind(callable $handler, \YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy, array $ctx) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { try { // Only rewind if the body has been read from. $body = $easy->request->getBody(); if ($body->tell() > 0) { $body->rewind(); } } catch (\RuntimeException $e) { $ctx['error'] = 'The connection unexpectedly failed without ' . 'providing an error. The request would have been retried, ' . 'but attempting to rewind the request body failed. ' . 'Exception: ' . $e; return self::createRejection($easy, $ctx); } // Retry no more than 3 times before giving up. if (!isset($easy->options['_curl_retries'])) { $easy->options['_curl_retries'] = 1; } elseif ($easy->options['_curl_retries'] == 2) { $ctx['error'] = 'The cURL request was retried 3 times ' . 'and did not succeed. The most likely reason for the failure ' . 'is that cURL was unable to rewind the body of the request ' . 'and subsequent retries resulted in the same error. Turn on ' . 'the debug option to see what went wrong. See ' . 'https://bugs.php.net/bug.php?id=47204 for more information.'; return self::createRejection($easy, $ctx); } else { ++$easy->options['_curl_retries']; } return $handler($easy->request, $easy->options); } private function createHeaderFn(\YoastSEO_Vendor\GuzzleHttp\Handler\EasyHandle $easy) : callable { if (isset($easy->options['on_headers'])) { $onHeaders = $easy->options['on_headers']; if (!\is_callable($onHeaders)) { throw new \InvalidArgumentException('on_headers must be callable'); } } else { $onHeaders = null; } return static function ($ch, $h) use($onHeaders, $easy, &$startingResponse) { $value = \trim($h); if ($value === '') { $startingResponse = \true; try { $easy->createResponse(); } catch (\Exception $e) { $easy->createResponseException = $e; return -1; } if ($onHeaders !== null) { try { $onHeaders($easy->response); } catch (\Exception $e) { // Associate the exception with the handle and trigger // a curl header write error by returning 0. $easy->onHeadersException = $e; return -1; } } } elseif ($startingResponse) { $startingResponse = \false; $easy->headers = [$value]; } else { $easy->headers[] = $value; } return \strlen($h); }; } public function __destruct() { foreach ($this->handles as $id => $handle) { \curl_close($handle); unset($this->handles[$id]); } } } PK!5> ,guzzlehttp/guzzle/src/Handler/EasyHandle.phpnu[headers); $normalizedKeys = \YoastSEO_Vendor\GuzzleHttp\Utils::normalizeHeaderKeys($headers); if (!empty($this->options['decode_content']) && isset($normalizedKeys['content-encoding'])) { $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']]; unset($headers[$normalizedKeys['content-encoding']]); if (isset($normalizedKeys['content-length'])) { $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']]; $bodyLength = (int) $this->sink->getSize(); if ($bodyLength) { $headers[$normalizedKeys['content-length']] = $bodyLength; } else { unset($headers[$normalizedKeys['content-length']]); } } } // Attach a response to the easy handle with the parsed headers. $this->response = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($status, $headers, $this->sink, $ver, $reason); } /** * @param string $name * * @return void * * @throws \BadMethodCallException */ public function __get($name) { $msg = $name === 'handle' ? 'The EasyHandle has been released' : 'Invalid property: ' . $name; throw new \BadMethodCallException($msg); } } PK!"V"V/guzzlehttp/guzzle/src/Handler/StreamHandler.phpnu[withoutHeader('Expect'); // Append a content-length header if body size is zero to match // cURL's behavior. if (0 === $request->getBody()->getSize()) { $request = $request->withHeader('Content-Length', '0'); } return $this->createResponse($request, $options, $this->createStream($request, $options), $startTime); } catch (\InvalidArgumentException $e) { throw $e; } catch (\Exception $e) { // Determine if the error was a networking error. $message = $e->getMessage(); // This list can probably get more comprehensive. if (\false !== \strpos($message, 'getaddrinfo') || \false !== \strpos($message, 'Connection refused') || \false !== \strpos($message, "couldn't connect to host") || \false !== \strpos($message, 'connection attempt failed')) { $e = new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException($e->getMessage(), $request, $e); } else { $e = \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException::wrapException($request, $e); } $this->invokeStats($options, $request, $startTime, null, $e); return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($e); } } private function invokeStats(array $options, \YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, ?float $startTime, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Throwable $error = null) : void { if (isset($options['on_stats'])) { $stats = new \YoastSEO_Vendor\GuzzleHttp\TransferStats($request, $response, \YoastSEO_Vendor\GuzzleHttp\Utils::currentTime() - $startTime, $error, []); $options['on_stats']($stats); } } /** * @param resource $stream */ private function createResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, $stream, ?float $startTime) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { $hdrs = $this->lastHeaders; $this->lastHeaders = []; try { [$ver, $status, $reason, $headers] = \YoastSEO_Vendor\GuzzleHttp\Handler\HeaderProcessor::parseHeaders($hdrs); } catch (\Exception $e) { return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered while creating the response', $request, null, $e)); } [$stream, $headers] = $this->checkDecode($options, $headers, $stream); $stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($stream); $sink = $stream; if (\strcasecmp('HEAD', $request->getMethod())) { $sink = $this->createSink($stream, $options); } try { $response = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($status, $headers, $sink, $ver, $reason); } catch (\Exception $e) { return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered while creating the response', $request, null, $e)); } if (isset($options['on_headers'])) { try { $options['on_headers']($response); } catch (\Exception $e) { return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor(new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException('An error was encountered during the on_headers event', $request, $response, $e)); } } // Do not drain when the request is a HEAD request because they have // no body. if ($sink !== $stream) { $this->drain($stream, $sink, $response->getHeaderLine('Content-Length')); } $this->invokeStats($options, $request, $startTime, $response, null); return new \YoastSEO_Vendor\GuzzleHttp\Promise\FulfilledPromise($response); } private function createSink(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, array $options) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface { if (!empty($options['stream'])) { return $stream; } $sink = $options['sink'] ?? \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'r+'); return \is_string($sink) ? new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($sink, 'w+') : \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($sink); } /** * @param resource $stream */ private function checkDecode(array $options, array $headers, $stream) : array { // Automatically decode responses when instructed. if (!empty($options['decode_content'])) { $normalizedKeys = \YoastSEO_Vendor\GuzzleHttp\Utils::normalizeHeaderKeys($headers); if (isset($normalizedKeys['content-encoding'])) { $encoding = $headers[$normalizedKeys['content-encoding']]; if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') { $stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\InflateStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($stream)); $headers['x-encoded-content-encoding'] = $headers[$normalizedKeys['content-encoding']]; // Remove content-encoding header unset($headers[$normalizedKeys['content-encoding']]); // Fix content-length header if (isset($normalizedKeys['content-length'])) { $headers['x-encoded-content-length'] = $headers[$normalizedKeys['content-length']]; $length = (int) $stream->getSize(); if ($length === 0) { unset($headers[$normalizedKeys['content-length']]); } else { $headers[$normalizedKeys['content-length']] = [$length]; } } } } } return [$stream, $headers]; } /** * Drains the source stream into the "sink" client option. * * @param string $contentLength Header specifying the amount of * data to read. * * @throws \RuntimeException when the sink option is invalid. */ private function drain(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $source, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $sink, string $contentLength) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface { // If a content-length header is provided, then stop reading once // that number of bytes has been read. This can prevent infinitely // reading from a stream when dealing with servers that do not honor // Connection: Close headers. \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToStream($source, $sink, \strlen($contentLength) > 0 && (int) $contentLength > 0 ? (int) $contentLength : -1); $sink->seek(0); $source->close(); return $sink; } /** * Create a resource and check to ensure it was created successfully * * @param callable $callback Callable that returns stream resource * * @return resource * * @throws \RuntimeException on error */ private function createResource(callable $callback) { $errors = []; \set_error_handler(static function ($_, $msg, $file, $line) use(&$errors) : bool { $errors[] = ['message' => $msg, 'file' => $file, 'line' => $line]; return \true; }); try { $resource = $callback(); } finally { \restore_error_handler(); } if (!$resource) { $message = 'Error creating resource: '; foreach ($errors as $err) { foreach ($err as $key => $value) { $message .= "[{$key}] {$value}" . \PHP_EOL; } } throw new \RuntimeException(\trim($message)); } return $resource; } /** * @return resource */ private function createStream(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) { static $methods; if (!$methods) { $methods = \array_flip(\get_class_methods(__CLASS__)); } if (!\in_array($request->getUri()->getScheme(), ['http', 'https'])) { throw new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException(\sprintf("The scheme '%s' is not supported.", $request->getUri()->getScheme()), $request); } // HTTP/1.1 streams using the PHP stream wrapper require a // Connection: close header if ($request->getProtocolVersion() == '1.1' && !$request->hasHeader('Connection')) { $request = $request->withHeader('Connection', 'close'); } // Ensure SSL is verified by default if (!isset($options['verify'])) { $options['verify'] = \true; } $params = []; $context = $this->getDefaultContext($request); if (isset($options['on_headers']) && !\is_callable($options['on_headers'])) { throw new \InvalidArgumentException('on_headers must be callable'); } if (!empty($options)) { foreach ($options as $key => $value) { $method = "add_{$key}"; if (isset($methods[$method])) { $this->{$method}($request, $context, $value, $params); } } } if (isset($options['stream_context'])) { if (!\is_array($options['stream_context'])) { throw new \InvalidArgumentException('stream_context must be an array'); } $context = \array_replace_recursive($context, $options['stream_context']); } // Microsoft NTLM authentication only supported with curl handler if (isset($options['auth'][2]) && 'ntlm' === $options['auth'][2]) { throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler'); } $uri = $this->resolveHost($request, $options); $contextResource = $this->createResource(static function () use($context, $params) { return \stream_context_create($context, $params); }); return $this->createResource(function () use($uri, &$http_response_header, $contextResource, $context, $options, $request) { $resource = @\fopen((string) $uri, 'r', \false, $contextResource); $this->lastHeaders = $http_response_header ?? []; if (\false === $resource) { throw new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException(\sprintf('Connection refused for URI %s', $uri), $request, null, $context); } if (isset($options['read_timeout'])) { $readTimeout = $options['read_timeout']; $sec = (int) $readTimeout; $usec = ($readTimeout - $sec) * 100000; \stream_set_timeout($resource, $sec, $usec); } return $resource; }); } private function resolveHost(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $uri = $request->getUri(); if (isset($options['force_ip_resolve']) && !\filter_var($uri->getHost(), \FILTER_VALIDATE_IP)) { if ('v4' === $options['force_ip_resolve']) { $records = \dns_get_record($uri->getHost(), \DNS_A); if (\false === $records || !isset($records[0]['ip'])) { throw new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException(\sprintf("Could not resolve IPv4 address for host '%s'", $uri->getHost()), $request); } return $uri->withHost($records[0]['ip']); } if ('v6' === $options['force_ip_resolve']) { $records = \dns_get_record($uri->getHost(), \DNS_AAAA); if (\false === $records || !isset($records[0]['ipv6'])) { throw new \YoastSEO_Vendor\GuzzleHttp\Exception\ConnectException(\sprintf("Could not resolve IPv6 address for host '%s'", $uri->getHost()), $request); } return $uri->withHost('[' . $records[0]['ipv6'] . ']'); } } return $uri; } private function getDefaultContext(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : array { $headers = ''; foreach ($request->getHeaders() as $name => $value) { foreach ($value as $val) { $headers .= "{$name}: {$val}\r\n"; } } $context = ['http' => ['method' => $request->getMethod(), 'header' => $headers, 'protocol_version' => $request->getProtocolVersion(), 'ignore_errors' => \true, 'follow_location' => 0], 'ssl' => ['peer_name' => $request->getUri()->getHost()]]; $body = (string) $request->getBody(); if ('' !== $body) { $context['http']['content'] = $body; // Prevent the HTTP handler from adding a Content-Type header. if (!$request->hasHeader('Content-Type')) { $context['http']['header'] .= "Content-Type:\r\n"; } } $context['http']['header'] = \rtrim($context['http']['header']); return $context; } /** * @param mixed $value as passed via Request transfer options. */ private function add_proxy(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void { $uri = null; if (!\is_array($value)) { $uri = $value; } else { $scheme = $request->getUri()->getScheme(); if (isset($value[$scheme])) { if (!isset($value['no']) || !\YoastSEO_Vendor\GuzzleHttp\Utils::isHostInNoProxy($request->getUri()->getHost(), $value['no'])) { $uri = $value[$scheme]; } } } if (!$uri) { return; } $parsed = $this->parse_proxy($uri); $options['http']['proxy'] = $parsed['proxy']; if ($parsed['auth']) { if (!isset($options['http']['header'])) { $options['http']['header'] = []; } $options['http']['header'] .= "\r\nProxy-Authorization: {$parsed['auth']}"; } } /** * Parses the given proxy URL to make it compatible with the format PHP's stream context expects. */ private function parse_proxy(string $url) : array { $parsed = \parse_url($url); if ($parsed !== \false && isset($parsed['scheme']) && $parsed['scheme'] === 'http') { if (isset($parsed['host']) && isset($parsed['port'])) { $auth = null; if (isset($parsed['user']) && isset($parsed['pass'])) { $auth = \base64_encode("{$parsed['user']}:{$parsed['pass']}"); } return ['proxy' => "tcp://{$parsed['host']}:{$parsed['port']}", 'auth' => $auth ? "Basic {$auth}" : null]; } } // Return proxy as-is. return ['proxy' => $url, 'auth' => null]; } /** * @param mixed $value as passed via Request transfer options. */ private function add_timeout(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void { if ($value > 0) { $options['http']['timeout'] = $value; } } /** * @param mixed $value as passed via Request transfer options. */ private function add_crypto_method(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void { if ($value === \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT || $value === \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT || $value === \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT || \defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT') && $value === \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT) { $options['http']['crypto_method'] = $value; return; } throw new \InvalidArgumentException('Invalid crypto_method request option: unknown version provided'); } /** * @param mixed $value as passed via Request transfer options. */ private function add_verify(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void { if ($value === \false) { $options['ssl']['verify_peer'] = \false; $options['ssl']['verify_peer_name'] = \false; return; } if (\is_string($value)) { $options['ssl']['cafile'] = $value; if (!\file_exists($value)) { throw new \RuntimeException("SSL CA bundle not found: {$value}"); } } elseif ($value !== \true) { throw new \InvalidArgumentException('Invalid verify request option'); } $options['ssl']['verify_peer'] = \true; $options['ssl']['verify_peer_name'] = \true; $options['ssl']['allow_self_signed'] = \false; } /** * @param mixed $value as passed via Request transfer options. */ private function add_cert(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void { if (\is_array($value)) { $options['ssl']['passphrase'] = $value[1]; $value = $value[0]; } if (!\file_exists($value)) { throw new \RuntimeException("SSL certificate not found: {$value}"); } $options['ssl']['local_cert'] = $value; } /** * @param mixed $value as passed via Request transfer options. */ private function add_progress(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void { self::addNotification($params, static function ($code, $a, $b, $c, $transferred, $total) use($value) { if ($code == \STREAM_NOTIFY_PROGRESS) { // The upload progress cannot be determined. Use 0 for cURL compatibility: // https://curl.se/libcurl/c/CURLOPT_PROGRESSFUNCTION.html $value($total, $transferred, 0, 0); } }); } /** * @param mixed $value as passed via Request transfer options. */ private function add_debug(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options, $value, array &$params) : void { if ($value === \false) { return; } static $map = [\STREAM_NOTIFY_CONNECT => 'CONNECT', \STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED', \STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT', \STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS', \STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS', \STREAM_NOTIFY_REDIRECTED => 'REDIRECTED', \STREAM_NOTIFY_PROGRESS => 'PROGRESS', \STREAM_NOTIFY_FAILURE => 'FAILURE', \STREAM_NOTIFY_COMPLETED => 'COMPLETED', \STREAM_NOTIFY_RESOLVE => 'RESOLVE']; static $args = ['severity', 'message', 'message_code', 'bytes_transferred', 'bytes_max']; $value = \YoastSEO_Vendor\GuzzleHttp\Utils::debugResource($value); $ident = $request->getMethod() . ' ' . $request->getUri()->withFragment(''); self::addNotification($params, static function (int $code, ...$passed) use($ident, $value, $map, $args) : void { \fprintf($value, '<%s> [%s] ', $ident, $map[$code]); foreach (\array_filter($passed) as $i => $v) { \fwrite($value, $args[$i] . ': "' . $v . '" '); } \fwrite($value, "\n"); }); } private static function addNotification(array &$params, callable $notify) : void { // Wrap the existing function if needed. if (!isset($params['notification'])) { $params['notification'] = $notify; } else { $params['notification'] = self::callArray([$params['notification'], $notify]); } } private static function callArray(array $functions) : callable { return static function (...$args) use($functions) { foreach ($functions as $fn) { $fn(...$args); } }; } } PK!Zv-guzzlehttp/guzzle/src/Handler/MockHandler.phpnu[|null $queue The parameters to be passed to the append function, as an indexed array. * @param callable|null $onFulfilled Callback to invoke when the return value is fulfilled. * @param callable|null $onRejected Callback to invoke when the return value is rejected. */ public function __construct(array $queue = null, callable $onFulfilled = null, callable $onRejected = null) { $this->onFulfilled = $onFulfilled; $this->onRejected = $onRejected; if ($queue) { // array_values included for BC $this->append(...\array_values($queue)); } } public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { if (!$this->queue) { throw new \OutOfBoundsException('Mock queue is empty'); } if (isset($options['delay']) && \is_numeric($options['delay'])) { \usleep((int) $options['delay'] * 1000); } $this->lastRequest = $request; $this->lastOptions = $options; $response = \array_shift($this->queue); if (isset($options['on_headers'])) { if (!\is_callable($options['on_headers'])) { throw new \InvalidArgumentException('on_headers must be callable'); } try { $options['on_headers']($response); } catch (\Exception $e) { $msg = 'An error was encountered during the on_headers event'; $response = new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException($msg, $request, $response, $e); } } if (\is_callable($response)) { $response = $response($request, $options); } $response = $response instanceof \Throwable ? \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($response) : \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($response); return $response->then(function (?\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $value) use($request, $options) { $this->invokeStats($request, $options, $value); if ($this->onFulfilled) { ($this->onFulfilled)($value); } if ($value !== null && isset($options['sink'])) { $contents = (string) $value->getBody(); $sink = $options['sink']; if (\is_resource($sink)) { \fwrite($sink, $contents); } elseif (\is_string($sink)) { \file_put_contents($sink, $contents); } elseif ($sink instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) { $sink->write($contents); } } return $value; }, function ($reason) use($request, $options) { $this->invokeStats($request, $options, null, $reason); if ($this->onRejected) { ($this->onRejected)($reason); } return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($reason); }); } /** * Adds one or more variadic requests, exceptions, callables, or promises * to the queue. * * @param mixed ...$values */ public function append(...$values) : void { foreach ($values as $value) { if ($value instanceof \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface || $value instanceof \Throwable || $value instanceof \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface || \is_callable($value)) { $this->queue[] = $value; } else { throw new \TypeError('Expected a Response, Promise, Throwable or callable. Found ' . \YoastSEO_Vendor\GuzzleHttp\Utils::describeType($value)); } } } /** * Get the last received request. */ public function getLastRequest() : ?\YoastSEO_Vendor\Psr\Http\Message\RequestInterface { return $this->lastRequest; } /** * Get the last received request options. */ public function getLastOptions() : array { return $this->lastOptions; } /** * Returns the number of remaining items in the queue. */ public function count() : int { return \count($this->queue); } public function reset() : void { $this->queue = []; } /** * @param mixed $reason Promise or reason. */ private function invokeStats(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, $reason = null) : void { if (isset($options['on_stats'])) { $transferTime = $options['transfer_time'] ?? 0; $stats = new \YoastSEO_Vendor\GuzzleHttp\TransferStats($request, $response, $transferTime, $reason); $options['on_stats']($stats); } } } PK!il-guzzlehttp/guzzle/src/Handler/CurlHandler.phpnu[factory = $options['handle_factory'] ?? new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory(3); } public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { if (isset($options['delay'])) { \usleep($options['delay'] * 1000); } $easy = $this->factory->create($request, $options); \curl_exec($easy->handle); $easy->errno = \curl_errno($easy->handle); return \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory::finish($this, $easy, $this->factory); } } PK!ڸp p 2guzzlehttp/guzzle/src/Handler/CurlMultiHandler.phpnu[ An array of delay times, indexed by handle id in `addRequest`. * * @see CurlMultiHandler::addRequest */ private $delays = []; /** * @var array An associative array of CURLMOPT_* options and corresponding values for curl_multi_setopt() */ private $options = []; /** @var resource|\CurlMultiHandle */ private $_mh; /** * This handler accepts the following options: * * - handle_factory: An optional factory used to create curl handles * - select_timeout: Optional timeout (in seconds) to block before timing * out while selecting curl handles. Defaults to 1 second. * - options: An associative array of CURLMOPT_* options and * corresponding values for curl_multi_setopt() */ public function __construct(array $options = []) { $this->factory = $options['handle_factory'] ?? new \YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory(50); if (isset($options['select_timeout'])) { $this->selectTimeout = $options['select_timeout']; } elseif ($selectTimeout = \YoastSEO_Vendor\GuzzleHttp\Utils::getenv('GUZZLE_CURL_SELECT_TIMEOUT')) { @\trigger_error('Since guzzlehttp/guzzle 7.2.0: Using environment variable GUZZLE_CURL_SELECT_TIMEOUT is deprecated. Use option "select_timeout" instead.', \E_USER_DEPRECATED); $this->selectTimeout = (int) $selectTimeout; } else { $this->selectTimeout = 1; } $this->options = $options['options'] ?? []; // unsetting the property forces the first access to go through // __get(). unset($this->_mh); } /** * @param string $name * * @return resource|\CurlMultiHandle * * @throws \BadMethodCallException when another field as `_mh` will be gotten * @throws \RuntimeException when curl can not initialize a multi handle */ public function __get($name) { if ($name !== '_mh') { throw new \BadMethodCallException("Can not get other property as '_mh'."); } $multiHandle = \curl_multi_init(); if (\false === $multiHandle) { throw new \RuntimeException('Can not initialize curl multi handle.'); } $this->_mh = $multiHandle; foreach ($this->options as $option => $value) { // A warning is raised in case of a wrong option. \curl_multi_setopt($this->_mh, $option, $value); } return $this->_mh; } public function __destruct() { if (isset($this->_mh)) { \curl_multi_close($this->_mh); unset($this->_mh); } } public function __invoke(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { $easy = $this->factory->create($request, $options); $id = (int) $easy->handle; $promise = new \YoastSEO_Vendor\GuzzleHttp\Promise\Promise([$this, 'execute'], function () use($id) { return $this->cancel($id); }); $this->addRequest(['easy' => $easy, 'deferred' => $promise]); return $promise; } /** * Ticks the curl event loop. */ public function tick() : void { // Add any delayed handles if needed. if ($this->delays) { $currentTime = \YoastSEO_Vendor\GuzzleHttp\Utils::currentTime(); foreach ($this->delays as $id => $delay) { if ($currentTime >= $delay) { unset($this->delays[$id]); \curl_multi_add_handle($this->_mh, $this->handles[$id]['easy']->handle); } } } // Step through the task queue which may add additional requests. \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue()->run(); if ($this->active && \curl_multi_select($this->_mh, $this->selectTimeout) === -1) { // Perform a usleep if a select returns -1. // See: https://bugs.php.net/bug.php?id=61141 \usleep(250); } while (\curl_multi_exec($this->_mh, $this->active) === \CURLM_CALL_MULTI_PERFORM) { } $this->processMessages(); } /** * Runs until all outstanding connections have completed. */ public function execute() : void { $queue = \YoastSEO_Vendor\GuzzleHttp\Promise\Utils::queue(); while ($this->handles || !$queue->isEmpty()) { // If there are no transfers, then sleep for the next delay if (!$this->active && $this->delays) { \usleep($this->timeToNext()); } $this->tick(); } } private function addRequest(array $entry) : void { $easy = $entry['easy']; $id = (int) $easy->handle; $this->handles[$id] = $entry; if (empty($easy->options['delay'])) { \curl_multi_add_handle($this->_mh, $easy->handle); } else { $this->delays[$id] = \YoastSEO_Vendor\GuzzleHttp\Utils::currentTime() + $easy->options['delay'] / 1000; } } /** * Cancels a handle from sending and removes references to it. * * @param int $id Handle ID to cancel and remove. * * @return bool True on success, false on failure. */ private function cancel($id) : bool { if (!\is_int($id)) { trigger_deprecation('guzzlehttp/guzzle', '7.4', 'Not passing an integer to %s::%s() is deprecated and will cause an error in 8.0.', __CLASS__, __FUNCTION__); } // Cannot cancel if it has been processed. if (!isset($this->handles[$id])) { return \false; } $handle = $this->handles[$id]['easy']->handle; unset($this->delays[$id], $this->handles[$id]); \curl_multi_remove_handle($this->_mh, $handle); \curl_close($handle); return \true; } private function processMessages() : void { while ($done = \curl_multi_info_read($this->_mh)) { if ($done['msg'] !== \CURLMSG_DONE) { // if it's not done, then it would be premature to remove the handle. ref https://github.com/guzzle/guzzle/pull/2892#issuecomment-945150216 continue; } $id = (int) $done['handle']; \curl_multi_remove_handle($this->_mh, $done['handle']); if (!isset($this->handles[$id])) { // Probably was cancelled. continue; } $entry = $this->handles[$id]; unset($this->handles[$id], $this->delays[$id]); $entry['easy']->errno = $done['result']; $entry['deferred']->resolve(\YoastSEO_Vendor\GuzzleHttp\Handler\CurlFactory::finish($this, $entry['easy'], $this->factory)); } } private function timeToNext() : int { $currentTime = \YoastSEO_Vendor\GuzzleHttp\Utils::currentTime(); $nextTime = \PHP_INT_MAX; foreach ($this->delays as $time) { if ($time < $nextTime) { $nextTime = $time; } } return (int) \max(0, $nextTime - $currentTime) * 1000000; } } PK!  'guzzlehttp/guzzle/src/Handler/Proxy.phpnu[request = $request; $this->handlerContext = $handlerContext; } /** * Get the request that caused the exception */ public function getRequest() : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface { return $this->request; } /** * Get contextual information about the error from the underlying handler. * * The contents of this array will vary depending on which handler you are * using. It may also be just an empty array. Relying on this data will * couple you to a specific handler, but can give more debug information * when needed. */ public function getHandlerContext() : array { return $this->handlerContext; } } PK!].gW3guzzlehttp/guzzle/src/Exception/ClientException.phpnu[getStatusCode() : 0; parent::__construct($message, $code, $previous); $this->request = $request; $this->response = $response; $this->handlerContext = $handlerContext; } /** * Wrap non-RequestExceptions with a RequestException */ public static function wrapException(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \Throwable $e) : \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException { return $e instanceof \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException ? $e : new \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException($e->getMessage(), $request, null, $e); } /** * Factory method to create a new exception with a normalized error message * * @param RequestInterface $request Request sent * @param ResponseInterface $response Response received * @param \Throwable|null $previous Previous exception * @param array $handlerContext Optional handler context * @param BodySummarizerInterface|null $bodySummarizer Optional body summarizer */ public static function create(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response = null, \Throwable $previous = null, array $handlerContext = [], \YoastSEO_Vendor\GuzzleHttp\BodySummarizerInterface $bodySummarizer = null) : self { if (!$response) { return new self('Error completing request', $request, null, $previous, $handlerContext); } $level = (int) \floor($response->getStatusCode() / 100); if ($level === 4) { $label = 'Client error'; $className = \YoastSEO_Vendor\GuzzleHttp\Exception\ClientException::class; } elseif ($level === 5) { $label = 'Server error'; $className = \YoastSEO_Vendor\GuzzleHttp\Exception\ServerException::class; } else { $label = 'Unsuccessful request'; $className = __CLASS__; } $uri = $request->getUri(); $uri = static::obfuscateUri($uri); // Client Error: `GET /` resulted in a `404 Not Found` response: // ... (truncated) $message = \sprintf('%s: `%s %s` resulted in a `%s %s` response', $label, $request->getMethod(), $uri->__toString(), $response->getStatusCode(), $response->getReasonPhrase()); $summary = ($bodySummarizer ?? new \YoastSEO_Vendor\GuzzleHttp\BodySummarizer())->summarize($response); if ($summary !== null) { $message .= ":\n{$summary}\n"; } return new $className($message, $request, $response, $previous, $handlerContext); } /** * Obfuscates URI if there is a username and a password present */ private static function obfuscateUri(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $userInfo = $uri->getUserInfo(); if (\false !== ($pos = \strpos($userInfo, ':'))) { return $uri->withUserInfo(\substr($userInfo, 0, $pos), '***'); } return $uri; } /** * Get the request that caused the exception */ public function getRequest() : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface { return $this->request; } /** * Get the associated response */ public function getResponse() : ?\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface { return $this->response; } /** * Check if a response was received */ public function hasResponse() : bool { return $this->response !== null; } /** * Get contextual information about the error from the underlying handler. * * The contents of this array will vary depending on which handler you are * using. It may also be just an empty array. Relying on this data will * couple you to a specific handler, but can give more debug information * when needed. */ public function getHandlerContext() : array { return $this->handlerContext; } } PK!aO=guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.phpnu[withCookieHeader($request); return $handler($request, $options)->then(static function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($cookieJar, $request) : ResponseInterface { $cookieJar->extractCookies($request, $response); return $response; }); }; }; } /** * Middleware that throws exceptions for 4xx or 5xx responses when the * "http_errors" request option is set to true. * * @param BodySummarizerInterface|null $bodySummarizer The body summarizer to use in exception messages. * * @return callable(callable): callable Returns a function that accepts the next handler. */ public static function httpErrors(\YoastSEO_Vendor\GuzzleHttp\BodySummarizerInterface $bodySummarizer = null) : callable { return static function (callable $handler) use($bodySummarizer) : callable { return static function ($request, array $options) use($handler, $bodySummarizer) { if (empty($options['http_errors'])) { return $handler($request, $options); } return $handler($request, $options)->then(static function (\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) use($request, $bodySummarizer) { $code = $response->getStatusCode(); if ($code < 400) { return $response; } throw \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException::create($request, $response, null, [], $bodySummarizer); }); }; }; } /** * Middleware that pushes history data to an ArrayAccess container. * * @param array|\ArrayAccess $container Container to hold the history (by reference). * * @return callable(callable): callable Returns a function that accepts the next handler. * * @throws \InvalidArgumentException if container is not an array or ArrayAccess. */ public static function history(&$container) : callable { if (!\is_array($container) && !$container instanceof \ArrayAccess) { throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess'); } return static function (callable $handler) use(&$container) : callable { return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($handler, &$container) { return $handler($request, $options)->then(static function ($value) use($request, &$container, $options) { $container[] = ['request' => $request, 'response' => $value, 'error' => null, 'options' => $options]; return $value; }, static function ($reason) use($request, &$container, $options) { $container[] = ['request' => $request, 'response' => null, 'error' => $reason, 'options' => $options]; return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($reason); }); }; }; } /** * Middleware that invokes a callback before and after sending a request. * * The provided listener cannot modify or alter the response. It simply * "taps" into the chain to be notified before returning the promise. The * before listener accepts a request and options array, and the after * listener accepts a request, options array, and response promise. * * @param callable $before Function to invoke before forwarding the request. * @param callable $after Function invoked after forwarding. * * @return callable Returns a function that accepts the next handler. */ public static function tap(callable $before = null, callable $after = null) : callable { return static function (callable $handler) use($before, $after) : callable { return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($handler, $before, $after) { if ($before) { $before($request, $options); } $response = $handler($request, $options); if ($after) { $after($request, $options, $response); } return $response; }; }; } /** * Middleware that handles request redirects. * * @return callable Returns a function that accepts the next handler. */ public static function redirect() : callable { return static function (callable $handler) : RedirectMiddleware { return new \YoastSEO_Vendor\GuzzleHttp\RedirectMiddleware($handler); }; } /** * Middleware that retries requests based on the boolean result of * invoking the provided "decider" function. * * If no delay function is provided, a simple implementation of exponential * backoff will be utilized. * * @param callable $decider Function that accepts the number of retries, * a request, [response], and [exception] and * returns true if the request is to be retried. * @param callable $delay Function that accepts the number of retries and * returns the number of milliseconds to delay. * * @return callable Returns a function that accepts the next handler. */ public static function retry(callable $decider, callable $delay = null) : callable { return static function (callable $handler) use($decider, $delay) : RetryMiddleware { return new \YoastSEO_Vendor\GuzzleHttp\RetryMiddleware($decider, $handler, $delay); }; } /** * Middleware that logs requests, responses, and errors using a message * formatter. * * @phpstan-param \Psr\Log\LogLevel::* $logLevel Level at which to log requests. * * @param LoggerInterface $logger Logs messages. * @param MessageFormatterInterface|MessageFormatter $formatter Formatter used to create message strings. * @param string $logLevel Level at which to log requests. * * @return callable Returns a function that accepts the next handler. */ public static function log(\YoastSEO_Vendor\Psr\Log\LoggerInterface $logger, $formatter, string $logLevel = 'info') : callable { // To be compatible with Guzzle 7.1.x we need to allow users to pass a MessageFormatter if (!$formatter instanceof \YoastSEO_Vendor\GuzzleHttp\MessageFormatter && !$formatter instanceof \YoastSEO_Vendor\GuzzleHttp\MessageFormatterInterface) { throw new \LogicException(\sprintf('Argument 2 to %s::log() must be of type %s', self::class, \YoastSEO_Vendor\GuzzleHttp\MessageFormatterInterface::class)); } return static function (callable $handler) use($logger, $formatter, $logLevel) : callable { return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []) use($handler, $logger, $formatter, $logLevel) { return $handler($request, $options)->then(static function ($response) use($logger, $request, $formatter, $logLevel) : ResponseInterface { $message = $formatter->format($request, $response); $logger->log($logLevel, $message); return $response; }, static function ($reason) use($logger, $request, $formatter) : PromiseInterface { $response = $reason instanceof \YoastSEO_Vendor\GuzzleHttp\Exception\RequestException ? $reason->getResponse() : null; $message = $formatter->format($request, $response, \YoastSEO_Vendor\GuzzleHttp\Promise\Create::exceptionFor($reason)); $logger->error($message); return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($reason); }); }; }; } /** * This middleware adds a default content-type if possible, a default * content-length or transfer-encoding header, and the expect header. */ public static function prepareBody() : callable { return static function (callable $handler) : PrepareBodyMiddleware { return new \YoastSEO_Vendor\GuzzleHttp\PrepareBodyMiddleware($handler); }; } /** * Middleware that applies a map function to the request before passing to * the next handler. * * @param callable $fn Function that accepts a RequestInterface and returns * a RequestInterface. */ public static function mapRequest(callable $fn) : callable { return static function (callable $handler) use($fn) : callable { return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($handler, $fn) { return $handler($fn($request), $options); }; }; } /** * Middleware that applies a map function to the resolved promise's * response. * * @param callable $fn Function that accepts a ResponseInterface and * returns a ResponseInterface. */ public static function mapResponse(callable $fn) : callable { return static function (callable $handler) use($fn) : callable { return static function (\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) use($handler, $fn) { return $handler($request, $options)->then($fn); }; }; } } PK!EsvNN guzzlehttp/guzzle/src/Client.phpnu[ 'http://www.foo.com/1.0/', * 'timeout' => 0, * 'allow_redirects' => false, * 'proxy' => '192.168.16.1:10' * ]); * * Client configuration settings include the following options: * * - handler: (callable) Function that transfers HTTP requests over the * wire. The function is called with a Psr7\Http\Message\RequestInterface * and array of transfer options, and must return a * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a * Psr7\Http\Message\ResponseInterface on success. * If no handler is provided, a default handler will be created * that enables all of the request options below by attaching all of the * default middleware to the handler. * - base_uri: (string|UriInterface) Base URI of the client that is merged * into relative URIs. Can be a string or instance of UriInterface. * - **: any request option * * @param array $config Client configuration settings. * * @see \GuzzleHttp\RequestOptions for a list of available request options. */ public function __construct(array $config = []) { if (!isset($config['handler'])) { $config['handler'] = \YoastSEO_Vendor\GuzzleHttp\HandlerStack::create(); } elseif (!\is_callable($config['handler'])) { throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('handler must be a callable'); } // Convert the base_uri to a UriInterface if (isset($config['base_uri'])) { $config['base_uri'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::uriFor($config['base_uri']); } $this->configureDefaults($config); } /** * @param string $method * @param array $args * * @return PromiseInterface|ResponseInterface * * @deprecated Client::__call will be removed in guzzlehttp/guzzle:8.0. */ public function __call($method, $args) { if (\count($args) < 1) { throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('Magic request methods require a URI and optional options array'); } $uri = $args[0]; $opts = $args[1] ?? []; return \substr($method, -5) === 'Async' ? $this->requestAsync(\substr($method, 0, -5), $uri, $opts) : $this->request($method, $uri, $opts); } /** * Asynchronously send an HTTP request. * * @param array $options Request options to apply to the given * request and to the transfer. See \GuzzleHttp\RequestOptions. */ public function sendAsync(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { // Merge the base URI into the request URI if needed. $options = $this->prepareDefaults($options); return $this->transfer($request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')), $options); } /** * Send an HTTP request. * * @param array $options Request options to apply to the given * request and to the transfer. See \GuzzleHttp\RequestOptions. * * @throws GuzzleException */ public function send(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface { $options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::SYNCHRONOUS] = \true; return $this->sendAsync($request, $options)->wait(); } /** * The HttpClient PSR (PSR-18) specify this method. * * {@inheritDoc} */ public function sendRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface { $options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::SYNCHRONOUS] = \true; $options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::ALLOW_REDIRECTS] = \false; $options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::HTTP_ERRORS] = \false; return $this->sendAsync($request, $options)->wait(); } /** * Create and send an asynchronous HTTP request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. Use an array to provide a URL * template and additional variables to use in the URL template expansion. * * @param string $method HTTP method * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions. */ public function requestAsync(string $method, $uri = '', array $options = []) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { $options = $this->prepareDefaults($options); // Remove request modifying parameter because it can be done up-front. $headers = $options['headers'] ?? []; $body = $options['body'] ?? null; $version = $options['version'] ?? '1.1'; // Merge the URI into the base URI. $uri = $this->buildUri(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::uriFor($uri), $options); if (\is_array($body)) { throw $this->invalidBody(); } $request = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($method, $uri, $headers, $body, $version); // Remove the option so that they are not doubly-applied. unset($options['headers'], $options['body'], $options['version']); return $this->transfer($request, $options); } /** * Create and send an HTTP request. * * Use an absolute path to override the base path of the client, or a * relative path to append to the base path of the client. The URL can * contain the query string as well. * * @param string $method HTTP method. * @param string|UriInterface $uri URI object or string. * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions. * * @throws GuzzleException */ public function request(string $method, $uri = '', array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface { $options[\YoastSEO_Vendor\GuzzleHttp\RequestOptions::SYNCHRONOUS] = \true; return $this->requestAsync($method, $uri, $options)->wait(); } /** * Get a client configuration option. * * These options include default request options of the client, a "handler" * (if utilized by the concrete client), and a "base_uri" if utilized by * the concrete client. * * @param string|null $option The config option to retrieve. * * @return mixed * * @deprecated Client::getConfig will be removed in guzzlehttp/guzzle:8.0. */ public function getConfig(string $option = null) { return $option === null ? $this->config : $this->config[$option] ?? null; } private function buildUri(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, array $config) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { if (isset($config['base_uri'])) { $uri = \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::uriFor($config['base_uri']), $uri); } if (isset($config['idn_conversion']) && $config['idn_conversion'] !== \false) { $idnOptions = $config['idn_conversion'] === \true ? \IDNA_DEFAULT : $config['idn_conversion']; $uri = \YoastSEO_Vendor\GuzzleHttp\Utils::idnUriConvert($uri, $idnOptions); } return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri; } /** * Configures the default options for a client. */ private function configureDefaults(array $config) : void { $defaults = ['allow_redirects' => \YoastSEO_Vendor\GuzzleHttp\RedirectMiddleware::$defaultSettings, 'http_errors' => \true, 'decode_content' => \true, 'verify' => \true, 'cookies' => \false, 'idn_conversion' => \false]; // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set. // We can only trust the HTTP_PROXY environment variable in a CLI // process due to the fact that PHP has no reliable mechanism to // get environment variables that start with "HTTP_". if (\PHP_SAPI === 'cli' && ($proxy = \YoastSEO_Vendor\GuzzleHttp\Utils::getenv('HTTP_PROXY'))) { $defaults['proxy']['http'] = $proxy; } if ($proxy = \YoastSEO_Vendor\GuzzleHttp\Utils::getenv('HTTPS_PROXY')) { $defaults['proxy']['https'] = $proxy; } if ($noProxy = \YoastSEO_Vendor\GuzzleHttp\Utils::getenv('NO_PROXY')) { $cleanedNoProxy = \str_replace(' ', '', $noProxy); $defaults['proxy']['no'] = \explode(',', $cleanedNoProxy); } $this->config = $config + $defaults; if (!empty($config['cookies']) && $config['cookies'] === \true) { $this->config['cookies'] = new \YoastSEO_Vendor\GuzzleHttp\Cookie\CookieJar(); } // Add the default user-agent header. if (!isset($this->config['headers'])) { $this->config['headers'] = ['User-Agent' => \YoastSEO_Vendor\GuzzleHttp\Utils::defaultUserAgent()]; } else { // Add the User-Agent header if one was not already set. foreach (\array_keys($this->config['headers']) as $name) { if (\strtolower($name) === 'user-agent') { return; } } $this->config['headers']['User-Agent'] = \YoastSEO_Vendor\GuzzleHttp\Utils::defaultUserAgent(); } } /** * Merges default options into the array. * * @param array $options Options to modify by reference */ private function prepareDefaults(array $options) : array { $defaults = $this->config; if (!empty($defaults['headers'])) { // Default headers are only added if they are not present. $defaults['_conditional'] = $defaults['headers']; unset($defaults['headers']); } // Special handling for headers is required as they are added as // conditional headers and as headers passed to a request ctor. if (\array_key_exists('headers', $options)) { // Allows default headers to be unset. if ($options['headers'] === null) { $defaults['_conditional'] = []; unset($options['headers']); } elseif (!\is_array($options['headers'])) { throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('headers must be an array'); } } // Shallow merge defaults underneath options. $result = $options + $defaults; // Remove null values. foreach ($result as $k => $v) { if ($v === null) { unset($result[$k]); } } return $result; } /** * Transfers the given request and applies request options. * * The URI of the request is not modified and the request options are used * as-is without merging in default options. * * @param array $options See \GuzzleHttp\RequestOptions. */ private function transfer(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $options) : \YoastSEO_Vendor\GuzzleHttp\Promise\PromiseInterface { $request = $this->applyOptions($request, $options); /** @var HandlerStack $handler */ $handler = $options['handler']; try { return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::promiseFor($handler($request, $options)); } catch (\Exception $e) { return \YoastSEO_Vendor\GuzzleHttp\Promise\Create::rejectionFor($e); } } /** * Applies the array of request options to a request. */ private function applyOptions(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array &$options) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface { $modify = ['set_headers' => []]; if (isset($options['headers'])) { if (\array_keys($options['headers']) === \range(0, \count($options['headers']) - 1)) { throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('The headers array must have header name as keys.'); } $modify['set_headers'] = $options['headers']; unset($options['headers']); } if (isset($options['form_params'])) { if (isset($options['multipart'])) { throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('You cannot use ' . 'form_params and multipart at the same time. Use the ' . 'form_params option if you want to send application/' . 'x-www-form-urlencoded requests, and the multipart ' . 'option to send multipart/form-data requests.'); } $options['body'] = \http_build_query($options['form_params'], '', '&'); unset($options['form_params']); // Ensure that we don't have the header in different case and set the new value. $options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded'; } if (isset($options['multipart'])) { $options['body'] = new \YoastSEO_Vendor\GuzzleHttp\Psr7\MultipartStream($options['multipart']); unset($options['multipart']); } if (isset($options['json'])) { $options['body'] = \YoastSEO_Vendor\GuzzleHttp\Utils::jsonEncode($options['json']); unset($options['json']); // Ensure that we don't have the header in different case and set the new value. $options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'application/json'; } if (!empty($options['decode_content']) && $options['decode_content'] !== \true) { // Ensure that we don't have the header in different case and set the new value. $options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Accept-Encoding'], $options['_conditional']); $modify['set_headers']['Accept-Encoding'] = $options['decode_content']; } if (isset($options['body'])) { if (\is_array($options['body'])) { throw $this->invalidBody(); } $modify['body'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($options['body']); unset($options['body']); } if (!empty($options['auth']) && \is_array($options['auth'])) { $value = $options['auth']; $type = isset($value[2]) ? \strtolower($value[2]) : 'basic'; switch ($type) { case 'basic': // Ensure that we don't have the header in different case and set the new value. $modify['set_headers'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Authorization'], $modify['set_headers']); $modify['set_headers']['Authorization'] = 'Basic ' . \base64_encode("{$value[0]}:{$value[1]}"); break; case 'digest': // @todo: Do not rely on curl $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_DIGEST; $options['curl'][\CURLOPT_USERPWD] = "{$value[0]}:{$value[1]}"; break; case 'ntlm': $options['curl'][\CURLOPT_HTTPAUTH] = \CURLAUTH_NTLM; $options['curl'][\CURLOPT_USERPWD] = "{$value[0]}:{$value[1]}"; break; } } if (isset($options['query'])) { $value = $options['query']; if (\is_array($value)) { $value = \http_build_query($value, '', '&', \PHP_QUERY_RFC3986); } if (!\is_string($value)) { throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('query must be a string or array'); } $modify['query'] = $value; unset($options['query']); } // Ensure that sink is not an invalid value. if (isset($options['sink'])) { // TODO: Add more sink validation? if (\is_bool($options['sink'])) { throw new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('sink must not be a boolean'); } } if (isset($options['version'])) { $modify['version'] = $options['version']; } $request = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::modifyRequest($request, $modify); if ($request->getBody() instanceof \YoastSEO_Vendor\GuzzleHttp\Psr7\MultipartStream) { // Use a multipart/form-data POST if a Content-Type is not set. // Ensure that we don't have the header in different case and set the new value. $options['_conditional'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::caselessRemove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary=' . $request->getBody()->getBoundary(); } // Merge in conditional headers if they are not present. if (isset($options['_conditional'])) { // Build up the changes so it's in a single clone of the message. $modify = []; foreach ($options['_conditional'] as $k => $v) { if (!$request->hasHeader($k)) { $modify['set_headers'][$k] = $v; } } $request = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::modifyRequest($request, $modify); // Don't pass this internal value along to middleware/handlers. unset($options['_conditional']); } return $request; } /** * Return an InvalidArgumentException with pre-set message. */ private function invalidBody() : \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException { return new \YoastSEO_Vendor\GuzzleHttp\Exception\InvalidArgumentException('Passing in the "body" request ' . 'option as an array to send a request is not supported. ' . 'Please use the "form_params" request option to send a ' . 'application/x-www-form-urlencoded request, or the "multipart" ' . 'request option to send a multipart/form-data request.'); } } PK!x{33$guzzlehttp/psr7/src/UploadedFile.phpnu[setError($errorStatus); $this->size = $size; $this->clientFilename = $clientFilename; $this->clientMediaType = $clientMediaType; if ($this->isOk()) { $this->setStreamOrFile($streamOrFile); } } /** * Depending on the value set file or stream variable * * @param StreamInterface|string|resource $streamOrFile * * @throws InvalidArgumentException */ private function setStreamOrFile($streamOrFile) : void { if (\is_string($streamOrFile)) { $this->file = $streamOrFile; } elseif (\is_resource($streamOrFile)) { $this->stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($streamOrFile); } elseif ($streamOrFile instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) { $this->stream = $streamOrFile; } else { throw new \InvalidArgumentException('Invalid stream or file provided for UploadedFile'); } } /** * @throws InvalidArgumentException */ private function setError(int $error) : void { if (\false === \in_array($error, \YoastSEO_Vendor\GuzzleHttp\Psr7\UploadedFile::ERRORS, \true)) { throw new \InvalidArgumentException('Invalid error status for UploadedFile'); } $this->error = $error; } private static function isStringNotEmpty($param) : bool { return \is_string($param) && \false === empty($param); } /** * Return true if there is no upload error */ private function isOk() : bool { return $this->error === \UPLOAD_ERR_OK; } public function isMoved() : bool { return $this->moved; } /** * @throws RuntimeException if is moved or not ok */ private function validateActive() : void { if (\false === $this->isOk()) { throw new \RuntimeException('Cannot retrieve stream due to upload error'); } if ($this->isMoved()) { throw new \RuntimeException('Cannot retrieve stream after it has already been moved'); } } public function getStream() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface { $this->validateActive(); if ($this->stream instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) { return $this->stream; } /** @var string $file */ $file = $this->file; return new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($file, 'r+'); } public function moveTo($targetPath) : void { $this->validateActive(); if (\false === self::isStringNotEmpty($targetPath)) { throw new \InvalidArgumentException('Invalid path provided for move operation; must be a non-empty string'); } if ($this->file) { $this->moved = \PHP_SAPI === 'cli' ? \rename($this->file, $targetPath) : \move_uploaded_file($this->file, $targetPath); } else { \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToStream($this->getStream(), new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream($targetPath, 'w')); $this->moved = \true; } if (\false === $this->moved) { throw new \RuntimeException(\sprintf('Uploaded file could not be moved to %s', $targetPath)); } } public function getSize() : ?int { return $this->size; } public function getError() : int { return $this->error; } public function getClientFilename() : ?string { return $this->clientFilename; } public function getClientMediaType() : ?string { return $this->clientMediaType; } } PK!u$$guzzlehttp/psr7/src/MessageTrait.phpnu[ array of values */ private $headers = []; /** @var string[] Map of lowercase header name => original name at registration */ private $headerNames = []; /** @var string */ private $protocol = '1.1'; /** @var StreamInterface|null */ private $stream; public function getProtocolVersion() : string { return $this->protocol; } public function withProtocolVersion($version) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface { if ($this->protocol === $version) { return $this; } $new = clone $this; $new->protocol = $version; return $new; } public function getHeaders() : array { return $this->headers; } public function hasHeader($header) : bool { return isset($this->headerNames[\strtolower($header)]); } public function getHeader($header) : array { $header = \strtolower($header); if (!isset($this->headerNames[$header])) { return []; } $header = $this->headerNames[$header]; return $this->headers[$header]; } public function getHeaderLine($header) : string { return \implode(', ', $this->getHeader($header)); } public function withHeader($header, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface { $this->assertHeader($header); $value = $this->normalizeHeaderValue($value); $normalized = \strtolower($header); $new = clone $this; if (isset($new->headerNames[$normalized])) { unset($new->headers[$new->headerNames[$normalized]]); } $new->headerNames[$normalized] = $header; $new->headers[$header] = $value; return $new; } public function withAddedHeader($header, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface { $this->assertHeader($header); $value = $this->normalizeHeaderValue($value); $normalized = \strtolower($header); $new = clone $this; if (isset($new->headerNames[$normalized])) { $header = $this->headerNames[$normalized]; $new->headers[$header] = \array_merge($this->headers[$header], $value); } else { $new->headerNames[$normalized] = $header; $new->headers[$header] = $value; } return $new; } public function withoutHeader($header) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface { $normalized = \strtolower($header); if (!isset($this->headerNames[$normalized])) { return $this; } $header = $this->headerNames[$normalized]; $new = clone $this; unset($new->headers[$header], $new->headerNames[$normalized]); return $new; } public function getBody() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface { if (!$this->stream) { $this->stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor(''); } return $this->stream; } public function withBody(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $body) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface { if ($body === $this->stream) { return $this; } $new = clone $this; $new->stream = $body; return $new; } /** * @param (string|string[])[] $headers */ private function setHeaders(array $headers) : void { $this->headerNames = $this->headers = []; foreach ($headers as $header => $value) { // Numeric array keys are converted to int by PHP. $header = (string) $header; $this->assertHeader($header); $value = $this->normalizeHeaderValue($value); $normalized = \strtolower($header); if (isset($this->headerNames[$normalized])) { $header = $this->headerNames[$normalized]; $this->headers[$header] = \array_merge($this->headers[$header], $value); } else { $this->headerNames[$normalized] = $header; $this->headers[$header] = $value; } } } /** * @param mixed $value * * @return string[] */ private function normalizeHeaderValue($value) : array { if (!\is_array($value)) { return $this->trimAndValidateHeaderValues([$value]); } if (\count($value) === 0) { throw new \InvalidArgumentException('Header value can not be an empty array.'); } return $this->trimAndValidateHeaderValues($value); } /** * Trims whitespace from the header values. * * Spaces and tabs ought to be excluded by parsers when extracting the field value from a header field. * * header-field = field-name ":" OWS field-value OWS * OWS = *( SP / HTAB ) * * @param mixed[] $values Header values * * @return string[] Trimmed header values * * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4 */ private function trimAndValidateHeaderValues(array $values) : array { return \array_map(function ($value) { if (!\is_scalar($value) && null !== $value) { throw new \InvalidArgumentException(\sprintf('Header value must be scalar or null but %s provided.', \is_object($value) ? \get_class($value) : \gettype($value))); } $trimmed = \trim((string) $value, " \t"); $this->assertValue($trimmed); return $trimmed; }, \array_values($values)); } /** * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2 * * @param mixed $header */ private function assertHeader($header) : void { if (!\is_string($header)) { throw new \InvalidArgumentException(\sprintf('Header name must be a string but %s provided.', \is_object($header) ? \get_class($header) : \gettype($header))); } if (!\preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/D', $header)) { throw new \InvalidArgumentException(\sprintf('"%s" is not valid header name.', $header)); } } /** * @see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2 * * field-value = *( field-content / obs-fold ) * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] * field-vchar = VCHAR / obs-text * VCHAR = %x21-7E * obs-text = %x80-FF * obs-fold = CRLF 1*( SP / HTAB ) */ private function assertValue(string $value) : void { // The regular expression intentionally does not support the obs-fold production, because as // per RFC 7230#3.2.4: // // A sender MUST NOT generate a message that includes // line folding (i.e., that has any field-value that contains a match to // the obs-fold rule) unless the message is intended for packaging // within the message/http media type. // // Clients must not send a request with line folding and a server sending folded headers is // likely very rare. Line folding is a fairly obscure feature of HTTP/1.1 and thus not accepting // folding is not likely to break any legitimate use case. if (!\preg_match('/^[\\x20\\x09\\x21-\\x7E\\x80-\\xFF]*$/D', $value)) { throw new \InvalidArgumentException(\sprintf('"%s" is not valid header value.', $value)); } } } PK!#?0guzzlehttp/psr7/src/Rfc7230.phpnu[@,;:\\\"/[\\]?={}\x01- ]++):[ \t]*+((?:[ \t]*+[!-~\x80-\xff]++)*+)[ \t]*+\r?\n)m"; public const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)"; } PK!f; guzzlehttp/psr7/src/Response.phpnu[ 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-status', 208 => 'Already Reported', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Switch Proxy', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Unordered Collection', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable For Legal Reasons', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 510 => 'Not Extended', 511 => 'Network Authentication Required']; /** @var string */ private $reasonPhrase; /** @var int */ private $statusCode; /** * @param int $status Status code * @param (string|string[])[] $headers Response headers * @param string|resource|StreamInterface|null $body Response body * @param string $version Protocol version * @param string|null $reason Reason phrase (when empty a default will be used based on the status code) */ public function __construct(int $status = 200, array $headers = [], $body = null, string $version = '1.1', string $reason = null) { $this->assertStatusCodeRange($status); $this->statusCode = $status; if ($body !== '' && $body !== null) { $this->stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($body); } $this->setHeaders($headers); if ($reason == '' && isset(self::PHRASES[$this->statusCode])) { $this->reasonPhrase = self::PHRASES[$this->statusCode]; } else { $this->reasonPhrase = (string) $reason; } $this->protocol = $version; } public function getStatusCode() : int { return $this->statusCode; } public function getReasonPhrase() : string { return $this->reasonPhrase; } public function withStatus($code, $reasonPhrase = '') : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface { $this->assertStatusCodeIsInteger($code); $code = (int) $code; $this->assertStatusCodeRange($code); $new = clone $this; $new->statusCode = $code; if ($reasonPhrase == '' && isset(self::PHRASES[$new->statusCode])) { $reasonPhrase = self::PHRASES[$new->statusCode]; } $new->reasonPhrase = (string) $reasonPhrase; return $new; } /** * @param mixed $statusCode */ private function assertStatusCodeIsInteger($statusCode) : void { if (\filter_var($statusCode, \FILTER_VALIDATE_INT) === \false) { throw new \InvalidArgumentException('Status code must be an integer value.'); } } private function assertStatusCodeRange(int $statusCode) : void { if ($statusCode < 100 || $statusCode >= 600) { throw new \InvalidArgumentException('Status code must be an integer value between 1xx and 5xx.'); } } } PK!.NN$guzzlehttp/psr7/src/NoSeekStream.phpnu[ */ private $methods; /** * @param array $methods Hash of method name to a callable. */ public function __construct(array $methods) { $this->methods = $methods; // Create the functions on the class foreach ($methods as $name => $fn) { $this->{'_fn_' . $name} = $fn; } } /** * Lazily determine which methods are not implemented. * * @throws \BadMethodCallException */ public function __get(string $name) : void { throw new \BadMethodCallException(\str_replace('_fn_', '', $name) . '() is not implemented in the FnStream'); } /** * The close method is called on the underlying stream only if possible. */ public function __destruct() { if (isset($this->_fn_close)) { ($this->_fn_close)(); } } /** * An unserialize would allow the __destruct to run when the unserialized value goes out of scope. * * @throws \LogicException */ public function __wakeup() : void { throw new \LogicException('FnStream should never be unserialized'); } /** * Adds custom functionality to an underlying stream by intercepting * specific method calls. * * @param StreamInterface $stream Stream to decorate * @param array $methods Hash of method name to a closure * * @return FnStream */ public static function decorate(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, array $methods) { // If any of the required methods were not provided, then simply // proxy to the decorated stream. foreach (\array_diff(self::SLOTS, \array_keys($methods)) as $diff) { /** @var callable $callable */ $callable = [$stream, $diff]; $methods[$diff] = $callable; } return new self($methods); } public function __toString() : string { try { /** @var string */ return ($this->_fn___toString)(); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } \trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR); return ''; } } public function close() : void { ($this->_fn_close)(); } public function detach() { return ($this->_fn_detach)(); } public function getSize() : ?int { return ($this->_fn_getSize)(); } public function tell() : int { return ($this->_fn_tell)(); } public function eof() : bool { return ($this->_fn_eof)(); } public function isSeekable() : bool { return ($this->_fn_isSeekable)(); } public function rewind() : void { ($this->_fn_rewind)(); } public function seek($offset, $whence = \SEEK_SET) : void { ($this->_fn_seek)($offset, $whence); } public function isWritable() : bool { return ($this->_fn_isWritable)(); } public function write($string) : int { return ($this->_fn_write)($string); } public function isReadable() : bool { return ($this->_fn_isReadable)(); } public function read($length) : string { return ($this->_fn_read)($length); } public function getContents() : string { return ($this->_fn_getContents)(); } /** * @return mixed */ public function getMetadata($key = null) { return ($this->_fn_getMetadata)($key); } } PK! $guzzlehttp/psr7/src/BufferStream.phpnu[hwm = $hwm; } public function __toString() : string { return $this->getContents(); } public function getContents() : string { $buffer = $this->buffer; $this->buffer = ''; return $buffer; } public function close() : void { $this->buffer = ''; } public function detach() { $this->close(); return null; } public function getSize() : ?int { return \strlen($this->buffer); } public function isReadable() : bool { return \true; } public function isWritable() : bool { return \true; } public function isSeekable() : bool { return \false; } public function rewind() : void { $this->seek(0); } public function seek($offset, $whence = \SEEK_SET) : void { throw new \RuntimeException('Cannot seek a BufferStream'); } public function eof() : bool { return \strlen($this->buffer) === 0; } public function tell() : int { throw new \RuntimeException('Cannot determine the position of a BufferStream'); } /** * Reads data from the buffer. */ public function read($length) : string { $currentLength = \strlen($this->buffer); if ($length >= $currentLength) { // No need to slice the buffer because we don't have enough data. $result = $this->buffer; $this->buffer = ''; } else { // Slice up the result to provide a subset of the buffer. $result = \substr($this->buffer, 0, $length); $this->buffer = \substr($this->buffer, $length); } return $result; } /** * Writes data to the buffer. */ public function write($string) : int { $this->buffer .= $string; if (\strlen($this->buffer) >= $this->hwm) { return 0; } return \strlen($string); } /** * @return mixed */ public function getMetadata($key = null) { if ($key === 'hwm') { return $this->hwm; } return $key ? null : []; } } PK!#ccguzzlehttp/psr7/src/Request.phpnu[assertMethod($method); if (!$uri instanceof \YoastSEO_Vendor\Psr\Http\Message\UriInterface) { $uri = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($uri); } $this->method = \strtoupper($method); $this->uri = $uri; $this->setHeaders($headers); $this->protocol = $version; if (!isset($this->headerNames['host'])) { $this->updateHostFromUri(); } if ($body !== '' && $body !== null) { $this->stream = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($body); } } public function getRequestTarget() : string { if ($this->requestTarget !== null) { return $this->requestTarget; } $target = $this->uri->getPath(); if ($target === '') { $target = '/'; } if ($this->uri->getQuery() != '') { $target .= '?' . $this->uri->getQuery(); } return $target; } public function withRequestTarget($requestTarget) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface { if (\preg_match('#\\s#', $requestTarget)) { throw new \InvalidArgumentException('Invalid request target provided; cannot contain whitespace'); } $new = clone $this; $new->requestTarget = $requestTarget; return $new; } public function getMethod() : string { return $this->method; } public function withMethod($method) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface { $this->assertMethod($method); $new = clone $this; $new->method = \strtoupper($method); return $new; } public function getUri() : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { return $this->uri; } public function withUri(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, $preserveHost = \false) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface { if ($uri === $this->uri) { return $this; } $new = clone $this; $new->uri = $uri; if (!$preserveHost || !isset($this->headerNames['host'])) { $new->updateHostFromUri(); } return $new; } private function updateHostFromUri() : void { $host = $this->uri->getHost(); if ($host == '') { return; } if (($port = $this->uri->getPort()) !== null) { $host .= ':' . $port; } if (isset($this->headerNames['host'])) { $header = $this->headerNames['host']; } else { $header = 'Host'; $this->headerNames['host'] = 'Host'; } // Ensure Host is the first header. // See: https://datatracker.ietf.org/doc/html/rfc7230#section-5.4 $this->headers = [$header => [$host]] + $this->headers; } /** * @param mixed $method */ private function assertMethod($method) : void { if (!\is_string($method) || $method === '') { throw new \InvalidArgumentException('Method must be a non-empty string.'); } } } PK!te guzzlehttp/psr7/src/MimeType.phpnu[ 'application/vnd.1000minds.decision-model+xml', '3dml' => 'text/vnd.in3d.3dml', '3ds' => 'image/x-3ds', '3g2' => 'video/3gpp2', '3gp' => 'video/3gp', '3gpp' => 'video/3gpp', '3mf' => 'model/3mf', '7z' => 'application/x-7z-compressed', '7zip' => 'application/x-7z-compressed', '123' => 'application/vnd.lotus-1-2-3', 'aab' => 'application/x-authorware-bin', 'aac' => 'audio/aac', 'aam' => 'application/x-authorware-map', 'aas' => 'application/x-authorware-seg', 'abw' => 'application/x-abiword', 'ac' => 'application/vnd.nokia.n-gage.ac+xml', 'ac3' => 'audio/ac3', 'acc' => 'application/vnd.americandynamics.acc', 'ace' => 'application/x-ace-compressed', 'acu' => 'application/vnd.acucobol', 'acutc' => 'application/vnd.acucorp', 'adp' => 'audio/adpcm', 'adts' => 'audio/aac', 'aep' => 'application/vnd.audiograph', 'afm' => 'application/x-font-type1', 'afp' => 'application/vnd.ibm.modcap', 'age' => 'application/vnd.age', 'ahead' => 'application/vnd.ahead.space', 'ai' => 'application/pdf', 'aif' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff', 'aiff' => 'audio/x-aiff', 'air' => 'application/vnd.adobe.air-application-installer-package+zip', 'ait' => 'application/vnd.dvb.ait', 'ami' => 'application/vnd.amiga.ami', 'aml' => 'application/automationml-aml+xml', 'amlx' => 'application/automationml-amlx+zip', 'amr' => 'audio/amr', 'apk' => 'application/vnd.android.package-archive', 'apng' => 'image/apng', 'appcache' => 'text/cache-manifest', 'appinstaller' => 'application/appinstaller', 'application' => 'application/x-ms-application', 'appx' => 'application/appx', 'appxbundle' => 'application/appxbundle', 'apr' => 'application/vnd.lotus-approach', 'arc' => 'application/x-freearc', 'arj' => 'application/x-arj', 'asc' => 'application/pgp-signature', 'asf' => 'video/x-ms-asf', 'asm' => 'text/x-asm', 'aso' => 'application/vnd.accpac.simply.aso', 'asx' => 'video/x-ms-asf', 'atc' => 'application/vnd.acucorp', 'atom' => 'application/atom+xml', 'atomcat' => 'application/atomcat+xml', 'atomdeleted' => 'application/atomdeleted+xml', 'atomsvc' => 'application/atomsvc+xml', 'atx' => 'application/vnd.antix.game-component', 'au' => 'audio/x-au', 'avci' => 'image/avci', 'avcs' => 'image/avcs', 'avi' => 'video/x-msvideo', 'avif' => 'image/avif', 'aw' => 'application/applixware', 'azf' => 'application/vnd.airzip.filesecure.azf', 'azs' => 'application/vnd.airzip.filesecure.azs', 'azv' => 'image/vnd.airzip.accelerator.azv', 'azw' => 'application/vnd.amazon.ebook', 'b16' => 'image/vnd.pco.b16', 'bat' => 'application/x-msdownload', 'bcpio' => 'application/x-bcpio', 'bdf' => 'application/x-font-bdf', 'bdm' => 'application/vnd.syncml.dm+wbxml', 'bdoc' => 'application/x-bdoc', 'bed' => 'application/vnd.realvnc.bed', 'bh2' => 'application/vnd.fujitsu.oasysprs', 'bin' => 'application/octet-stream', 'blb' => 'application/x-blorb', 'blorb' => 'application/x-blorb', 'bmi' => 'application/vnd.bmi', 'bmml' => 'application/vnd.balsamiq.bmml+xml', 'bmp' => 'image/bmp', 'book' => 'application/vnd.framemaker', 'box' => 'application/vnd.previewsystems.box', 'boz' => 'application/x-bzip2', 'bpk' => 'application/octet-stream', 'bpmn' => 'application/octet-stream', 'bsp' => 'model/vnd.valve.source.compiled-map', 'btf' => 'image/prs.btif', 'btif' => 'image/prs.btif', 'buffer' => 'application/octet-stream', 'bz' => 'application/x-bzip', 'bz2' => 'application/x-bzip2', 'c' => 'text/x-c', 'c4d' => 'application/vnd.clonk.c4group', 'c4f' => 'application/vnd.clonk.c4group', 'c4g' => 'application/vnd.clonk.c4group', 'c4p' => 'application/vnd.clonk.c4group', 'c4u' => 'application/vnd.clonk.c4group', 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', 'cab' => 'application/vnd.ms-cab-compressed', 'caf' => 'audio/x-caf', 'cap' => 'application/vnd.tcpdump.pcap', 'car' => 'application/vnd.curl.car', 'cat' => 'application/vnd.ms-pki.seccat', 'cb7' => 'application/x-cbr', 'cba' => 'application/x-cbr', 'cbr' => 'application/x-cbr', 'cbt' => 'application/x-cbr', 'cbz' => 'application/x-cbr', 'cc' => 'text/x-c', 'cco' => 'application/x-cocoa', 'cct' => 'application/x-director', 'ccxml' => 'application/ccxml+xml', 'cdbcmsg' => 'application/vnd.contact.cmsg', 'cdf' => 'application/x-netcdf', 'cdfx' => 'application/cdfx+xml', 'cdkey' => 'application/vnd.mediastation.cdkey', 'cdmia' => 'application/cdmi-capability', 'cdmic' => 'application/cdmi-container', 'cdmid' => 'application/cdmi-domain', 'cdmio' => 'application/cdmi-object', 'cdmiq' => 'application/cdmi-queue', 'cdr' => 'application/cdr', 'cdx' => 'chemical/x-cdx', 'cdxml' => 'application/vnd.chemdraw+xml', 'cdy' => 'application/vnd.cinderella', 'cer' => 'application/pkix-cert', 'cfs' => 'application/x-cfs-compressed', 'cgm' => 'image/cgm', 'chat' => 'application/x-chat', 'chm' => 'application/vnd.ms-htmlhelp', 'chrt' => 'application/vnd.kde.kchart', 'cif' => 'chemical/x-cif', 'cii' => 'application/vnd.anser-web-certificate-issue-initiation', 'cil' => 'application/vnd.ms-artgalry', 'cjs' => 'application/node', 'cla' => 'application/vnd.claymore', 'class' => 'application/octet-stream', 'cld' => 'model/vnd.cld', 'clkk' => 'application/vnd.crick.clicker.keyboard', 'clkp' => 'application/vnd.crick.clicker.palette', 'clkt' => 'application/vnd.crick.clicker.template', 'clkw' => 'application/vnd.crick.clicker.wordbank', 'clkx' => 'application/vnd.crick.clicker', 'clp' => 'application/x-msclip', 'cmc' => 'application/vnd.cosmocaller', 'cmdf' => 'chemical/x-cmdf', 'cml' => 'chemical/x-cml', 'cmp' => 'application/vnd.yellowriver-custom-menu', 'cmx' => 'image/x-cmx', 'cod' => 'application/vnd.rim.cod', 'coffee' => 'text/coffeescript', 'com' => 'application/x-msdownload', 'conf' => 'text/plain', 'cpio' => 'application/x-cpio', 'cpl' => 'application/cpl+xml', 'cpp' => 'text/x-c', 'cpt' => 'application/mac-compactpro', 'crd' => 'application/x-mscardfile', 'crl' => 'application/pkix-crl', 'crt' => 'application/x-x509-ca-cert', 'crx' => 'application/x-chrome-extension', 'cryptonote' => 'application/vnd.rig.cryptonote', 'csh' => 'application/x-csh', 'csl' => 'application/vnd.citationstyles.style+xml', 'csml' => 'chemical/x-csml', 'csp' => 'application/vnd.commonspace', 'csr' => 'application/octet-stream', 'css' => 'text/css', 'cst' => 'application/x-director', 'csv' => 'text/csv', 'cu' => 'application/cu-seeme', 'curl' => 'text/vnd.curl', 'cwl' => 'application/cwl', 'cww' => 'application/prs.cww', 'cxt' => 'application/x-director', 'cxx' => 'text/x-c', 'dae' => 'model/vnd.collada+xml', 'daf' => 'application/vnd.mobius.daf', 'dart' => 'application/vnd.dart', 'dataless' => 'application/vnd.fdsn.seed', 'davmount' => 'application/davmount+xml', 'dbf' => 'application/vnd.dbf', 'dbk' => 'application/docbook+xml', 'dcr' => 'application/x-director', 'dcurl' => 'text/vnd.curl.dcurl', 'dd2' => 'application/vnd.oma.dd2+xml', 'ddd' => 'application/vnd.fujixerox.ddd', 'ddf' => 'application/vnd.syncml.dmddf+xml', 'dds' => 'image/vnd.ms-dds', 'deb' => 'application/x-debian-package', 'def' => 'text/plain', 'deploy' => 'application/octet-stream', 'der' => 'application/x-x509-ca-cert', 'dfac' => 'application/vnd.dreamfactory', 'dgc' => 'application/x-dgc-compressed', 'dib' => 'image/bmp', 'dic' => 'text/x-c', 'dir' => 'application/x-director', 'dis' => 'application/vnd.mobius.dis', 'disposition-notification' => 'message/disposition-notification', 'dist' => 'application/octet-stream', 'distz' => 'application/octet-stream', 'djv' => 'image/vnd.djvu', 'djvu' => 'image/vnd.djvu', 'dll' => 'application/octet-stream', 'dmg' => 'application/x-apple-diskimage', 'dmn' => 'application/octet-stream', 'dmp' => 'application/vnd.tcpdump.pcap', 'dms' => 'application/octet-stream', 'dna' => 'application/vnd.dna', 'doc' => 'application/msword', 'docm' => 'application/vnd.ms-word.template.macroEnabled.12', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'dot' => 'application/msword', 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12', 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 'dp' => 'application/vnd.osgi.dp', 'dpg' => 'application/vnd.dpgraph', 'dpx' => 'image/dpx', 'dra' => 'audio/vnd.dra', 'drle' => 'image/dicom-rle', 'dsc' => 'text/prs.lines.tag', 'dssc' => 'application/dssc+der', 'dtb' => 'application/x-dtbook+xml', 'dtd' => 'application/xml-dtd', 'dts' => 'audio/vnd.dts', 'dtshd' => 'audio/vnd.dts.hd', 'dump' => 'application/octet-stream', 'dvb' => 'video/vnd.dvb.file', 'dvi' => 'application/x-dvi', 'dwd' => 'application/atsc-dwd+xml', 'dwf' => 'model/vnd.dwf', 'dwg' => 'image/vnd.dwg', 'dxf' => 'image/vnd.dxf', 'dxp' => 'application/vnd.spotfire.dxp', 'dxr' => 'application/x-director', 'ear' => 'application/java-archive', 'ecelp4800' => 'audio/vnd.nuera.ecelp4800', 'ecelp7470' => 'audio/vnd.nuera.ecelp7470', 'ecelp9600' => 'audio/vnd.nuera.ecelp9600', 'ecma' => 'application/ecmascript', 'edm' => 'application/vnd.novadigm.edm', 'edx' => 'application/vnd.novadigm.edx', 'efif' => 'application/vnd.picsel', 'ei6' => 'application/vnd.pg.osasli', 'elc' => 'application/octet-stream', 'emf' => 'image/emf', 'eml' => 'message/rfc822', 'emma' => 'application/emma+xml', 'emotionml' => 'application/emotionml+xml', 'emz' => 'application/x-msmetafile', 'eol' => 'audio/vnd.digital-winds', 'eot' => 'application/vnd.ms-fontobject', 'eps' => 'application/postscript', 'epub' => 'application/epub+zip', 'es3' => 'application/vnd.eszigno3+xml', 'esa' => 'application/vnd.osgi.subsystem', 'esf' => 'application/vnd.epson.esf', 'et3' => 'application/vnd.eszigno3+xml', 'etx' => 'text/x-setext', 'eva' => 'application/x-eva', 'evy' => 'application/x-envoy', 'exe' => 'application/octet-stream', 'exi' => 'application/exi', 'exp' => 'application/express', 'exr' => 'image/aces', 'ext' => 'application/vnd.novadigm.ext', 'ez' => 'application/andrew-inset', 'ez2' => 'application/vnd.ezpix-album', 'ez3' => 'application/vnd.ezpix-package', 'f' => 'text/x-fortran', 'f4v' => 'video/mp4', 'f77' => 'text/x-fortran', 'f90' => 'text/x-fortran', 'fbs' => 'image/vnd.fastbidsheet', 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', 'fcs' => 'application/vnd.isac.fcs', 'fdf' => 'application/vnd.fdf', 'fdt' => 'application/fdt+xml', 'fe_launch' => 'application/vnd.denovo.fcselayout-link', 'fg5' => 'application/vnd.fujitsu.oasysgp', 'fgd' => 'application/x-director', 'fh' => 'image/x-freehand', 'fh4' => 'image/x-freehand', 'fh5' => 'image/x-freehand', 'fh7' => 'image/x-freehand', 'fhc' => 'image/x-freehand', 'fig' => 'application/x-xfig', 'fits' => 'image/fits', 'flac' => 'audio/x-flac', 'fli' => 'video/x-fli', 'flo' => 'application/vnd.micrografx.flo', 'flv' => 'video/x-flv', 'flw' => 'application/vnd.kde.kivio', 'flx' => 'text/vnd.fmi.flexstor', 'fly' => 'text/vnd.fly', 'fm' => 'application/vnd.framemaker', 'fnc' => 'application/vnd.frogans.fnc', 'fo' => 'application/vnd.software602.filler.form+xml', 'for' => 'text/x-fortran', 'fpx' => 'image/vnd.fpx', 'frame' => 'application/vnd.framemaker', 'fsc' => 'application/vnd.fsc.weblaunch', 'fst' => 'image/vnd.fst', 'ftc' => 'application/vnd.fluxtime.clip', 'fti' => 'application/vnd.anser-web-funds-transfer-initiation', 'fvt' => 'video/vnd.fvt', 'fxp' => 'application/vnd.adobe.fxp', 'fxpl' => 'application/vnd.adobe.fxp', 'fzs' => 'application/vnd.fuzzysheet', 'g2w' => 'application/vnd.geoplan', 'g3' => 'image/g3fax', 'g3w' => 'application/vnd.geospace', 'gac' => 'application/vnd.groove-account', 'gam' => 'application/x-tads', 'gbr' => 'application/rpki-ghostbusters', 'gca' => 'application/x-gca-compressed', 'gdl' => 'model/vnd.gdl', 'gdoc' => 'application/vnd.google-apps.document', 'ged' => 'text/vnd.familysearch.gedcom', 'geo' => 'application/vnd.dynageo', 'geojson' => 'application/geo+json', 'gex' => 'application/vnd.geometry-explorer', 'ggb' => 'application/vnd.geogebra.file', 'ggt' => 'application/vnd.geogebra.tool', 'ghf' => 'application/vnd.groove-help', 'gif' => 'image/gif', 'gim' => 'application/vnd.groove-identity-message', 'glb' => 'model/gltf-binary', 'gltf' => 'model/gltf+json', 'gml' => 'application/gml+xml', 'gmx' => 'application/vnd.gmx', 'gnumeric' => 'application/x-gnumeric', 'gpg' => 'application/gpg-keys', 'gph' => 'application/vnd.flographit', 'gpx' => 'application/gpx+xml', 'gqf' => 'application/vnd.grafeq', 'gqs' => 'application/vnd.grafeq', 'gram' => 'application/srgs', 'gramps' => 'application/x-gramps-xml', 'gre' => 'application/vnd.geometry-explorer', 'grv' => 'application/vnd.groove-injector', 'grxml' => 'application/srgs+xml', 'gsf' => 'application/x-font-ghostscript', 'gsheet' => 'application/vnd.google-apps.spreadsheet', 'gslides' => 'application/vnd.google-apps.presentation', 'gtar' => 'application/x-gtar', 'gtm' => 'application/vnd.groove-tool-message', 'gtw' => 'model/vnd.gtw', 'gv' => 'text/vnd.graphviz', 'gxf' => 'application/gxf', 'gxt' => 'application/vnd.geonext', 'gz' => 'application/gzip', 'gzip' => 'application/gzip', 'h' => 'text/x-c', 'h261' => 'video/h261', 'h263' => 'video/h263', 'h264' => 'video/h264', 'hal' => 'application/vnd.hal+xml', 'hbci' => 'application/vnd.hbci', 'hbs' => 'text/x-handlebars-template', 'hdd' => 'application/x-virtualbox-hdd', 'hdf' => 'application/x-hdf', 'heic' => 'image/heic', 'heics' => 'image/heic-sequence', 'heif' => 'image/heif', 'heifs' => 'image/heif-sequence', 'hej2' => 'image/hej2k', 'held' => 'application/atsc-held+xml', 'hh' => 'text/x-c', 'hjson' => 'application/hjson', 'hlp' => 'application/winhlp', 'hpgl' => 'application/vnd.hp-hpgl', 'hpid' => 'application/vnd.hp-hpid', 'hps' => 'application/vnd.hp-hps', 'hqx' => 'application/mac-binhex40', 'hsj2' => 'image/hsj2', 'htc' => 'text/x-component', 'htke' => 'application/vnd.kenameaapp', 'htm' => 'text/html', 'html' => 'text/html', 'hvd' => 'application/vnd.yamaha.hv-dic', 'hvp' => 'application/vnd.yamaha.hv-voice', 'hvs' => 'application/vnd.yamaha.hv-script', 'i2g' => 'application/vnd.intergeo', 'icc' => 'application/vnd.iccprofile', 'ice' => 'x-conference/x-cooltalk', 'icm' => 'application/vnd.iccprofile', 'ico' => 'image/x-icon', 'ics' => 'text/calendar', 'ief' => 'image/ief', 'ifb' => 'text/calendar', 'ifm' => 'application/vnd.shana.informed.formdata', 'iges' => 'model/iges', 'igl' => 'application/vnd.igloader', 'igm' => 'application/vnd.insors.igm', 'igs' => 'model/iges', 'igx' => 'application/vnd.micrografx.igx', 'iif' => 'application/vnd.shana.informed.interchange', 'img' => 'application/octet-stream', 'imp' => 'application/vnd.accpac.simply.imp', 'ims' => 'application/vnd.ms-ims', 'in' => 'text/plain', 'ini' => 'text/plain', 'ink' => 'application/inkml+xml', 'inkml' => 'application/inkml+xml', 'install' => 'application/x-install-instructions', 'iota' => 'application/vnd.astraea-software.iota', 'ipfix' => 'application/ipfix', 'ipk' => 'application/vnd.shana.informed.package', 'irm' => 'application/vnd.ibm.rights-management', 'irp' => 'application/vnd.irepository.package+xml', 'iso' => 'application/x-iso9660-image', 'itp' => 'application/vnd.shana.informed.formtemplate', 'its' => 'application/its+xml', 'ivp' => 'application/vnd.immervision-ivp', 'ivu' => 'application/vnd.immervision-ivu', 'jad' => 'text/vnd.sun.j2me.app-descriptor', 'jade' => 'text/jade', 'jam' => 'application/vnd.jam', 'jar' => 'application/java-archive', 'jardiff' => 'application/x-java-archive-diff', 'java' => 'text/x-java-source', 'jhc' => 'image/jphc', 'jisp' => 'application/vnd.jisp', 'jls' => 'image/jls', 'jlt' => 'application/vnd.hp-jlyt', 'jng' => 'image/x-jng', 'jnlp' => 'application/x-java-jnlp-file', 'joda' => 'application/vnd.joost.joda-archive', 'jp2' => 'image/jp2', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpf' => 'image/jpx', 'jpg' => 'image/jpeg', 'jpg2' => 'image/jp2', 'jpgm' => 'video/jpm', 'jpgv' => 'video/jpeg', 'jph' => 'image/jph', 'jpm' => 'video/jpm', 'jpx' => 'image/jpx', 'js' => 'application/javascript', 'json' => 'application/json', 'json5' => 'application/json5', 'jsonld' => 'application/ld+json', 'jsonml' => 'application/jsonml+json', 'jsx' => 'text/jsx', 'jt' => 'model/jt', 'jxr' => 'image/jxr', 'jxra' => 'image/jxra', 'jxrs' => 'image/jxrs', 'jxs' => 'image/jxs', 'jxsc' => 'image/jxsc', 'jxsi' => 'image/jxsi', 'jxss' => 'image/jxss', 'kar' => 'audio/midi', 'karbon' => 'application/vnd.kde.karbon', 'kdb' => 'application/octet-stream', 'kdbx' => 'application/x-keepass2', 'key' => 'application/x-iwork-keynote-sffkey', 'kfo' => 'application/vnd.kde.kformula', 'kia' => 'application/vnd.kidspiration', 'kml' => 'application/vnd.google-earth.kml+xml', 'kmz' => 'application/vnd.google-earth.kmz', 'kne' => 'application/vnd.kinar', 'knp' => 'application/vnd.kinar', 'kon' => 'application/vnd.kde.kontour', 'kpr' => 'application/vnd.kde.kpresenter', 'kpt' => 'application/vnd.kde.kpresenter', 'kpxx' => 'application/vnd.ds-keypoint', 'ksp' => 'application/vnd.kde.kspread', 'ktr' => 'application/vnd.kahootz', 'ktx' => 'image/ktx', 'ktx2' => 'image/ktx2', 'ktz' => 'application/vnd.kahootz', 'kwd' => 'application/vnd.kde.kword', 'kwt' => 'application/vnd.kde.kword', 'lasxml' => 'application/vnd.las.las+xml', 'latex' => 'application/x-latex', 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop', 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml', 'les' => 'application/vnd.hhe.lesson-player', 'less' => 'text/less', 'lgr' => 'application/lgr+xml', 'lha' => 'application/octet-stream', 'link66' => 'application/vnd.route66.link66+xml', 'list' => 'text/plain', 'list3820' => 'application/vnd.ibm.modcap', 'listafp' => 'application/vnd.ibm.modcap', 'litcoffee' => 'text/coffeescript', 'lnk' => 'application/x-ms-shortcut', 'log' => 'text/plain', 'lostxml' => 'application/lost+xml', 'lrf' => 'application/octet-stream', 'lrm' => 'application/vnd.ms-lrm', 'ltf' => 'application/vnd.frogans.ltf', 'lua' => 'text/x-lua', 'luac' => 'application/x-lua-bytecode', 'lvp' => 'audio/vnd.lucent.voice', 'lwp' => 'application/vnd.lotus-wordpro', 'lzh' => 'application/octet-stream', 'm1v' => 'video/mpeg', 'm2a' => 'audio/mpeg', 'm2v' => 'video/mpeg', 'm3a' => 'audio/mpeg', 'm3u' => 'text/plain', 'm3u8' => 'application/vnd.apple.mpegurl', 'm4a' => 'audio/x-m4a', 'm4p' => 'application/mp4', 'm4s' => 'video/iso.segment', 'm4u' => 'application/vnd.mpegurl', 'm4v' => 'video/x-m4v', 'm13' => 'application/x-msmediaview', 'm14' => 'application/x-msmediaview', 'm21' => 'application/mp21', 'ma' => 'application/mathematica', 'mads' => 'application/mads+xml', 'maei' => 'application/mmt-aei+xml', 'mag' => 'application/vnd.ecowin.chart', 'maker' => 'application/vnd.framemaker', 'man' => 'text/troff', 'manifest' => 'text/cache-manifest', 'map' => 'application/json', 'mar' => 'application/octet-stream', 'markdown' => 'text/markdown', 'mathml' => 'application/mathml+xml', 'mb' => 'application/mathematica', 'mbk' => 'application/vnd.mobius.mbk', 'mbox' => 'application/mbox', 'mc1' => 'application/vnd.medcalcdata', 'mcd' => 'application/vnd.mcd', 'mcurl' => 'text/vnd.curl.mcurl', 'md' => 'text/markdown', 'mdb' => 'application/x-msaccess', 'mdi' => 'image/vnd.ms-modi', 'mdx' => 'text/mdx', 'me' => 'text/troff', 'mesh' => 'model/mesh', 'meta4' => 'application/metalink4+xml', 'metalink' => 'application/metalink+xml', 'mets' => 'application/mets+xml', 'mfm' => 'application/vnd.mfmp', 'mft' => 'application/rpki-manifest', 'mgp' => 'application/vnd.osgeo.mapguide.package', 'mgz' => 'application/vnd.proteus.magazine', 'mid' => 'audio/midi', 'midi' => 'audio/midi', 'mie' => 'application/x-mie', 'mif' => 'application/vnd.mif', 'mime' => 'message/rfc822', 'mj2' => 'video/mj2', 'mjp2' => 'video/mj2', 'mjs' => 'text/javascript', 'mk3d' => 'video/x-matroska', 'mka' => 'audio/x-matroska', 'mkd' => 'text/x-markdown', 'mks' => 'video/x-matroska', 'mkv' => 'video/x-matroska', 'mlp' => 'application/vnd.dolby.mlp', 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', 'mmf' => 'application/vnd.smaf', 'mml' => 'text/mathml', 'mmr' => 'image/vnd.fujixerox.edmics-mmr', 'mng' => 'video/x-mng', 'mny' => 'application/x-msmoney', 'mobi' => 'application/x-mobipocket-ebook', 'mods' => 'application/mods+xml', 'mov' => 'video/quicktime', 'movie' => 'video/x-sgi-movie', 'mp2' => 'audio/mpeg', 'mp2a' => 'audio/mpeg', 'mp3' => 'audio/mpeg', 'mp4' => 'video/mp4', 'mp4a' => 'audio/mp4', 'mp4s' => 'application/mp4', 'mp4v' => 'video/mp4', 'mp21' => 'application/mp21', 'mpc' => 'application/vnd.mophun.certificate', 'mpd' => 'application/dash+xml', 'mpe' => 'video/mpeg', 'mpeg' => 'video/mpeg', 'mpf' => 'application/media-policy-dataset+xml', 'mpg' => 'video/mpeg', 'mpg4' => 'video/mp4', 'mpga' => 'audio/mpeg', 'mpkg' => 'application/vnd.apple.installer+xml', 'mpm' => 'application/vnd.blueice.multipass', 'mpn' => 'application/vnd.mophun.application', 'mpp' => 'application/vnd.ms-project', 'mpt' => 'application/vnd.ms-project', 'mpy' => 'application/vnd.ibm.minipay', 'mqy' => 'application/vnd.mobius.mqy', 'mrc' => 'application/marc', 'mrcx' => 'application/marcxml+xml', 'ms' => 'text/troff', 'mscml' => 'application/mediaservercontrol+xml', 'mseed' => 'application/vnd.fdsn.mseed', 'mseq' => 'application/vnd.mseq', 'msf' => 'application/vnd.epson.msf', 'msg' => 'application/vnd.ms-outlook', 'msh' => 'model/mesh', 'msi' => 'application/x-msdownload', 'msix' => 'application/msix', 'msixbundle' => 'application/msixbundle', 'msl' => 'application/vnd.mobius.msl', 'msm' => 'application/octet-stream', 'msp' => 'application/octet-stream', 'msty' => 'application/vnd.muvee.style', 'mtl' => 'model/mtl', 'mts' => 'model/vnd.mts', 'mus' => 'application/vnd.musician', 'musd' => 'application/mmt-usd+xml', 'musicxml' => 'application/vnd.recordare.musicxml+xml', 'mvb' => 'application/x-msmediaview', 'mvt' => 'application/vnd.mapbox-vector-tile', 'mwf' => 'application/vnd.mfer', 'mxf' => 'application/mxf', 'mxl' => 'application/vnd.recordare.musicxml', 'mxmf' => 'audio/mobile-xmf', 'mxml' => 'application/xv+xml', 'mxs' => 'application/vnd.triscape.mxs', 'mxu' => 'video/vnd.mpegurl', 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install', 'n3' => 'text/n3', 'nb' => 'application/mathematica', 'nbp' => 'application/vnd.wolfram.player', 'nc' => 'application/x-netcdf', 'ncx' => 'application/x-dtbncx+xml', 'nfo' => 'text/x-nfo', 'ngdat' => 'application/vnd.nokia.n-gage.data', 'nitf' => 'application/vnd.nitf', 'nlu' => 'application/vnd.neurolanguage.nlu', 'nml' => 'application/vnd.enliven', 'nnd' => 'application/vnd.noblenet-directory', 'nns' => 'application/vnd.noblenet-sealer', 'nnw' => 'application/vnd.noblenet-web', 'npx' => 'image/vnd.net-fpx', 'nq' => 'application/n-quads', 'nsc' => 'application/x-conference', 'nsf' => 'application/vnd.lotus-notes', 'nt' => 'application/n-triples', 'ntf' => 'application/vnd.nitf', 'numbers' => 'application/x-iwork-numbers-sffnumbers', 'nzb' => 'application/x-nzb', 'oa2' => 'application/vnd.fujitsu.oasys2', 'oa3' => 'application/vnd.fujitsu.oasys3', 'oas' => 'application/vnd.fujitsu.oasys', 'obd' => 'application/x-msbinder', 'obgx' => 'application/vnd.openblox.game+xml', 'obj' => 'model/obj', 'oda' => 'application/oda', 'odb' => 'application/vnd.oasis.opendocument.database', 'odc' => 'application/vnd.oasis.opendocument.chart', 'odf' => 'application/vnd.oasis.opendocument.formula', 'odft' => 'application/vnd.oasis.opendocument.formula-template', 'odg' => 'application/vnd.oasis.opendocument.graphics', 'odi' => 'application/vnd.oasis.opendocument.image', 'odm' => 'application/vnd.oasis.opendocument.text-master', 'odp' => 'application/vnd.oasis.opendocument.presentation', 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', 'odt' => 'application/vnd.oasis.opendocument.text', 'oga' => 'audio/ogg', 'ogex' => 'model/vnd.opengex', 'ogg' => 'audio/ogg', 'ogv' => 'video/ogg', 'ogx' => 'application/ogg', 'omdoc' => 'application/omdoc+xml', 'onepkg' => 'application/onenote', 'onetmp' => 'application/onenote', 'onetoc' => 'application/onenote', 'onetoc2' => 'application/onenote', 'opf' => 'application/oebps-package+xml', 'opml' => 'text/x-opml', 'oprc' => 'application/vnd.palm', 'opus' => 'audio/ogg', 'org' => 'text/x-org', 'osf' => 'application/vnd.yamaha.openscoreformat', 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', 'osm' => 'application/vnd.openstreetmap.data+xml', 'otc' => 'application/vnd.oasis.opendocument.chart-template', 'otf' => 'font/otf', 'otg' => 'application/vnd.oasis.opendocument.graphics-template', 'oth' => 'application/vnd.oasis.opendocument.text-web', 'oti' => 'application/vnd.oasis.opendocument.image-template', 'otp' => 'application/vnd.oasis.opendocument.presentation-template', 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', 'ott' => 'application/vnd.oasis.opendocument.text-template', 'ova' => 'application/x-virtualbox-ova', 'ovf' => 'application/x-virtualbox-ovf', 'owl' => 'application/rdf+xml', 'oxps' => 'application/oxps', 'oxt' => 'application/vnd.openofficeorg.extension', 'p' => 'text/x-pascal', 'p7a' => 'application/x-pkcs7-signature', 'p7b' => 'application/x-pkcs7-certificates', 'p7c' => 'application/pkcs7-mime', 'p7m' => 'application/pkcs7-mime', 'p7r' => 'application/x-pkcs7-certreqresp', 'p7s' => 'application/pkcs7-signature', 'p8' => 'application/pkcs8', 'p10' => 'application/x-pkcs10', 'p12' => 'application/x-pkcs12', 'pac' => 'application/x-ns-proxy-autoconfig', 'pages' => 'application/x-iwork-pages-sffpages', 'pas' => 'text/x-pascal', 'paw' => 'application/vnd.pawaafile', 'pbd' => 'application/vnd.powerbuilder6', 'pbm' => 'image/x-portable-bitmap', 'pcap' => 'application/vnd.tcpdump.pcap', 'pcf' => 'application/x-font-pcf', 'pcl' => 'application/vnd.hp-pcl', 'pclxl' => 'application/vnd.hp-pclxl', 'pct' => 'image/x-pict', 'pcurl' => 'application/vnd.curl.pcurl', 'pcx' => 'image/x-pcx', 'pdb' => 'application/x-pilot', 'pde' => 'text/x-processing', 'pdf' => 'application/pdf', 'pem' => 'application/x-x509-user-cert', 'pfa' => 'application/x-font-type1', 'pfb' => 'application/x-font-type1', 'pfm' => 'application/x-font-type1', 'pfr' => 'application/font-tdpfr', 'pfx' => 'application/x-pkcs12', 'pgm' => 'image/x-portable-graymap', 'pgn' => 'application/x-chess-pgn', 'pgp' => 'application/pgp', 'phar' => 'application/octet-stream', 'php' => 'application/x-httpd-php', 'php3' => 'application/x-httpd-php', 'php4' => 'application/x-httpd-php', 'phps' => 'application/x-httpd-php-source', 'phtml' => 'application/x-httpd-php', 'pic' => 'image/x-pict', 'pkg' => 'application/octet-stream', 'pki' => 'application/pkixcmp', 'pkipath' => 'application/pkix-pkipath', 'pkpass' => 'application/vnd.apple.pkpass', 'pl' => 'application/x-perl', 'plb' => 'application/vnd.3gpp.pic-bw-large', 'plc' => 'application/vnd.mobius.plc', 'plf' => 'application/vnd.pocketlearn', 'pls' => 'application/pls+xml', 'pm' => 'application/x-perl', 'pml' => 'application/vnd.ctc-posml', 'png' => 'image/png', 'pnm' => 'image/x-portable-anymap', 'portpkg' => 'application/vnd.macports.portpkg', 'pot' => 'application/vnd.ms-powerpoint', 'potm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', 'ppa' => 'application/vnd.ms-powerpoint', 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', 'ppd' => 'application/vnd.cups-ppd', 'ppm' => 'image/x-portable-pixmap', 'pps' => 'application/vnd.ms-powerpoint', 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', 'ppt' => 'application/powerpoint', 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'pqa' => 'application/vnd.palm', 'prc' => 'model/prc', 'pre' => 'application/vnd.lotus-freelance', 'prf' => 'application/pics-rules', 'provx' => 'application/provenance+xml', 'ps' => 'application/postscript', 'psb' => 'application/vnd.3gpp.pic-bw-small', 'psd' => 'application/x-photoshop', 'psf' => 'application/x-font-linux-psf', 'pskcxml' => 'application/pskc+xml', 'pti' => 'image/prs.pti', 'ptid' => 'application/vnd.pvi.ptid1', 'pub' => 'application/x-mspublisher', 'pvb' => 'application/vnd.3gpp.pic-bw-var', 'pwn' => 'application/vnd.3m.post-it-notes', 'pya' => 'audio/vnd.ms-playready.media.pya', 'pyo' => 'model/vnd.pytha.pyox', 'pyox' => 'model/vnd.pytha.pyox', 'pyv' => 'video/vnd.ms-playready.media.pyv', 'qam' => 'application/vnd.epson.quickanime', 'qbo' => 'application/vnd.intu.qbo', 'qfx' => 'application/vnd.intu.qfx', 'qps' => 'application/vnd.publishare-delta-tree', 'qt' => 'video/quicktime', 'qwd' => 'application/vnd.quark.quarkxpress', 'qwt' => 'application/vnd.quark.quarkxpress', 'qxb' => 'application/vnd.quark.quarkxpress', 'qxd' => 'application/vnd.quark.quarkxpress', 'qxl' => 'application/vnd.quark.quarkxpress', 'qxt' => 'application/vnd.quark.quarkxpress', 'ra' => 'audio/x-realaudio', 'ram' => 'audio/x-pn-realaudio', 'raml' => 'application/raml+yaml', 'rapd' => 'application/route-apd+xml', 'rar' => 'application/x-rar', 'ras' => 'image/x-cmu-raster', 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', 'rdf' => 'application/rdf+xml', 'rdz' => 'application/vnd.data-vision.rdz', 'relo' => 'application/p2p-overlay+xml', 'rep' => 'application/vnd.businessobjects', 'res' => 'application/x-dtbresource+xml', 'rgb' => 'image/x-rgb', 'rif' => 'application/reginfo+xml', 'rip' => 'audio/vnd.rip', 'ris' => 'application/x-research-info-systems', 'rl' => 'application/resource-lists+xml', 'rlc' => 'image/vnd.fujixerox.edmics-rlc', 'rld' => 'application/resource-lists-diff+xml', 'rm' => 'audio/x-pn-realaudio', 'rmi' => 'audio/midi', 'rmp' => 'audio/x-pn-realaudio-plugin', 'rms' => 'application/vnd.jcp.javame.midlet-rms', 'rmvb' => 'application/vnd.rn-realmedia-vbr', 'rnc' => 'application/relax-ng-compact-syntax', 'rng' => 'application/xml', 'roa' => 'application/rpki-roa', 'roff' => 'text/troff', 'rp9' => 'application/vnd.cloanto.rp9', 'rpm' => 'audio/x-pn-realaudio-plugin', 'rpss' => 'application/vnd.nokia.radio-presets', 'rpst' => 'application/vnd.nokia.radio-preset', 'rq' => 'application/sparql-query', 'rs' => 'application/rls-services+xml', 'rsa' => 'application/x-pkcs7', 'rsat' => 'application/atsc-rsat+xml', 'rsd' => 'application/rsd+xml', 'rsheet' => 'application/urc-ressheet+xml', 'rss' => 'application/rss+xml', 'rtf' => 'text/rtf', 'rtx' => 'text/richtext', 'run' => 'application/x-makeself', 'rusd' => 'application/route-usd+xml', 'rv' => 'video/vnd.rn-realvideo', 's' => 'text/x-asm', 's3m' => 'audio/s3m', 'saf' => 'application/vnd.yamaha.smaf-audio', 'sass' => 'text/x-sass', 'sbml' => 'application/sbml+xml', 'sc' => 'application/vnd.ibm.secure-container', 'scd' => 'application/x-msschedule', 'scm' => 'application/vnd.lotus-screencam', 'scq' => 'application/scvp-cv-request', 'scs' => 'application/scvp-cv-response', 'scss' => 'text/x-scss', 'scurl' => 'text/vnd.curl.scurl', 'sda' => 'application/vnd.stardivision.draw', 'sdc' => 'application/vnd.stardivision.calc', 'sdd' => 'application/vnd.stardivision.impress', 'sdkd' => 'application/vnd.solent.sdkm+xml', 'sdkm' => 'application/vnd.solent.sdkm+xml', 'sdp' => 'application/sdp', 'sdw' => 'application/vnd.stardivision.writer', 'sea' => 'application/octet-stream', 'see' => 'application/vnd.seemail', 'seed' => 'application/vnd.fdsn.seed', 'sema' => 'application/vnd.sema', 'semd' => 'application/vnd.semd', 'semf' => 'application/vnd.semf', 'senmlx' => 'application/senml+xml', 'sensmlx' => 'application/sensml+xml', 'ser' => 'application/java-serialized-object', 'setpay' => 'application/set-payment-initiation', 'setreg' => 'application/set-registration-initiation', 'sfd-hdstx' => 'application/vnd.hydrostatix.sof-data', 'sfs' => 'application/vnd.spotfire.sfs', 'sfv' => 'text/x-sfv', 'sgi' => 'image/sgi', 'sgl' => 'application/vnd.stardivision.writer-global', 'sgm' => 'text/sgml', 'sgml' => 'text/sgml', 'sh' => 'application/x-sh', 'shar' => 'application/x-shar', 'shex' => 'text/shex', 'shf' => 'application/shf+xml', 'shtml' => 'text/html', 'sid' => 'image/x-mrsid-image', 'sieve' => 'application/sieve', 'sig' => 'application/pgp-signature', 'sil' => 'audio/silk', 'silo' => 'model/mesh', 'sis' => 'application/vnd.symbian.install', 'sisx' => 'application/vnd.symbian.install', 'sit' => 'application/x-stuffit', 'sitx' => 'application/x-stuffitx', 'siv' => 'application/sieve', 'skd' => 'application/vnd.koan', 'skm' => 'application/vnd.koan', 'skp' => 'application/vnd.koan', 'skt' => 'application/vnd.koan', 'sldm' => 'application/vnd.ms-powerpoint.slide.macroenabled.12', 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', 'slim' => 'text/slim', 'slm' => 'text/slim', 'sls' => 'application/route-s-tsid+xml', 'slt' => 'application/vnd.epson.salt', 'sm' => 'application/vnd.stepmania.stepchart', 'smf' => 'application/vnd.stardivision.math', 'smi' => 'application/smil', 'smil' => 'application/smil', 'smv' => 'video/x-smv', 'smzip' => 'application/vnd.stepmania.package', 'snd' => 'audio/basic', 'snf' => 'application/x-font-snf', 'so' => 'application/octet-stream', 'spc' => 'application/x-pkcs7-certificates', 'spdx' => 'text/spdx', 'spf' => 'application/vnd.yamaha.smaf-phrase', 'spl' => 'application/x-futuresplash', 'spot' => 'text/vnd.in3d.spot', 'spp' => 'application/scvp-vp-response', 'spq' => 'application/scvp-vp-request', 'spx' => 'audio/ogg', 'sql' => 'application/x-sql', 'src' => 'application/x-wais-source', 'srt' => 'application/x-subrip', 'sru' => 'application/sru+xml', 'srx' => 'application/sparql-results+xml', 'ssdl' => 'application/ssdl+xml', 'sse' => 'application/vnd.kodak-descriptor', 'ssf' => 'application/vnd.epson.ssf', 'ssml' => 'application/ssml+xml', 'sst' => 'application/octet-stream', 'st' => 'application/vnd.sailingtracker.track', 'stc' => 'application/vnd.sun.xml.calc.template', 'std' => 'application/vnd.sun.xml.draw.template', 'step' => 'application/STEP', 'stf' => 'application/vnd.wt.stf', 'sti' => 'application/vnd.sun.xml.impress.template', 'stk' => 'application/hyperstudio', 'stl' => 'model/stl', 'stp' => 'application/STEP', 'stpx' => 'model/step+xml', 'stpxz' => 'model/step-xml+zip', 'stpz' => 'model/step+zip', 'str' => 'application/vnd.pg.format', 'stw' => 'application/vnd.sun.xml.writer.template', 'styl' => 'text/stylus', 'stylus' => 'text/stylus', 'sub' => 'text/vnd.dvb.subtitle', 'sus' => 'application/vnd.sus-calendar', 'susp' => 'application/vnd.sus-calendar', 'sv4cpio' => 'application/x-sv4cpio', 'sv4crc' => 'application/x-sv4crc', 'svc' => 'application/vnd.dvb.service', 'svd' => 'application/vnd.svd', 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml', 'swa' => 'application/x-director', 'swf' => 'application/x-shockwave-flash', 'swi' => 'application/vnd.aristanetworks.swi', 'swidtag' => 'application/swid+xml', 'sxc' => 'application/vnd.sun.xml.calc', 'sxd' => 'application/vnd.sun.xml.draw', 'sxg' => 'application/vnd.sun.xml.writer.global', 'sxi' => 'application/vnd.sun.xml.impress', 'sxm' => 'application/vnd.sun.xml.math', 'sxw' => 'application/vnd.sun.xml.writer', 't' => 'text/troff', 't3' => 'application/x-t3vm-image', 't38' => 'image/t38', 'taglet' => 'application/vnd.mynfc', 'tao' => 'application/vnd.tao.intent-module-archive', 'tap' => 'image/vnd.tencent.tap', 'tar' => 'application/x-tar', 'tcap' => 'application/vnd.3gpp2.tcap', 'tcl' => 'application/x-tcl', 'td' => 'application/urc-targetdesc+xml', 'teacher' => 'application/vnd.smart.teacher', 'tei' => 'application/tei+xml', 'teicorpus' => 'application/tei+xml', 'tex' => 'application/x-tex', 'texi' => 'application/x-texinfo', 'texinfo' => 'application/x-texinfo', 'text' => 'text/plain', 'tfi' => 'application/thraud+xml', 'tfm' => 'application/x-tex-tfm', 'tfx' => 'image/tiff-fx', 'tga' => 'image/x-tga', 'tgz' => 'application/x-tar', 'thmx' => 'application/vnd.ms-officetheme', 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'tk' => 'application/x-tcl', 'tmo' => 'application/vnd.tmobile-livetv', 'toml' => 'application/toml', 'torrent' => 'application/x-bittorrent', 'tpl' => 'application/vnd.groove-tool-template', 'tpt' => 'application/vnd.trid.tpt', 'tr' => 'text/troff', 'tra' => 'application/vnd.trueapp', 'trig' => 'application/trig', 'trm' => 'application/x-msterminal', 'ts' => 'video/mp2t', 'tsd' => 'application/timestamped-data', 'tsv' => 'text/tab-separated-values', 'ttc' => 'font/collection', 'ttf' => 'font/ttf', 'ttl' => 'text/turtle', 'ttml' => 'application/ttml+xml', 'twd' => 'application/vnd.simtech-mindmapper', 'twds' => 'application/vnd.simtech-mindmapper', 'txd' => 'application/vnd.genomatix.tuxedo', 'txf' => 'application/vnd.mobius.txf', 'txt' => 'text/plain', 'u3d' => 'model/u3d', 'u8dsn' => 'message/global-delivery-status', 'u8hdr' => 'message/global-headers', 'u8mdn' => 'message/global-disposition-notification', 'u8msg' => 'message/global', 'u32' => 'application/x-authorware-bin', 'ubj' => 'application/ubjson', 'udeb' => 'application/x-debian-package', 'ufd' => 'application/vnd.ufdl', 'ufdl' => 'application/vnd.ufdl', 'ulx' => 'application/x-glulx', 'umj' => 'application/vnd.umajin', 'unityweb' => 'application/vnd.unity', 'uo' => 'application/vnd.uoml+xml', 'uoml' => 'application/vnd.uoml+xml', 'uri' => 'text/uri-list', 'uris' => 'text/uri-list', 'urls' => 'text/uri-list', 'usda' => 'model/vnd.usda', 'usdz' => 'model/vnd.usdz+zip', 'ustar' => 'application/x-ustar', 'utz' => 'application/vnd.uiq.theme', 'uu' => 'text/x-uuencode', 'uva' => 'audio/vnd.dece.audio', 'uvd' => 'application/vnd.dece.data', 'uvf' => 'application/vnd.dece.data', 'uvg' => 'image/vnd.dece.graphic', 'uvh' => 'video/vnd.dece.hd', 'uvi' => 'image/vnd.dece.graphic', 'uvm' => 'video/vnd.dece.mobile', 'uvp' => 'video/vnd.dece.pd', 'uvs' => 'video/vnd.dece.sd', 'uvt' => 'application/vnd.dece.ttml+xml', 'uvu' => 'video/vnd.uvvu.mp4', 'uvv' => 'video/vnd.dece.video', 'uvva' => 'audio/vnd.dece.audio', 'uvvd' => 'application/vnd.dece.data', 'uvvf' => 'application/vnd.dece.data', 'uvvg' => 'image/vnd.dece.graphic', 'uvvh' => 'video/vnd.dece.hd', 'uvvi' => 'image/vnd.dece.graphic', 'uvvm' => 'video/vnd.dece.mobile', 'uvvp' => 'video/vnd.dece.pd', 'uvvs' => 'video/vnd.dece.sd', 'uvvt' => 'application/vnd.dece.ttml+xml', 'uvvu' => 'video/vnd.uvvu.mp4', 'uvvv' => 'video/vnd.dece.video', 'uvvx' => 'application/vnd.dece.unspecified', 'uvvz' => 'application/vnd.dece.zip', 'uvx' => 'application/vnd.dece.unspecified', 'uvz' => 'application/vnd.dece.zip', 'vbox' => 'application/x-virtualbox-vbox', 'vbox-extpack' => 'application/x-virtualbox-vbox-extpack', 'vcard' => 'text/vcard', 'vcd' => 'application/x-cdlink', 'vcf' => 'text/x-vcard', 'vcg' => 'application/vnd.groove-vcard', 'vcs' => 'text/x-vcalendar', 'vcx' => 'application/vnd.vcx', 'vdi' => 'application/x-virtualbox-vdi', 'vds' => 'model/vnd.sap.vds', 'vhd' => 'application/x-virtualbox-vhd', 'vis' => 'application/vnd.visionary', 'viv' => 'video/vnd.vivo', 'vlc' => 'application/videolan', 'vmdk' => 'application/x-virtualbox-vmdk', 'vob' => 'video/x-ms-vob', 'vor' => 'application/vnd.stardivision.writer', 'vox' => 'application/x-authorware-bin', 'vrml' => 'model/vrml', 'vsd' => 'application/vnd.visio', 'vsf' => 'application/vnd.vsf', 'vss' => 'application/vnd.visio', 'vst' => 'application/vnd.visio', 'vsw' => 'application/vnd.visio', 'vtf' => 'image/vnd.valve.source.texture', 'vtt' => 'text/vtt', 'vtu' => 'model/vnd.vtu', 'vxml' => 'application/voicexml+xml', 'w3d' => 'application/x-director', 'wad' => 'application/x-doom', 'wadl' => 'application/vnd.sun.wadl+xml', 'war' => 'application/java-archive', 'wasm' => 'application/wasm', 'wav' => 'audio/x-wav', 'wax' => 'audio/x-ms-wax', 'wbmp' => 'image/vnd.wap.wbmp', 'wbs' => 'application/vnd.criticaltools.wbs+xml', 'wbxml' => 'application/wbxml', 'wcm' => 'application/vnd.ms-works', 'wdb' => 'application/vnd.ms-works', 'wdp' => 'image/vnd.ms-photo', 'weba' => 'audio/webm', 'webapp' => 'application/x-web-app-manifest+json', 'webm' => 'video/webm', 'webmanifest' => 'application/manifest+json', 'webp' => 'image/webp', 'wg' => 'application/vnd.pmi.widget', 'wgsl' => 'text/wgsl', 'wgt' => 'application/widget', 'wif' => 'application/watcherinfo+xml', 'wks' => 'application/vnd.ms-works', 'wm' => 'video/x-ms-wm', 'wma' => 'audio/x-ms-wma', 'wmd' => 'application/x-ms-wmd', 'wmf' => 'image/wmf', 'wml' => 'text/vnd.wap.wml', 'wmlc' => 'application/wmlc', 'wmls' => 'text/vnd.wap.wmlscript', 'wmlsc' => 'application/vnd.wap.wmlscriptc', 'wmv' => 'video/x-ms-wmv', 'wmx' => 'video/x-ms-wmx', 'wmz' => 'application/x-msmetafile', 'woff' => 'font/woff', 'woff2' => 'font/woff2', 'word' => 'application/msword', 'wpd' => 'application/vnd.wordperfect', 'wpl' => 'application/vnd.ms-wpl', 'wps' => 'application/vnd.ms-works', 'wqd' => 'application/vnd.wqd', 'wri' => 'application/x-mswrite', 'wrl' => 'model/vrml', 'wsc' => 'message/vnd.wfa.wsc', 'wsdl' => 'application/wsdl+xml', 'wspolicy' => 'application/wspolicy+xml', 'wtb' => 'application/vnd.webturbo', 'wvx' => 'video/x-ms-wvx', 'x3d' => 'model/x3d+xml', 'x3db' => 'model/x3d+fastinfoset', 'x3dbz' => 'model/x3d+binary', 'x3dv' => 'model/x3d-vrml', 'x3dvz' => 'model/x3d+vrml', 'x3dz' => 'model/x3d+xml', 'x32' => 'application/x-authorware-bin', 'x_b' => 'model/vnd.parasolid.transmit.binary', 'x_t' => 'model/vnd.parasolid.transmit.text', 'xaml' => 'application/xaml+xml', 'xap' => 'application/x-silverlight-app', 'xar' => 'application/vnd.xara', 'xav' => 'application/xcap-att+xml', 'xbap' => 'application/x-ms-xbap', 'xbd' => 'application/vnd.fujixerox.docuworks.binder', 'xbm' => 'image/x-xbitmap', 'xca' => 'application/xcap-caps+xml', 'xcs' => 'application/calendar+xml', 'xdf' => 'application/xcap-diff+xml', 'xdm' => 'application/vnd.syncml.dm+xml', 'xdp' => 'application/vnd.adobe.xdp+xml', 'xdssc' => 'application/dssc+xml', 'xdw' => 'application/vnd.fujixerox.docuworks', 'xel' => 'application/xcap-el+xml', 'xenc' => 'application/xenc+xml', 'xer' => 'application/patch-ops-error+xml', 'xfdf' => 'application/xfdf', 'xfdl' => 'application/vnd.xfdl', 'xht' => 'application/xhtml+xml', 'xhtm' => 'application/vnd.pwg-xhtml-print+xml', 'xhtml' => 'application/xhtml+xml', 'xhvml' => 'application/xv+xml', 'xif' => 'image/vnd.xiff', 'xl' => 'application/excel', 'xla' => 'application/vnd.ms-excel', 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', 'xlc' => 'application/vnd.ms-excel', 'xlf' => 'application/xliff+xml', 'xlm' => 'application/vnd.ms-excel', 'xls' => 'application/vnd.ms-excel', 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xlt' => 'application/vnd.ms-excel', 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12', 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 'xlw' => 'application/vnd.ms-excel', 'xm' => 'audio/xm', 'xml' => 'application/xml', 'xns' => 'application/xcap-ns+xml', 'xo' => 'application/vnd.olpc-sugar', 'xop' => 'application/xop+xml', 'xpi' => 'application/x-xpinstall', 'xpl' => 'application/xproc+xml', 'xpm' => 'image/x-xpixmap', 'xpr' => 'application/vnd.is-xpr', 'xps' => 'application/vnd.ms-xpsdocument', 'xpw' => 'application/vnd.intercon.formnet', 'xpx' => 'application/vnd.intercon.formnet', 'xsd' => 'application/xml', 'xsf' => 'application/prs.xsf+xml', 'xsl' => 'application/xml', 'xslt' => 'application/xslt+xml', 'xsm' => 'application/vnd.syncml+xml', 'xspf' => 'application/xspf+xml', 'xul' => 'application/vnd.mozilla.xul+xml', 'xvm' => 'application/xv+xml', 'xvml' => 'application/xv+xml', 'xwd' => 'image/x-xwindowdump', 'xyz' => 'chemical/x-xyz', 'xz' => 'application/x-xz', 'yaml' => 'text/yaml', 'yang' => 'application/yang', 'yin' => 'application/yin+xml', 'yml' => 'text/yaml', 'ymp' => 'text/x-suse-ymp', 'z' => 'application/x-compress', 'z1' => 'application/x-zmachine', 'z2' => 'application/x-zmachine', 'z3' => 'application/x-zmachine', 'z4' => 'application/x-zmachine', 'z5' => 'application/x-zmachine', 'z6' => 'application/x-zmachine', 'z7' => 'application/x-zmachine', 'z8' => 'application/x-zmachine', 'zaz' => 'application/vnd.zzazz.deck+xml', 'zip' => 'application/zip', 'zir' => 'application/vnd.zul', 'zirz' => 'application/vnd.zul', 'zmm' => 'application/vnd.handheld-entertainment+xml', 'zsh' => 'text/x-scriptzsh']; /** * Determines the mimetype of a file by looking at its extension. * * @see https://raw.githubusercontent.com/jshttp/mime-db/master/db.json */ public static function fromFilename(string $filename) : ?string { return self::fromExtension(\pathinfo($filename, \PATHINFO_EXTENSION)); } /** * Maps a file extensions to a mimetype. * * @see https://raw.githubusercontent.com/jshttp/mime-db/master/db.json */ public static function fromExtension(string $extension) : ?string { return self::MIME_TYPES[\strtolower($extension)] ?? null; } } PK!N %guzzlehttp/psr7/src/CachingStream.phpnu[remoteStream = $stream; $this->stream = $target ?: new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen('php://temp', 'r+')); } public function getSize() : ?int { $remoteSize = $this->remoteStream->getSize(); if (null === $remoteSize) { return null; } return \max($this->stream->getSize(), $remoteSize); } public function rewind() : void { $this->seek(0); } public function seek($offset, $whence = \SEEK_SET) : void { if ($whence === \SEEK_SET) { $byte = $offset; } elseif ($whence === \SEEK_CUR) { $byte = $offset + $this->tell(); } elseif ($whence === \SEEK_END) { $size = $this->remoteStream->getSize(); if ($size === null) { $size = $this->cacheEntireStream(); } $byte = $size + $offset; } else { throw new \InvalidArgumentException('Invalid whence'); } $diff = $byte - $this->stream->getSize(); if ($diff > 0) { // Read the remoteStream until we have read in at least the amount // of bytes requested, or we reach the end of the file. while ($diff > 0 && !$this->remoteStream->eof()) { $this->read($diff); $diff = $byte - $this->stream->getSize(); } } else { // We can just do a normal seek since we've already seen this byte. $this->stream->seek($byte); } } public function read($length) : string { // Perform a regular read on any previously read data from the buffer $data = $this->stream->read($length); $remaining = $length - \strlen($data); // More data was requested so read from the remote stream if ($remaining) { // If data was written to the buffer in a position that would have // been filled from the remote stream, then we must skip bytes on // the remote stream to emulate overwriting bytes from that // position. This mimics the behavior of other PHP stream wrappers. $remoteData = $this->remoteStream->read($remaining + $this->skipReadBytes); if ($this->skipReadBytes) { $len = \strlen($remoteData); $remoteData = \substr($remoteData, $this->skipReadBytes); $this->skipReadBytes = \max(0, $this->skipReadBytes - $len); } $data .= $remoteData; $this->stream->write($remoteData); } return $data; } public function write($string) : int { // When appending to the end of the currently read stream, you'll want // to skip bytes from being read from the remote stream to emulate // other stream wrappers. Basically replacing bytes of data of a fixed // length. $overflow = \strlen($string) + $this->tell() - $this->remoteStream->tell(); if ($overflow > 0) { $this->skipReadBytes += $overflow; } return $this->stream->write($string); } public function eof() : bool { return $this->stream->eof() && $this->remoteStream->eof(); } /** * Close both the remote stream and buffer stream */ public function close() : void { $this->remoteStream->close(); $this->stream->close(); } private function cacheEntireStream() : int { $target = new \YoastSEO_Vendor\GuzzleHttp\Psr7\FnStream(['write' => 'strlen']); \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToStream($this, $target); return $this->tell(); } } PK![Pc&&%guzzlehttp/psr7/src/ServerRequest.phpnu[serverParams = $serverParams; parent::__construct($method, $uri, $headers, $body, $version); } /** * Return an UploadedFile instance array. * * @param array $files An array which respect $_FILES structure * * @throws InvalidArgumentException for unrecognized values */ public static function normalizeFiles(array $files) : array { $normalized = []; foreach ($files as $key => $value) { if ($value instanceof \YoastSEO_Vendor\Psr\Http\Message\UploadedFileInterface) { $normalized[$key] = $value; } elseif (\is_array($value) && isset($value['tmp_name'])) { $normalized[$key] = self::createUploadedFileFromSpec($value); } elseif (\is_array($value)) { $normalized[$key] = self::normalizeFiles($value); continue; } else { throw new \InvalidArgumentException('Invalid value in files specification'); } } return $normalized; } /** * Create and return an UploadedFile instance from a $_FILES specification. * * If the specification represents an array of values, this method will * delegate to normalizeNestedFileSpec() and return that return value. * * @param array $value $_FILES struct * * @return UploadedFileInterface|UploadedFileInterface[] */ private static function createUploadedFileFromSpec(array $value) { if (\is_array($value['tmp_name'])) { return self::normalizeNestedFileSpec($value); } return new \YoastSEO_Vendor\GuzzleHttp\Psr7\UploadedFile($value['tmp_name'], (int) $value['size'], (int) $value['error'], $value['name'], $value['type']); } /** * Normalize an array of file specifications. * * Loops through all nested files and returns a normalized array of * UploadedFileInterface instances. * * @return UploadedFileInterface[] */ private static function normalizeNestedFileSpec(array $files = []) : array { $normalizedFiles = []; foreach (\array_keys($files['tmp_name']) as $key) { $spec = ['tmp_name' => $files['tmp_name'][$key], 'size' => $files['size'][$key] ?? null, 'error' => $files['error'][$key] ?? null, 'name' => $files['name'][$key] ?? null, 'type' => $files['type'][$key] ?? null]; $normalizedFiles[$key] = self::createUploadedFileFromSpec($spec); } return $normalizedFiles; } /** * Return a ServerRequest populated with superglobals: * $_GET * $_POST * $_COOKIE * $_FILES * $_SERVER */ public static function fromGlobals() : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface { $method = $_SERVER['REQUEST_METHOD'] ?? 'GET'; $headers = \getallheaders(); $uri = self::getUriFromGlobals(); $body = new \YoastSEO_Vendor\GuzzleHttp\Psr7\CachingStream(new \YoastSEO_Vendor\GuzzleHttp\Psr7\LazyOpenStream('php://input', 'r+')); $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? \str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1'; $serverRequest = new \YoastSEO_Vendor\GuzzleHttp\Psr7\ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER); return $serverRequest->withCookieParams($_COOKIE)->withQueryParams($_GET)->withParsedBody($_POST)->withUploadedFiles(self::normalizeFiles($_FILES)); } private static function extractHostAndPortFromAuthority(string $authority) : array { $uri = 'http://' . $authority; $parts = \parse_url($uri); if (\false === $parts) { return [null, null]; } $host = $parts['host'] ?? null; $port = $parts['port'] ?? null; return [$host, $port]; } /** * Get a Uri populated with values from $_SERVER. */ public static function getUriFromGlobals() : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $uri = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri(''); $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http'); $hasPort = \false; if (isset($_SERVER['HTTP_HOST'])) { [$host, $port] = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']); if ($host !== null) { $uri = $uri->withHost($host); } if ($port !== null) { $hasPort = \true; $uri = $uri->withPort($port); } } elseif (isset($_SERVER['SERVER_NAME'])) { $uri = $uri->withHost($_SERVER['SERVER_NAME']); } elseif (isset($_SERVER['SERVER_ADDR'])) { $uri = $uri->withHost($_SERVER['SERVER_ADDR']); } if (!$hasPort && isset($_SERVER['SERVER_PORT'])) { $uri = $uri->withPort($_SERVER['SERVER_PORT']); } $hasQuery = \false; if (isset($_SERVER['REQUEST_URI'])) { $requestUriParts = \explode('?', $_SERVER['REQUEST_URI'], 2); $uri = $uri->withPath($requestUriParts[0]); if (isset($requestUriParts[1])) { $hasQuery = \true; $uri = $uri->withQuery($requestUriParts[1]); } } if (!$hasQuery && isset($_SERVER['QUERY_STRING'])) { $uri = $uri->withQuery($_SERVER['QUERY_STRING']); } return $uri; } public function getServerParams() : array { return $this->serverParams; } public function getUploadedFiles() : array { return $this->uploadedFiles; } public function withUploadedFiles(array $uploadedFiles) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface { $new = clone $this; $new->uploadedFiles = $uploadedFiles; return $new; } public function getCookieParams() : array { return $this->cookieParams; } public function withCookieParams(array $cookies) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface { $new = clone $this; $new->cookieParams = $cookies; return $new; } public function getQueryParams() : array { return $this->queryParams; } public function withQueryParams(array $query) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface { $new = clone $this; $new->queryParams = $query; return $new; } /** * @return array|object|null */ public function getParsedBody() { return $this->parsedBody; } public function withParsedBody($data) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface { $new = clone $this; $new->parsedBody = $data; return $new; } public function getAttributes() : array { return $this->attributes; } /** * @return mixed */ public function getAttribute($attribute, $default = null) { if (\false === \array_key_exists($attribute, $this->attributes)) { return $default; } return $this->attributes[$attribute]; } public function withAttribute($attribute, $value) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface { $new = clone $this; $new->attributes[$attribute] = $value; return $new; } public function withoutAttribute($attribute) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface { if (\false === \array_key_exists($attribute, $this->attributes)) { return $this; } $new = clone $this; unset($new->attributes[$attribute]); return $new; } } PK!Ovv"guzzlehttp/psr7/src/PumpStream.phpnu[source = $source; $this->size = $options['size'] ?? null; $this->metadata = $options['metadata'] ?? []; $this->buffer = new \YoastSEO_Vendor\GuzzleHttp\Psr7\BufferStream(); } public function __toString() : string { try { return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToString($this); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } \trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR); return ''; } } public function close() : void { $this->detach(); } public function detach() { $this->tellPos = 0; $this->source = null; return null; } public function getSize() : ?int { return $this->size; } public function tell() : int { return $this->tellPos; } public function eof() : bool { return $this->source === null; } public function isSeekable() : bool { return \false; } public function rewind() : void { $this->seek(0); } public function seek($offset, $whence = \SEEK_SET) : void { throw new \RuntimeException('Cannot seek a PumpStream'); } public function isWritable() : bool { return \false; } public function write($string) : int { throw new \RuntimeException('Cannot write to a PumpStream'); } public function isReadable() : bool { return \true; } public function read($length) : string { $data = $this->buffer->read($length); $readLen = \strlen($data); $this->tellPos += $readLen; $remaining = $length - $readLen; if ($remaining) { $this->pump($remaining); $data .= $this->buffer->read($remaining); $this->tellPos += \strlen($data) - $readLen; } return $data; } public function getContents() : string { $result = ''; while (!$this->eof()) { $result .= $this->read(1000000); } return $result; } /** * @return mixed */ public function getMetadata($key = null) { if (!$key) { return $this->metadata; } return $this->metadata[$key] ?? null; } private function pump(int $length) : void { if ($this->source !== null) { do { $data = ($this->source)($length); if ($data === \false || $data === null) { $this->source = null; return; } $this->buffer->write($data); $length -= \strlen($data); } while ($length > 0); } } } PK!X``guzzlehttp/psr7/src/Query.phpnu[ '1', 'foo[b]' => '2'])`. * * @param string $str Query string to parse * @param int|bool $urlEncoding How the query string is encoded */ public static function parse(string $str, $urlEncoding = \true) : array { $result = []; if ($str === '') { return $result; } if ($urlEncoding === \true) { $decoder = function ($value) { return \rawurldecode(\str_replace('+', ' ', (string) $value)); }; } elseif ($urlEncoding === \PHP_QUERY_RFC3986) { $decoder = 'rawurldecode'; } elseif ($urlEncoding === \PHP_QUERY_RFC1738) { $decoder = 'urldecode'; } else { $decoder = function ($str) { return $str; }; } foreach (\explode('&', $str) as $kvp) { $parts = \explode('=', $kvp, 2); $key = $decoder($parts[0]); $value = isset($parts[1]) ? $decoder($parts[1]) : null; if (!\array_key_exists($key, $result)) { $result[$key] = $value; } else { if (!\is_array($result[$key])) { $result[$key] = [$result[$key]]; } $result[$key][] = $value; } } return $result; } /** * Build a query string from an array of key value pairs. * * This function can use the return value of `parse()` to build a query * string. This function does not modify the provided keys when an array is * encountered (like `http_build_query()` would). * * @param array $params Query string parameters. * @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986 * to encode using RFC3986, or PHP_QUERY_RFC1738 * to encode using RFC1738. */ public static function build(array $params, $encoding = \PHP_QUERY_RFC3986) : string { if (!$params) { return ''; } if ($encoding === \false) { $encoder = function (string $str) : string { return $str; }; } elseif ($encoding === \PHP_QUERY_RFC3986) { $encoder = 'rawurlencode'; } elseif ($encoding === \PHP_QUERY_RFC1738) { $encoder = 'urlencode'; } else { throw new \InvalidArgumentException('Invalid type'); } $qs = ''; foreach ($params as $k => $v) { $k = $encoder((string) $k); if (!\is_array($v)) { $qs .= $k; $v = \is_bool($v) ? (int) $v : $v; if ($v !== null) { $qs .= '=' . $encoder((string) $v); } $qs .= '&'; } else { foreach ($v as $vv) { $qs .= $k; $vv = \is_bool($vv) ? (int) $vv : $vv; if ($vv !== null) { $qs .= '=' . $encoder((string) $vv); } $qs .= '&'; } } } return $qs ? (string) \substr($qs, 0, -1) : ''; } } PK!\U  &guzzlehttp/psr7/src/DroppingStream.phpnu[stream = $stream; $this->maxLength = $maxLength; } public function write($string) : int { $diff = $this->maxLength - $this->stream->getSize(); // Begin returning 0 when the underlying stream is too large. if ($diff <= 0) { return 0; } // Write the stream or a subset of the stream if needed. if (\strlen($string) < $diff) { return $this->stream->write($string); } return $this->stream->write(\substr($string, 0, $diff)); } } PK!,'guzzlehttp/psr7/src/MultipartStream.phpnu[boundary = $boundary ?: \bin2hex(\random_bytes(20)); $this->stream = $this->createStream($elements); } public function getBoundary() : string { return $this->boundary; } public function isWritable() : bool { return \false; } /** * Get the headers needed before transferring the content of a POST file * * @param string[] $headers */ private function getHeaders(array $headers) : string { $str = ''; foreach ($headers as $key => $value) { $str .= "{$key}: {$value}\r\n"; } return "--{$this->boundary}\r\n" . \trim($str) . "\r\n\r\n"; } /** * Create the aggregate stream that will be used to upload the POST data */ protected function createStream(array $elements = []) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface { $stream = new \YoastSEO_Vendor\GuzzleHttp\Psr7\AppendStream(); foreach ($elements as $element) { if (!\is_array($element)) { throw new \UnexpectedValueException('An array is expected'); } $this->addElement($stream, $element); } // Add the trailing boundary with CRLF $stream->addStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor("--{$this->boundary}--\r\n")); return $stream; } private function addElement(\YoastSEO_Vendor\GuzzleHttp\Psr7\AppendStream $stream, array $element) : void { foreach (['contents', 'name'] as $key) { if (!\array_key_exists($key, $element)) { throw new \InvalidArgumentException("A '{$key}' key is required"); } } $element['contents'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($element['contents']); if (empty($element['filename'])) { $uri = $element['contents']->getMetadata('uri'); if ($uri && \is_string($uri) && \substr($uri, 0, 6) !== 'php://' && \substr($uri, 0, 7) !== 'data://') { $element['filename'] = $uri; } } [$body, $headers] = $this->createElement($element['name'], $element['contents'], $element['filename'] ?? null, $element['headers'] ?? []); $stream->addStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($this->getHeaders($headers))); $stream->addStream($body); $stream->addStream(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor("\r\n")); } /** * @param string[] $headers * * @return array{0: StreamInterface, 1: string[]} */ private function createElement(string $name, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, ?string $filename, array $headers) : array { // Set a default content-disposition header if one was no provided $disposition = self::getHeader($headers, 'content-disposition'); if (!$disposition) { $headers['Content-Disposition'] = $filename === '0' || $filename ? \sprintf('form-data; name="%s"; filename="%s"', $name, \basename($filename)) : "form-data; name=\"{$name}\""; } // Set a default content-length header if one was no provided $length = self::getHeader($headers, 'content-length'); if (!$length) { if ($length = $stream->getSize()) { $headers['Content-Length'] = (string) $length; } } // Set a default Content-Type if one was not supplied $type = self::getHeader($headers, 'content-type'); if (!$type && ($filename === '0' || $filename)) { $headers['Content-Type'] = \YoastSEO_Vendor\GuzzleHttp\Psr7\MimeType::fromFilename($filename) ?? 'application/octet-stream'; } return [$stream, $headers]; } /** * @param string[] $headers */ private static function getHeader(array $headers, string $key) : ?string { $lowercaseHeader = \strtolower($key); foreach ($headers as $k => $v) { if (\strtolower((string) $k) === $lowercaseHeader) { return $v; } } return null; } } PK!Ӳ==guzzlehttp/psr7/src/Utils.phpnu[ $v) { if (!\in_array(\strtolower((string) $k), $keys)) { $result[$k] = $v; } } return $result; } /** * Copy the contents of a stream into another stream until the given number * of bytes have been read. * * @param StreamInterface $source Stream to read from * @param StreamInterface $dest Stream to write to * @param int $maxLen Maximum number of bytes to read. Pass -1 * to read the entire stream. * * @throws \RuntimeException on error. */ public static function copyToStream(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $source, \YoastSEO_Vendor\Psr\Http\Message\StreamInterface $dest, int $maxLen = -1) : void { $bufferSize = 8192; if ($maxLen === -1) { while (!$source->eof()) { if (!$dest->write($source->read($bufferSize))) { break; } } } else { $remaining = $maxLen; while ($remaining > 0 && !$source->eof()) { $buf = $source->read(\min($bufferSize, $remaining)); $len = \strlen($buf); if (!$len) { break; } $remaining -= $len; $dest->write($buf); } } } /** * Copy the contents of a stream into a string until the given number of * bytes have been read. * * @param StreamInterface $stream Stream to read * @param int $maxLen Maximum number of bytes to read. Pass -1 * to read the entire stream. * * @throws \RuntimeException on error. */ public static function copyToString(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, int $maxLen = -1) : string { $buffer = ''; if ($maxLen === -1) { while (!$stream->eof()) { $buf = $stream->read(1048576); if ($buf === '') { break; } $buffer .= $buf; } return $buffer; } $len = 0; while (!$stream->eof() && $len < $maxLen) { $buf = $stream->read($maxLen - $len); if ($buf === '') { break; } $buffer .= $buf; $len = \strlen($buffer); } return $buffer; } /** * Calculate a hash of a stream. * * This method reads the entire stream to calculate a rolling hash, based * on PHP's `hash_init` functions. * * @param StreamInterface $stream Stream to calculate the hash for * @param string $algo Hash algorithm (e.g. md5, crc32, etc) * @param bool $rawOutput Whether or not to use raw output * * @throws \RuntimeException on error. */ public static function hash(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, string $algo, bool $rawOutput = \false) : string { $pos = $stream->tell(); if ($pos > 0) { $stream->rewind(); } $ctx = \hash_init($algo); while (!$stream->eof()) { \hash_update($ctx, $stream->read(1048576)); } $out = \hash_final($ctx, $rawOutput); $stream->seek($pos); return $out; } /** * Clone and modify a request with the given changes. * * This method is useful for reducing the number of clones needed to mutate * a message. * * The changes can be one of: * - method: (string) Changes the HTTP method. * - set_headers: (array) Sets the given headers. * - remove_headers: (array) Remove the given headers. * - body: (mixed) Sets the given body. * - uri: (UriInterface) Set the URI. * - query: (string) Set the query string value of the URI. * - version: (string) Set the protocol version. * * @param RequestInterface $request Request to clone and modify. * @param array $changes Changes to apply. */ public static function modifyRequest(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request, array $changes) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface { if (!$changes) { return $request; } $headers = $request->getHeaders(); if (!isset($changes['uri'])) { $uri = $request->getUri(); } else { // Remove the host header if one is on the URI if ($host = $changes['uri']->getHost()) { $changes['set_headers']['Host'] = $host; if ($port = $changes['uri']->getPort()) { $standardPorts = ['http' => 80, 'https' => 443]; $scheme = $changes['uri']->getScheme(); if (isset($standardPorts[$scheme]) && $port != $standardPorts[$scheme]) { $changes['set_headers']['Host'] .= ':' . $port; } } } $uri = $changes['uri']; } if (!empty($changes['remove_headers'])) { $headers = self::caselessRemove($changes['remove_headers'], $headers); } if (!empty($changes['set_headers'])) { $headers = self::caselessRemove(\array_keys($changes['set_headers']), $headers); $headers = $changes['set_headers'] + $headers; } if (isset($changes['query'])) { $uri = $uri->withQuery($changes['query']); } if ($request instanceof \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface) { $new = (new \YoastSEO_Vendor\GuzzleHttp\Psr7\ServerRequest($changes['method'] ?? $request->getMethod(), $uri, $headers, $changes['body'] ?? $request->getBody(), $changes['version'] ?? $request->getProtocolVersion(), $request->getServerParams()))->withParsedBody($request->getParsedBody())->withQueryParams($request->getQueryParams())->withCookieParams($request->getCookieParams())->withUploadedFiles($request->getUploadedFiles()); foreach ($request->getAttributes() as $key => $value) { $new = $new->withAttribute($key, $value); } return $new; } return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($changes['method'] ?? $request->getMethod(), $uri, $headers, $changes['body'] ?? $request->getBody(), $changes['version'] ?? $request->getProtocolVersion()); } /** * Read a line from the stream up to the maximum allowed buffer length. * * @param StreamInterface $stream Stream to read from * @param int|null $maxLength Maximum buffer length */ public static function readLine(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream, int $maxLength = null) : string { $buffer = ''; $size = 0; while (!$stream->eof()) { if ('' === ($byte = $stream->read(1))) { return $buffer; } $buffer .= $byte; // Break when a new line is found or the max length - 1 is reached if ($byte === "\n" || ++$size === $maxLength - 1) { break; } } return $buffer; } /** * Create a new stream based on the input type. * * Options is an associative array that can contain the following keys: * - metadata: Array of custom metadata. * - size: Size of the stream. * * This method accepts the following `$resource` types: * - `Psr\Http\Message\StreamInterface`: Returns the value as-is. * - `string`: Creates a stream object that uses the given string as the contents. * - `resource`: Creates a stream object that wraps the given PHP stream resource. * - `Iterator`: If the provided value implements `Iterator`, then a read-only * stream object will be created that wraps the given iterable. Each time the * stream is read from, data from the iterator will fill a buffer and will be * continuously called until the buffer is equal to the requested read size. * Subsequent read calls will first read from the buffer and then call `next` * on the underlying iterator until it is exhausted. * - `object` with `__toString()`: If the object has the `__toString()` method, * the object will be cast to a string and then a stream will be returned that * uses the string value. * - `NULL`: When `null` is passed, an empty stream object is returned. * - `callable` When a callable is passed, a read-only stream object will be * created that invokes the given callable. The callable is invoked with the * number of suggested bytes to read. The callable can return any number of * bytes, but MUST return `false` when there is no more data to return. The * stream object that wraps the callable will invoke the callable until the * number of requested bytes are available. Any additional bytes will be * buffered and used in subsequent reads. * * @param resource|string|int|float|bool|StreamInterface|callable|\Iterator|null $resource Entity body data * @param array{size?: int, metadata?: array} $options Additional options * * @throws \InvalidArgumentException if the $resource arg is not valid. */ public static function streamFor($resource = '', array $options = []) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface { if (\is_scalar($resource)) { $stream = self::tryFopen('php://temp', 'r+'); if ($resource !== '') { \fwrite($stream, (string) $resource); \fseek($stream, 0); } return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($stream, $options); } switch (\gettype($resource)) { case 'resource': /* * The 'php://input' is a special stream with quirks and inconsistencies. * We avoid using that stream by reading it into php://temp */ /** @var resource $resource */ if ((\stream_get_meta_data($resource)['uri'] ?? '') === 'php://input') { $stream = self::tryFopen('php://temp', 'w+'); \stream_copy_to_stream($resource, $stream); \fseek($stream, 0); $resource = $stream; } return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($resource, $options); case 'object': /** @var object $resource */ if ($resource instanceof \YoastSEO_Vendor\Psr\Http\Message\StreamInterface) { return $resource; } elseif ($resource instanceof \Iterator) { return new \YoastSEO_Vendor\GuzzleHttp\Psr7\PumpStream(function () use($resource) { if (!$resource->valid()) { return \false; } $result = $resource->current(); $resource->next(); return $result; }, $options); } elseif (\method_exists($resource, '__toString')) { return self::streamFor((string) $resource, $options); } break; case 'NULL': return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream(self::tryFopen('php://temp', 'r+'), $options); } if (\is_callable($resource)) { return new \YoastSEO_Vendor\GuzzleHttp\Psr7\PumpStream($resource, $options); } throw new \InvalidArgumentException('Invalid resource type: ' . \gettype($resource)); } /** * Safely opens a PHP stream resource using a filename. * * When fopen fails, PHP normally raises a warning. This function adds an * error handler that checks for errors and throws an exception instead. * * @param string $filename File to open * @param string $mode Mode used to open the file * * @return resource * * @throws \RuntimeException if the file cannot be opened */ public static function tryFopen(string $filename, string $mode) { $ex = null; \set_error_handler(static function (int $errno, string $errstr) use($filename, $mode, &$ex) : bool { $ex = new \RuntimeException(\sprintf('Unable to open "%s" using mode "%s": %s', $filename, $mode, $errstr)); return \true; }); try { /** @var resource $handle */ $handle = \fopen($filename, $mode); } catch (\Throwable $e) { $ex = new \RuntimeException(\sprintf('Unable to open "%s" using mode "%s": %s', $filename, $mode, $e->getMessage()), 0, $e); } \restore_error_handler(); if ($ex) { /** @var $ex \RuntimeException */ throw $ex; } return $handle; } /** * Safely gets the contents of a given stream. * * When stream_get_contents fails, PHP normally raises a warning. This * function adds an error handler that checks for errors and throws an * exception instead. * * @param resource $stream * * @throws \RuntimeException if the stream cannot be read */ public static function tryGetContents($stream) : string { $ex = null; \set_error_handler(static function (int $errno, string $errstr) use(&$ex) : bool { $ex = new \RuntimeException(\sprintf('Unable to read stream contents: %s', $errstr)); return \true; }); try { /** @var string|false $contents */ $contents = \stream_get_contents($stream); if ($contents === \false) { $ex = new \RuntimeException('Unable to read stream contents'); } } catch (\Throwable $e) { $ex = new \RuntimeException(\sprintf('Unable to read stream contents: %s', $e->getMessage()), 0, $e); } \restore_error_handler(); if ($ex) { /** @var $ex \RuntimeException */ throw $ex; } return $contents; } /** * Returns a UriInterface for the given value. * * This function accepts a string or UriInterface and returns a * UriInterface for the given value. If the value is already a * UriInterface, it is returned as-is. * * @param string|UriInterface $uri * * @throws \InvalidArgumentException */ public static function uriFor($uri) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { if ($uri instanceof \YoastSEO_Vendor\Psr\Http\Message\UriInterface) { return $uri; } if (\is_string($uri)) { return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($uri); } throw new \InvalidArgumentException('URI must be a string or UriInterface'); } } PK!uC$guzzlehttp/psr7/src/AppendStream.phpnu[addStream($stream); } } public function __toString() : string { try { $this->rewind(); return $this->getContents(); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } \trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR); return ''; } } /** * Add a stream to the AppendStream * * @param StreamInterface $stream Stream to append. Must be readable. * * @throws \InvalidArgumentException if the stream is not readable */ public function addStream(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream) : void { if (!$stream->isReadable()) { throw new \InvalidArgumentException('Each stream must be readable'); } // The stream is only seekable if all streams are seekable if (!$stream->isSeekable()) { $this->seekable = \false; } $this->streams[] = $stream; } public function getContents() : string { return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToString($this); } /** * Closes each attached stream. */ public function close() : void { $this->pos = $this->current = 0; $this->seekable = \true; foreach ($this->streams as $stream) { $stream->close(); } $this->streams = []; } /** * Detaches each attached stream. * * Returns null as it's not clear which underlying stream resource to return. */ public function detach() { $this->pos = $this->current = 0; $this->seekable = \true; foreach ($this->streams as $stream) { $stream->detach(); } $this->streams = []; return null; } public function tell() : int { return $this->pos; } /** * Tries to calculate the size by adding the size of each stream. * * If any of the streams do not return a valid number, then the size of the * append stream cannot be determined and null is returned. */ public function getSize() : ?int { $size = 0; foreach ($this->streams as $stream) { $s = $stream->getSize(); if ($s === null) { return null; } $size += $s; } return $size; } public function eof() : bool { return !$this->streams || $this->current >= \count($this->streams) - 1 && $this->streams[$this->current]->eof(); } public function rewind() : void { $this->seek(0); } /** * Attempts to seek to the given position. Only supports SEEK_SET. */ public function seek($offset, $whence = \SEEK_SET) : void { if (!$this->seekable) { throw new \RuntimeException('This AppendStream is not seekable'); } elseif ($whence !== \SEEK_SET) { throw new \RuntimeException('The AppendStream can only seek with SEEK_SET'); } $this->pos = $this->current = 0; // Rewind each stream foreach ($this->streams as $i => $stream) { try { $stream->rewind(); } catch (\Exception $e) { throw new \RuntimeException('Unable to seek stream ' . $i . ' of the AppendStream', 0, $e); } } // Seek to the actual position by reading from each stream while ($this->pos < $offset && !$this->eof()) { $result = $this->read(\min(8096, $offset - $this->pos)); if ($result === '') { break; } } } /** * Reads from all of the appended streams until the length is met or EOF. */ public function read($length) : string { $buffer = ''; $total = \count($this->streams) - 1; $remaining = $length; $progressToNext = \false; while ($remaining > 0) { // Progress to the next stream if needed. if ($progressToNext || $this->streams[$this->current]->eof()) { $progressToNext = \false; if ($this->current === $total) { break; } ++$this->current; } $result = $this->streams[$this->current]->read($remaining); if ($result === '') { $progressToNext = \true; continue; } $buffer .= $result; $remaining = $length - \strlen($buffer); } $this->pos += \strlen($buffer); return $buffer; } public function isReadable() : bool { return \true; } public function isWritable() : bool { return \false; } public function isSeekable() : bool { return $this->seekable; } public function write($string) : int { throw new \RuntimeException('Cannot write to an AppendStream'); } /** * @return mixed */ public function getMetadata($key = null) { return $key ? null : []; } } PK!O-""#guzzlehttp/psr7/src/UriResolver.phpnu[getScheme() != '') { return $rel->withPath(self::removeDotSegments($rel->getPath())); } if ($rel->getAuthority() != '') { $targetAuthority = $rel->getAuthority(); $targetPath = self::removeDotSegments($rel->getPath()); $targetQuery = $rel->getQuery(); } else { $targetAuthority = $base->getAuthority(); if ($rel->getPath() === '') { $targetPath = $base->getPath(); $targetQuery = $rel->getQuery() != '' ? $rel->getQuery() : $base->getQuery(); } else { if ($rel->getPath()[0] === '/') { $targetPath = $rel->getPath(); } else { if ($targetAuthority != '' && $base->getPath() === '') { $targetPath = '/' . $rel->getPath(); } else { $lastSlashPos = \strrpos($base->getPath(), '/'); if ($lastSlashPos === \false) { $targetPath = $rel->getPath(); } else { $targetPath = \substr($base->getPath(), 0, $lastSlashPos + 1) . $rel->getPath(); } } } $targetPath = self::removeDotSegments($targetPath); $targetQuery = $rel->getQuery(); } } return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri(\YoastSEO_Vendor\GuzzleHttp\Psr7\Uri::composeComponents($base->getScheme(), $targetAuthority, $targetPath, $targetQuery, $rel->getFragment())); } /** * Returns the target URI as a relative reference from the base URI. * * This method is the counterpart to resolve(): * * (string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target)) * * One use-case is to use the current request URI as base URI and then generate relative links in your documents * to reduce the document size or offer self-contained downloadable document archives. * * $base = new Uri('http://example.com/a/b/'); * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'. * echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'. * echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'. * echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'. * * This method also accepts a target that is already relative and will try to relativize it further. Only a * relative-path reference will be returned as-is. * * echo UriResolver::relativize($base, new Uri('/a/b/c')); // prints 'c' as well */ public static function relativize(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $target) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { if ($target->getScheme() !== '' && ($base->getScheme() !== $target->getScheme() || $target->getAuthority() === '' && $base->getAuthority() !== '')) { return $target; } if (\YoastSEO_Vendor\GuzzleHttp\Psr7\Uri::isRelativePathReference($target)) { // As the target is already highly relative we return it as-is. It would be possible to resolve // the target with `$target = self::resolve($base, $target);` and then try make it more relative // by removing a duplicate query. But let's not do that automatically. return $target; } if ($target->getAuthority() !== '' && $base->getAuthority() !== $target->getAuthority()) { return $target->withScheme(''); } // We must remove the path before removing the authority because if the path starts with two slashes, the URI // would turn invalid. And we also cannot set a relative path before removing the authority, as that is also // invalid. $emptyPathUri = $target->withScheme('')->withPath('')->withUserInfo('')->withPort(null)->withHost(''); if ($base->getPath() !== $target->getPath()) { return $emptyPathUri->withPath(self::getRelativePath($base, $target)); } if ($base->getQuery() === $target->getQuery()) { // Only the target fragment is left. And it must be returned even if base and target fragment are the same. return $emptyPathUri->withQuery(''); } // If the base URI has a query but the target has none, we cannot return an empty path reference as it would // inherit the base query component when resolving. if ($target->getQuery() === '') { $segments = \explode('/', $target->getPath()); /** @var string $lastSegment */ $lastSegment = \end($segments); return $emptyPathUri->withPath($lastSegment === '' ? './' : $lastSegment); } return $emptyPathUri; } private static function getRelativePath(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $base, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $target) : string { $sourceSegments = \explode('/', $base->getPath()); $targetSegments = \explode('/', $target->getPath()); \array_pop($sourceSegments); $targetLastSegment = \array_pop($targetSegments); foreach ($sourceSegments as $i => $segment) { if (isset($targetSegments[$i]) && $segment === $targetSegments[$i]) { unset($sourceSegments[$i], $targetSegments[$i]); } else { break; } } $targetSegments[] = $targetLastSegment; $relativePath = \str_repeat('../', \count($sourceSegments)) . \implode('/', $targetSegments); // A reference to am empty last segment or an empty first sub-segment must be prefixed with "./". // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used // as the first segment of a relative-path reference, as it would be mistaken for a scheme name. if ('' === $relativePath || \false !== \strpos(\explode('/', $relativePath, 2)[0], ':')) { $relativePath = "./{$relativePath}"; } elseif ('/' === $relativePath[0]) { if ($base->getAuthority() != '' && $base->getPath() === '') { // In this case an extra slash is added by resolve() automatically. So we must not add one here. $relativePath = ".{$relativePath}"; } else { $relativePath = "./{$relativePath}"; } } return $relativePath; } private function __construct() { // cannot be instantiated } } PK!Nu u ,guzzlehttp/psr7/src/StreamDecoratorTrait.phpnu[stream = $stream; } /** * Magic method used to create a new stream if streams are not added in * the constructor of a decorator (e.g., LazyOpenStream). * * @return StreamInterface */ public function __get(string $name) { if ($name === 'stream') { $this->stream = $this->createStream(); return $this->stream; } throw new \UnexpectedValueException("{$name} not found on class"); } public function __toString() : string { try { if ($this->isSeekable()) { $this->seek(0); } return $this->getContents(); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } \trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR); return ''; } } public function getContents() : string { return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::copyToString($this); } /** * Allow decorators to implement custom methods * * @return mixed */ public function __call(string $method, array $args) { /** @var callable $callable */ $callable = [$this->stream, $method]; $result = $callable(...$args); // Always return the wrapped object if the result is a return $this return $result === $this->stream ? $this : $result; } public function close() : void { $this->stream->close(); } /** * @return mixed */ public function getMetadata($key = null) { return $this->stream->getMetadata($key); } public function detach() { return $this->stream->detach(); } public function getSize() : ?int { return $this->stream->getSize(); } public function eof() : bool { return $this->stream->eof(); } public function tell() : int { return $this->stream->tell(); } public function isReadable() : bool { return $this->stream->isReadable(); } public function isWritable() : bool { return $this->stream->isWritable(); } public function isSeekable() : bool { return $this->stream->isSeekable(); } public function rewind() : void { $this->seek(0); } public function seek($offset, $whence = \SEEK_SET) : void { $this->stream->seek($offset, $whence); } public function read($length) : string { return $this->stream->read($length); } public function write($string) : int { return $this->stream->write($string); } /** * Implement in subclasses to dynamically create streams when requested. * * @throws \BadMethodCallException */ protected function createStream() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface { throw new \BadMethodCallException('Not implemented'); } } PK!cSqq%guzzlehttp/psr7/src/StreamWrapper.phpnu[isReadable()) { $mode = $stream->isWritable() ? 'r+' : 'r'; } elseif ($stream->isWritable()) { $mode = 'w'; } else { throw new \InvalidArgumentException('The stream must be readable, ' . 'writable, or both.'); } return \fopen('guzzle://stream', $mode, \false, self::createStreamContext($stream)); } /** * Creates a stream context that can be used to open a stream as a php stream resource. * * @return resource */ public static function createStreamContext(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $stream) { return \stream_context_create(['guzzle' => ['stream' => $stream]]); } /** * Registers the stream wrapper if needed */ public static function register() : void { if (!\in_array('guzzle', \stream_get_wrappers())) { \stream_wrapper_register('guzzle', __CLASS__); } } public function stream_open(string $path, string $mode, int $options, string &$opened_path = null) : bool { $options = \stream_context_get_options($this->context); if (!isset($options['guzzle']['stream'])) { return \false; } $this->mode = $mode; $this->stream = $options['guzzle']['stream']; return \true; } public function stream_read(int $count) : string { return $this->stream->read($count); } public function stream_write(string $data) : int { return $this->stream->write($data); } public function stream_tell() : int { return $this->stream->tell(); } public function stream_eof() : bool { return $this->stream->eof(); } public function stream_seek(int $offset, int $whence) : bool { $this->stream->seek($offset, $whence); return \true; } /** * @return resource|false */ public function stream_cast(int $cast_as) { $stream = clone $this->stream; $resource = $stream->detach(); return $resource ?? \false; } /** * @return array{ * dev: int, * ino: int, * mode: int, * nlink: int, * uid: int, * gid: int, * rdev: int, * size: int, * atime: int, * mtime: int, * ctime: int, * blksize: int, * blocks: int * } */ public function stream_stat() : array { static $modeMap = ['r' => 33060, 'rb' => 33060, 'r+' => 33206, 'w' => 33188, 'wb' => 33188]; return ['dev' => 0, 'ino' => 0, 'mode' => $modeMap[$this->mode], 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => $this->stream->getSize() ?: 0, 'atime' => 0, 'mtime' => 0, 'ctime' => 0, 'blksize' => 0, 'blocks' => 0]; } /** * @return array{ * dev: int, * ino: int, * mode: int, * nlink: int, * uid: int, * gid: int, * rdev: int, * size: int, * atime: int, * mtime: int, * ctime: int, * blksize: int, * blocks: int * } */ public function url_stat(string $path, int $flags) : array { return ['dev' => 0, 'ino' => 0, 'mode' => 0, 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => 0, 'atime' => 0, 'mtime' => 0, 'ctime' => 0, 'blksize' => 0, 'blocks' => 0]; } } PK!,*!!guzzlehttp/psr7/src/Message.phpnu[getMethod() . ' ' . $message->getRequestTarget()) . ' HTTP/' . $message->getProtocolVersion(); if (!$message->hasHeader('host')) { $msg .= "\r\nHost: " . $message->getUri()->getHost(); } } elseif ($message instanceof \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface) { $msg = 'HTTP/' . $message->getProtocolVersion() . ' ' . $message->getStatusCode() . ' ' . $message->getReasonPhrase(); } else { throw new \InvalidArgumentException('Unknown message type'); } foreach ($message->getHeaders() as $name => $values) { if (\is_string($name) && \strtolower($name) === 'set-cookie') { foreach ($values as $value) { $msg .= "\r\n{$name}: " . $value; } } else { $msg .= "\r\n{$name}: " . \implode(', ', $values); } } return "{$msg}\r\n\r\n" . $message->getBody(); } /** * Get a short summary of the message body. * * Will return `null` if the response is not printable. * * @param MessageInterface $message The message to get the body summary * @param int $truncateAt The maximum allowed size of the summary */ public static function bodySummary(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message, int $truncateAt = 120) : ?string { $body = $message->getBody(); if (!$body->isSeekable() || !$body->isReadable()) { return null; } $size = $body->getSize(); if ($size === 0) { return null; } $body->rewind(); $summary = $body->read($truncateAt); $body->rewind(); if ($size > $truncateAt) { $summary .= ' (truncated...)'; } // Matches any printable character, including unicode characters: // letters, marks, numbers, punctuation, spacing, and separators. if (\preg_match('/[^\\pL\\pM\\pN\\pP\\pS\\pZ\\n\\r\\t]/u', $summary) !== 0) { return null; } return $summary; } /** * Attempts to rewind a message body and throws an exception on failure. * * The body of the message will only be rewound if a call to `tell()` * returns a value other than `0`. * * @param MessageInterface $message Message to rewind * * @throws \RuntimeException */ public static function rewindBody(\YoastSEO_Vendor\Psr\Http\Message\MessageInterface $message) : void { $body = $message->getBody(); if ($body->tell()) { $body->rewind(); } } /** * Parses an HTTP message into an associative array. * * The array contains the "start-line" key containing the start line of * the message, "headers" key containing an associative array of header * array values, and a "body" key containing the body of the message. * * @param string $message HTTP request or response to parse. */ public static function parseMessage(string $message) : array { if (!$message) { throw new \InvalidArgumentException('Invalid message'); } $message = \ltrim($message, "\r\n"); $messageParts = \preg_split("/\r?\n\r?\n/", $message, 2); if ($messageParts === \false || \count($messageParts) !== 2) { throw new \InvalidArgumentException('Invalid message: Missing header delimiter'); } [$rawHeaders, $body] = $messageParts; $rawHeaders .= "\r\n"; // Put back the delimiter we split previously $headerParts = \preg_split("/\r?\n/", $rawHeaders, 2); if ($headerParts === \false || \count($headerParts) !== 2) { throw new \InvalidArgumentException('Invalid message: Missing status line'); } [$startLine, $rawHeaders] = $headerParts; if (\preg_match("/(?:^HTTP\\/|^[A-Z]+ \\S+ HTTP\\/)(\\d+(?:\\.\\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') { // Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0 $rawHeaders = \preg_replace(\YoastSEO_Vendor\GuzzleHttp\Psr7\Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders); } /** @var array[] $headerLines */ $count = \preg_match_all(\YoastSEO_Vendor\GuzzleHttp\Psr7\Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, \PREG_SET_ORDER); // If these aren't the same, then one line didn't match and there's an invalid header. if ($count !== \substr_count($rawHeaders, "\n")) { // Folding is deprecated, see https://datatracker.ietf.org/doc/html/rfc7230#section-3.2.4 if (\preg_match(\YoastSEO_Vendor\GuzzleHttp\Psr7\Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) { throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding'); } throw new \InvalidArgumentException('Invalid header syntax'); } $headers = []; foreach ($headerLines as $headerLine) { $headers[$headerLine[1]][] = $headerLine[2]; } return ['start-line' => $startLine, 'headers' => $headers, 'body' => $body]; } /** * Constructs a URI for an HTTP request message. * * @param string $path Path from the start-line * @param array $headers Array of headers (each value an array). */ public static function parseRequestUri(string $path, array $headers) : string { $hostKey = \array_filter(\array_keys($headers), function ($k) { // Numeric array keys are converted to int by PHP. $k = (string) $k; return \strtolower($k) === 'host'; }); // If no host is found, then a full URI cannot be constructed. if (!$hostKey) { return $path; } $host = $headers[\reset($hostKey)][0]; $scheme = \substr($host, -4) === ':443' ? 'https' : 'http'; return $scheme . '://' . $host . '/' . \ltrim($path, '/'); } /** * Parses a request message string into a request object. * * @param string $message Request message string. */ public static function parseRequest(string $message) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface { $data = self::parseMessage($message); $matches = []; if (!\preg_match('/^[\\S]+\\s+([a-zA-Z]+:\\/\\/|\\/).*/', $data['start-line'], $matches)) { throw new \InvalidArgumentException('Invalid request string'); } $parts = \explode(' ', $data['start-line'], 3); $version = isset($parts[2]) ? \explode('/', $parts[2])[1] : '1.1'; $request = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($parts[0], $matches[1] === '/' ? self::parseRequestUri($parts[1], $data['headers']) : $parts[1], $data['headers'], $data['body'], $version); return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]); } /** * Parses a response message string into a response object. * * @param string $message Response message string. */ public static function parseResponse(string $message) : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface { $data = self::parseMessage($message); // According to https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2 // the space between status-code and reason-phrase is required. But // browsers accept responses without space and reason as well. if (!\preg_match('/^HTTP\\/.* [0-9]{3}( .*|$)/', $data['start-line'])) { throw new \InvalidArgumentException('Invalid response string: ' . $data['start-line']); } $parts = \explode(' ', $data['start-line'], 3); return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response((int) $parts[1], $data['headers'], $data['body'], \explode('/', $parts[0])[1], $parts[2] ?? null); } } PK!I6VVguzzlehttp/psr7/src/Uri.phpnu[ 80, 'https' => 443, 'ftp' => 21, 'gopher' => 70, 'nntp' => 119, 'news' => 119, 'telnet' => 23, 'tn3270' => 23, 'imap' => 143, 'pop' => 110, 'ldap' => 389]; /** * Unreserved characters for use in a regex. * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-2.3 */ private const CHAR_UNRESERVED = 'a-zA-Z0-9_\\-\\.~'; /** * Sub-delims for use in a regex. * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-2.2 */ private const CHAR_SUB_DELIMS = '!\\$&\'\\(\\)\\*\\+,;='; private const QUERY_SEPARATORS_REPLACEMENT = ['=' => '%3D', '&' => '%26']; /** @var string Uri scheme. */ private $scheme = ''; /** @var string Uri user info. */ private $userInfo = ''; /** @var string Uri host. */ private $host = ''; /** @var int|null Uri port. */ private $port; /** @var string Uri path. */ private $path = ''; /** @var string Uri query string. */ private $query = ''; /** @var string Uri fragment. */ private $fragment = ''; /** @var string|null String representation */ private $composedComponents; public function __construct(string $uri = '') { if ($uri !== '') { $parts = self::parse($uri); if ($parts === \false) { throw new \YoastSEO_Vendor\GuzzleHttp\Psr7\Exception\MalformedUriException("Unable to parse URI: {$uri}"); } $this->applyParts($parts); } } /** * UTF-8 aware \parse_url() replacement. * * The internal function produces broken output for non ASCII domain names * (IDN) when used with locales other than "C". * * On the other hand, cURL understands IDN correctly only when UTF-8 locale * is configured ("C.UTF-8", "en_US.UTF-8", etc.). * * @see https://bugs.php.net/bug.php?id=52923 * @see https://www.php.net/manual/en/function.parse-url.php#114817 * @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING * * @return array|false */ private static function parse(string $url) { // If IPv6 $prefix = ''; if (\preg_match('%^(.*://\\[[0-9:a-f]+\\])(.*?)$%', $url, $matches)) { /** @var array{0:string, 1:string, 2:string} $matches */ $prefix = $matches[1]; $url = $matches[2]; } /** @var string */ $encodedUrl = \preg_replace_callback('%[^:/@?&=#]+%usD', static function ($matches) { return \urlencode($matches[0]); }, $url); $result = \parse_url($prefix . $encodedUrl); if ($result === \false) { return \false; } return \array_map('urldecode', $result); } public function __toString() : string { if ($this->composedComponents === null) { $this->composedComponents = self::composeComponents($this->scheme, $this->getAuthority(), $this->path, $this->query, $this->fragment); } return $this->composedComponents; } /** * Composes a URI reference string from its various components. * * Usually this method does not need to be called manually but instead is used indirectly via * `Psr\Http\Message\UriInterface::__toString`. * * PSR-7 UriInterface treats an empty component the same as a missing component as * getQuery(), getFragment() etc. always return a string. This explains the slight * difference to RFC 3986 Section 5.3. * * Another adjustment is that the authority separator is added even when the authority is missing/empty * for the "file" scheme. This is because PHP stream functions like `file_get_contents` only work with * `file:///myfile` but not with `file:/myfile` although they are equivalent according to RFC 3986. But * `file:///` is the more common syntax for the file scheme anyway (Chrome for example redirects to * that format). * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-5.3 */ public static function composeComponents(?string $scheme, ?string $authority, string $path, ?string $query, ?string $fragment) : string { $uri = ''; // weak type checks to also accept null until we can add scalar type hints if ($scheme != '') { $uri .= $scheme . ':'; } if ($authority != '' || $scheme === 'file') { $uri .= '//' . $authority; } if ($authority != '' && $path != '' && $path[0] != '/') { $path = '/' . $path; } $uri .= $path; if ($query != '') { $uri .= '?' . $query; } if ($fragment != '') { $uri .= '#' . $fragment; } return $uri; } /** * Whether the URI has the default port of the current scheme. * * `Psr\Http\Message\UriInterface::getPort` may return null or the standard port. This method can be used * independently of the implementation. */ public static function isDefaultPort(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool { return $uri->getPort() === null || isset(self::DEFAULT_PORTS[$uri->getScheme()]) && $uri->getPort() === self::DEFAULT_PORTS[$uri->getScheme()]; } /** * Whether the URI is absolute, i.e. it has a scheme. * * An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true * if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative * to another URI, the base URI. Relative references can be divided into several forms: * - network-path references, e.g. '//example.com/path' * - absolute-path references, e.g. '/path' * - relative-path references, e.g. 'subpath' * * @see Uri::isNetworkPathReference * @see Uri::isAbsolutePathReference * @see Uri::isRelativePathReference * @see https://datatracker.ietf.org/doc/html/rfc3986#section-4 */ public static function isAbsolute(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool { return $uri->getScheme() !== ''; } /** * Whether the URI is a network-path reference. * * A relative reference that begins with two slash characters is termed an network-path reference. * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.2 */ public static function isNetworkPathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool { return $uri->getScheme() === '' && $uri->getAuthority() !== ''; } /** * Whether the URI is a absolute-path reference. * * A relative reference that begins with a single slash character is termed an absolute-path reference. * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.2 */ public static function isAbsolutePathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool { return $uri->getScheme() === '' && $uri->getAuthority() === '' && isset($uri->getPath()[0]) && $uri->getPath()[0] === '/'; } /** * Whether the URI is a relative-path reference. * * A relative reference that does not begin with a slash character is termed a relative-path reference. * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.2 */ public static function isRelativePathReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : bool { return $uri->getScheme() === '' && $uri->getAuthority() === '' && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/'); } /** * Whether the URI is a same-document reference. * * A same-document reference refers to a URI that is, aside from its fragment * component, identical to the base URI. When no base URI is given, only an empty * URI reference (apart from its fragment) is considered a same-document reference. * * @param UriInterface $uri The URI to check * @param UriInterface|null $base An optional base URI to compare against * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-4.4 */ public static function isSameDocumentReference(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $base = null) : bool { if ($base !== null) { $uri = \YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::resolve($base, $uri); return $uri->getScheme() === $base->getScheme() && $uri->getAuthority() === $base->getAuthority() && $uri->getPath() === $base->getPath() && $uri->getQuery() === $base->getQuery(); } return $uri->getScheme() === '' && $uri->getAuthority() === '' && $uri->getPath() === '' && $uri->getQuery() === ''; } /** * Creates a new URI with a specific query string value removed. * * Any existing query string values that exactly match the provided key are * removed. * * @param UriInterface $uri URI to use as a base. * @param string $key Query string key to remove. */ public static function withoutQueryValue(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, string $key) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $result = self::getFilteredQueryString($uri, [$key]); return $uri->withQuery(\implode('&', $result)); } /** * Creates a new URI with a specific query string value. * * Any existing query string values that exactly match the provided key are * removed and replaced with the given key value pair. * * A value of null will set the query string key without a value, e.g. "key" * instead of "key=value". * * @param UriInterface $uri URI to use as a base. * @param string $key Key to set. * @param string|null $value Value to set */ public static function withQueryValue(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, string $key, ?string $value) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $result = self::getFilteredQueryString($uri, [$key]); $result[] = self::generateQueryString($key, $value); return $uri->withQuery(\implode('&', $result)); } /** * Creates a new URI with multiple specific query string values. * * It has the same behavior as withQueryValue() but for an associative array of key => value. * * @param UriInterface $uri URI to use as a base. * @param (string|null)[] $keyValueArray Associative array of key and values */ public static function withQueryValues(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, array $keyValueArray) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $result = self::getFilteredQueryString($uri, \array_keys($keyValueArray)); foreach ($keyValueArray as $key => $value) { $result[] = self::generateQueryString((string) $key, $value !== null ? (string) $value : null); } return $uri->withQuery(\implode('&', $result)); } /** * Creates a URI from a hash of `parse_url` components. * * @see https://www.php.net/manual/en/function.parse-url.php * * @throws MalformedUriException If the components do not form a valid URI. */ public static function fromParts(array $parts) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $uri = new self(); $uri->applyParts($parts); $uri->validateState(); return $uri; } public function getScheme() : string { return $this->scheme; } public function getAuthority() : string { $authority = $this->host; if ($this->userInfo !== '') { $authority = $this->userInfo . '@' . $authority; } if ($this->port !== null) { $authority .= ':' . $this->port; } return $authority; } public function getUserInfo() : string { return $this->userInfo; } public function getHost() : string { return $this->host; } public function getPort() : ?int { return $this->port; } public function getPath() : string { return $this->path; } public function getQuery() : string { return $this->query; } public function getFragment() : string { return $this->fragment; } public function withScheme($scheme) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $scheme = $this->filterScheme($scheme); if ($this->scheme === $scheme) { return $this; } $new = clone $this; $new->scheme = $scheme; $new->composedComponents = null; $new->removeDefaultPort(); $new->validateState(); return $new; } public function withUserInfo($user, $password = null) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $info = $this->filterUserInfoComponent($user); if ($password !== null) { $info .= ':' . $this->filterUserInfoComponent($password); } if ($this->userInfo === $info) { return $this; } $new = clone $this; $new->userInfo = $info; $new->composedComponents = null; $new->validateState(); return $new; } public function withHost($host) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $host = $this->filterHost($host); if ($this->host === $host) { return $this; } $new = clone $this; $new->host = $host; $new->composedComponents = null; $new->validateState(); return $new; } public function withPort($port) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $port = $this->filterPort($port); if ($this->port === $port) { return $this; } $new = clone $this; $new->port = $port; $new->composedComponents = null; $new->removeDefaultPort(); $new->validateState(); return $new; } public function withPath($path) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $path = $this->filterPath($path); if ($this->path === $path) { return $this; } $new = clone $this; $new->path = $path; $new->composedComponents = null; $new->validateState(); return $new; } public function withQuery($query) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $query = $this->filterQueryAndFragment($query); if ($this->query === $query) { return $this; } $new = clone $this; $new->query = $query; $new->composedComponents = null; return $new; } public function withFragment($fragment) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $fragment = $this->filterQueryAndFragment($fragment); if ($this->fragment === $fragment) { return $this; } $new = clone $this; $new->fragment = $fragment; $new->composedComponents = null; return $new; } public function jsonSerialize() : string { return $this->__toString(); } /** * Apply parse_url parts to a URI. * * @param array $parts Array of parse_url parts to apply. */ private function applyParts(array $parts) : void { $this->scheme = isset($parts['scheme']) ? $this->filterScheme($parts['scheme']) : ''; $this->userInfo = isset($parts['user']) ? $this->filterUserInfoComponent($parts['user']) : ''; $this->host = isset($parts['host']) ? $this->filterHost($parts['host']) : ''; $this->port = isset($parts['port']) ? $this->filterPort($parts['port']) : null; $this->path = isset($parts['path']) ? $this->filterPath($parts['path']) : ''; $this->query = isset($parts['query']) ? $this->filterQueryAndFragment($parts['query']) : ''; $this->fragment = isset($parts['fragment']) ? $this->filterQueryAndFragment($parts['fragment']) : ''; if (isset($parts['pass'])) { $this->userInfo .= ':' . $this->filterUserInfoComponent($parts['pass']); } $this->removeDefaultPort(); } /** * @param mixed $scheme * * @throws \InvalidArgumentException If the scheme is invalid. */ private function filterScheme($scheme) : string { if (!\is_string($scheme)) { throw new \InvalidArgumentException('Scheme must be a string'); } return \strtr($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); } /** * @param mixed $component * * @throws \InvalidArgumentException If the user info is invalid. */ private function filterUserInfoComponent($component) : string { if (!\is_string($component)) { throw new \InvalidArgumentException('User info must be a string'); } return \preg_replace_callback('/(?:[^%' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . ']+|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $component); } /** * @param mixed $host * * @throws \InvalidArgumentException If the host is invalid. */ private function filterHost($host) : string { if (!\is_string($host)) { throw new \InvalidArgumentException('Host must be a string'); } return \strtr($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); } /** * @param mixed $port * * @throws \InvalidArgumentException If the port is invalid. */ private function filterPort($port) : ?int { if ($port === null) { return null; } $port = (int) $port; if (0 > $port || 0xffff < $port) { throw new \InvalidArgumentException(\sprintf('Invalid port: %d. Must be between 0 and 65535', $port)); } return $port; } /** * @param (string|int)[] $keys * * @return string[] */ private static function getFilteredQueryString(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri, array $keys) : array { $current = $uri->getQuery(); if ($current === '') { return []; } $decodedKeys = \array_map(function ($k) : string { return \rawurldecode((string) $k); }, $keys); return \array_filter(\explode('&', $current), function ($part) use($decodedKeys) { return !\in_array(\rawurldecode(\explode('=', $part)[0]), $decodedKeys, \true); }); } private static function generateQueryString(string $key, ?string $value) : string { // Query string separators ("=", "&") within the key or value need to be encoded // (while preventing double-encoding) before setting the query string. All other // chars that need percent-encoding will be encoded by withQuery(). $queryString = \strtr($key, self::QUERY_SEPARATORS_REPLACEMENT); if ($value !== null) { $queryString .= '=' . \strtr($value, self::QUERY_SEPARATORS_REPLACEMENT); } return $queryString; } private function removeDefaultPort() : void { if ($this->port !== null && self::isDefaultPort($this)) { $this->port = null; } } /** * Filters the path of a URI * * @param mixed $path * * @throws \InvalidArgumentException If the path is invalid. */ private function filterPath($path) : string { if (!\is_string($path)) { throw new \InvalidArgumentException('Path must be a string'); } return \preg_replace_callback('/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\\/]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $path); } /** * Filters the query string or fragment of a URI. * * @param mixed $str * * @throws \InvalidArgumentException If the query or fragment is invalid. */ private function filterQueryAndFragment($str) : string { if (!\is_string($str)) { throw new \InvalidArgumentException('Query and fragment must be a string'); } return \preg_replace_callback('/(?:[^' . self::CHAR_UNRESERVED . self::CHAR_SUB_DELIMS . '%:@\\/\\?]++|%(?![A-Fa-f0-9]{2}))/', [$this, 'rawurlencodeMatchZero'], $str); } private function rawurlencodeMatchZero(array $match) : string { return \rawurlencode($match[0]); } private function validateState() : void { if ($this->host === '' && ($this->scheme === 'http' || $this->scheme === 'https')) { $this->host = self::HTTP_DEFAULT_HOST; } if ($this->getAuthority() === '') { if (0 === \strpos($this->path, '//')) { throw new \YoastSEO_Vendor\GuzzleHttp\Psr7\Exception\MalformedUriException('The path of a URI without an authority must not start with two slashes "//"'); } if ($this->scheme === '' && \false !== \strpos(\explode('/', $this->path, 2)[0], ':')) { throw new \YoastSEO_Vendor\GuzzleHttp\Psr7\Exception\MalformedUriException('A relative URI must not have a path beginning with a segment containing a colon'); } } } } PK!m5H-nn%guzzlehttp/psr7/src/InflateStream.phpnu[ 15 + 32]); $this->stream = $stream->isSeekable() ? new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($resource) : new \YoastSEO_Vendor\GuzzleHttp\Psr7\NoSeekStream(new \YoastSEO_Vendor\GuzzleHttp\Psr7\Stream($resource)); } } PK!ܴ&guzzlehttp/psr7/src/LazyOpenStream.phpnu[filename = $filename; $this->mode = $mode; // unsetting the property forces the first access to go through // __get(). unset($this->stream); } /** * Creates the underlying stream lazily when required. */ protected function createStream() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface { return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor(\YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen($this->filename, $this->mode)); } } PK!K#guzzlehttp/psr7/src/HttpFactory.phpnu[getSize(); } return new \YoastSEO_Vendor\GuzzleHttp\Psr7\UploadedFile($stream, $size, $error, $clientFilename, $clientMediaType); } public function createStream(string $content = '') : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface { return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($content); } public function createStreamFromFile(string $file, string $mode = 'r') : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface { try { $resource = \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryFopen($file, $mode); } catch (\RuntimeException $e) { if ('' === $mode || \false === \in_array($mode[0], ['r', 'w', 'a', 'x', 'c'], \true)) { throw new \InvalidArgumentException(\sprintf('Invalid file opening mode "%s"', $mode), 0, $e); } throw $e; } return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($resource); } public function createStreamFromResource($resource) : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface { return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::streamFor($resource); } public function createServerRequest(string $method, $uri, array $serverParams = []) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface { if (empty($method)) { if (!empty($serverParams['REQUEST_METHOD'])) { $method = $serverParams['REQUEST_METHOD']; } else { throw new \InvalidArgumentException('Cannot determine HTTP method'); } } return new \YoastSEO_Vendor\GuzzleHttp\Psr7\ServerRequest($method, $uri, [], null, '1.1', $serverParams); } public function createResponse(int $code = 200, string $reasonPhrase = '') : \YoastSEO_Vendor\Psr\Http\Message\ResponseInterface { return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Response($code, [], null, '1.1', $reasonPhrase); } public function createRequest(string $method, $uri) : \YoastSEO_Vendor\Psr\Http\Message\RequestInterface { return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($method, $uri); } public function createUri(string $uri = '') : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($uri); } } PK!"ƴ%guzzlehttp/psr7/src/UriComparator.phpnu[getHost(), $modified->getHost()) !== 0) { return \true; } if ($original->getScheme() !== $modified->getScheme()) { return \true; } if (self::computePort($original) !== self::computePort($modified)) { return \true; } return \false; } private static function computePort(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : int { $port = $uri->getPort(); if (null !== $port) { return $port; } return 'https' === $uri->getScheme() ? 443 : 80; } private function __construct() { // cannot be instantiated } } PK!L#guzzlehttp/psr7/src/LimitStream.phpnu[stream = $stream; $this->setLimit($limit); $this->setOffset($offset); } public function eof() : bool { // Always return true if the underlying stream is EOF if ($this->stream->eof()) { return \true; } // No limit and the underlying stream is not at EOF if ($this->limit === -1) { return \false; } return $this->stream->tell() >= $this->offset + $this->limit; } /** * Returns the size of the limited subset of data */ public function getSize() : ?int { if (null === ($length = $this->stream->getSize())) { return null; } elseif ($this->limit === -1) { return $length - $this->offset; } else { return \min($this->limit, $length - $this->offset); } } /** * Allow for a bounded seek on the read limited stream */ public function seek($offset, $whence = \SEEK_SET) : void { if ($whence !== \SEEK_SET || $offset < 0) { throw new \RuntimeException(\sprintf('Cannot seek to offset %s with whence %s', $offset, $whence)); } $offset += $this->offset; if ($this->limit !== -1) { if ($offset > $this->offset + $this->limit) { $offset = $this->offset + $this->limit; } } $this->stream->seek($offset); } /** * Give a relative tell() */ public function tell() : int { return $this->stream->tell() - $this->offset; } /** * Set the offset to start limiting from * * @param int $offset Offset to seek to and begin byte limiting from * * @throws \RuntimeException if the stream cannot be seeked. */ public function setOffset(int $offset) : void { $current = $this->stream->tell(); if ($current !== $offset) { // If the stream cannot seek to the offset position, then read to it if ($this->stream->isSeekable()) { $this->stream->seek($offset); } elseif ($current > $offset) { throw new \RuntimeException("Could not seek to stream offset {$offset}"); } else { $this->stream->read($offset - $current); } } $this->offset = $offset; } /** * Set the limit of bytes that the decorator allows to be read from the * stream. * * @param int $limit Number of bytes to allow to be read from the stream. * Use -1 for no limit. */ public function setLimit(int $limit) : void { $this->limit = $limit; } public function read($length) : string { if ($this->limit === -1) { return $this->stream->read($length); } // Check if the current position is less than the total allowed // bytes + original offset $remaining = $this->offset + $this->limit - $this->stream->tell(); if ($remaining > 0) { // Only return the amount of requested data, ensuring that the byte // limit is not exceeded return $this->stream->read(\min($remaining, $length)); } return ''; } } PK!b966guzzlehttp/psr7/src/Stream.phpnu[size = $options['size']; } $this->customMetadata = $options['metadata'] ?? []; $this->stream = $stream; $meta = \stream_get_meta_data($this->stream); $this->seekable = $meta['seekable']; $this->readable = (bool) \preg_match(self::READABLE_MODES, $meta['mode']); $this->writable = (bool) \preg_match(self::WRITABLE_MODES, $meta['mode']); $this->uri = $this->getMetadata('uri'); } /** * Closes the stream when the destructed */ public function __destruct() { $this->close(); } public function __toString() : string { try { if ($this->isSeekable()) { $this->seek(0); } return $this->getContents(); } catch (\Throwable $e) { if (\PHP_VERSION_ID >= 70400) { throw $e; } \trigger_error(\sprintf('%s::__toString exception: %s', self::class, (string) $e), \E_USER_ERROR); return ''; } } public function getContents() : string { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->readable) { throw new \RuntimeException('Cannot read from non-readable stream'); } return \YoastSEO_Vendor\GuzzleHttp\Psr7\Utils::tryGetContents($this->stream); } public function close() : void { if (isset($this->stream)) { if (\is_resource($this->stream)) { \fclose($this->stream); } $this->detach(); } } public function detach() { if (!isset($this->stream)) { return null; } $result = $this->stream; unset($this->stream); $this->size = $this->uri = null; $this->readable = $this->writable = $this->seekable = \false; return $result; } public function getSize() : ?int { if ($this->size !== null) { return $this->size; } if (!isset($this->stream)) { return null; } // Clear the stat cache if the stream has a URI if ($this->uri) { \clearstatcache(\true, $this->uri); } $stats = \fstat($this->stream); if (\is_array($stats) && isset($stats['size'])) { $this->size = $stats['size']; return $this->size; } return null; } public function isReadable() : bool { return $this->readable; } public function isWritable() : bool { return $this->writable; } public function isSeekable() : bool { return $this->seekable; } public function eof() : bool { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } return \feof($this->stream); } public function tell() : int { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } $result = \ftell($this->stream); if ($result === \false) { throw new \RuntimeException('Unable to determine stream position'); } return $result; } public function rewind() : void { $this->seek(0); } public function seek($offset, $whence = \SEEK_SET) : void { $whence = (int) $whence; if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->seekable) { throw new \RuntimeException('Stream is not seekable'); } if (\fseek($this->stream, $offset, $whence) === -1) { throw new \RuntimeException('Unable to seek to stream position ' . $offset . ' with whence ' . \var_export($whence, \true)); } } public function read($length) : string { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->readable) { throw new \RuntimeException('Cannot read from non-readable stream'); } if ($length < 0) { throw new \RuntimeException('Length parameter cannot be negative'); } if (0 === $length) { return ''; } try { $string = \fread($this->stream, $length); } catch (\Exception $e) { throw new \RuntimeException('Unable to read from stream', 0, $e); } if (\false === $string) { throw new \RuntimeException('Unable to read from stream'); } return $string; } public function write($string) : int { if (!isset($this->stream)) { throw new \RuntimeException('Stream is detached'); } if (!$this->writable) { throw new \RuntimeException('Cannot write to a non-writable stream'); } // We can't know the size after writing anything $this->size = null; $result = \fwrite($this->stream, $string); if ($result === \false) { throw new \RuntimeException('Unable to write to stream'); } return $result; } /** * @return mixed */ public function getMetadata($key = null) { if (!isset($this->stream)) { return $key ? null : []; } elseif (!$key) { return $this->customMetadata + \stream_get_meta_data($this->stream); } elseif (isset($this->customMetadata[$key])) { return $this->customMetadata[$key]; } $meta = \stream_get_meta_data($this->stream); return $meta[$key] ?? null; } } PK! }7guzzlehttp/psr7/src/Exception/MalformedUriException.phpnu[getPath() === '' && ($uri->getScheme() === 'http' || $uri->getScheme() === 'https')) { $uri = $uri->withPath('/'); } if ($flags & self::REMOVE_DEFAULT_HOST && $uri->getScheme() === 'file' && $uri->getHost() === 'localhost') { $uri = $uri->withHost(''); } if ($flags & self::REMOVE_DEFAULT_PORT && $uri->getPort() !== null && \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri::isDefaultPort($uri)) { $uri = $uri->withPort(null); } if ($flags & self::REMOVE_DOT_SEGMENTS && !\YoastSEO_Vendor\GuzzleHttp\Psr7\Uri::isRelativePathReference($uri)) { $uri = $uri->withPath(\YoastSEO_Vendor\GuzzleHttp\Psr7\UriResolver::removeDotSegments($uri->getPath())); } if ($flags & self::REMOVE_DUPLICATE_SLASHES) { $uri = $uri->withPath(\preg_replace('#//++#', '/', $uri->getPath())); } if ($flags & self::SORT_QUERY_PARAMETERS && $uri->getQuery() !== '') { $queryKeyValues = \explode('&', $uri->getQuery()); \sort($queryKeyValues); $uri = $uri->withQuery(\implode('&', $queryKeyValues)); } return $uri; } /** * Whether two URIs can be considered equivalent. * * Both URIs are normalized automatically before comparison with the given $normalizations bitmask. The method also * accepts relative URI references and returns true when they are equivalent. This of course assumes they will be * resolved against the same base URI. If this is not the case, determination of equivalence or difference of * relative references does not mean anything. * * @param UriInterface $uri1 An URI to compare * @param UriInterface $uri2 An URI to compare * @param int $normalizations A bitmask of normalizations to apply, see constants * * @see https://datatracker.ietf.org/doc/html/rfc3986#section-6.1 */ public static function isEquivalent(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri1, \YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri2, int $normalizations = self::PRESERVING_NORMALIZATIONS) : bool { return (string) self::normalize($uri1, $normalizations) === (string) self::normalize($uri2, $normalizations); } private static function capitalizePercentEncoding(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $regex = '/(?:%[A-Fa-f0-9]{2})++/'; $callback = function (array $match) : string { return \strtoupper($match[0]); }; return $uri->withPath(\preg_replace_callback($regex, $callback, $uri->getPath()))->withQuery(\preg_replace_callback($regex, $callback, $uri->getQuery())); } private static function decodeUnreservedCharacters(\YoastSEO_Vendor\Psr\Http\Message\UriInterface $uri) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface { $regex = '/%(?:2D|2E|5F|7E|3[0-9]|[46][1-9A-F]|[57][0-9A])/i'; $callback = function (array $match) : string { return \rawurldecode($match[0]); }; return $uri->withPath(\preg_replace_callback($regex, $callback, $uri->getPath()))->withQuery(\preg_replace_callback($regex, $callback, $uri->getQuery())); } private function __construct() { // cannot be instantiated } } PK!2\qqguzzlehttp/psr7/src/Header.phpnu[]+>|[^=]+/', $kvp, $matches)) { $m = $matches[0]; if (isset($m[1])) { $part[\trim($m[0], $trimmed)] = \trim($m[1], $trimmed); } else { $part[] = \trim($m[0], $trimmed); } } } if ($part) { $params[] = $part; } } } return $params; } /** * Converts an array of header values that may contain comma separated * headers into an array of headers with no comma separated values. * * @param string|array $header Header to normalize. * * @deprecated Use self::splitList() instead. */ public static function normalize($header) : array { $result = []; foreach ((array) $header as $value) { foreach (self::splitList($value) as $parsed) { $result[] = $parsed; } } return $result; } /** * Splits a HTTP header defined to contain a comma-separated list into * each individual value. Empty values will be removed. * * Example headers include 'accept', 'cache-control' and 'if-none-match'. * * This method must not be used to parse headers that are not defined as * a list, such as 'user-agent' or 'set-cookie'. * * @param string|string[] $values Header value as returned by MessageInterface::getHeader() * * @return string[] */ public static function splitList($values) : array { if (!\is_array($values)) { $values = [$values]; } $result = []; foreach ($values as $value) { if (!\is_string($value)) { throw new \TypeError('$header must either be a string or an array containing strings.'); } $v = ''; $isQuoted = \false; $isEscaped = \false; for ($i = 0, $max = \strlen($value); $i < $max; ++$i) { if ($isEscaped) { $v .= $value[$i]; $isEscaped = \false; continue; } if (!$isQuoted && $value[$i] === ',') { $v = \trim($v); if ($v !== '') { $result[] = $v; } $v = ''; continue; } if ($isQuoted && $value[$i] === '\\') { $isEscaped = \true; $v .= $value[$i]; continue; } if ($value[$i] === '"') { $isQuoted = !$isQuoted; $v .= $value[$i]; continue; } $v .= $value[$i]; } $v = \trim($v); if ($v !== '') { $result[] = $v; } } return $result; } } PK!C;3league/oauth2-client/src/Tool/QueryBuilderTrait.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; /** * Provides a standard way to generate query strings. */ trait QueryBuilderTrait { /** * Build a query string from an array. * * @param array $params * * @return string */ protected function buildQueryString(array $params) { return \http_build_query($params, '', '&', \PHP_QUERY_RFC3986); } } PK!S6league/oauth2-client/src/Tool/GuardedPropertyTrait.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; /** * Provides support for blacklisting explicit properties from the * mass assignment behavior. */ trait GuardedPropertyTrait { /** * The properties that aren't mass assignable. * * @var array */ protected $guarded = []; /** * Attempts to mass assign the given options to explicitly defined properties, * skipping over any properties that are defined in the guarded array. * * @param array $options * @return mixed */ protected function fillProperties(array $options = []) { if (isset($options['guarded'])) { unset($options['guarded']); } foreach ($options as $option => $value) { if (\property_exists($this, $option) && !$this->isGuarded($option)) { $this->{$option} = $value; } } } /** * Returns current guarded properties. * * @return array */ public function getGuarded() { return $this->guarded; } /** * Determines if the given property is guarded. * * @param string $property * @return bool */ public function isGuarded($property) { return \in_array($property, $this->getGuarded()); } } PK!Ǵ0league/oauth2-client/src/Tool/RequestFactory.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; use YoastSEO_Vendor\GuzzleHttp\Psr7\Request; /** * Used to produce PSR-7 Request instances. * * @link https://github.com/guzzle/guzzle/pull/1101 */ class RequestFactory { /** * Creates a PSR-7 Request instance. * * @param null|string $method HTTP method for the request. * @param null|string $uri URI for the request. * @param array $headers Headers for the message. * @param string|resource|StreamInterface $body Message body. * @param string $version HTTP protocol version. * * @return Request */ public function getRequest($method, $uri, array $headers = [], $body = null, $version = '1.1') { return new \YoastSEO_Vendor\GuzzleHttp\Psr7\Request($method, $uri, $headers, $body, $version); } /** * Parses simplified options. * * @param array $options Simplified options. * * @return array Extended options for use with getRequest. */ protected function parseOptions(array $options) { // Should match default values for getRequest $defaults = ['headers' => [], 'body' => null, 'version' => '1.1']; return \array_merge($defaults, $options); } /** * Creates a request using a simplified array of options. * * @param null|string $method * @param null|string $uri * @param array $options * * @return Request */ public function getRequestWithOptions($method, $uri, array $options = []) { $options = $this->parseOptions($options); return $this->getRequest($method, $uri, $options['headers'], $options['body'], $options['version']); } } PK! 4league/oauth2-client/src/Tool/ArrayAccessorTrait.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; /** * Provides generic array navigation tools. */ trait ArrayAccessorTrait { /** * Returns a value by key using dot notation. * * @param array $data * @param string $key * @param mixed|null $default * @return mixed */ private function getValueByKey(array $data, $key, $default = null) { if (!\is_string($key) || empty($key) || !\count($data)) { return $default; } if (\strpos($key, '.') !== \false) { $keys = \explode('.', $key); foreach ($keys as $innerKey) { if (!\is_array($data) || !\array_key_exists($innerKey, $data)) { return $default; } $data = $data[$innerKey]; } return $data; } return \array_key_exists($key, $data) ? $data[$key] : $default; } } PK!0[ [ 7league/oauth2-client/src/Tool/MacAuthorizationTrait.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken; use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface; /** * Enables `MAC` header authorization for providers. * * @link http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-05 Message Authentication Code (MAC) Tokens */ trait MacAuthorizationTrait { /** * Returns the id of this token for MAC generation. * * @param AccessToken $token * @return string */ protected abstract function getTokenId(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token); /** * Returns the MAC signature for the current request. * * @param string $id * @param integer $ts * @param string $nonce * @return string */ protected abstract function getMacSignature($id, $ts, $nonce); /** * Returns a new random string to use as the state parameter in an * authorization flow. * * @param int $length Length of the random string to be generated. * @return string */ protected abstract function getRandomState($length = 32); /** * Returns the authorization headers for the 'mac' grant. * * @param AccessTokenInterface|string|null $token Either a string or an access token instance * @return array * @codeCoverageIgnore * * @todo This is currently untested and provided only as an example. If you * complete the implementation, please create a pull request for * https://github.com/thephpleague/oauth2-client */ protected function getAuthorizationHeaders($token = null) { if ($token === null) { return []; } $ts = \time(); $id = $this->getTokenId($token); $nonce = $this->getRandomState(16); $mac = $this->getMacSignature($id, $ts, $nonce); $parts = []; foreach (\compact('id', 'ts', 'nonce', 'mac') as $key => $value) { $parts[] = \sprintf('%s="%s"', $key, $value); } return ['Authorization' => 'MAC ' . \implode(', ', $parts)]; } } PK!-N(: : 7league/oauth2-client/src/Tool/ProviderRedirectTrait.phpnu[redirectLimit) { $attempts++; $response = $this->getHttpClient()->send($request, ['allow_redirects' => \false]); if ($this->isRedirect($response)) { $redirectUrl = new \YoastSEO_Vendor\GuzzleHttp\Psr7\Uri($response->getHeader('Location')[0]); $request = $request->withUri($redirectUrl); } else { break; } } return $response; } /** * Returns the HTTP client instance. * * @return GuzzleHttp\ClientInterface */ public abstract function getHttpClient(); /** * Retrieves current redirect limit. * * @return integer */ public function getRedirectLimit() { return $this->redirectLimit; } /** * Determines if a given response is a redirect. * * @param ResponseInterface $response * * @return boolean */ protected function isRedirect(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) { $statusCode = $response->getStatusCode(); return $statusCode > 300 && $statusCode < 400 && $response->hasHeader('Location'); } /** * Sends a request instance and returns a response instance. * * WARNING: This method does not attempt to catch exceptions caused by HTTP * errors! It is recommended to wrap this method in a try/catch block. * * @param RequestInterface $request * @return ResponseInterface */ public function getResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) { try { $response = $this->followRequestRedirects($request); } catch (\YoastSEO_Vendor\GuzzleHttp\Exception\BadResponseException $e) { $response = $e->getResponse(); } return $response; } /** * Updates the redirect limit. * * @param integer $limit * @return League\OAuth2\Client\Provider\AbstractProvider * @throws InvalidArgumentException */ public function setRedirectLimit($limit) { if (!\is_int($limit)) { throw new \InvalidArgumentException('redirectLimit must be an integer.'); } if ($limit < 1) { throw new \InvalidArgumentException('redirectLimit must be greater than or equal to one.'); } $this->redirectLimit = $limit; return $this; } } PK!,8league/oauth2-client/src/Tool/RequiredParameterTrait.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; use BadMethodCallException; /** * Provides functionality to check for required parameters. */ trait RequiredParameterTrait { /** * Checks for a required parameter in a hash. * * @throws BadMethodCallException * @param string $name * @param array $params * @return void */ private function checkRequiredParameter($name, array $params) { if (!isset($params[$name])) { throw new \BadMethodCallException(\sprintf('Required parameter not passed: "%s"', $name)); } } /** * Checks for multiple required parameters in a hash. * * @throws InvalidArgumentException * @param array $names * @param array $params * @return void */ private function checkRequiredParameters(array $names, array $params) { foreach ($names as $name) { $this->checkRequiredParameter($name, $params); } } } PK!)ƌ{{:league/oauth2-client/src/Tool/BearerAuthorizationTrait.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Tool; use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface; /** * Enables `Bearer` header authorization for providers. * * @link http://tools.ietf.org/html/rfc6750 Bearer Token Usage (RFC 6750) */ trait BearerAuthorizationTrait { /** * Returns authorization headers for the 'bearer' grant. * * @param AccessTokenInterface|string|null $token Either a string or an access token instance * @return array */ protected function getAuthorizationHeaders($token = null) { return ['Authorization' => 'Bearer ' . $token]; } } PK! /league/oauth2-client/src/Grant/GrantFactory.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Grant; use YoastSEO_Vendor\League\OAuth2\Client\Grant\Exception\InvalidGrantException; /** * Represents a factory used when retrieving an authorization grant type. */ class GrantFactory { /** * @var array */ protected $registry = []; /** * Defines a grant singleton in the registry. * * @param string $name * @param AbstractGrant $grant * @return self */ public function setGrant($name, \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant $grant) { $this->registry[$name] = $grant; return $this; } /** * Returns a grant singleton by name. * * If the grant has not be registered, a default grant will be loaded. * * @param string $name * @return AbstractGrant */ public function getGrant($name) { if (empty($this->registry[$name])) { $this->registerDefaultGrant($name); } return $this->registry[$name]; } /** * Registers a default grant singleton by name. * * @param string $name * @return self */ protected function registerDefaultGrant($name) { // PascalCase the grant. E.g: 'authorization_code' becomes 'AuthorizationCode' $class = \str_replace(' ', '', \ucwords(\str_replace(['-', '_'], ' ', $name))); $class = 'YoastSEO_Vendor\\League\\OAuth2\\Client\\Grant\\' . $class; $this->checkGrant($class); return $this->setGrant($name, new $class()); } /** * Determines if a variable is a valid grant. * * @param mixed $class * @return boolean */ public function isGrant($class) { return \is_subclass_of($class, \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant::class); } /** * Checks if a variable is a valid grant. * * @throws InvalidGrantException * @param mixed $class * @return void */ public function checkGrant($class) { if (!$this->isGrant($class)) { throw new \YoastSEO_Vendor\League\OAuth2\Client\Grant\Exception\InvalidGrantException(\sprintf('Grant "%s" must extend AbstractGrant', \is_object($class) ? \get_class($class) : $class)); } } } PK!^ڿU4league/oauth2-client/src/Grant/ClientCredentials.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Grant; /** * Represents a client credentials grant. * * @link http://tools.ietf.org/html/rfc6749#section-1.3.4 Client Credentials (RFC 6749, §1.3.4) */ class ClientCredentials extends \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant { /** * @inheritdoc */ protected function getName() { return 'client_credentials'; } /** * @inheritdoc */ protected function getRequiredRequestParameters() { return []; } } PK!IsJ??+league/oauth2-client/src/Grant/Password.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Grant; /** * Represents a resource owner password credentials grant. * * @link http://tools.ietf.org/html/rfc6749#section-1.3.3 Resource Owner Password Credentials (RFC 6749, §1.3.3) */ class Password extends \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant { /** * @inheritdoc */ protected function getName() { return 'password'; } /** * @inheritdoc */ protected function getRequiredRequestParameters() { return ['username', 'password']; } } PK!)g,/league/oauth2-client/src/Grant/RefreshToken.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Grant; /** * Represents a refresh token grant. * * @link http://tools.ietf.org/html/rfc6749#section-6 Refreshing an Access Token (RFC 6749, §6) */ class RefreshToken extends \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant { /** * @inheritdoc */ protected function getName() { return 'refresh_token'; } /** * @inheritdoc */ protected function getRequiredRequestParameters() { return ['refresh_token']; } } PK!F!!4league/oauth2-client/src/Grant/AuthorizationCode.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Grant; /** * Represents an authorization code grant. * * @link http://tools.ietf.org/html/rfc6749#section-1.3.1 Authorization Code (RFC 6749, §1.3.1) */ class AuthorizationCode extends \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant { /** * @inheritdoc */ protected function getName() { return 'authorization_code'; } /** * @inheritdoc */ protected function getRequiredRequestParameters() { return ['code']; } } PK!/? 0league/oauth2-client/src/Grant/AbstractGrant.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Grant; use YoastSEO_Vendor\League\OAuth2\Client\Tool\RequiredParameterTrait; /** * Represents a type of authorization grant. * * An authorization grant is a credential representing the resource * owner's authorization (to access its protected resources) used by the * client to obtain an access token. OAuth 2.0 defines four * grant types -- authorization code, implicit, resource owner password * credentials, and client credentials -- as well as an extensibility * mechanism for defining additional types. * * @link http://tools.ietf.org/html/rfc6749#section-1.3 Authorization Grant (RFC 6749, §1.3) */ abstract class AbstractGrant { use RequiredParameterTrait; /** * Returns the name of this grant, eg. 'grant_name', which is used as the * grant type when encoding URL query parameters. * * @return string */ protected abstract function getName(); /** * Returns a list of all required request parameters. * * @return array */ protected abstract function getRequiredRequestParameters(); /** * Returns this grant's name as its string representation. This allows for * string interpolation when building URL query parameters. * * @return string */ public function __toString() { return $this->getName(); } /** * Prepares an access token request's parameters by checking that all * required parameters are set, then merging with any given defaults. * * @param array $defaults * @param array $options * @return array */ public function prepareRequestParameters(array $defaults, array $options) { $defaults['grant_type'] = $this->getName(); $required = $this->getRequiredRequestParameters(); $provided = \array_merge($defaults, $options); $this->checkRequiredParameters($required, $provided); return $provided; } } PK! +$$Bleague/oauth2-client/src/Grant/Exception/InvalidGrantException.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Grant\Exception; use InvalidArgumentException; /** * Exception thrown if the grant does not extend from AbstractGrant. * * @see League\OAuth2\Client\Grant\AbstractGrant */ class InvalidGrantException extends \InvalidArgumentException { } PK!GCleague/oauth2-client/src/OptionProvider/OptionProviderInterface.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\OptionProvider; /** * Interface for access token options provider */ interface OptionProviderInterface { /** * Builds request options used for requesting an access token. * * @param string $method * @param array $params * @return array */ public function getAccessTokenOptions($method, array $params); } PK!d!!Bleague/oauth2-client/src/OptionProvider/PostAuthOptionProvider.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\OptionProvider; use YoastSEO_Vendor\League\OAuth2\Client\Provider\AbstractProvider; use YoastSEO_Vendor\League\OAuth2\Client\Tool\QueryBuilderTrait; /** * Provide options for access token */ class PostAuthOptionProvider implements \YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\OptionProviderInterface { use QueryBuilderTrait; /** * @inheritdoc */ public function getAccessTokenOptions($method, array $params) { $options = ['headers' => ['content-type' => 'application/x-www-form-urlencoded']]; if ($method === \YoastSEO_Vendor\League\OAuth2\Client\Provider\AbstractProvider::METHOD_POST) { $options['body'] = $this->getAccessTokenBody($params); } return $options; } /** * Returns the request body for requesting an access token. * * @param array $params * @return string */ protected function getAccessTokenBody(array $params) { return $this->buildQueryString($params); } } PK!Gleague/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\OptionProvider; use InvalidArgumentException; /** * Add http basic auth into access token request options * @link https://tools.ietf.org/html/rfc6749#section-2.3.1 */ class HttpBasicAuthOptionProvider extends \YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\PostAuthOptionProvider { /** * @inheritdoc */ public function getAccessTokenOptions($method, array $params) { if (empty($params['client_id']) || empty($params['client_secret'])) { throw new \InvalidArgumentException('clientId and clientSecret are required for http basic auth'); } $encodedCredentials = \base64_encode(\sprintf('%s:%s', $params['client_id'], $params['client_secret'])); unset($params['client_id'], $params['client_secret']); $options = parent::getAccessTokenOptions($method, $params); $options['headers']['Authorization'] = 'Basic ' . $encodedCredentials; return $options; } } PK!+447league/oauth2-client/src/Token/AccessTokenInterface.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Token; use JsonSerializable; use ReturnTypeWillChange; use RuntimeException; interface AccessTokenInterface extends \JsonSerializable { /** * Returns the access token string of this instance. * * @return string */ public function getToken(); /** * Returns the refresh token, if defined. * * @return string|null */ public function getRefreshToken(); /** * Returns the expiration timestamp in seconds, if defined. * * @return integer|null */ public function getExpires(); /** * Checks if this token has expired. * * @return boolean true if the token has expired, false otherwise. * @throws RuntimeException if 'expires' is not set on the token. */ public function hasExpired(); /** * Returns additional vendor values stored in the token. * * @return array */ public function getValues(); /** * Returns a string representation of the access token * * @return string */ public function __toString(); /** * Returns an array of parameters to serialize when this is serialized with * json_encode(). * * @return array */ #[ReturnTypeWillChange] public function jsonSerialize(); } PK!ElHHDleague/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Token; interface ResourceOwnerAccessTokenInterface extends \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface { /** * Returns the resource owner identifier, if defined. * * @return string|null */ public function getResourceOwnerId(); } PK!ʾ~~.league/oauth2-client/src/Token/AccessToken.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Token; use InvalidArgumentException; use RuntimeException; /** * Represents an access token. * * @link http://tools.ietf.org/html/rfc6749#section-1.4 Access Token (RFC 6749, §1.4) */ class AccessToken implements \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface, \YoastSEO_Vendor\League\OAuth2\Client\Token\ResourceOwnerAccessTokenInterface { /** * @var string */ protected $accessToken; /** * @var int */ protected $expires; /** * @var string */ protected $refreshToken; /** * @var string */ protected $resourceOwnerId; /** * @var array */ protected $values = []; /** * @var int */ private static $timeNow; /** * Set the time now. This should only be used for testing purposes. * * @param int $timeNow the time in seconds since epoch * @return void */ public static function setTimeNow($timeNow) { self::$timeNow = $timeNow; } /** * Reset the time now if it was set for test purposes. * * @return void */ public static function resetTimeNow() { self::$timeNow = null; } /** * @return int */ public function getTimeNow() { return self::$timeNow ? self::$timeNow : \time(); } /** * Constructs an access token. * * @param array $options An array of options returned by the service provider * in the access token request. The `access_token` option is required. * @throws InvalidArgumentException if `access_token` is not provided in `$options`. */ public function __construct(array $options = []) { if (empty($options['access_token'])) { throw new \InvalidArgumentException('Required option not passed: "access_token"'); } $this->accessToken = $options['access_token']; if (!empty($options['resource_owner_id'])) { $this->resourceOwnerId = $options['resource_owner_id']; } if (!empty($options['refresh_token'])) { $this->refreshToken = $options['refresh_token']; } // We need to know when the token expires. Show preference to // 'expires_in' since it is defined in RFC6749 Section 5.1. // Defer to 'expires' if it is provided instead. if (isset($options['expires_in'])) { if (!\is_numeric($options['expires_in'])) { throw new \InvalidArgumentException('expires_in value must be an integer'); } $this->expires = $options['expires_in'] != 0 ? $this->getTimeNow() + $options['expires_in'] : 0; } elseif (!empty($options['expires'])) { // Some providers supply the seconds until expiration rather than // the exact timestamp. Take a best guess at which we received. $expires = $options['expires']; if (!$this->isExpirationTimestamp($expires)) { $expires += $this->getTimeNow(); } $this->expires = $expires; } // Capture any additional values that might exist in the token but are // not part of the standard response. Vendors will sometimes pass // additional user data this way. $this->values = \array_diff_key($options, \array_flip(['access_token', 'resource_owner_id', 'refresh_token', 'expires_in', 'expires'])); } /** * Check if a value is an expiration timestamp or second value. * * @param integer $value * @return bool */ protected function isExpirationTimestamp($value) { // If the given value is larger than the original OAuth 2 draft date, // assume that it is meant to be a (possible expired) timestamp. $oauth2InceptionDate = 1349067600; // 2012-10-01 return $value > $oauth2InceptionDate; } /** * @inheritdoc */ public function getToken() { return $this->accessToken; } /** * @inheritdoc */ public function getRefreshToken() { return $this->refreshToken; } /** * @inheritdoc */ public function getExpires() { return $this->expires; } /** * @inheritdoc */ public function getResourceOwnerId() { return $this->resourceOwnerId; } /** * @inheritdoc */ public function hasExpired() { $expires = $this->getExpires(); if (empty($expires)) { throw new \RuntimeException('"expires" is not set on the token'); } return $expires < \time(); } /** * @inheritdoc */ public function getValues() { return $this->values; } /** * @inheritdoc */ public function __toString() { return (string) $this->getToken(); } /** * @inheritdoc */ public function jsonSerialize() { $parameters = $this->values; if ($this->accessToken) { $parameters['access_token'] = $this->accessToken; } if ($this->refreshToken) { $parameters['refresh_token'] = $this->refreshToken; } if ($this->expires) { $parameters['expires'] = $this->expires; } if ($this->resourceOwnerId) { $parameters['resource_owner_id'] = $this->resourceOwnerId; } return $parameters; } } PK!V|<league/oauth2-client/src/Provider/ResourceOwnerInterface.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Provider; /** * Classes implementing `ResourceOwnerInterface` may be used to represent * the resource owner authenticated with a service provider. */ interface ResourceOwnerInterface { /** * Returns the identifier of the authorized resource owner. * * @return mixed */ public function getId(); /** * Return all of the owner details available as an array. * * @return array */ public function toArray(); } PK!h8hh6league/oauth2-client/src/Provider/AbstractProvider.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Provider; use YoastSEO_Vendor\GuzzleHttp\Client as HttpClient; use YoastSEO_Vendor\GuzzleHttp\ClientInterface as HttpClientInterface; use YoastSEO_Vendor\GuzzleHttp\Exception\BadResponseException; use InvalidArgumentException; use YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant; use YoastSEO_Vendor\League\OAuth2\Client\Grant\GrantFactory; use YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\OptionProviderInterface; use YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\PostAuthOptionProvider; use YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception\IdentityProviderException; use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken; use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface; use YoastSEO_Vendor\League\OAuth2\Client\Tool\ArrayAccessorTrait; use YoastSEO_Vendor\League\OAuth2\Client\Tool\GuardedPropertyTrait; use YoastSEO_Vendor\League\OAuth2\Client\Tool\QueryBuilderTrait; use YoastSEO_Vendor\League\OAuth2\Client\Tool\RequestFactory; use YoastSEO_Vendor\Psr\Http\Message\RequestInterface; use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface; use UnexpectedValueException; /** * Represents a service provider (authorization server). * * @link http://tools.ietf.org/html/rfc6749#section-1.1 Roles (RFC 6749, §1.1) */ abstract class AbstractProvider { use ArrayAccessorTrait; use GuardedPropertyTrait; use QueryBuilderTrait; /** * @var string|null Key used in a token response to identify the resource owner. */ const ACCESS_TOKEN_RESOURCE_OWNER_ID = null; /** * @var string HTTP method used to fetch access tokens. */ const METHOD_GET = 'GET'; /** * @var string HTTP method used to fetch access tokens. */ const METHOD_POST = 'POST'; /** * @var string PKCE method used to fetch authorization token. * The PKCE code challenge will be hashed with sha256 (recommended). */ const PKCE_METHOD_S256 = 'S256'; /** * @var string PKCE method used to fetch authorization token. * The PKCE code challenge will be sent as plain text, this is NOT recommended. * Only use `plain` if no other option is possible. */ const PKCE_METHOD_PLAIN = 'plain'; /** * @var string */ protected $clientId; /** * @var string */ protected $clientSecret; /** * @var string */ protected $redirectUri; /** * @var string */ protected $state; /** * @var string|null */ protected $pkceCode = null; /** * @var GrantFactory */ protected $grantFactory; /** * @var RequestFactory */ protected $requestFactory; /** * @var HttpClientInterface */ protected $httpClient; /** * @var OptionProviderInterface */ protected $optionProvider; /** * Constructs an OAuth 2.0 service provider. * * @param array $options An array of options to set on this provider. * Options include `clientId`, `clientSecret`, `redirectUri`, and `state`. * Individual providers may introduce more options, as needed. * @param array $collaborators An array of collaborators that may be used to * override this provider's default behavior. Collaborators include * `grantFactory`, `requestFactory`, and `httpClient`. * Individual providers may introduce more collaborators, as needed. */ public function __construct(array $options = [], array $collaborators = []) { // We'll let the GuardedPropertyTrait handle mass assignment of incoming // options, skipping any blacklisted properties defined in the provider $this->fillProperties($options); if (empty($collaborators['grantFactory'])) { $collaborators['grantFactory'] = new \YoastSEO_Vendor\League\OAuth2\Client\Grant\GrantFactory(); } $this->setGrantFactory($collaborators['grantFactory']); if (empty($collaborators['requestFactory'])) { $collaborators['requestFactory'] = new \YoastSEO_Vendor\League\OAuth2\Client\Tool\RequestFactory(); } $this->setRequestFactory($collaborators['requestFactory']); if (empty($collaborators['httpClient'])) { $client_options = $this->getAllowedClientOptions($options); $collaborators['httpClient'] = new \YoastSEO_Vendor\GuzzleHttp\Client(\array_intersect_key($options, \array_flip($client_options))); } $this->setHttpClient($collaborators['httpClient']); if (empty($collaborators['optionProvider'])) { $collaborators['optionProvider'] = new \YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\PostAuthOptionProvider(); } $this->setOptionProvider($collaborators['optionProvider']); } /** * Returns the list of options that can be passed to the HttpClient * * @param array $options An array of options to set on this provider. * Options include `clientId`, `clientSecret`, `redirectUri`, and `state`. * Individual providers may introduce more options, as needed. * @return array The options to pass to the HttpClient constructor */ protected function getAllowedClientOptions(array $options) { $client_options = ['timeout', 'proxy']; // Only allow turning off ssl verification if it's for a proxy if (!empty($options['proxy'])) { $client_options[] = 'verify'; } return $client_options; } /** * Sets the grant factory instance. * * @param GrantFactory $factory * @return self */ public function setGrantFactory(\YoastSEO_Vendor\League\OAuth2\Client\Grant\GrantFactory $factory) { $this->grantFactory = $factory; return $this; } /** * Returns the current grant factory instance. * * @return GrantFactory */ public function getGrantFactory() { return $this->grantFactory; } /** * Sets the request factory instance. * * @param RequestFactory $factory * @return self */ public function setRequestFactory(\YoastSEO_Vendor\League\OAuth2\Client\Tool\RequestFactory $factory) { $this->requestFactory = $factory; return $this; } /** * Returns the request factory instance. * * @return RequestFactory */ public function getRequestFactory() { return $this->requestFactory; } /** * Sets the HTTP client instance. * * @param HttpClientInterface $client * @return self */ public function setHttpClient(\YoastSEO_Vendor\GuzzleHttp\ClientInterface $client) { $this->httpClient = $client; return $this; } /** * Returns the HTTP client instance. * * @return HttpClientInterface */ public function getHttpClient() { return $this->httpClient; } /** * Sets the option provider instance. * * @param OptionProviderInterface $provider * @return self */ public function setOptionProvider(\YoastSEO_Vendor\League\OAuth2\Client\OptionProvider\OptionProviderInterface $provider) { $this->optionProvider = $provider; return $this; } /** * Returns the option provider instance. * * @return OptionProviderInterface */ public function getOptionProvider() { return $this->optionProvider; } /** * Returns the current value of the state parameter. * * This can be accessed by the redirect handler during authorization. * * @return string */ public function getState() { return $this->state; } /** * Set the value of the pkceCode parameter. * * When using PKCE this should be set before requesting an access token. * * @param string $pkceCode * @return self */ public function setPkceCode($pkceCode) { $this->pkceCode = $pkceCode; return $this; } /** * Returns the current value of the pkceCode parameter. * * This can be accessed by the redirect handler during authorization. * * @return string|null */ public function getPkceCode() { return $this->pkceCode; } /** * Returns the base URL for authorizing a client. * * Eg. https://oauth.service.com/authorize * * @return string */ public abstract function getBaseAuthorizationUrl(); /** * Returns the base URL for requesting an access token. * * Eg. https://oauth.service.com/token * * @param array $params * @return string */ public abstract function getBaseAccessTokenUrl(array $params); /** * Returns the URL for requesting the resource owner's details. * * @param AccessToken $token * @return string */ public abstract function getResourceOwnerDetailsUrl(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token); /** * Returns a new random string to use as the state parameter in an * authorization flow. * * @param int $length Length of the random string to be generated. * @return string */ protected function getRandomState($length = 32) { // Converting bytes to hex will always double length. Hence, we can reduce // the amount of bytes by half to produce the correct length. return \bin2hex(\random_bytes($length / 2)); } /** * Returns a new random string to use as PKCE code_verifier and * hashed as code_challenge parameters in an authorization flow. * Must be between 43 and 128 characters long. * * @param int $length Length of the random string to be generated. * @return string */ protected function getRandomPkceCode($length = 64) { return \substr(\strtr(\base64_encode(\random_bytes($length)), '+/', '-_'), 0, $length); } /** * Returns the default scopes used by this provider. * * This should only be the scopes that are required to request the details * of the resource owner, rather than all the available scopes. * * @return array */ protected abstract function getDefaultScopes(); /** * Returns the string that should be used to separate scopes when building * the URL for requesting an access token. * * @return string Scope separator, defaults to ',' */ protected function getScopeSeparator() { return ','; } /** * @return string|null */ protected function getPkceMethod() { return null; } /** * Returns authorization parameters based on provided options. * * @param array $options * @return array Authorization parameters */ protected function getAuthorizationParameters(array $options) { if (empty($options['state'])) { $options['state'] = $this->getRandomState(); } if (empty($options['scope'])) { $options['scope'] = $this->getDefaultScopes(); } $options += ['response_type' => 'code', 'approval_prompt' => 'auto']; if (\is_array($options['scope'])) { $separator = $this->getScopeSeparator(); $options['scope'] = \implode($separator, $options['scope']); } // Store the state as it may need to be accessed later on. $this->state = $options['state']; $pkceMethod = $this->getPkceMethod(); if (!empty($pkceMethod)) { $this->pkceCode = $this->getRandomPkceCode(); if ($pkceMethod === static::PKCE_METHOD_S256) { $options['code_challenge'] = \trim(\strtr(\base64_encode(\hash('sha256', $this->pkceCode, \true)), '+/', '-_'), '='); } elseif ($pkceMethod === static::PKCE_METHOD_PLAIN) { $options['code_challenge'] = $this->pkceCode; } else { throw new \InvalidArgumentException('Unknown PKCE method "' . $pkceMethod . '".'); } $options['code_challenge_method'] = $pkceMethod; } // Business code layer might set a different redirect_uri parameter // depending on the context, leave it as-is if (!isset($options['redirect_uri'])) { $options['redirect_uri'] = $this->redirectUri; } $options['client_id'] = $this->clientId; return $options; } /** * Builds the authorization URL's query string. * * @param array $params Query parameters * @return string Query string */ protected function getAuthorizationQuery(array $params) { return $this->buildQueryString($params); } /** * Builds the authorization URL. * * @param array $options * @return string Authorization URL */ public function getAuthorizationUrl(array $options = []) { $base = $this->getBaseAuthorizationUrl(); $params = $this->getAuthorizationParameters($options); $query = $this->getAuthorizationQuery($params); return $this->appendQuery($base, $query); } /** * Redirects the client for authorization. * * @param array $options * @param callable|null $redirectHandler * @return mixed */ public function authorize(array $options = [], callable $redirectHandler = null) { $url = $this->getAuthorizationUrl($options); if ($redirectHandler) { return $redirectHandler($url, $this); } // @codeCoverageIgnoreStart \header('Location: ' . $url); exit; // @codeCoverageIgnoreEnd } /** * Appends a query string to a URL. * * @param string $url The URL to append the query to * @param string $query The HTTP query string * @return string The resulting URL */ protected function appendQuery($url, $query) { $query = \trim($query, '?&'); if ($query) { $glue = \strstr($url, '?') === \false ? '?' : '&'; return $url . $glue . $query; } return $url; } /** * Returns the method to use when requesting an access token. * * @return string HTTP method */ protected function getAccessTokenMethod() { return self::METHOD_POST; } /** * Returns the key used in the access token response to identify the resource owner. * * @return string|null Resource owner identifier key */ protected function getAccessTokenResourceOwnerId() { return static::ACCESS_TOKEN_RESOURCE_OWNER_ID; } /** * Builds the access token URL's query string. * * @param array $params Query parameters * @return string Query string */ protected function getAccessTokenQuery(array $params) { return $this->buildQueryString($params); } /** * Checks that a provided grant is valid, or attempts to produce one if the * provided grant is a string. * * @param AbstractGrant|string $grant * @return AbstractGrant */ protected function verifyGrant($grant) { if (\is_string($grant)) { return $this->grantFactory->getGrant($grant); } $this->grantFactory->checkGrant($grant); return $grant; } /** * Returns the full URL to use when requesting an access token. * * @param array $params Query parameters * @return string */ protected function getAccessTokenUrl(array $params) { $url = $this->getBaseAccessTokenUrl($params); if ($this->getAccessTokenMethod() === self::METHOD_GET) { $query = $this->getAccessTokenQuery($params); return $this->appendQuery($url, $query); } return $url; } /** * Returns a prepared request for requesting an access token. * * @param array $params Query string parameters * @return RequestInterface */ protected function getAccessTokenRequest(array $params) { $method = $this->getAccessTokenMethod(); $url = $this->getAccessTokenUrl($params); $options = $this->optionProvider->getAccessTokenOptions($this->getAccessTokenMethod(), $params); return $this->getRequest($method, $url, $options); } /** * Requests an access token using a specified grant and option set. * * @param mixed $grant * @param array $options * @throws IdentityProviderException * @return AccessTokenInterface */ public function getAccessToken($grant, array $options = []) { $grant = $this->verifyGrant($grant); $params = ['client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'redirect_uri' => $this->redirectUri]; if (!empty($this->pkceCode)) { $params['code_verifier'] = $this->pkceCode; } $params = $grant->prepareRequestParameters($params, $options); $request = $this->getAccessTokenRequest($params); $response = $this->getParsedResponse($request); if (\false === \is_array($response)) { throw new \UnexpectedValueException('Invalid response received from Authorization Server. Expected JSON.'); } $prepared = $this->prepareAccessTokenResponse($response); $token = $this->createAccessToken($prepared, $grant); return $token; } /** * Returns a PSR-7 request instance that is not authenticated. * * @param string $method * @param string $url * @param array $options * @return RequestInterface */ public function getRequest($method, $url, array $options = []) { return $this->createRequest($method, $url, null, $options); } /** * Returns an authenticated PSR-7 request instance. * * @param string $method * @param string $url * @param AccessTokenInterface|string|null $token * @param array $options Any of "headers", "body", and "protocolVersion". * @return RequestInterface */ public function getAuthenticatedRequest($method, $url, $token, array $options = []) { return $this->createRequest($method, $url, $token, $options); } /** * Creates a PSR-7 request instance. * * @param string $method * @param string $url * @param AccessTokenInterface|string|null $token * @param array $options * @return RequestInterface */ protected function createRequest($method, $url, $token, array $options) { $defaults = ['headers' => $this->getHeaders($token)]; $options = \array_merge_recursive($defaults, $options); $factory = $this->getRequestFactory(); return $factory->getRequestWithOptions($method, $url, $options); } /** * Sends a request instance and returns a response instance. * * WARNING: This method does not attempt to catch exceptions caused by HTTP * errors! It is recommended to wrap this method in a try/catch block. * * @param RequestInterface $request * @return ResponseInterface */ public function getResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) { return $this->getHttpClient()->send($request); } /** * Sends a request and returns the parsed response. * * @param RequestInterface $request * @throws IdentityProviderException * @return mixed */ public function getParsedResponse(\YoastSEO_Vendor\Psr\Http\Message\RequestInterface $request) { try { $response = $this->getResponse($request); } catch (\YoastSEO_Vendor\GuzzleHttp\Exception\BadResponseException $e) { $response = $e->getResponse(); } $parsed = $this->parseResponse($response); $this->checkResponse($response, $parsed); return $parsed; } /** * Attempts to parse a JSON response. * * @param string $content JSON content from response body * @return array Parsed JSON data * @throws UnexpectedValueException if the content could not be parsed */ protected function parseJson($content) { $content = \json_decode($content, \true); if (\json_last_error() !== \JSON_ERROR_NONE) { throw new \UnexpectedValueException(\sprintf("Failed to parse JSON response: %s", \json_last_error_msg())); } return $content; } /** * Returns the content type header of a response. * * @param ResponseInterface $response * @return string Semi-colon separated join of content-type headers. */ protected function getContentType(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) { return \join(';', (array) $response->getHeader('content-type')); } /** * Parses the response according to its content-type header. * * @throws UnexpectedValueException * @param ResponseInterface $response * @return array */ protected function parseResponse(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response) { $content = (string) $response->getBody(); $type = $this->getContentType($response); if (\strpos($type, 'urlencoded') !== \false) { \parse_str($content, $parsed); return $parsed; } // Attempt to parse the string as JSON regardless of content type, // since some providers use non-standard content types. Only throw an // exception if the JSON could not be parsed when it was expected to. try { return $this->parseJson($content); } catch (\UnexpectedValueException $e) { if (\strpos($type, 'json') !== \false) { throw $e; } if ($response->getStatusCode() == 500) { throw new \UnexpectedValueException('An OAuth server error was encountered that did not contain a JSON body', 0, $e); } return $content; } } /** * Checks a provider response for errors. * * @throws IdentityProviderException * @param ResponseInterface $response * @param array|string $data Parsed response data * @return void */ protected abstract function checkResponse(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, $data); /** * Prepares an parsed access token response for a grant. * * Custom mapping of expiration, etc should be done here. Always call the * parent method when overloading this method. * * @param mixed $result * @return array */ protected function prepareAccessTokenResponse(array $result) { if ($this->getAccessTokenResourceOwnerId() !== null) { $result['resource_owner_id'] = $this->getValueByKey($result, $this->getAccessTokenResourceOwnerId()); } return $result; } /** * Creates an access token from a response. * * The grant that was used to fetch the response can be used to provide * additional context. * * @param array $response * @param AbstractGrant $grant * @return AccessTokenInterface */ protected function createAccessToken(array $response, \YoastSEO_Vendor\League\OAuth2\Client\Grant\AbstractGrant $grant) { return new \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken($response); } /** * Generates a resource owner object from a successful resource owner * details request. * * @param array $response * @param AccessToken $token * @return ResourceOwnerInterface */ protected abstract function createResourceOwner(array $response, \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token); /** * Requests and returns the resource owner of given access token. * * @param AccessToken $token * @return ResourceOwnerInterface */ public function getResourceOwner(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token) { $response = $this->fetchResourceOwnerDetails($token); return $this->createResourceOwner($response, $token); } /** * Requests resource owner details. * * @param AccessToken $token * @return mixed */ protected function fetchResourceOwnerDetails(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token) { $url = $this->getResourceOwnerDetailsUrl($token); $request = $this->getAuthenticatedRequest(self::METHOD_GET, $url, $token); $response = $this->getParsedResponse($request); if (\false === \is_array($response)) { throw new \UnexpectedValueException('Invalid response received from Authorization Server. Expected JSON.'); } return $response; } /** * Returns the default headers used by this provider. * * Typically this is used to set 'Accept' or 'Content-Type' headers. * * @return array */ protected function getDefaultHeaders() { return []; } /** * Returns the authorization headers used by this provider. * * Typically this is "Bearer" or "MAC". For more information see: * http://tools.ietf.org/html/rfc6749#section-7.1 * * No default is provided, providers must overload this method to activate * authorization headers. * * @param mixed|null $token Either a string or an access token instance * @return array */ protected function getAuthorizationHeaders($token = null) { return []; } /** * Returns all headers used by this provider for a request. * * The request will be authenticated if an access token is provided. * * @param mixed|null $token object or string * @return array */ public function getHeaders($token = null) { if ($token) { return \array_merge($this->getDefaultHeaders(), $this->getAuthorizationHeaders($token)); } return $this->getDefaultHeaders(); } } PK!*:league/oauth2-client/src/Provider/GenericResourceOwner.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Provider; /** * Represents a generic resource owner for use with the GenericProvider. */ class GenericResourceOwner implements \YoastSEO_Vendor\League\OAuth2\Client\Provider\ResourceOwnerInterface { /** * @var array */ protected $response; /** * @var string */ protected $resourceOwnerId; /** * @param array $response * @param string $resourceOwnerId */ public function __construct(array $response, $resourceOwnerId) { $this->response = $response; $this->resourceOwnerId = $resourceOwnerId; } /** * Returns the identifier of the authorized resource owner. * * @return mixed */ public function getId() { return $this->response[$this->resourceOwnerId]; } /** * Returns the raw resource owner response. * * @return array */ public function toArray() { return $this->response; } } PK!>Ileague/oauth2-client/src/Provider/Exception/IdentityProviderException.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception; /** * Exception thrown if the provider response contains errors. */ class IdentityProviderException extends \Exception { /** * @var mixed */ protected $response; /** * @param string $message * @param int $code * @param mixed $response The response body */ public function __construct($message, $code, $response) { $this->response = $response; parent::__construct($message, $code); } /** * Returns the exception's response body. * * @return mixed */ public function getResponseBody() { return $this->response; } } PK!65league/oauth2-client/src/Provider/GenericProvider.phpnu[ * @license http://opensource.org/licenses/MIT MIT * @link http://thephpleague.com/oauth2-client/ Documentation * @link https://packagist.org/packages/league/oauth2-client Packagist * @link https://github.com/thephpleague/oauth2-client GitHub */ namespace YoastSEO_Vendor\League\OAuth2\Client\Provider; use InvalidArgumentException; use YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception\IdentityProviderException; use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken; use YoastSEO_Vendor\League\OAuth2\Client\Tool\BearerAuthorizationTrait; use YoastSEO_Vendor\Psr\Http\Message\ResponseInterface; /** * Represents a generic service provider that may be used to interact with any * OAuth 2.0 service provider, using Bearer token authentication. */ class GenericProvider extends \YoastSEO_Vendor\League\OAuth2\Client\Provider\AbstractProvider { use BearerAuthorizationTrait; /** * @var string */ private $urlAuthorize; /** * @var string */ private $urlAccessToken; /** * @var string */ private $urlResourceOwnerDetails; /** * @var string */ private $accessTokenMethod; /** * @var string */ private $accessTokenResourceOwnerId; /** * @var array|null */ private $scopes = null; /** * @var string */ private $scopeSeparator; /** * @var string */ private $responseError = 'error'; /** * @var string */ private $responseCode; /** * @var string */ private $responseResourceOwnerId = 'id'; /** * @var string|null */ private $pkceMethod = null; /** * @param array $options * @param array $collaborators */ public function __construct(array $options = [], array $collaborators = []) { $this->assertRequiredOptions($options); $possible = $this->getConfigurableOptions(); $configured = \array_intersect_key($options, \array_flip($possible)); foreach ($configured as $key => $value) { $this->{$key} = $value; } // Remove all options that are only used locally $options = \array_diff_key($options, $configured); parent::__construct($options, $collaborators); } /** * Returns all options that can be configured. * * @return array */ protected function getConfigurableOptions() { return \array_merge($this->getRequiredOptions(), ['accessTokenMethod', 'accessTokenResourceOwnerId', 'scopeSeparator', 'responseError', 'responseCode', 'responseResourceOwnerId', 'scopes', 'pkceMethod']); } /** * Returns all options that are required. * * @return array */ protected function getRequiredOptions() { return ['urlAuthorize', 'urlAccessToken', 'urlResourceOwnerDetails']; } /** * Verifies that all required options have been passed. * * @param array $options * @return void * @throws InvalidArgumentException */ private function assertRequiredOptions(array $options) { $missing = \array_diff_key(\array_flip($this->getRequiredOptions()), $options); if (!empty($missing)) { throw new \InvalidArgumentException('Required options not defined: ' . \implode(', ', \array_keys($missing))); } } /** * @inheritdoc */ public function getBaseAuthorizationUrl() { return $this->urlAuthorize; } /** * @inheritdoc */ public function getBaseAccessTokenUrl(array $params) { return $this->urlAccessToken; } /** * @inheritdoc */ public function getResourceOwnerDetailsUrl(\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token) { return $this->urlResourceOwnerDetails; } /** * @inheritdoc */ public function getDefaultScopes() { return $this->scopes; } /** * @inheritdoc */ protected function getAccessTokenMethod() { return $this->accessTokenMethod ?: parent::getAccessTokenMethod(); } /** * @inheritdoc */ protected function getAccessTokenResourceOwnerId() { return $this->accessTokenResourceOwnerId ?: parent::getAccessTokenResourceOwnerId(); } /** * @inheritdoc */ protected function getScopeSeparator() { return $this->scopeSeparator ?: parent::getScopeSeparator(); } /** * @inheritdoc */ protected function getPkceMethod() { return $this->pkceMethod ?: parent::getPkceMethod(); } /** * @inheritdoc */ protected function checkResponse(\YoastSEO_Vendor\Psr\Http\Message\ResponseInterface $response, $data) { if (!empty($data[$this->responseError])) { $error = $data[$this->responseError]; if (!\is_string($error)) { $error = \var_export($error, \true); } $code = $this->responseCode && !empty($data[$this->responseCode]) ? $data[$this->responseCode] : 0; if (!\is_int($code)) { $code = \intval($code); } throw new \YoastSEO_Vendor\League\OAuth2\Client\Provider\Exception\IdentityProviderException($error, $code, $data); } } /** * @inheritdoc */ protected function createResourceOwner(array $response, \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken $token) { return new \YoastSEO_Vendor\League\OAuth2\Client\Provider\GenericResourceOwner($response, $this->responseResourceOwnerId); } } PK!;Ar1psr/http-client/src/NetworkExceptionInterface.phpnu[logger = $logger; } } PK!H''psr/log/Psr/Log/LoggerTrait.phpnu[log(\YoastSEO_Vendor\Psr\Log\LogLevel::EMERGENCY, $message, $context); } /** * Action must be taken immediately. * * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * * @param string $message * @param array $context * * @return void */ public function alert($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::ALERT, $message, $context); } /** * Critical conditions. * * Example: Application component unavailable, unexpected exception. * * @param string $message * @param array $context * * @return void */ public function critical($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::CRITICAL, $message, $context); } /** * Runtime errors that do not require immediate action but should typically * be logged and monitored. * * @param string $message * @param array $context * * @return void */ public function error($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::ERROR, $message, $context); } /** * Exceptional occurrences that are not errors. * * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * * @param string $message * @param array $context * * @return void */ public function warning($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::WARNING, $message, $context); } /** * Normal but significant events. * * @param string $message * @param array $context * * @return void */ public function notice($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::NOTICE, $message, $context); } /** * Interesting events. * * Example: User logs in, SQL logs. * * @param string $message * @param array $context * * @return void */ public function info($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::INFO, $message, $context); } /** * Detailed debug information. * * @param string $message * @param array $context * * @return void */ public function debug($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::DEBUG, $message, $context); } /** * Logs with an arbitrary level. * * @param mixed $level * @param string $message * @param array $context * * @return void * * @throws \Psr\Log\InvalidArgumentException */ public abstract function log($level, $message, array $context = array()); } PK!RR(psr/log/Psr/Log/LoggerAwareInterface.phpnu[logger) { }` * blocks. */ class NullLogger extends \YoastSEO_Vendor\Psr\Log\AbstractLogger { /** * Logs with an arbitrary level. * * @param mixed $level * @param string $message * @param array $context * * @return void * * @throws \Psr\Log\InvalidArgumentException */ public function log($level, $message, array $context = array()) { // noop } } PK! "psr/log/Psr/Log/AbstractLogger.phpnu[log(\YoastSEO_Vendor\Psr\Log\LogLevel::EMERGENCY, $message, $context); } /** * Action must be taken immediately. * * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * * @param string $message * @param mixed[] $context * * @return void */ public function alert($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::ALERT, $message, $context); } /** * Critical conditions. * * Example: Application component unavailable, unexpected exception. * * @param string $message * @param mixed[] $context * * @return void */ public function critical($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::CRITICAL, $message, $context); } /** * Runtime errors that do not require immediate action but should typically * be logged and monitored. * * @param string $message * @param mixed[] $context * * @return void */ public function error($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::ERROR, $message, $context); } /** * Exceptional occurrences that are not errors. * * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * * @param string $message * @param mixed[] $context * * @return void */ public function warning($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::WARNING, $message, $context); } /** * Normal but significant events. * * @param string $message * @param mixed[] $context * * @return void */ public function notice($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::NOTICE, $message, $context); } /** * Interesting events. * * Example: User logs in, SQL logs. * * @param string $message * @param mixed[] $context * * @return void */ public function info($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::INFO, $message, $context); } /** * Detailed debug information. * * @param string $message * @param mixed[] $context * * @return void */ public function debug($message, array $context = array()) { $this->log(\YoastSEO_Vendor\Psr\Log\LogLevel::DEBUG, $message, $context); } } PK!\Ppp,psr/log/Psr/Log/InvalidArgumentException.phpnu[getHeaders() as $name => $values) { * echo $name . ": " . implode(", ", $values); * } * * // Emit headers iteratively: * foreach ($message->getHeaders() as $name => $values) { * foreach ($values as $value) { * header(sprintf('%s: %s', $name, $value), false); * } * } * * While header names are not case-sensitive, getHeaders() will preserve the * exact case in which headers were originally specified. * * @return string[][] Returns an associative array of the message's headers. Each * key MUST be a header name, and each value MUST be an array of strings * for that header. */ public function getHeaders() : array; /** * Checks if a header exists by the given case-insensitive name. * * @param string $name Case-insensitive header field name. * @return bool Returns true if any header names match the given header * name using a case-insensitive string comparison. Returns false if * no matching header name is found in the message. */ public function hasHeader(string $name) : bool; /** * Retrieves a message header value by the given case-insensitive name. * * This method returns an array of all the header values of the given * case-insensitive header name. * * If the header does not appear in the message, this method MUST return an * empty array. * * @param string $name Case-insensitive header field name. * @return string[] An array of string values as provided for the given * header. If the header does not appear in the message, this method MUST * return an empty array. */ public function getHeader(string $name) : array; /** * Retrieves a comma-separated string of the values for a single header. * * This method returns all of the header values of the given * case-insensitive header name as a string concatenated together using * a comma. * * NOTE: Not all header values may be appropriately represented using * comma concatenation. For such headers, use getHeader() instead * and supply your own delimiter when concatenating. * * If the header does not appear in the message, this method MUST return * an empty string. * * @param string $name Case-insensitive header field name. * @return string A string of values as provided for the given header * concatenated together using a comma. If the header does not appear in * the message, this method MUST return an empty string. */ public function getHeaderLine(string $name) : string; /** * Return an instance with the provided value replacing the specified header. * * While header names are case-insensitive, the casing of the header will * be preserved by this function, and returned from getHeaders(). * * This method MUST be implemented in such a way as to retain the * immutability of the message, and MUST return an instance that has the * new and/or updated header and value. * * @param string $name Case-insensitive header field name. * @param string|string[] $value Header value(s). * @return static * @throws \InvalidArgumentException for invalid header names or values. */ public function withHeader(string $name, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface; /** * Return an instance with the specified header appended with the given value. * * Existing values for the specified header will be maintained. The new * value(s) will be appended to the existing list. If the header did not * exist previously, it will be added. * * This method MUST be implemented in such a way as to retain the * immutability of the message, and MUST return an instance that has the * new header and/or value. * * @param string $name Case-insensitive header field name to add. * @param string|string[] $value Header value(s). * @return static * @throws \InvalidArgumentException for invalid header names or values. */ public function withAddedHeader(string $name, $value) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface; /** * Return an instance without the specified header. * * Header resolution MUST be done without case-sensitivity. * * This method MUST be implemented in such a way as to retain the * immutability of the message, and MUST return an instance that removes * the named header. * * @param string $name Case-insensitive header field name to remove. * @return static */ public function withoutHeader(string $name) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface; /** * Gets the body of the message. * * @return StreamInterface Returns the body as a stream. */ public function getBody() : \YoastSEO_Vendor\Psr\Http\Message\StreamInterface; /** * Return an instance with the specified message body. * * The body MUST be a StreamInterface object. * * This method MUST be implemented in such a way as to retain the * immutability of the message, and MUST return a new instance that has the * new body stream. * * @param StreamInterface $body Body. * @return static * @throws \InvalidArgumentException When the body is not valid. */ public function withBody(\YoastSEO_Vendor\Psr\Http\Message\StreamInterface $body) : \YoastSEO_Vendor\Psr\Http\Message\MessageInterface; } PK!y|7)7)/psr/http-message/src/ServerRequestInterface.phpnu[getQuery()` * or from the `QUERY_STRING` server param. * * @return array */ public function getQueryParams() : array; /** * Return an instance with the specified query string arguments. * * These values SHOULD remain immutable over the course of the incoming * request. They MAY be injected during instantiation, such as from PHP's * $_GET superglobal, or MAY be derived from some other value such as the * URI. In cases where the arguments are parsed from the URI, the data * MUST be compatible with what PHP's parse_str() would return for * purposes of how duplicate query parameters are handled, and how nested * sets are handled. * * Setting query string arguments MUST NOT change the URI stored by the * request, nor the values in the server params. * * This method MUST be implemented in such a way as to retain the * immutability of the message, and MUST return an instance that has the * updated query string arguments. * * @param array $query Array of query string arguments, typically from * $_GET. * @return static */ public function withQueryParams(array $query) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface; /** * Retrieve normalized file upload data. * * This method returns upload metadata in a normalized tree, with each leaf * an instance of Psr\Http\Message\UploadedFileInterface. * * These values MAY be prepared from $_FILES or the message body during * instantiation, or MAY be injected via withUploadedFiles(). * * @return array An array tree of UploadedFileInterface instances; an empty * array MUST be returned if no data is present. */ public function getUploadedFiles() : array; /** * Create a new instance with the specified uploaded files. * * This method MUST be implemented in such a way as to retain the * immutability of the message, and MUST return an instance that has the * updated body parameters. * * @param array $uploadedFiles An array tree of UploadedFileInterface instances. * @return static * @throws \InvalidArgumentException if an invalid structure is provided. */ public function withUploadedFiles(array $uploadedFiles) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface; /** * Retrieve any parameters provided in the request body. * * If the request Content-Type is either application/x-www-form-urlencoded * or multipart/form-data, and the request method is POST, this method MUST * return the contents of $_POST. * * Otherwise, this method may return any results of deserializing * the request body content; as parsing returns structured content, the * potential types MUST be arrays or objects only. A null value indicates * the absence of body content. * * @return null|array|object The deserialized body parameters, if any. * These will typically be an array or object. */ public function getParsedBody(); /** * Return an instance with the specified body parameters. * * These MAY be injected during instantiation. * * If the request Content-Type is either application/x-www-form-urlencoded * or multipart/form-data, and the request method is POST, use this method * ONLY to inject the contents of $_POST. * * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of * deserializing the request body content. Deserialization/parsing returns * structured data, and, as such, this method ONLY accepts arrays or objects, * or a null value if nothing was available to parse. * * As an example, if content negotiation determines that the request data * is a JSON payload, this method could be used to create a request * instance with the deserialized parameters. * * This method MUST be implemented in such a way as to retain the * immutability of the message, and MUST return an instance that has the * updated body parameters. * * @param null|array|object $data The deserialized body data. This will * typically be in an array or object. * @return static * @throws \InvalidArgumentException if an unsupported argument type is * provided. */ public function withParsedBody($data) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface; /** * Retrieve attributes derived from the request. * * The request "attributes" may be used to allow injection of any * parameters derived from the request: e.g., the results of path * match operations; the results of decrypting cookies; the results of * deserializing non-form-encoded message bodies; etc. Attributes * will be application and request specific, and CAN be mutable. * * @return array Attributes derived from the request. */ public function getAttributes() : array; /** * Retrieve a single derived request attribute. * * Retrieves a single derived request attribute as described in * getAttributes(). If the attribute has not been previously set, returns * the default value as provided. * * This method obviates the need for a hasAttribute() method, as it allows * specifying a default value to return if the attribute is not found. * * @see getAttributes() * @param string $name The attribute name. * @param mixed $default Default value to return if the attribute does not exist. * @return mixed */ public function getAttribute(string $name, $default = null); /** * Return an instance with the specified derived request attribute. * * This method allows setting a single derived request attribute as * described in getAttributes(). * * This method MUST be implemented in such a way as to retain the * immutability of the message, and MUST return an instance that has the * updated attribute. * * @see getAttributes() * @param string $name The attribute name. * @param mixed $value The value of the attribute. * @return static */ public function withAttribute(string $name, $value) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface; /** * Return an instance that removes the specified derived request attribute. * * This method allows removing a single derived request attribute as * described in getAttributes(). * * This method MUST be implemented in such a way as to retain the * immutability of the message, and MUST return an instance that removes * the attribute. * * @see getAttributes() * @param string $name The attribute name. * @return static */ public function withoutAttribute(string $name) : \YoastSEO_Vendor\Psr\Http\Message\ServerRequestInterface; } PK!NJ)psr/http-message/src/RequestInterface.phpnu[ * [user-info@]host[:port] * * * If the port component is not set or is the standard port for the current * scheme, it SHOULD NOT be included. * * @see https://tools.ietf.org/html/rfc3986#section-3.2 * @return string The URI authority, in "[user-info@]host[:port]" format. */ public function getAuthority() : string; /** * Retrieve the user information component of the URI. * * If no user information is present, this method MUST return an empty * string. * * If a user is present in the URI, this will return that value; * additionally, if the password is also present, it will be appended to the * user value, with a colon (":") separating the values. * * The trailing "@" character is not part of the user information and MUST * NOT be added. * * @return string The URI user information, in "username[:password]" format. */ public function getUserInfo() : string; /** * Retrieve the host component of the URI. * * If no host is present, this method MUST return an empty string. * * The value returned MUST be normalized to lowercase, per RFC 3986 * Section 3.2.2. * * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 * @return string The URI host. */ public function getHost() : string; /** * Retrieve the port component of the URI. * * If a port is present, and it is non-standard for the current scheme, * this method MUST return it as an integer. If the port is the standard port * used with the current scheme, this method SHOULD return null. * * If no port is present, and no scheme is present, this method MUST return * a null value. * * If no port is present, but a scheme is present, this method MAY return * the standard port for that scheme, but SHOULD return null. * * @return null|int The URI port. */ public function getPort() : ?int; /** * Retrieve the path component of the URI. * * The path can either be empty or absolute (starting with a slash) or * rootless (not starting with a slash). Implementations MUST support all * three syntaxes. * * Normally, the empty path "" and absolute path "/" are considered equal as * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically * do this normalization because in contexts with a trimmed base path, e.g. * the front controller, this difference becomes significant. It's the task * of the user to handle both "" and "/". * * The value returned MUST be percent-encoded, but MUST NOT double-encode * any characters. To determine what characters to encode, please refer to * RFC 3986, Sections 2 and 3.3. * * As an example, if the value should include a slash ("/") not intended as * delimiter between path segments, that value MUST be passed in encoded * form (e.g., "%2F") to the instance. * * @see https://tools.ietf.org/html/rfc3986#section-2 * @see https://tools.ietf.org/html/rfc3986#section-3.3 * @return string The URI path. */ public function getPath() : string; /** * Retrieve the query string of the URI. * * If no query string is present, this method MUST return an empty string. * * The leading "?" character is not part of the query and MUST NOT be * added. * * The value returned MUST be percent-encoded, but MUST NOT double-encode * any characters. To determine what characters to encode, please refer to * RFC 3986, Sections 2 and 3.4. * * As an example, if a value in a key/value pair of the query string should * include an ampersand ("&") not intended as a delimiter between values, * that value MUST be passed in encoded form (e.g., "%26") to the instance. * * @see https://tools.ietf.org/html/rfc3986#section-2 * @see https://tools.ietf.org/html/rfc3986#section-3.4 * @return string The URI query string. */ public function getQuery() : string; /** * Retrieve the fragment component of the URI. * * If no fragment is present, this method MUST return an empty string. * * The leading "#" character is not part of the fragment and MUST NOT be * added. * * The value returned MUST be percent-encoded, but MUST NOT double-encode * any characters. To determine what characters to encode, please refer to * RFC 3986, Sections 2 and 3.5. * * @see https://tools.ietf.org/html/rfc3986#section-2 * @see https://tools.ietf.org/html/rfc3986#section-3.5 * @return string The URI fragment. */ public function getFragment() : string; /** * Return an instance with the specified scheme. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified scheme. * * Implementations MUST support the schemes "http" and "https" case * insensitively, and MAY accommodate other schemes if required. * * An empty scheme is equivalent to removing the scheme. * * @param string $scheme The scheme to use with the new instance. * @return static A new instance with the specified scheme. * @throws \InvalidArgumentException for invalid or unsupported schemes. */ public function withScheme(string $scheme) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface; /** * Return an instance with the specified user information. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified user information. * * Password is optional, but the user information MUST include the * user; an empty string for the user is equivalent to removing user * information. * * @param string $user The user name to use for authority. * @param null|string $password The password associated with $user. * @return static A new instance with the specified user information. */ public function withUserInfo(string $user, ?string $password = null) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface; /** * Return an instance with the specified host. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified host. * * An empty host value is equivalent to removing the host. * * @param string $host The hostname to use with the new instance. * @return static A new instance with the specified host. * @throws \InvalidArgumentException for invalid hostnames. */ public function withHost(string $host) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface; /** * Return an instance with the specified port. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified port. * * Implementations MUST raise an exception for ports outside the * established TCP and UDP port ranges. * * A null value provided for the port is equivalent to removing the port * information. * * @param null|int $port The port to use with the new instance; a null value * removes the port information. * @return static A new instance with the specified port. * @throws \InvalidArgumentException for invalid ports. */ public function withPort(?int $port) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface; /** * Return an instance with the specified path. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified path. * * The path can either be empty or absolute (starting with a slash) or * rootless (not starting with a slash). Implementations MUST support all * three syntaxes. * * If the path is intended to be domain-relative rather than path relative then * it must begin with a slash ("/"). Paths not starting with a slash ("/") * are assumed to be relative to some base path known to the application or * consumer. * * Users can provide both encoded and decoded path characters. * Implementations ensure the correct encoding as outlined in getPath(). * * @param string $path The path to use with the new instance. * @return static A new instance with the specified path. * @throws \InvalidArgumentException for invalid paths. */ public function withPath(string $path) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface; /** * Return an instance with the specified query string. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified query string. * * Users can provide both encoded and decoded query characters. * Implementations ensure the correct encoding as outlined in getQuery(). * * An empty query string value is equivalent to removing the query string. * * @param string $query The query string to use with the new instance. * @return static A new instance with the specified query string. * @throws \InvalidArgumentException for invalid query strings. */ public function withQuery(string $query) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface; /** * Return an instance with the specified URI fragment. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified URI fragment. * * Users can provide both encoded and decoded fragment characters. * Implementations ensure the correct encoding as outlined in getFragment(). * * An empty fragment value is equivalent to removing the fragment. * * @param string $fragment The fragment to use with the new instance. * @return static A new instance with the specified fragment. */ public function withFragment(string $fragment) : \YoastSEO_Vendor\Psr\Http\Message\UriInterface; /** * Return the string representation as a URI reference. * * Depending on which components of the URI are present, the resulting * string is either a full URI or relative reference according to RFC 3986, * Section 4.1. The method concatenates the various components of the URI, * using the appropriate delimiters: * * - If a scheme is present, it MUST be suffixed by ":". * - If an authority is present, it MUST be prefixed by "//". * - The path can be concatenated without delimiters. But there are two * cases where the path has to be adjusted to make the URI reference * valid as PHP does not allow to throw an exception in __toString(): * - If the path is rootless and an authority is present, the path MUST * be prefixed by "/". * - If the path is starting with more than one "/" and no authority is * present, the starting slashes MUST be reduced to one. * - If a query is present, it MUST be prefixed by "?". * - If a fragment is present, it MUST be prefixed by "#". * * @see http://tools.ietf.org/html/rfc3986#section-4.1 * @return string */ public function __toString() : string; } PK!" .psr/http-message/src/UploadedFileInterface.phpnu[wordproof/wordpress-sdk/app/Exceptions/ValidationException.phpnu[ ['endpoint' => '/posts/(?P\\d+)/hashinput/(?P[a-fA-F0-9]{64})', 'method' => 'get'], 'authenticate' => ['endpoint' => '/oauth/authenticate', 'method' => 'post'], 'timestamp' => ['endpoint' => '/posts/(?P\\d+)/timestamp', 'method' => 'post'], 'timestamp.transaction.latest' => ['endpoint' => '/posts/(?P\\d+)/timestamp/transaction/latest', 'method' => 'get'], 'webhook' => ['endpoint' => '/webhook', 'method' => 'get'], 'settings' => ['endpoint' => '/settings', 'method' => 'get'], 'saveSettings' => ['endpoint' => '/settings', 'method' => 'POST'], 'authentication' => ['endpoint' => '/authentication', 'method' => 'post'], 'authentication.destroy' => ['endpoint' => '/oauth/destroy', 'method' => 'post']]; } } PK!kG557wordproof/wordpress-sdk/app/Config/DefaultAppConfig.phpnu[ ['dependencies' => ['wp-data', 'lodash', 'wp-api-fetch'], 'type' => 'js'], 'wordproof-block-editor' => ['dependencies' => ['wp-i18n', 'wp-element', 'wp-components', 'wp-editor', 'wp-edit-post', 'wp-data', 'lodash', 'wordproof-data'], 'type' => 'js'], 'wordproof-elementor-editor' => ['dependencies' => ['wp-i18n', 'wp-element', 'wp-components', 'wp-editor', 'wp-edit-post', 'wp-data', 'lodash', 'wordproof-data', 'elementor-common'], 'type' => 'js'], 'wordproof-classic-editor' => ['dependencies' => ['wp-i18n', 'wp-element', 'wp-components', 'wp-editor', 'wp-edit-post', 'wp-data', 'lodash', 'wordproof-data'], 'type' => 'js']]; } } PK!3+8wordproof/wordpress-sdk/app/Config/EnvironmentConfig.phpnu[ ['url' => 'https://staging.wordproof.com', 'client' => 78], 'production' => ['url' => 'https://my.wordproof.com', 'client' => 79]]; } } PK!,4wordproof/wordpress-sdk/app/Config/OptionsConfig.phpnu[ ['escape' => 'integer', 'default' => null], 'access_token' => ['escape' => 'text_field', 'default' => null], 'balance' => ['escape' => 'integer', 'default' => 0], 'settings' => ['cast' => 'object', 'options' => ['certificate_link_text' => ['escape' => 'text_field', 'default' => __('View this content\'s Timestamp certificate', 'wordproof')], 'hide_certificate_link' => ['escape' => 'boolean', 'default' => \false], 'selected_post_types' => ['escape' => 'text_field', 'default' => []], 'show_revisions' => ['escape' => 'boolean', 'default' => \true]]], 'identity' => ['cast' => 'object', 'options' => ['provider' => ['escape' => 'text_field', 'default' => null], 'first_name' => ['escape' => 'text_field', 'default' => null], 'last_name' => ['escape' => 'text_field', 'default' => null], 'profile_picture' => ['escape' => 'url', 'default' => null], 'proof_url' => ['escape' => 'url', 'default' => null]]]]; } } PK!͌%-wordproof/wordpress-sdk/app/Config/Config.phpnu[timestampAfterPostRequest($postId, $post); } /** * Timestamp posts inserted by the API. * * @param \WP_Post $post The post to be timestamped. * @action rest_after_insert_post */ public function timestampAfterRestApiRequest($post) { return \YoastSEO_Vendor\WordProof\SDK\Helpers\TimestampHelper::debounce($post); } /** * Removes action to timestamp post on insert if Elementor is used. */ public function beforeElementorSave() { \remove_action('rest_after_insert_post', [$this, 'timestampAfterRestApiRequest']); \remove_action('wp_insert_post', [$this, 'timestampAfterPostRequest'], \PHP_INT_MAX); } /** * Syncs timestamp override post meta keys. * * @param $metaId * @param $postId * @param $metaKey * @param $metaValue */ public function syncPostMetaTimestampOverrides($metaId, $postId, $metaKey, $metaValue) { $timestampablePostMetaKeys = \apply_filters('wordproof_timestamp_post_meta_key_overrides', ['_wordproof_timestamp']); if (\in_array($metaKey, $timestampablePostMetaKeys, \true) && \count($timestampablePostMetaKeys) > 1) { $arrayKey = \array_search($metaKey, $timestampablePostMetaKeys, \true); unset($timestampablePostMetaKeys[$arrayKey]); \YoastSEO_Vendor\WordProof\SDK\Helpers\TransientHelper::set('wordproof_debounce_post_meta_sync_' . $metaKey . '_' . $postId, \true, 5); foreach ($timestampablePostMetaKeys as $key) { \YoastSEO_Vendor\WordProof\SDK\Helpers\TransientHelper::debounce($postId, 'post_meta_sync_' . $key, function () use($postId, $key, $metaValue) { return \YoastSEO_Vendor\WordProof\SDK\Helpers\PostMetaHelper::update($postId, $key, $metaValue); }); } } } } PK!m9zIwordproof/wordpress-sdk/app/Controllers/PostEditorTimestampController.phpnu[metaKey, ['show_in_rest' => \true, 'single' => \true, 'type' => 'boolean', 'default' => \false, 'supports' => ['editor', 'title', 'custom-fields'], 'auth_callback' => [$this, 'userCanEditPosts']]); } } /** * Returns if the current user can edit posts. * * @return boolean */ public function userCanEditPosts() { return \current_user_can('edit_posts'); } /** * Enqueues the wordproof-block-editor script. * * @action enqueue_block_editor_assets * @script wordproof-block-editor */ public function enqueueBlockEditorScript() { \YoastSEO_Vendor\WordProof\SDK\Helpers\AssetHelper::enqueue('wordproof-block-editor'); } /** * Enqueues the wordproof-elementor-editor script. * * @action elementor/editor/after_enqueue_scripts * @script wordproof-elementor-editor */ public function enqueueElementorEditorScript() { \YoastSEO_Vendor\WordProof\SDK\Helpers\AssetHelper::enqueue('wordproof-elementor-editor'); } /** * Enqueues the wordproof-classic-editor script. * * @action admin_enqueue_scripts * @script wordproof-classic-editor */ public function enqueueClassicEditorScript($hook) { if (!\YoastSEO_Vendor\WordProof\SDK\Helpers\PostEditorHelper::isPostEdit($hook)) { return; } if (\YoastSEO_Vendor\WordProof\SDK\Helpers\PostEditorHelper::getPostEditor() === 'classic') { \YoastSEO_Vendor\WordProof\SDK\Helpers\AssetHelper::enqueue('wordproof-classic-editor'); } } /** * Add Metabox to classic editor. * * @action add_meta_boxes */ public function addMetaboxToClassicEditor() { foreach (\YoastSEO_Vendor\WordProof\SDK\Helpers\PostTypeHelper::getPublicPostTypes() as $postType) { \add_meta_box('wordproof_timestamp_metabox', 'WordProof Timestamp', [$this, 'classicMetaboxHtml'], $postType, 'side', 'default', ['__back_compat_meta_box' => \true]); } } /** * Save the meta box meta value for the classic editor. * * @param integer $postId The post ID. * @action save_post */ public function saveClassicMetaboxPostMeta($postId) { if (\array_key_exists($this->classicEditorNonceKey, $_POST)) { if (\wp_verify_nonce(\sanitize_key($_POST[$this->classicEditorNonceKey]), 'save_post')) { \update_post_meta($postId, $this->metaKey, \array_key_exists($this->metaKey, $_POST)); } } } /** * Display the meta box HTML to Classic Editor users. * * @param \WP_Post $post Post object. */ public function classicMetaboxHtml($post) { $value = \YoastSEO_Vendor\WordProof\SDK\Helpers\PostMetaHelper::get($post->ID, $this->metaKey); \wp_nonce_field('save_post', $this->classicEditorNonceKey); ?>
>
start_controls_section('wordproof_timestamp_section', ['label' => \esc_html__('WordProof Timestamp', 'wordproof'), 'tab' => \Elementor\Controls_Manager::TAB_SETTINGS]); // Get meta value $postId = $document->get_id(); $metaValue = \YoastSEO_Vendor\WordProof\SDK\Helpers\PostMetaHelper::get($postId, $this->metaKey, \true); // Override elementor value $pageSettingsManager = \Elementor\Core\Settings\Manager::get_settings_managers('page'); $pageSettingsModel = $pageSettingsManager->get_model($postId); $pageSettingsModel->set_settings($this->metaKey, \boolval($metaValue) ? 'yes' : ''); // Add Switcher $document->add_control($this->metaKey, ['label' => \esc_html__('Timestamp this post', 'wordproof'), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'no']); $document->end_controls_section(); } /** * @param integer $postId * @action elementor/document/save/data */ public function elementorSave($postId) { if (\get_post_type($postId) !== 'page') { return; } $pageSettingsManager = \Elementor\Core\Settings\Manager::get_settings_managers('page'); $pageSettingsModel = $pageSettingsManager->get_model($postId); $value = $pageSettingsModel->get_settings($this->metaKey); // Update meta key with Elementor value. \YoastSEO_Vendor\WordProof\SDK\Helpers\PostMetaHelper::update($postId, $this->metaKey, $value === 'yes'); } } PK!>wordproof/wordpress-sdk/app/Controllers/IdentityController.phpnu[ $data['first_name'], 'last_name' => $data['last_name'], 'provider' => $data['provider'], 'profile_picture' => $data['profile_picture'], 'proof_url' => \YoastSEO_Vendor\WordProof\SDK\Helpers\EnvironmentHelper::url() . '/identity/' . \YoastSEO_Vendor\WordProof\SDK\Helpers\OptionsHelper::sourceId()]; } /** * Store identity data * * @param array $data * * @return bool * @throws ValidationException */ public function store($data) { return \YoastSEO_Vendor\WordProof\SDK\Helpers\OptionsHelper::set('identity', $this->validate($data)); } /** * Delete the stored identity data * * @return mixed */ public function delete() { return \YoastSEO_Vendor\WordProof\SDK\Helpers\OptionsHelper::delete('identity'); } } PK!L --=wordproof/wordpress-sdk/app/Controllers/RestApiController.phpnu[ 'POST', 'callback' => [$this, 'authenticate'], 'permission_callback' => [$this, 'canPublishPermission']]); \register_rest_route(\YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::getNamespace(), \YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::endpoint('webhook'), ['methods' => 'POST', 'callback' => [$this, 'webhook'], 'permission_callback' => [$this, 'isValidWebhookRequest']]); \register_rest_route(\YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::getNamespace(), \YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::endpoint('hashInput'), ['methods' => 'GET', 'callback' => [$this, 'hashInput'], 'permission_callback' => function () { return \true; }]); \register_rest_route(\YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::getNamespace(), \YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::endpoint('timestamp'), ['methods' => 'POST', 'callback' => [$this, 'timestamp'], 'permission_callback' => [$this, 'canPublishPermission']]); \register_rest_route(\YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::getNamespace(), \YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::endpoint('timestamp.transaction.latest'), ['methods' => 'GET', 'callback' => [$this, 'showLatestTimestampTransaction'], 'permission_callback' => [$this, 'canPublishPermission']]); \register_rest_route(\YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::getNamespace(), \YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::endpoint('settings'), ['methods' => 'GET', 'callback' => [$this, 'settings'], 'permission_callback' => [$this, 'canPublishPermission']]); \register_rest_route(\YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::getNamespace(), \YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::endpoint('saveSettings'), ['methods' => 'POST', 'callback' => [$this, 'saveSettings'], 'permission_callback' => [$this, 'canPublishPermission']]); \register_rest_route(\YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::getNamespace(), \YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::endpoint('authentication'), ['methods' => 'GET', 'callback' => [$this, 'authentication'], 'permission_callback' => [$this, 'canPublishPermission']]); \register_rest_route(\YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::getNamespace(), \YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::endpoint('authentication.destroy'), ['methods' => 'POST', 'callback' => [$this, 'destroyAuthentication'], 'permission_callback' => [$this, 'canPublishPermission']]); } /** * Returns an object containing the settings. * * @return \WP_REST_Response Returns the settings. */ public function settings() { $data = \YoastSEO_Vendor\WordProof\SDK\Helpers\SettingsHelper::get(); $data->status = 200; return new \WP_REST_Response($data, $data->status); } /** * Save the settings. * * @return \WP_REST_Response Returns the settings. */ public function saveSettings(\WP_REST_Request $request) { $data = $request->get_params(); $settings = $data['settings']; $snakeCaseSettings = []; foreach ($settings as $key => $value) { $key = \YoastSEO_Vendor\WordProof\SDK\Helpers\StringHelper::toUnderscore($key); $snakeCaseSettings[$key] = $value; } \YoastSEO_Vendor\WordProof\SDK\Helpers\OptionsHelper::set('settings', $snakeCaseSettings); $data = (object) []; $data->status = 200; return new \WP_REST_Response($data, $data->status); } /** * Returns if the user is authenticated. * * @return \WP_REST_Response Returns if the user is authenticated. */ public function authentication() { $data = (object) ['is_authenticated' => \YoastSEO_Vendor\WordProof\SDK\Helpers\AuthenticationHelper::isAuthenticated(), 'status' => 200]; return new \WP_REST_Response($data, $data->status); } /** * Logout the user and return if the user is authenticated. * * @return \WP_REST_Response Returns if the user is authenticated. */ public function destroyAuthentication() { \YoastSEO_Vendor\WordProof\SDK\Helpers\AuthenticationHelper::logout(); return $this->authentication(); } /** * Send a post request to WordProof to timestamp a post. * * @param \WP_REST_Request $request The Rest Request. * @return \WP_REST_Response */ public function timestamp(\WP_REST_Request $request) { $data = $request->get_params(); $postId = \intval($data['id']); return \YoastSEO_Vendor\WordProof\SDK\Controllers\TimestampController::timestamp($postId); } /** * The latest timestamp transaction is returned. * * @param \WP_REST_Request $request * @return \WP_REST_Response */ public function showLatestTimestampTransaction(\WP_REST_Request $request) { $data = $request->get_params(); $postId = \intval($data['id']); $transactions = \YoastSEO_Vendor\WordProof\SDK\Helpers\PostMetaHelper::get($postId, '_wordproof_blockchain_transaction', \false); $transaction = \array_pop($transactions); $response = new \WP_REST_Response((object) $transaction); $response->header('X-Robots-Tag', 'noindex'); return $response; } /** * Returns the hash input of a post. * * @param \WP_REST_Request $request The Rest Request. * @return \WP_REST_Response The hash input of a post. */ public function hashInput(\WP_REST_Request $request) { $data = $request->get_params(); $postId = \intval($data['id']); $hash = \sanitize_text_field($data['hash']); $hashInput = \YoastSEO_Vendor\WordProof\SDK\Helpers\PostMetaHelper::get($postId, '_wordproof_hash_input_' . $hash); $response = new \WP_REST_Response((object) $hashInput); $response->header('X-Robots-Tag', 'noindex'); return $response; } /** * Retrieves the access token when the code and state are retrieved in the frontend. * * @throws \Exception */ public function authenticate(\WP_REST_Request $request) { $state = \sanitize_text_field($request->get_param('state')); $code = \sanitize_text_field($request->get_param('code')); return \YoastSEO_Vendor\WordProof\SDK\Support\Authentication::token($state, $code); } /** * Handles webhooks sent by WordProof. * * @param \WP_REST_Request $request The Rest Request. * @return bool|null|\WP_REST_Response|void The value returned by the action undertaken. * * TODO: Improve */ public function webhook(\WP_REST_Request $request) { $response = \json_decode($request->get_body()); /** * Handle webhooks with type and data */ if (isset($response->type) && isset($response->data)) { switch ($response->type) { case 'source_settings': return \YoastSEO_Vendor\WordProof\SDK\Helpers\OptionsHelper::set('settings', $response->data); case 'ping': $data = (object) ['status' => 200, 'source_id' => \YoastSEO_Vendor\WordProof\SDK\Helpers\OptionsHelper::sourceId()]; return new \WP_REST_Response($data, $data->status); case 'logout': \YoastSEO_Vendor\WordProof\SDK\Helpers\AuthenticationHelper::logout(); break; case 'dump_item': $key = '_wordproof_hash_input_' . $response->data->hash; \YoastSEO_Vendor\WordProof\SDK\Helpers\PostMetaHelper::update($response->data->uid, $key, \json_decode($response->data->hash_input)); $this->setBlockchainTransaction($response->data); break; case 'set_identity': try { (new \YoastSEO_Vendor\WordProof\SDK\Controllers\IdentityController())->store((array) $response->data); return new \WP_REST_Response(null, 201); } catch (\YoastSEO_Vendor\WordProof\SDK\Exceptions\ValidationException $e) { return new \WP_REST_Response(['message' => $e->getMessage()], 400); } case 'delete_identity': (new \YoastSEO_Vendor\WordProof\SDK\Controllers\IdentityController())->delete(); $data = (object) ['status' => 200, 'message' => 'success']; return new \WP_REST_Response($data, $data->status); default: break; } } /** * Handle timestamping webhooks without type */ if (isset($response->uid) && isset($response->schema)) { $this->setBlockchainTransaction($response); } } /** * @param $response * * TODO: Improve */ private function setBlockchainTransaction($response) { $postId = \intval($response->uid); $blockchainTransaction = \YoastSEO_Vendor\WordProof\SDK\Helpers\SchemaHelper::getBlockchainTransaction($response); \YoastSEO_Vendor\WordProof\SDK\Helpers\PostMetaHelper::add($postId, '_wordproof_blockchain_transaction', $blockchainTransaction); $schema = \YoastSEO_Vendor\WordProof\SDK\Helpers\SchemaHelper::getSchema($postId); \YoastSEO_Vendor\WordProof\SDK\Helpers\PostMetaHelper::update($postId, '_wordproof_schema', $schema); } /** * Checks if the user has permission to publish a post. * * @return bool Returns if a user has permission to publish. */ public function canPublishPermission() { return \current_user_can('publish_posts') && \current_user_can('publish_pages'); } /** * Validates if the webhook is valid and signed with the correct secret. * * @param \WP_REST_Request $request The Rest Request. * @return bool If the webhook can be accepted. */ public static function isValidWebhookRequest(\WP_REST_Request $request) { if (!\YoastSEO_Vendor\WordProof\SDK\Helpers\AuthenticationHelper::isAuthenticated()) { return \false; } $hashedToken = \hash('sha256', \YoastSEO_Vendor\WordProof\SDK\Helpers\OptionsHelper::accessToken()); $hmac = \hash_hmac('sha256', $request->get_body(), $hashedToken); return $request->get_header('signature') === $hmac; } } PK!Y#66Dwordproof/wordpress-sdk/app/Controllers/AuthenticationController.phpnu['; echo 'window.close();'; echo ''; } } PK!YDwordproof/wordpress-sdk/app/Controllers/PostEditorDataController.phpnu[translations = $translations; } /** * Add script for post edit pages. * * @param string $hook The current page. */ public function addScript($hook) { $loadWordProofData = \apply_filters('wordproof_load_data_on_pages', \YoastSEO_Vendor\WordProof\SDK\Helpers\PostEditorHelper::getPostEditPages()); if (\in_array($hook, $loadWordProofData, \true)) { $this->enqueueAndLocalizeScript(); } } /** * Localizes the elementor script. */ public function addScriptForElementor() { $this->enqueueAndLocalizeScript(); } /** * Enqueues and localizes data script. */ private function enqueueAndLocalizeScript() { $data = \YoastSEO_Vendor\WordProof\SDK\Helpers\PostEditorHelper::getPostEditorData($this->translations); $data = \apply_filters('wordproof_data', $data); \YoastSEO_Vendor\WordProof\SDK\Helpers\AssetHelper::enqueue('data'); \YoastSEO_Vendor\WordProof\SDK\Helpers\AssetHelper::localize('data', 'wordproofSdk', $data); } } PK!_ɋAwordproof/wordpress-sdk/app/Controllers/CertificateController.phpnu['; $schema .= "\n"; $schema .= ''; $schema .= "\n"; } $schema .= '"; $schema .= "\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo $schema; } /** * Adds the certificate tag to the content before rendering it. * * @param $content * @return mixed|string Content string from 'the_content' filter * @filter the_content */ public function certificateTag($content) { if (!\YoastSEO_Vendor\WordProof\SDK\Helpers\CertificateHelper::show()) { return $content; } if (\YoastSEO_Vendor\WordProof\SDK\Helpers\SettingsHelper::hideCertificateLink()) { return $content; } global $post; $identifier = $post->ID; $text = \YoastSEO_Vendor\WordProof\SDK\Helpers\SettingsHelper::certificateLinkText(); $showRevisions = \YoastSEO_Vendor\WordProof\SDK\Helpers\SettingsHelper::showRevisions() ? 'true' : 'false'; $debug = \YoastSEO_Vendor\WordProof\SDK\Helpers\EnvironmentHelper::development() ? 'true' : 'false'; $lastModified = \get_the_modified_date('c', $post->ID); $identity = \YoastSEO_Vendor\WordProof\SDK\Helpers\OptionsHelper::get('identity'); $identityProvider = isset($identity->provider) ? $identity->provider : ''; $identityName = (isset($identity->first_name) ? $identity->first_name : '') . ' ' . (isset($identity->last_name) ? $identity->last_name : ''); $identityProfilePicture = isset($identity->profile_picture) ? $identity->profile_picture : ''; $identityProofUrl = isset($identity->proof_url) ? $identity->proof_url : ''; $content .= "\n" . ''; $content .= "\n" . '

'; $content .= "\n"; return $content; } } PK!V;  <wordproof/wordpress-sdk/app/Controllers/NoticeController.phpnu[translations = $translations; } /** * Showing notices for the classic editor and delete them so they are only shown once. * * @action admin_notices */ public function show() { $screen = \get_current_screen(); if (!\in_array($screen->base, $this->screens, \true)) { return; } $notice = \YoastSEO_Vendor\WordProof\SDK\Helpers\TransientHelper::getOnce(\YoastSEO_Vendor\WordProof\SDK\Helpers\ClassicNoticeHelper::$transientKey); if (!isset($notice) || !$notice) { return; } switch ($notice) { case 'no_balance': $type = 'error'; $message = $this->translations->getNoBalanceNotice(); $buttonText = $this->translations->getOpenSettingsButtonText(); $buttonEventName = 'wordproof:open_settings'; break; case 'timestamp_success': $type = 'success'; $message = $this->translations->getTimestampSuccessNotice(); break; case 'timestamp_failed': $type = 'error'; $message = $this->translations->getTimestampFailedNotice(); break; case 'not_authenticated': $type = 'error'; $message = $this->translations->getNotAuthenticatedNotice(); $buttonText = $this->translations->getOpenAuthenticationButtonText(); $buttonEventName = 'wordproof:open_authentication'; break; default: break; } if (isset($message) && isset($type)) { $noticeClass = 'notice-' . $type; echo \sprintf('

%2$s

', \esc_attr($noticeClass), \esc_html($message)); if (isset($buttonText) && isset($buttonEventName)) { echo \sprintf('

', \esc_html($buttonText), \esc_attr($buttonEventName)); } echo '
'; } } } PK!+QQ>wordproof/wordpress-sdk/app/Controllers/SettingsController.phpnu[redirect($closeWindowUrl) === \false) { \do_action('wordproof_authenticate', $closeWindowUrl); } } } PK!?,wordproof/wordpress-sdk/app/WordPressSDK.phpnu[loader = new \YoastSEO_Vendor\WordProof\SDK\Support\Loader(); $this->appConfig = $appConfig ?: new \YoastSEO_Vendor\WordProof\SDK\Config\DefaultAppConfig(); $this->translations = $translations ?: new \YoastSEO_Vendor\WordProof\SDK\Translations\DefaultTranslations(); $this->authentication(); $this->api(); $this->timestamp(); $this->settings(); $this->postEditorData(); $this->notices(); if (!\defined('WORDPROOF_TIMESTAMP_SDK_FILE')) { \define('WORDPROOF_TIMESTAMP_SDK_FILE', __FILE__); } if (!\defined('WORDPROOF_TIMESTAMP_SDK_VERSION')) { \define('WORDPROOF_TIMESTAMP_SDK_VERSION', $this->version); } return $this; } /** * Singleton implementation of WordPress SDK. * * @param AppConfigInterface|null $appConfig * @param TranslationsInterface|null $translations * @return WordPressSDK|null Returns the WordPress SDK instance. * @throws \Exception */ public static function getInstance(\YoastSEO_Vendor\WordProof\SDK\Config\AppConfigInterface $appConfig = null, \YoastSEO_Vendor\WordProof\SDK\Translations\TranslationsInterface $translations = null) { if (self::$instance === null) { self::$instance = new \YoastSEO_Vendor\WordProof\SDK\WordPressSDK($appConfig, $translations); } return self::$instance; } /** * Runs the loader and initializes the class. * * @return $this */ public function initialize() { $this->loader->run(); return $this; } /** * Initializes the authentication feature. */ private function authentication() { $class = new \YoastSEO_Vendor\WordProof\SDK\Controllers\AuthenticationController(); $this->loader->addAction('wordproof_authenticate', $class, 'authenticate'); $this->loader->addAction('admin_menu', $class, 'addRedirectPage'); $this->loader->addAction('admin_menu', $class, 'addSelfDestructPage'); $this->loader->addAction('load-admin_page_wordproof-redirect-authenticate', $class, 'redirectOnLoad'); } /** * Initializes the api feature. */ private function api() { $class = new \YoastSEO_Vendor\WordProof\SDK\Controllers\RestApiController(); $this->loader->addAction('rest_api_init', $class, 'init'); } /** * Adds hooks to timestamp posts on new inserts or on a custom action. */ private function timestamp() { $class = new \YoastSEO_Vendor\WordProof\SDK\Controllers\TimestampController(); $this->loader->addAction('added_post_meta', $class, 'syncPostMetaTimestampOverrides', \PHP_INT_MAX, 4); $this->loader->addAction('updated_post_meta', $class, 'syncPostMetaTimestampOverrides', \PHP_INT_MAX, 4); $this->loader->addAction('rest_after_insert_post', $class, 'timestampAfterRestApiRequest'); $this->loader->addAction('wp_insert_post', $class, 'timestampAfterPostRequest', \PHP_INT_MAX, 2); $this->loader->addAction('edit_attachment', $class, 'timestampAfterAttachmentRequest', \PHP_INT_MAX); $this->loader->addAction('add_attachment', $class, 'timestampAfterAttachmentRequest', \PHP_INT_MAX); $this->loader->addAction('wordproof_timestamp', $class, 'timestamp'); $this->loader->addAction('elementor/document/before_save', $class, 'beforeElementorSave'); } /** * Adds admin pages that redirect to the WordProof My settings page. */ private function settings() { $class = new \YoastSEO_Vendor\WordProof\SDK\Controllers\SettingsController(); $this->loader->addAction('wordproof_settings', $class, 'redirect'); $this->loader->addAction('admin_menu', $class, 'addRedirectPage'); $this->loader->addAction('load-admin_page_wordproof-redirect-settings', $class, 'redirectOnLoad'); } /** * Registers and localizes post editor scripts. */ private function postEditorData() { $class = new \YoastSEO_Vendor\WordProof\SDK\Controllers\PostEditorDataController($this->translations); $this->loader->addAction('admin_enqueue_scripts', $class, 'addScript'); $this->loader->addAction('elementor/editor/before_enqueue_scripts', $class, 'addScriptForElementor'); } /** * Initializes the notices feature. */ private function notices() { $class = new \YoastSEO_Vendor\WordProof\SDK\Controllers\NoticeController($this->translations); $this->loader->addAction('admin_notices', $class, 'show'); } /** * Optional feature to include the schema and certificate to the page. * * @return $this */ public function certificate() { $class = new \YoastSEO_Vendor\WordProof\SDK\Controllers\CertificateController(); $this->loader->addAction('wp_head', $class, 'head'); $this->loader->addFilter('the_content', $class, 'certificateTag'); return $this; } /** * Optional feature to timestamp with JS in the post editor. * * @return $this */ public function timestampInPostEditor() { $class = new \YoastSEO_Vendor\WordProof\SDK\Controllers\PostEditorTimestampController(); // Gutenberg $this->loader->addAction('init', $class, 'registerPostMeta', \PHP_INT_MAX); $this->loader->addAction('enqueue_block_editor_assets', $class, 'enqueueBlockEditorScript'); // Classic editor $this->loader->addAction('add_meta_boxes', $class, 'addMetaboxToClassicEditor'); $this->loader->addAction('save_post', $class, 'saveClassicMetaboxPostMeta'); $this->loader->addAction('edit_attachment', $class, 'saveClassicMetaboxPostMeta'); $this->loader->addAction('admin_enqueue_scripts', $class, 'enqueueClassicEditorScript'); // Elementor $this->loader->addAction('elementor/editor/after_enqueue_scripts', $class, 'enqueueElementorEditorScript'); $this->loader->addAction('elementor/documents/register_controls', $class, 'registerControl'); $this->loader->addAction('elementor/editor/after_save', $class, 'elementorSave'); return $this; } } PK!v~n5wordproof/wordpress-sdk/app/Helpers/OptionsHelper.phpnu[ $optionValue) { $optionConfig = self::getOptionFromConfig($key . '.options.' . $optionKey); if (!$optionConfig) { continue; } if ($method === 'escape') { $securedValue = \YoastSEO_Vendor\WordProof\SDK\Helpers\EscapeHelper::escape($optionValue, $optionConfig['escape']); } else { $securedValue = \YoastSEO_Vendor\WordProof\SDK\Helpers\SanitizeHelper::sanitize($optionValue, $optionConfig['escape']); } $values[$optionKey] = $securedValue; } if ($isObject) { return (object) $values; } return $values; } return []; } } PK!WK..4wordproof/wordpress-sdk/app/Helpers/EscapeHelper.phpnu[ $value) { $values[$key] = self::escapeSingleValue($value, $escapeKey); } return $values; } /** * Escapes a single value using an escape function set in the class. * * @param string $value The value to be escaped. * @param string $escapeKey The escape function to be used. * @return bool|int|string The escaped value. */ private static function escapeSingleValue($value, $escapeKey) { switch ($escapeKey) { case 'integer': return \intval($value); case 'boolean': return \boolval($value); case 'html_class': return \esc_html_class($value); case 'email': return \esc_email($value); case 'url': return \esc_url_raw($value); case 'key': return \esc_key($value); case 'text_field': default: return \esc_html($value); } } } PK!'@y9wordproof/wordpress-sdk/app/Helpers/CertificateHelper.phpnu[ID, '_wordproof_schema'), $post); } } PK!I1TT<wordproof/wordpress-sdk/app/Helpers/AuthenticationHelper.phpnu[access_token && $options->source_id; } } PK!f+7wordproof/wordpress-sdk/app/Helpers/TransientHelper.phpnu[getWordProofUrl()) { return $appConfig->getWordProofUrl(); } return self::get('url'); } public static function client() { $appConfig = \YoastSEO_Vendor\WordProof\SDK\Helpers\AppConfigHelper::getAppConfig(); if ($appConfig->getOauthClient()) { return $appConfig->getOauthClient(); } return self::get('client'); } public static function sslVerify() { return !\YoastSEO_Vendor\WordProof\SDK\Helpers\EnvironmentHelper::development(); } public static function development() { return \YoastSEO_Vendor\WordProof\SDK\Helpers\AppConfigHelper::getEnvironment() === 'development'; } public static function get($key) { $envConfig = self::environmentConfig(); if ($envConfig && isset($envConfig[$key])) { return $envConfig[$key]; } return null; } private static function environmentConfig() { $env = \YoastSEO_Vendor\WordProof\SDK\Helpers\AppConfigHelper::getEnvironment(); return \YoastSEO_Vendor\WordProof\SDK\Config\EnvironmentConfig::get($env); } } PK!ROa4wordproof/wordpress-sdk/app/Helpers/SchemaHelper.phpnu[uid; $hashLink = \YoastSEO_Vendor\WordProof\SDK\Helpers\RestApiHelper::getRestRoute('hashInput', [$postId, $response->hash]); $identifier = null; if (isset($response->transaction)) { $transaction = $response->transaction; if (isset($transaction->transactionId)) { $identifier = $transaction->transactionId; } if (isset($transaction->tx)) { $identifier = $transaction->tx; } } return ['@type' => 'BlockchainTransaction', 'identifier' => $identifier, 'hash' => $response->hash, 'hashLink' => $hashLink, 'recordedIn' => ['@type' => 'Blockchain', 'name' => $response->transaction->blockchain]]; } /** * Retrieves the schema as array for a post. * * @param integer $postId The post id for which the schema should be returned. * @return array The schema as array. */ public static function getSchema($postId) { $transactions = \YoastSEO_Vendor\WordProof\SDK\Helpers\PostMetaHelper::get($postId, '_wordproof_blockchain_transaction', \false); $latest = \array_pop($transactions); if (\count($transactions) === 0) { return ['timestamp' => $latest]; } return ['timestamp' => \array_merge($latest, ['revisions' => \array_reverse($transactions)])]; } } PK!9j+ 3wordproof/wordpress-sdk/app/Helpers/AssetHelper.phpnu[getScriptsFileOverwrite()) { $url = $appConfig->getScriptsFileOverwrite(); } else { $url = \plugin_dir_url(WORDPROOF_TIMESTAMP_SDK_FILE); } $base = \YoastSEO_Vendor\WordProof\SDK\Helpers\StringHelper::lastReplace(self::$filePath, self::$buildPath, $url); return $base . $name . '.' . $extension; } /** * Returns version for file. * * @return false|string */ private static function getVersion() { return \YoastSEO_Vendor\WordProof\SDK\Helpers\EnvironmentHelper::development() ? \false : WORDPROOF_TIMESTAMP_SDK_VERSION; } } PK!x1ll;wordproof/wordpress-sdk/app/Helpers/ClassicNoticeHelper.phpnu[get_data()); if ($notice) { self::add($notice); } } /** * Retrieve notice key for the timestamp response data. * * @param object $data The timestamp response data. * @return string The notice key for this response data. */ private static function getNoticeKeyForTimestampResponse($data) { if (isset($data->error) && $data->error === 'not_authenticated') { return 'not_authenticated'; } if (isset($data->balance) && $data->balance === 0) { return 'no_balance'; } if (isset($data->hash)) { return 'timestamp_success'; } if (isset($data->error) && $data->error === 'timestamp_failed') { return 'timestamp_failed'; } return null; } } PK!}+/}}6wordproof/wordpress-sdk/app/Helpers/SanitizeHelper.phpnu[ $value) { $values[$key] = self::sanitizeSingleValue($value, $sanitizeKey); } return $values; } /** * Sanitize a single value using an escape function set in the class. * * @param string $value The value to be sanitized. * @param string $sanitizeKey The sanitize function to be used. * @return bool|int|string The sanitized value. */ private static function sanitizeSingleValue($value, $sanitizeKey) { switch ($sanitizeKey) { case 'integer': return \intval($value); case 'boolean': return \boolval($value); case 'html_class': return \sanitize_html_class($value); case 'email': return \sanitize_email($value); case 'url': return \esc_url_raw($value); case 'key': return \sanitize_key($value); case 'text_field': default: return \sanitize_text_field($value); } } } PK!6wordproof/wordpress-sdk/app/Helpers/PostTypeHelper.phpnu[ \true])); } public static function getUnprotectedPosts($postType) { $query = ['post_type' => [$postType], 'fields' => 'ids', 'posts_per_page' => -1, 'post_status' => ['publish', 'inherit'], 'meta_query' => [['key' => '_wordproof_blockchain_transaction', 'compare' => 'NOT EXISTS']]]; $query = new \WP_Query($query); return ['count' => $query->found_posts, 'postIds' => $query->posts]; } } PK!b8wordproof/wordpress-sdk/app/Helpers/PostEditorHelper.phpnu[base)) { return null; } // Start with Elementor, otherwise the block editor will be returned. $action = \filter_input(\INPUT_GET, 'action', \FILTER_SANITIZE_STRING); if ($action === 'elementor') { return 'elementor'; } if (\method_exists($screen, 'is_block_editor') && $screen->is_block_editor()) { return 'block'; } return 'classic'; } /** * Returns if the page is a post edit page. * * @param string $page The page to check. * @return bool If the current page is a post edit page. */ public static function isPostEdit($page) { return \in_array($page, self::getPostEditPages(), \true); } /** * Returns an array of edit page hooks. * * @return array Post edit page hooks. */ public static function getPostEditPages() { return ['post.php', 'post', 'post-new.php', 'post-new']; } /** * Returns the data that should be added to the post editor. * * @param TranslationsInterface $translations The implemented translations interface. * * @return array[] The post editor data. */ public static function getPostEditorData(\YoastSEO_Vendor\WordProof\SDK\Translations\TranslationsInterface $translations) { global $post; $postId = isset($post->ID) ? $post->ID : null; $postType = isset($post->post_type) ? $post->post_type : null; $translations = ['no_balance' => $translations->getNoBalanceNotice(), 'timestamp_success' => $translations->getTimestampSuccessNotice(), 'timestamp_failed' => $translations->getTimestampFailedNotice(), 'webhook_failed' => $translations->getWebhookFailedNotice(), 'not_authenticated' => $translations->getNotAuthenticatedNotice(), 'open_authentication_button_text' => $translations->getOpenAuthenticationButtonText(), 'open_settings_button_text' => $translations->getOpenSettingsButtonText(), 'contact_wordproof_support_button_text' => $translations->getContactWordProofSupportButtonText()]; return ['data' => ['origin' => \YoastSEO_Vendor\WordProof\SDK\Helpers\EnvironmentHelper::url(), 'is_authenticated' => \YoastSEO_Vendor\WordProof\SDK\Helpers\AuthenticationHelper::isAuthenticated(), 'popup_redirect_authentication_url' => \admin_url('admin.php?page=wordproof-redirect-authenticate'), 'popup_redirect_settings_url' => \admin_url('admin.php?page=wordproof-redirect-settings'), 'settings' => \YoastSEO_Vendor\WordProof\SDK\Helpers\SettingsHelper::get(), 'current_post_id' => $postId, 'current_post_type' => $postType, 'post_editor' => self::getPostEditor(), 'translations' => $translations, 'balance' => \YoastSEO_Vendor\WordProof\SDK\Helpers\OptionsHelper::get('balance')]]; } /** * Returns the current post type. * * @return null|string The current post type. */ public static function getCurrentPostType() { global $post, $typenow, $current_screen; if ($post && $post->post_type) { return $post->post_type; } if ($typenow) { return $typenow; } if ($current_screen && $current_screen->post_type) { return $current_screen->post_type; } // phpcs:disable WordPress.Security.NonceVerification if (isset($_REQUEST['post_type'])) { return \sanitize_key($_REQUEST['post_type']); } // phpcs:enable WordPress.Security.NonceVerification return null; } } PK!Ep6wordproof/wordpress-sdk/app/Helpers/SettingsHelper.phpnu[{$setting}) && $option) { return $settings->{$setting}; } return $option['default']; } return (object) $settings; } public static function showRevisions() { return self::get('show_revisions'); } public static function certificateLinkText() { return self::get('certificate_link_text'); } public static function hideCertificateLink() { return self::get('hide_certificate_link'); } public static function selectedPostTypes() { return \apply_filters('wordproof_timestamp_post_types', self::get('selected_post_types')); } public static function postTypeIsInSelectedPostTypes($postType) { $postTypes = self::selectedPostTypes(); return \in_array($postType, $postTypes, \true); } } PK!]%d~~5wordproof/wordpress-sdk/app/Helpers/RestApiHelper.phpnu[ $match) { $url = \str_replace($match, $params[$index], $url); } return $url; } } PK!.A 7wordproof/wordpress-sdk/app/Helpers/TimestampHelper.phpnu[id; $data = \YoastSEO_Vendor\WordProof\SDK\DataTransferObjects\TimestampData::fromPost($post); $transient = \YoastSEO_Vendor\WordProof\SDK\Helpers\TransientHelper::get($key); if ($transient) { return new \WP_REST_Response($transient, $transient->status); } $response = self::shouldBeTimestamped($post, $data); if (\is_bool($response) && $response === \false) { $response = (object) ['status' => 200, 'message' => 'Post should not be timestamped']; return new \WP_REST_Response($response, $response->status); } if (\is_array($response) && $response['timestamp'] === \false) { $response = (object) ['status' => 400, 'message' => 'Post should not be timestamped', 'error' => 'not_authenticated']; return new \WP_REST_Response($response, $response->status); } $response = \YoastSEO_Vendor\WordProof\SDK\Support\Timestamp::sendPostRequest($data); if ($response === \false) { $response = (object) ['status' => 400, 'message' => 'Something went wrong.', 'error' => 'timestamp_failed']; return new \WP_REST_Response($response, $response->status); } $response->status = 201; \YoastSEO_Vendor\WordProof\SDK\Helpers\TransientHelper::set($key, $response, 5); return new \WP_REST_Response($response, $response->status); } public static function shouldBeTimestamped(\WP_Post $post, $data) { if (!\YoastSEO_Vendor\WordProof\SDK\Helpers\AuthenticationHelper::isAuthenticated()) { if (self::hasPostMetaOverrideSetToTrue($post)) { return ['timestamp' => \false, 'notice' => 'not_authenticated']; } return \false; } if ($post->post_type !== 'attachment' && $post->post_content === '') { return \false; } if ($post->post_type === 'attachment' && \get_attached_file($post->ID) === \false) { return \false; } if (!\in_array($post->post_status, ['publish', 'inherit'], \true)) { return \false; } if (\YoastSEO_Vendor\WordProof\SDK\Helpers\SettingsHelper::postTypeIsInSelectedPostTypes($post->post_type)) { return \true; } if (self::hasPostMetaOverrideSetToTrue($post)) { return \true; } return \false; } private static function hasPostMetaOverrideSetToTrue(\WP_Post $post) { $timestampablePostMetaKeys = \apply_filters('wordproof_timestamp_post_meta_key_overrides', ['_wordproof_timestamp']); //Do not use PostMeta helper $meta = \get_post_meta($post->ID); foreach ($timestampablePostMetaKeys as $key) { if (!isset($meta[$key])) { continue; } if (\is_array($meta[$key])) { $value = \boolval($meta[$key][0]); } else { $value = \boolval($meta[$key]); } if (!$value) { continue; } return \true; } return \false; } } PK!yss6wordproof/wordpress-sdk/app/Helpers/PostMetaHelper.phpnu[getName(); } return \false; } } PK!3TJJ6wordproof/wordpress-sdk/app/Helpers/RedirectHelper.phpnu[getPartner(); } return null; } /** * Returns the environment set during initialization. * @return string|null */ public static function getEnvironment() { $appConfig = self::getAppConfig(); if ($appConfig) { return $appConfig->getEnvironment(); } return null; } /** * Returns the environment set during initialization. * @return boolean */ public static function getLoadUikitFromCdn() { $appConfig = self::getAppConfig(); if ($appConfig) { return $appConfig->getLoadUikitFromCdn(); } return null; } public static function getAppConfig() { $sdk = \YoastSEO_Vendor\WordProof\SDK\WordPressSDK::getInstance(); if ($sdk) { return $sdk->appConfig; } return null; } } PK!;Bwordproof/wordpress-sdk/app/Translations/TranslationsInterface.phpnu[post_type === 'attachment') { $file = \get_attached_file($post->ID); $content = ''; if ($file) { $content = \hash_file('sha256', $file); } } else { $content = $post->post_content; } return ['uid' => $post->ID, 'date_modified' => \get_post_modified_time('c', \false, $post->ID), 'title' => $post->post_title, 'url' => \get_permalink($post), 'content' => $content]; } } PK!L7B B .wordproof/wordpress-sdk/app/Support/Loader.phpnu[actions = []; $this->filters = []; } /** * @param string $hook The name of the WordPress action that is being registered. * @param object $component A reference to the instance of the object on which the action is defined. * @param string $callback The name of the function definition on the $component. * @param int $priority Optional. The priority at which the function should be fired. Default is 10. * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1. */ public function addAction($hook, $component, $callback, $priority = 10, $accepted_args = 1) { $this->actions = $this->add($this->actions, $hook, $component, $callback, $priority, $accepted_args); } /** * @param string $hook The name of the WordPress filter that is being registered. * @param object $component A reference to the instance of the object on which the filter is defined. * @param string $callback The name of the function definition on the $component. * @param int $priority Optional. The priority at which the function should be fired. Default is 10. * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1 */ public function addFilter($hook, $component, $callback, $priority = 10, $accepted_args = 1) { $this->filters = $this->add($this->filters, $hook, $component, $callback, $priority, $accepted_args); } public function run() { foreach ($this->filters as $hook) { \add_filter($hook['hook'], [$hook['component'], $hook['callback']], $hook['priority'], $hook['accepted_args']); } foreach ($this->actions as $hook) { \add_action($hook['hook'], [$hook['component'], $hook['callback']], $hook['priority'], $hook['accepted_args']); } } private function add($hooks, $hook, $component, $callback, $priority, $accepted_args) { $hooks[] = ['hook' => $hook, 'component' => $component, 'callback' => $callback, 'priority' => $priority, 'accepted_args' => $accepted_args]; return $hooks; } } PK!s>C6wordproof/wordpress-sdk/app/Support/Authentication.phpnu[ \YoastSEO_Vendor\WordProof\SDK\Helpers\EnvironmentHelper::client(), 'redirect_uri' => self::getCallbackUrl(), 'response_type' => 'code', 'scope' => '', 'state' => $state, 'code_challenge' => $codeChallenge, 'code_challenge_method' => 'S256', 'partner' => \YoastSEO_Vendor\WordProof\SDK\Helpers\AppConfigHelper::getPartner()]; /** * Login with user if v2 plugin data exist. */ $accessToken = \YoastSEO_Vendor\WordProof\SDK\Helpers\TransientHelper::get('wordproof_v2_authenticate_with_token'); $sourceId = \YoastSEO_Vendor\WordProof\SDK\Helpers\TransientHelper::get('wordproof_v2_get_existing_source'); if ($accessToken && $sourceId) { $data = \array_merge($data, ['access_token_login' => $accessToken, 'source_id' => $sourceId]); } else { $data = \array_merge($data, ['confirm_account' => \true]); } self::redirect('/wordpress-sdk/authorize', $data); } /** * Retrieve the access token with the state and code. * * @param string $state The state from remote * @param string $code The code from remote * @return \WP_REST_Response * @throws \Exception */ public static function token($state, $code) { $localState = \YoastSEO_Vendor\WordProof\SDK\Helpers\TransientHelper::getOnce('wordproof_authorize_state'); $codeVerifier = \YoastSEO_Vendor\WordProof\SDK\Helpers\TransientHelper::getOnce('wordproof_authorize_code_verifier'); if (\strlen($localState) <= 0 || $localState !== $state) { throw new \Exception('WordProof: No state found.'); } $data = ['grant_type' => 'authorization_code', 'client_id' => \YoastSEO_Vendor\WordProof\SDK\Helpers\EnvironmentHelper::client(), 'redirect_uri' => self::getCallbackUrl(), 'code_verifier' => $codeVerifier, 'code' => $code]; $response = \YoastSEO_Vendor\WordProof\SDK\Support\Api::post('/api/wordpress-sdk/token', $data); if (isset($response->error) && $response->error === 'invalid_grant') { $data = (object) ['status' => 401, 'message' => 'invalid_grant']; return new \WP_REST_Response($data, $data->status); } if (!isset($response->access_token)) { $data = (object) ['status' => 401, 'message' => 'no_access_token']; return new \WP_REST_Response($data, $data->status); } \YoastSEO_Vendor\WordProof\SDK\Helpers\OptionsHelper::setAccessToken($response->access_token); $data = ['webhook_url' => \get_rest_url(null, 'wordproof/v1/webhook'), 'url' => \get_site_url(), 'available_post_types' => \YoastSEO_Vendor\WordProof\SDK\Helpers\PostTypeHelper::getPublicPostTypes(), 'partner' => \YoastSEO_Vendor\WordProof\SDK\Helpers\AppConfigHelper::getPartner(), 'local_settings' => (array) \YoastSEO_Vendor\WordProof\SDK\Helpers\SettingsHelper::get()]; /** * Use existing source if user was authenticated in v2 of the plugin. */ $sourceId = \YoastSEO_Vendor\WordProof\SDK\Helpers\TransientHelper::getOnce('wordproof_v2_get_existing_source'); if ($sourceId) { $data = \array_merge($data, ['source_id' => \intval($sourceId)]); } $response = \YoastSEO_Vendor\WordProof\SDK\Support\Api::post('/api/wordpress-sdk/source', $data); \YoastSEO_Vendor\WordProof\SDK\Helpers\OptionsHelper::setSourceId($response->source_id); $data = (object) ['status' => 200, 'message' => 'authentication_success', 'source_id' => \YoastSEO_Vendor\WordProof\SDK\Helpers\OptionsHelper::get('source_id'), 'is_authenticated' => \YoastSEO_Vendor\WordProof\SDK\Helpers\AuthenticationHelper::isAuthenticated()]; return new \WP_REST_Response($data, $data->status); } private static function getCallbackUrl() { return \get_rest_url(null, self::$callbackEndpoint); } public static function redirect($endpoint, $parameters) { $location = \YoastSEO_Vendor\WordProof\SDK\Helpers\EnvironmentHelper::url() . $endpoint . '?' . \http_build_query($parameters); \header("Location: " . $location); } } PK!H ZZ0wordproof/wordpress-sdk/app/Support/Settings.phpnu[source_id) { return \false; } $endpoint = "/sources/" . $options->source_id . "/settings"; if (\YoastSEO_Vendor\WordProof\SDK\Helpers\AppConfigHelper::getPartner() === 'yoast') { $endpoint = '/yoast/dashboard'; } \YoastSEO_Vendor\WordProof\SDK\Support\Authentication::redirect($endpoint, ['redirect_uri' => $redirectUrl, 'partner' => \YoastSEO_Vendor\WordProof\SDK\Helpers\AppConfigHelper::getPartner(), 'source_id' => $options->source_id, 'access_token_login' => $options->access_token]); } } PK!;WRd0wordproof/wordpress-sdk/app/Support/Template.phpnu[ $optionValue) { if (\property_exists(__CLASS__, $optionName)) { self::${$optionName} = $optionValue; } } } public static function setCachePath($path) { self::$cache_path = $path; } public static function setTemplatePath($path) { self::$template_path = $path; } public static function render($file, $data = []) { \ob_start(); self::view($file, $data); return \ob_get_contents(); } public static function view($file, $data = []) { if (self::$store_cache) { $cached_file = self::cache($file); \extract($data, \EXTR_SKIP); require $cached_file; } else { $code = self::includeFiles($file); $code = self::compileCode($code); $code = '?>' . \PHP_EOL . $code . \PHP_EOL . "' . \PHP_EOL . $code); } return $cached_file; } public static function clearCache() { foreach (\glob(self::$cache_path . '*') as $file) { \unlink($file); } } private static function compileCode($code) { $code = self::compileBlock($code); $code = self::compileYield($code); $code = self::compileEscapedEchos($code); $code = self::compileEchos($code); $code = self::compilePHP($code); return $code; } private static function includeFiles($file) { $code = \file_get_contents(self::$template_path . $file); \preg_match_all('/{% ?(extends|include) ?\'?(.*?)\'? ?%}/i', $code, $matches, \PREG_SET_ORDER); foreach ($matches as $value) { $code = \str_replace($value[0], self::includeFiles($value[2]), $code); } $code = \preg_replace('/{% ?(extends|include) ?\'?(.*?)\'? ?%}/i', '', $code); return $code; } private static function compilePHP($code) { return \preg_replace('~{%\\s*(.+?)\\s*%}~is', '', $code); } private static function compileEchos($code) { return \preg_replace('~{{\\s*(.+?)\\s*}}~is', '', $code); } private static function compileEscapedEchos($code) { return \preg_replace('~{{{\\s*(.+?)\\s*}}}~is', '', $code); } private static function compileBlock($code) { \preg_match_all('/{% ?block ?(.*?) ?%}(.*?){% ?endblock ?%}/is', $code, $matches, \PREG_SET_ORDER); foreach ($matches as $value) { if (!\array_key_exists($value[1], self::$blocks)) { self::$blocks[$value[1]] = ''; } if (\strpos($value[2], '@parent') === \false) { self::$blocks[$value[1]] = $value[2]; } else { self::$blocks[$value[1]] = \str_replace('@parent', self::$blocks[$value[1]], $value[2]); } $code = \str_replace($value[0], '', $code); } return $code; } private static function compileYield($code) { foreach (self::$blocks as $block => $value) { $code = \preg_replace('/{% ?yield ?' . $block . ' ?%}/', $value, $code); } $code = \preg_replace('/{% ?yield ?(.*?) ?%}/i', '', $code); return $code; } } PK!-0ܡ1wordproof/wordpress-sdk/app/Support/Timestamp.phpnu[hash)) { // AuthenticationHelper::logout(); // TODO Only if response is unauthenticated return \false; } if (isset($response->balance)) { \YoastSEO_Vendor\WordProof\SDK\Helpers\OptionsHelper::set('balance', $response->balance); } $key = '_wordproof_hash_input_' . $response->hash; \YoastSEO_Vendor\WordProof\SDK\Helpers\PostMetaHelper::update($data['uid'], $key, \json_decode($response->hash_input)); return $response; } } PK!1@'"+wordproof/wordpress-sdk/app/Support/Api.phpnu[ 'application/json', 'Accept' => 'application/json']; $headers = $accessToken ? \array_merge($headers, ['Authorization' => 'Bearer ' . $accessToken]) : $headers; $options = ['body' => $body, 'headers' => $headers, 'timeout' => 60, 'redirection' => 5, 'blocking' => \true, 'data_format' => 'body', 'sslverify' => \YoastSEO_Vendor\WordProof\SDK\Helpers\EnvironmentHelper::sslVerify()]; $request = \wp_remote_post($location, $options); $status = \wp_remote_retrieve_response_code($request); if ($status < 200 || $status >= 300) { return \false; } return \json_decode(\wp_remote_retrieve_body($request)); } } PK!՘%wordproof/wordpress-sdk/build/data.jsnu[!function(){"use strict";var e={n:function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,{a:n}),n},d:function(t,n){for(var s in n)e.o(n,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:n[s]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}},t=window.wp.apiFetch,n=e.n(t);const{get:s}=lodash,c=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return s(window,"wordproofSdk.data"+(e?`.${e}`:""),t)},{createReduxStore:a,registerStore:r,register:o}=wp.data,d="wordproof",i={isAuthenticated:c("is_authenticated",!1),balance:c("balance",0),selectedPostTypes:c("settings.selected_post_types",[])},u={setIsAuthenticated:e=>({type:"SET_IS_AUTHENTICATED",isAuthenticated:e}),getIsAuthenticated:()=>({type:"GET_IS_AUTHENTICATED"}),setBalance:e=>({type:"SET_BALANCE",balance:e}),getBalance:()=>({type:"GET_BALANCE"}),setSelectedPostTypes:e=>({type:"SET_SELECTED_POST_TYPES",selectedPostTypes:e}),getSelectedPostTypes:()=>({type:"GET_SELECTED_POST_TYPES"})},T={reducer:function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:i,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"SET_IS_AUTHENTICATED":return{...e,isAuthenticated:t.isAuthenticated};case"SET_BALANCE":return{...e,balance:t.balance};case"SET_SELECTED_POST_TYPES":return{...e,selectedPostTypes:t.selectedPostTypes};default:return e}},controls:{fetchIsAuthenticated:e=>n()({path:e.path})},selectors:{getIsAuthenticated(e){const{isAuthenticated:t}=e;return t},getBalance(e){const{balance:t}=e;return t},getSelectedPostTypes(e){const{selectedPostTypes:t}=e;return t}},resolvers:{*fetchIsAuthenticated(){const e=yield u.getIsAuthenticated();return u.setIsAuthenticated(e)}},actions:u};a?o(a(d,T)):r(d,T)}();PK!9wordproof/wordpress-sdk/build/wordproof-classic-editor.jsnu[!function(){var t={703:function(t,e,o){"use strict";var n=o(414);function r(){}function a(){}a.resetWarningCache=r,t.exports=function(){function t(t,e,o,r,a,i){if(i!==n){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function e(){return t}t.isRequired=t;var o={array:t,bigint:t,bool:t,func:t,number:t,object:t,string:t,symbol:t,any:t,arrayOf:e,element:t,elementType:t,instanceOf:e,node:t,objectOf:e,oneOf:e,oneOfType:e,shape:e,exact:e,checkPropTypes:a,resetWarningCache:r};return o.PropTypes=o,o}},697:function(t,e,o){t.exports=o(703)()},414:function(t){"use strict";t.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"}},e={};function o(n){var r=e[n];if(void 0!==r)return r.exports;var a=e[n]={exports:{}};return t[n](a,a.exports,o),a.exports}o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,{a:e}),e},o.d=function(t,e){for(var n in e)o.o(e,n)&&!o.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},function(){"use strict";var t=window.wp.element,e=window.wp.apiFetch,n=o.n(e);async function r(t,e,o){let n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:200;try{const r=await t();return!!r&&(r.status===n?e(r):o(r))}catch(t){}}async function a(t){try{return await n()(t)}catch(t){return t.error&&t.status?t:t instanceof window.Response&&await t.json()}}const i=async()=>await r((async()=>await(async()=>await a({path:"wordproof/v1/oauth/destroy",method:"POST"}))()),(t=>t),(()=>!1)),{get:s}=lodash,c=function(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return s(window,"wordproofSdk.data"+(t?`.${t}`:""),e)};function d(t){const e=new window.CustomEvent(t);window.dispatchEvent(e)}function p(){d("wordproof:open_authentication")}const{dispatch:u}=wp.data;var w=o(697),f=o.n(w);const{__:__}=wp.i18n,{useCallback:l}=wp.element,{withSelect:h}=wp.data,{compose:y}=wp.compose,g=e=>{const{isAuthenticated:o}=e,n=c("popup_redirect_authentication_url"),r=c("popup_redirect_settings_url"),a=l((t=>{t.preventDefault(),d("wordproof:open_settings")})),i=l((t=>{t.preventDefault(),p()}));return(0,t.createElement)(t.Fragment,null,o&&(0,t.createElement)("a",{href:r,onClick:a},__("Open settings","wordproof")),!o&&(0,t.createElement)("a",{href:n,onClick:i},__("Open authentication","wordproof")))};g.proptypes={isAuthenticated:f().bool.isRequired};var _=y([h((t=>({isAuthenticated:t("wordproof").getIsAuthenticated()})))])(g);const{render:v}=wp.element,{select:b,subscribe:m}=wp.data;(function(){const{setIsAuthenticated:t,setSelectedPostTypes:e}=u("wordproof"),o=c("popup_redirect_authentication_url"),n=c("popup_redirect_settings_url");let s=null;const p=(t,e)=>{s=function(t,e){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:800,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:680;const a=t.top.outerHeight/2+t.top.screenY-r/2,i=t.top.outerWidth/2+t.top.screenX-n/2;return t.open(e,o,`toolbar=no,\n\t\tlocation=no,\n\t\tdirectories=no,\n\t\tstatus=no,\n\t\tmenubar=no,\n\t\tresizable=no,\n\t\tcopyhistory=no,\n\t\twidth=${n},\n\t\theight=${r},\n\t\ttop=${a},\n\t\tleft=${i}`)}(window,t,e),s&&s.focus(),window.addEventListener("message",w,!1)},w=async t=>{const{data:e,source:o,origin:n}=t;if(n===c("origin")&&s===o)switch(e.type){case"wordproof:oauth:granted":!1===await h(e)&&await f("wordproof:oauth:failed",!1);break;case"wordproof:oauth:failed":await f("wordproof:oauth:failed",!1);break;case"wordproof:oauth:denied":await f("wordproof:oauth:denied",!1);break;case"wordproof:oauth:invalid_token":await f("wordproof:oauth:invalid_token",!1);break;case"wordproof:webhook:success":await f("wordproof:oauth:success",!0);break;case"wordproof:webhook:failed":await f("wordproof:webhook:failed",!1);break;case"wordproof:settings:updated":await f("wordproof:settings:updated"),await y(e);break;case"wordproof:oauth:destroy":await f("wordproof:oauth:destroy",!1);break;case"wordproof:oauth:retry":await f("wordproof:open_authentication",!1);break;case"wordproof:oauth:close":l()}},f=async function(e){let o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;l(),d(e),!1===o&&(await i(),t(!1)),!0===o&&t(!0)},l=()=>{window.removeEventListener("message",w,!1),s.close()},h=async t=>{await r((()=>(async t=>{const{state:e,code:o}=t;return await a({path:"wordproof/v1/oauth/authenticate",method:"POST",data:{state:e,code:o}})})(t)),(async t=>{const e={type:"wordproof:sdk:access-token",source_id:t.source_id};return s.postMessage(e,c("origin")),!0}),(async()=>!1))},y=async t=>{await r((()=>(async t=>{const{settings:e}=t;return await a({path:"wordproof/v1/settings",method:"POST",data:{settings:e}})})(t)),(async()=>{const o=t.settings;return o.selectedPostTypes&&e(o.selectedPostTypes),!0}),(async()=>!1))};window.addEventListener("wordproof:open_authentication",(t=>{t.preventDefault(),p(o,"WordProof_Authentication")}),!1),window.addEventListener("wordproof:open_settings",(t=>{t.preventDefault(),p(n,"WordProof_Settings")}),!1)})(),window.addEventListener("DOMContentLoaded",(e=>{O=document.querySelector("#_wordproof_timestamp"),E=O.checked,O&&(P=document.querySelector("#wordproof-action-link"),P&&v((0,t.createElement)(_,null),P),T(S()),m((()=>{T(S())})),O.addEventListener("change",(t=>{!b("wordproof").getIsAuthenticated()&&O.checked&&p()})))}));const k=c("current_post_type");let O=null,E=null,P=null;function T(t){t.includes(k)?(O.disabled=!0,O.checked=!0):(O.disabled=!1,O.checked=E)}function S(){return b("wordproof").getSelectedPostTypes()}}()}();PK!yrr;wordproof/wordpress-sdk/build/wordproof-elementor-editor.jsnu[!function(){var t={703:function(t,o,e){"use strict";var n=e(414);function a(){}function r(){}r.resetWarningCache=a,t.exports=function(){function t(t,o,e,a,r,s){if(s!==n){var i=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw i.name="Invariant Violation",i}}function o(){return t}t.isRequired=t;var e={array:t,bigint:t,bool:t,func:t,number:t,object:t,string:t,symbol:t,any:t,arrayOf:o,element:t,elementType:t,instanceOf:o,node:t,objectOf:o,oneOf:o,oneOfType:o,shape:o,exact:o,checkPropTypes:r,resetWarningCache:a};return e.PropTypes=e,e}},697:function(t,o,e){t.exports=e(703)()},414:function(t){"use strict";t.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"}},o={};function e(n){var a=o[n];if(void 0!==a)return a.exports;var r=o[n]={exports:{}};return t[n](r,r.exports,e),r.exports}e.n=function(t){var o=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(o,{a:o}),o},e.d=function(t,o){for(var n in o)e.o(o,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:o[n]})},e.o=function(t,o){return Object.prototype.hasOwnProperty.call(t,o)},function(){"use strict";var t=window.wp.apiFetch,o=e.n(t);async function n(t,o,e){let n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:200;try{const a=await t();return!!a&&(a.status===n?o(a):e(a))}catch(t){}}async function a(t){try{return await o()(t)}catch(t){return t.error&&t.status?t:t instanceof window.Response&&await t.json()}}const r=async()=>await n((async()=>await s()),(t=>t),(()=>!1)),s=async()=>await a({path:"wordproof/v1/oauth/destroy",method:"POST"}),{get:i}=lodash,c=function(t){let o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return i(window,"wordproofSdk.data"+(t?`.${t}`:""),o)};var d=e(697),p=e.n(d);function u(t){const o=new window.CustomEvent(t);window.dispatchEvent(o)}const w=t=>{const{response:o,createSuccessNotice:e,createErrorNotice:n,postId:a}=t;if(null===o||200===o.status)return;const r={id:"wordproof-timestamp-notice"};o&&201===o.status?0===o.balance?(r.actions=[{label:c("translations.open_settings_button_text"),onClick:()=>{u("wordproof:open_settings")},variant:"link"}],n(c("translations.no_balance"),r)):(e(c("translations.timestamp_success"),{type:"snackbar",id:"wordproof-timestamp-notice"}),f(a,o.hash,n,r)):o.error&&("not_authenticated"===o.error?(r.type="snackbar",r.actions=[{label:c("translations.open_authentication_button_text"),onClick:()=>{u("wordproof:open_authentication")},variant:"link"}],n(c("translations.not_authenticated"),r)):n(c("translations.timestamp_failed"),r))},f=async(t,o,e,n)=>{setTimeout((async()=>{const r=await(async t=>a({path:`wordproof/v1/posts/${t}/timestamp/transaction/latest`,method:"GET"}))(t);r.hash!==o&&(n.type="snackbar",e(c("translations.webhook_failed"),n))}),1e4)};w.proptypes={timestampResponse:p().any.isRequired,createSuccessNotice:p().func.isRequired,createErrorNotice:p().func.isRequired,postId:p().number.isRequired};const{debounce:l}=lodash,{applyFilters:h}=wp.hooks;const{dispatch:y}=wp.data;$e.modules.hookUI.Base;class m extends $e.modules.hookData.Base{constructor(t,o,e){super(),this.hook=t,this.id=o,this.callback=e}getCommand(){return this.hook}getId(){return this.id}apply(){return this.callback()}}function b(t,o){let e=null;o.actions&&(e=[],o.actions.forEach((t=>{e.push({name:"wordproof_notice_button",text:t.label,callback(){t.onClick()}})}))),window.elementor.notifications.showToast({message:t,buttons:e})}(function(){const{setIsAuthenticated:t,setSelectedPostTypes:o}=y("wordproof"),e=c("popup_redirect_authentication_url"),s=c("popup_redirect_settings_url");let i=null;const d=(t,o)=>{i=function(t,o){let e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:800,a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:680;const r=t.top.outerHeight/2+t.top.screenY-a/2,s=t.top.outerWidth/2+t.top.screenX-n/2;return t.open(o,e,`toolbar=no,\n\t\tlocation=no,\n\t\tdirectories=no,\n\t\tstatus=no,\n\t\tmenubar=no,\n\t\tresizable=no,\n\t\tcopyhistory=no,\n\t\twidth=${n},\n\t\theight=${a},\n\t\ttop=${r},\n\t\tleft=${s}`)}(window,t,o),i&&i.focus(),window.addEventListener("message",p,!1)},p=async t=>{const{data:o,source:e,origin:n}=t;if(n===c("origin")&&i===e)switch(o.type){case"wordproof:oauth:granted":!1===await l(o)&&await w("wordproof:oauth:failed",!1);break;case"wordproof:oauth:failed":await w("wordproof:oauth:failed",!1);break;case"wordproof:oauth:denied":await w("wordproof:oauth:denied",!1);break;case"wordproof:oauth:invalid_token":await w("wordproof:oauth:invalid_token",!1);break;case"wordproof:webhook:success":await w("wordproof:oauth:success",!0);break;case"wordproof:webhook:failed":await w("wordproof:webhook:failed",!1);break;case"wordproof:settings:updated":await w("wordproof:settings:updated"),await h(o);break;case"wordproof:oauth:destroy":await w("wordproof:oauth:destroy",!1);break;case"wordproof:oauth:retry":await w("wordproof:open_authentication",!1);break;case"wordproof:oauth:close":f()}},w=async function(o){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;f(),u(o),!1===e&&(await r(),t(!1)),!0===e&&t(!0)},f=()=>{window.removeEventListener("message",p,!1),i.close()},l=async t=>{await n((()=>(async t=>{const{state:o,code:e}=t;return await a({path:"wordproof/v1/oauth/authenticate",method:"POST",data:{state:o,code:e}})})(t)),(async t=>{const o={type:"wordproof:sdk:access-token",source_id:t.source_id};return i.postMessage(o,c("origin")),!0}),(async()=>!1))},h=async t=>{await n((()=>(async t=>{const{settings:o}=t;return await a({path:"wordproof/v1/settings",method:"POST",data:{settings:o}})})(t)),(async()=>{const e=t.settings;return e.selectedPostTypes&&o(e.selectedPostTypes),!0}),(async()=>!1))};window.addEventListener("wordproof:open_authentication",(t=>{t.preventDefault(),d(e,"WordProof_Authentication")}),!1),window.addEventListener("wordproof:open_settings",(t=>{t.preventDefault(),d(s,"WordProof_Settings")}),!1)})(),function(t,o,e){t(l((async()=>{if(h("wordproof.timestamp",!0)){const t=c("current_post_id"),n=await(async t=>a({path:`wordproof/v1/posts/${t}/timestamp`,method:"POST"}))(t);w({response:n,createSuccessNotice:o,createErrorNotice:e,postId:t})}}),500))}((function(t){!function(t,o,e){$e&&$e.hooks.registerDataAfter(new m("document/save/save","wordproof/timestamper",e))}(0,0,(()=>{window.setTimeout(t,1e3)}))}),b,b)}()}();PK!NaO007wordproof/wordpress-sdk/build/wordproof-block-editor.jsnu[!function(){var e={703:function(e,t,o){"use strict";var n=o(414);function r(){}function a(){}a.resetWarningCache=r,e.exports=function(){function e(e,t,o,r,a,s){if(s!==n){var i=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw i.name="Invariant Violation",i}}function t(){return e}e.isRequired=e;var o={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:r};return o.PropTypes=o,o}},697:function(e,t,o){e.exports=o(703)()},414:function(e){"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"}},t={};function o(n){var r=t[n];if(void 0!==r)return r.exports;var a=t[n]={exports:{}};return e[n](a,a.exports,o),a.exports}o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,{a:t}),t},o.d=function(e,t){for(var n in t)o.o(t,n)&&!o.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},function(){"use strict";var e=window.wp.element,t=window.wp.data,n=window.wp.apiFetch,r=o.n(n);async function a(e,t,o){let n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:200;try{const r=await e();return!!r&&(r.status===n?t(r):o(r))}catch(e){}}async function s(e){try{return await r()(e)}catch(e){return e.error&&e.status?e:e instanceof window.Response&&await e.json()}}const i=async()=>await a((async()=>await c()),(e=>e),(()=>!1)),c=async()=>await s({path:"wordproof/v1/oauth/destroy",method:"POST"}),{get:p}=lodash,d=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return p(window,"wordproofSdk.data"+(e?`.${e}`:""),t)};var l=o(697),u=o.n(l);function w(e){const t=new window.CustomEvent(e);window.dispatchEvent(t)}const f=e=>{const{response:t,createSuccessNotice:o,createErrorNotice:n,postId:r}=e;if(null===t||200===t.status)return;const a={id:"wordproof-timestamp-notice"};t&&201===t.status?0===t.balance?(a.actions=[{label:d("translations.open_settings_button_text"),onClick:()=>{w("wordproof:open_settings")},variant:"link"}],n(d("translations.no_balance"),a)):(o(d("translations.timestamp_success"),{type:"snackbar",id:"wordproof-timestamp-notice"}),h(r,t.hash,n,a)):t.error&&("not_authenticated"===t.error?(a.type="snackbar",a.actions=[{label:d("translations.open_authentication_button_text"),onClick:()=>{w("wordproof:open_authentication")},variant:"link"}],n(d("translations.not_authenticated"),a)):n(d("translations.timestamp_failed"),a))},h=async(e,t,o,n)=>{setTimeout((async()=>{const r=await(async e=>s({path:`wordproof/v1/posts/${e}/timestamp/transaction/latest`,method:"GET"}))(e);r.hash!==t&&(n.type="snackbar",o(d("translations.webhook_failed"),n))}),1e4)};f.proptypes={timestampResponse:u().any.isRequired,createSuccessNotice:u().func.isRequired,createErrorNotice:u().func.isRequired,postId:u().number.isRequired};const{debounce:m}=lodash,{applyFilters:y}=wp.hooks;const{dispatch:v}=wp.data;const{subscribe:_,select:g}=wp.data;function b(e){let t=!0;_((()=>{const o=g("core/editor").isSavingPost(),n=g("core/editor").isAutosavingPost(),r=g("core/editor").didPostSaveRequestSucceed();if(o&&r&&!n){if(t)return void(t=!1);e()}}))}const{__:__}=wp.i18n,{useCallback:E}=wp.element,{withSelect:k}=wp.data,{compose:P}=wp.compose,T=t=>{const{isAuthenticated:o}=t,n=d("popup_redirect_authentication_url"),r=d("popup_redirect_settings_url"),a=E((e=>{e.preventDefault(),w("wordproof:open_settings")})),s=E((e=>{e.preventDefault(),w("wordproof:open_authentication")}));return(0,e.createElement)(e.Fragment,null,o&&(0,e.createElement)("a",{href:r,onClick:a},__("Open settings","wordproof")),!o&&(0,e.createElement)("a",{href:n,onClick:s},__("Open authentication","wordproof")))};T.proptypes={isAuthenticated:u().bool.isRequired};var R=P([k((e=>({isAuthenticated:e("wordproof").getIsAuthenticated()})))])(T);const{Modal:S}=wp.components,C=t=>{const{title:o,children:n,close:r}=t;return(0,e.createElement)(e.Fragment,null,(0,e.createElement)(S,{style:{maxWidth:"440px"},title:o,onRequestClose:r},n))};C.proptypes={title:u().string.isRequired,children:u().any,close:u().func.isRequired};var O=C;const{Button:q}=wp.components,{useCallback:W}=wp.element,{__:A}=wp.i18n,L=t=>{const{close:o}=t,n=W((e=>{e.preventDefault(),w("wordproof:open_authentication")}));return(0,e.createElement)(O,{close:o,title:A("Authentication denied","wordproof")},(0,e.createElement)(e.Fragment,null,(0,e.createElement)("p",null,A("You need to allow WordProof to access your site to finish the WordProof installation.","wordproof")),(0,e.createElement)(q,{variant:"primary",onClick:n},A("Retry authentication","wordproof"))))};L.proptypes={close:u().func.isRequired};var $=L;function x(t,o){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return(0,e.createInterpolateElement)(t,{a:(0,e.createElement)("a",{id:n,href:o,target:"_blank",rel:"noopener noreferrer"})})}const{Button:I}=wp.components,{useCallback:D}=wp.element,{__:F,sprintf:M}=wp.i18n,N=t=>{const{close:o}=t,n=D((e=>{e.preventDefault(),w("wordproof:open_authentication")}));return(0,e.createElement)(O,{close:o,title:F("Authentication failed","wordproof")},(0,e.createElement)(e.Fragment,null,(0,e.createElement)("p",null,M( /* Translators: %s expands to WordProof */ F("Something failed during the authentication of your %s account.","wordproof"),"WordProof"),x(M( /* Translators: %1s and %2s are html tags. %3s expands to WordProof */ F("Please try again or contact the %1$s%3$s support team%2$s.","wordpress-seo"),"","","WordProof"),"https://help.wordproof.com/")),(0,e.createElement)(I,{variant:"primary",onClick:n},F("Retry authentication","wordproof"))))};N.proptypes={close:u().func.isRequired};var j=N;const{__:Y,sprintf:B}=wp.i18n,{compose:H}=wp.compose,{withSelect:U}=wp.data,z=t=>{const{close:o,postType:n}=t;return(0,e.createElement)(O,{close:o,title:Y("Authenticated","wordproof")},(0,e.createElement)("p",null,B( /* translators: %s expands to WordProof. */ Y("You have successfully connected your %s account with this site.","wordproof"),"WordProof"),n&&B( /* translators: %s is the singular post type. */ Y("Your %s will now be timestamped everytime you update or publish.","wordproof"),n)))};z.proptypes={close:u().func.isRequired};var G=H([U((e=>({postType:e("core/editor").getCurrentPostType()})))])(z);const{__:V,sprintf:X}=wp.i18n,J=t=>{const{close:o}=t;return(0,e.createElement)(O,{close:o,title:V("Webhook failed","wordproof")},(0,e.createElement)("p",null,X( /* Translators: %s expands to WordProof */ V("The timestamp sent by %s was not received on your website.","WordProof"),"WordProof"),x(X( /* Translators: %1s and %2s are html tags. %3s expands to WordProof */ V("Please contact the %1$s%3$s support team%2$s to help solve this problem.","wordpress-seo"),"","","WordProof"),"https://help.wordproof.com/")))};J.proptypes={close:u().func.isRequired};var K=J;const{useState:Q,useCallback:Z,useEffect:ee}=wp.element;var te=()=>{const[t,o]=Q(null),n=Z((()=>{o("oauth:failed")})),r=Z((()=>{o("oauth:denied")})),a=Z((()=>{o("webhook:failed")})),s=Z((()=>{o("oauth:success")})),i=Z((()=>{o(null)}));return ee((()=>(window.addEventListener("wordproof:oauth:success",s,!1),window.addEventListener("wordproof:oauth:failed",n,!1),window.addEventListener("wordproof:oauth:denied",r,!1),window.addEventListener("wordproof:webhook:failed",a,!1),()=>{window.removeEventListener("wordproof:oauth:success",s,!1),window.removeEventListener("wordproof:oauth:failed",n,!1),window.removeEventListener("wordproof:oauth:denied",r,!1),window.removeEventListener("wordproof:webhook:failed",a,!1)})),[]),(0,e.createElement)(e.Fragment,null,"oauth:success"===t&&(0,e.createElement)(G,{close:i}),"oauth:denied"===t&&(0,e.createElement)($,{close:i}),"oauth:failed"===t&&(0,e.createElement)(j,{close:i}),"webhook:failed"===t&&(0,e.createElement)(K,{close:i}))};const{__:oe,sprintf:ne}=wp.i18n,{PluginDocumentSettingPanel:re}=wp.editPost,{ToggleControl:ae,PanelRow:se}=wp.components,{compose:ie}=wp.compose,{withSelect:ce,withDispatch:pe}=wp.data,{useCallback:de}=wp.element,le=t=>{let{postType:o,postMeta:n,isAuthenticated:r,selectedPostTypes:a,setPostMeta:s}=t;const i=de((()=>a.includes(o)),[a,o]),c=de((()=>{w("wordproof:open_authentication")}));return void 0===n?(0,e.createElement)(e.Fragment,null):(0,e.createElement)(re,{title:oe("WordProof Timestamp","wordproof"),initialOpen:"true"},(0,e.createElement)(se,null,(0,e.createElement)(ae,{label:ne( /* translators: %s expands to the post type */ oe("Timestamp this %s","wordproof"),o),onChange:e=>{s({_wordproof_timestamp:e}),r||!0!==e||c()},checked:n._wordproof_timestamp||i(),disabled:i()})),(0,e.createElement)(se,null,(0,e.createElement)(R,null)),(0,e.createElement)(te,null))};le.proptypes={postType:u().string.isRequired,postMeta:u().object.isRequired,isAuthenticated:u().bool.isRequired,setPostMeta:u().func.isRequired};var ue=ie([ce((e=>({postMeta:e("core/editor").getEditedPostAttribute("meta"),postType:e("core/editor").getCurrentPostType(),isAuthenticated:e("wordproof").getIsAuthenticated(),selectedPostTypes:e("wordproof").getSelectedPostTypes()}))),pe((e=>({setPostMeta(t){e("core/editor").editPost({meta:t})}})))])(le);const{registerPlugin:we}=wp.plugins;we("wordproof-timestamp-panel",{render:()=>(0,e.createElement)(ue,null)}),function(){const{createSuccessNotice:e,createErrorNotice:o}=(0,t.dispatch)("core/notices");(function(){const{setIsAuthenticated:e,setSelectedPostTypes:t}=v("wordproof"),o=d("popup_redirect_authentication_url"),n=d("popup_redirect_settings_url");let r=null;const c=(e,t)=>{r=function(e,t){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"",n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:800,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:680;const a=e.top.outerHeight/2+e.top.screenY-r/2,s=e.top.outerWidth/2+e.top.screenX-n/2;return e.open(t,o,`toolbar=no,\n\t\tlocation=no,\n\t\tdirectories=no,\n\t\tstatus=no,\n\t\tmenubar=no,\n\t\tresizable=no,\n\t\tcopyhistory=no,\n\t\twidth=${n},\n\t\theight=${r},\n\t\ttop=${a},\n\t\tleft=${s}`)}(window,e,t),r&&r.focus(),window.addEventListener("message",p,!1)},p=async e=>{const{data:t,source:o,origin:n}=e;if(n===d("origin")&&r===o)switch(t.type){case"wordproof:oauth:granted":!1===await f(t)&&await l("wordproof:oauth:failed",!1);break;case"wordproof:oauth:failed":await l("wordproof:oauth:failed",!1);break;case"wordproof:oauth:denied":await l("wordproof:oauth:denied",!1);break;case"wordproof:oauth:invalid_token":await l("wordproof:oauth:invalid_token",!1);break;case"wordproof:webhook:success":await l("wordproof:oauth:success",!0);break;case"wordproof:webhook:failed":await l("wordproof:webhook:failed",!1);break;case"wordproof:settings:updated":await l("wordproof:settings:updated"),await h(t);break;case"wordproof:oauth:destroy":await l("wordproof:oauth:destroy",!1);break;case"wordproof:oauth:retry":await l("wordproof:open_authentication",!1);break;case"wordproof:oauth:close":u()}},l=async function(t){let o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;u(),w(t),!1===o&&(await i(),e(!1)),!0===o&&e(!0)},u=()=>{window.removeEventListener("message",p,!1),r.close()},f=async e=>{await a((()=>(async e=>{const{state:t,code:o}=e;return await s({path:"wordproof/v1/oauth/authenticate",method:"POST",data:{state:t,code:o}})})(e)),(async e=>{const t={type:"wordproof:sdk:access-token",source_id:e.source_id};return r.postMessage(t,d("origin")),!0}),(async()=>!1))},h=async e=>{await a((()=>(async e=>{const{settings:t}=e;return await s({path:"wordproof/v1/settings",method:"POST",data:{settings:t}})})(e)),(async()=>{const o=e.settings;return o.selectedPostTypes&&t(o.selectedPostTypes),!0}),(async()=>!1))};window.addEventListener("wordproof:open_authentication",(e=>{e.preventDefault(),c(o,"WordProof_Authentication")}),!1),window.addEventListener("wordproof:open_settings",(e=>{e.preventDefault(),c(n,"WordProof_Settings")}),!1)})(),function(e,t,o){e(m((async()=>{if(y("wordproof.timestamp",!0)){const e=d("current_post_id"),n=await(async e=>s({path:`wordproof/v1/posts/${e}/timestamp`,method:"POST"}))(e);f({response:n,createSuccessNotice:t,createErrorNotice:o,postId:e})}}),500))}(b,e,o)}()}()}();PK!rg*symfony/deprecation-contracts/function.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ if (!function_exists('trigger_deprecation')) { /** * Triggers a silenced deprecation notice. * * @param string $package The name of the Composer package that is triggering the deprecation * @param string $version The version of the package that introduced the deprecation * @param string $message The message of the deprecation * @param mixed ...$args Values to insert in the message using printf() formatting * * @author Nicolas Grekas */ function trigger_deprecation(string $package, string $version, string $message, ...$args): void { @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED); } } PK!)  =symfony/dependency-injection/ResettableContainerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection; /** * ResettableContainerInterface defines additional resetting functionality * for containers, allowing to release shared services when the container is * not needed anymore. * * @author Christophe Coevoet */ interface ResettableContainerInterface extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface { /** * Resets shared services from the container. * * The container is not intended to be used again after being reset in a normal workflow. This method is * meant as a way to release references for ref-counting. * A subsequent call to ContainerInterface::get will recreate a new instance of the shared service. */ public function reset(); } PK![OO*symfony/dependency-injection/Container.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; /** * Container is a dependency injection container. * * It gives access to object instances (services). * Services and parameters are simple key/pair stores. * The container can have four possible behaviors when a service * does not exist (or is not initialized for the last case): * * * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default) * * NULL_ON_INVALID_REFERENCE: Returns null * * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference * (for instance, ignore a setter if the service does not exist) * * IGNORE_ON_UNINITIALIZED_REFERENCE: Ignores/returns null for uninitialized services or invalid references * * @author Fabien Potencier * @author Johannes M. Schmitt */ class Container implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ResettableContainerInterface { protected $parameterBag; protected $services = []; protected $fileMap = []; protected $methodMap = []; protected $aliases = []; protected $loading = []; protected $resolving = []; protected $syntheticIds = []; /** * @internal */ protected $privates = []; /** * @internal */ protected $normalizedIds = []; private $underscoreMap = ['_' => '', '.' => '_', '\\' => '_']; private $envCache = []; private $compiled = \false; private $getEnv; public function __construct(\YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface $parameterBag = null) { $this->parameterBag = $parameterBag ?: new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag(); } /** * Compiles the container. * * This method does two things: * * * Parameter values are resolved; * * The parameter bag is frozen. */ public function compile() { $this->parameterBag->resolve(); $this->parameterBag = new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag($this->parameterBag->all()); $this->compiled = \true; } /** * Returns true if the container is compiled. * * @return bool */ public function isCompiled() { return $this->compiled; } /** * Returns true if the container parameter bag are frozen. * * @deprecated since version 3.3, to be removed in 4.0. * * @return bool true if the container parameter bag are frozen, false otherwise */ public function isFrozen() { @\trigger_error(\sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), \E_USER_DEPRECATED); return $this->parameterBag instanceof \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; } /** * Gets the service container parameter bag. * * @return ParameterBagInterface A ParameterBagInterface instance */ public function getParameterBag() { return $this->parameterBag; } /** * Gets a parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws InvalidArgumentException if the parameter is not defined */ public function getParameter($name) { return $this->parameterBag->get($name); } /** * Checks if a parameter exists. * * @param string $name The parameter name * * @return bool The presence of parameter in container */ public function hasParameter($name) { return $this->parameterBag->has($name); } /** * Sets a parameter. * * @param string $name The parameter name * @param mixed $value The parameter value */ public function setParameter($name, $value) { $this->parameterBag->set($name, $value); } /** * Sets a service. * * Setting a synthetic service to null resets it: has() returns false and get() * behaves in the same way as if the service was never created. * * @param string $id The service identifier * @param object|null $service The service instance */ public function set($id, $service) { // Runs the internal initializer; used by the dumped container to include always-needed files if (isset($this->privates['service_container']) && $this->privates['service_container'] instanceof \Closure) { $initialize = $this->privates['service_container']; unset($this->privates['service_container']); $initialize(); } $id = $this->normalizeId($id); if ('service_container' === $id) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException('You cannot set service "service_container".'); } if (isset($this->privates[$id]) || !(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) { if (!isset($this->privates[$id]) && !isset($this->getRemovedIds()[$id])) { // no-op } elseif (null === $service) { @\trigger_error(\sprintf('The "%s" service is private, unsetting it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), \E_USER_DEPRECATED); unset($this->privates[$id]); } else { @\trigger_error(\sprintf('The "%s" service is private, replacing it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), \E_USER_DEPRECATED); } } elseif (isset($this->services[$id])) { if (null === $service) { @\trigger_error(\sprintf('The "%s" service is already initialized, unsetting it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), \E_USER_DEPRECATED); } else { @\trigger_error(\sprintf('The "%s" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), \E_USER_DEPRECATED); } } if (isset($this->aliases[$id])) { unset($this->aliases[$id]); } if (null === $service) { unset($this->services[$id]); return; } $this->services[$id] = $service; } /** * Returns true if the given service is defined. * * @param string $id The service identifier * * @return bool true if the service is defined, false otherwise */ public function has($id) { for ($i = 2;;) { if (isset($this->privates[$id])) { @\trigger_error(\sprintf('The "%s" service is private, checking for its existence is deprecated since Symfony 3.2 and will fail in 4.0.', $id), \E_USER_DEPRECATED); } if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; } if (isset($this->services[$id])) { return \true; } if ('service_container' === $id) { return \true; } if (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) { return \true; } if (--$i && $id !== ($normalizedId = $this->normalizeId($id))) { $id = $normalizedId; continue; } // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) if (!$this->methodMap && !$this instanceof \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerBuilder && __CLASS__ !== static::class && \method_exists($this, 'get' . \strtr($id, $this->underscoreMap) . 'Service')) { @\trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', \E_USER_DEPRECATED); return \true; } return \false; } } /** * Gets a service. * * If a service is defined both through a set() method and * with a get{$id}Service() method, the former has always precedence. * * @param string $id The service identifier * @param int $invalidBehavior The behavior when the service does not exist * * @return object|null The associated service * * @throws ServiceCircularReferenceException When a circular reference is detected * @throws ServiceNotFoundException When the service is not defined * @throws \Exception if an exception has been thrown when the service has been resolved * * @see Reference */ public function get($id, $invalidBehavior = 1) { // Attempt to retrieve the service by checking first aliases then // available services. Service IDs are case insensitive, however since // this method can be called thousands of times during a request, avoid // calling $this->normalizeId($id) unless necessary. for ($i = 2;;) { if (isset($this->privates[$id])) { @\trigger_error(\sprintf('The "%s" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.', $id), \E_USER_DEPRECATED); } if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; } // Re-use shared service instance if it exists. if (isset($this->services[$id])) { return $this->services[$id]; } if ('service_container' === $id) { return $this; } if (isset($this->loading[$id])) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException($id, \array_merge(\array_keys($this->loading), [$id])); } $this->loading[$id] = \true; try { if (isset($this->fileMap[$id])) { return 4 === $invalidBehavior ? null : $this->load($this->fileMap[$id]); } elseif (isset($this->methodMap[$id])) { return 4 === $invalidBehavior ? null : $this->{$this->methodMap[$id]}(); } elseif (--$i && $id !== ($normalizedId = $this->normalizeId($id))) { unset($this->loading[$id]); $id = $normalizedId; continue; } elseif (!$this->methodMap && !$this instanceof \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerBuilder && __CLASS__ !== static::class && \method_exists($this, $method = 'get' . \strtr($id, $this->underscoreMap) . 'Service')) { // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) @\trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', \E_USER_DEPRECATED); return 4 === $invalidBehavior ? null : $this->{$method}(); } break; } catch (\Exception $e) { unset($this->services[$id]); throw $e; } finally { unset($this->loading[$id]); } } if (1 === $invalidBehavior) { if (!$id) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($id); } if (isset($this->syntheticIds[$id])) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($id, null, null, [], \sprintf('The "%s" service is synthetic, it needs to be set at boot time before it can be used.', $id)); } if (isset($this->getRemovedIds()[$id])) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($id, null, null, [], \sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.', $id)); } $alternatives = []; foreach ($this->getServiceIds() as $knownId) { $lev = \levenshtein($id, $knownId); if ($lev <= \strlen($id) / 3 || \false !== \strpos($knownId, $id)) { $alternatives[] = $knownId; } } throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException($id, null, null, $alternatives); } } /** * Returns true if the given service has actually been initialized. * * @param string $id The service identifier * * @return bool true if service has already been initialized, false otherwise */ public function initialized($id) { $id = $this->normalizeId($id); if (isset($this->privates[$id])) { @\trigger_error(\sprintf('Checking for the initialization of the "%s" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0.', $id), \E_USER_DEPRECATED); } if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; } if ('service_container' === $id) { return \false; } return isset($this->services[$id]); } /** * {@inheritdoc} */ public function reset() { $this->services = []; } /** * Gets all service ids. * * @return string[] An array of all defined service ids */ public function getServiceIds() { $ids = []; if (!$this->methodMap && !$this instanceof \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerBuilder && __CLASS__ !== static::class) { // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) @\trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', \E_USER_DEPRECATED); foreach (\get_class_methods($this) as $method) { if (\preg_match('/^get(.+)Service$/', $method, $match)) { $ids[] = self::underscore($match[1]); } } } $ids[] = 'service_container'; return \array_map('strval', \array_unique(\array_merge($ids, \array_keys($this->methodMap), \array_keys($this->fileMap), \array_keys($this->aliases), \array_keys($this->services)))); } /** * Gets service ids that existed at compile time. * * @return array */ public function getRemovedIds() { return []; } /** * Camelizes a string. * * @param string $id A string to camelize * * @return string The camelized string */ public static function camelize($id) { return \strtr(\ucwords(\strtr($id, ['_' => ' ', '.' => '_ ', '\\' => '_ '])), [' ' => '']); } /** * A string to underscore. * * @param string $id The string to underscore * * @return string The underscored string */ public static function underscore($id) { return \strtolower(\preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], \str_replace('_', '.', $id))); } /** * Creates a service by requiring its factory file. */ protected function load($file) { return require $file; } /** * Fetches a variable from the environment. * * @param string $name The name of the environment variable * * @return mixed The value to use for the provided environment variable name * * @throws EnvNotFoundException When the environment variable is not found and has no default value */ protected function getEnv($name) { if (isset($this->resolving[$envName = "env({$name})"])) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException(\array_keys($this->resolving)); } if (isset($this->envCache[$name]) || \array_key_exists($name, $this->envCache)) { return $this->envCache[$name]; } if (!$this->has($id = 'container.env_var_processors_locator')) { $this->set($id, new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ServiceLocator([])); } if (!$this->getEnv) { $this->getEnv = new \ReflectionMethod($this, __FUNCTION__); $this->getEnv->setAccessible(\true); $this->getEnv = $this->getEnv->getClosure($this); } $processors = $this->get($id); if (\false !== ($i = \strpos($name, ':'))) { $prefix = \substr($name, 0, $i); $localName = \substr($name, 1 + $i); } else { $prefix = 'string'; $localName = $name; } $processor = $processors->has($prefix) ? $processors->get($prefix) : new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\EnvVarProcessor($this); $this->resolving[$envName] = \true; try { return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv); } finally { unset($this->resolving[$envName]); } } /** * Returns the case sensitive id used at registration time. * * @param string $id * * @return string * * @internal */ public function normalizeId($id) { if (!\is_string($id)) { $id = (string) $id; } if (isset($this->normalizedIds[$normalizedId = \strtolower($id)])) { $normalizedId = $this->normalizedIds[$normalizedId]; if ($id !== $normalizedId) { @\trigger_error(\sprintf('Service identifiers will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.3.', $id, $normalizedId), \E_USER_DEPRECATED); } } else { $normalizedId = $this->normalizedIds[$normalizedId] = $id; } return $normalizedId; } private function __clone() { } } PK!tf=symfony/dependency-injection/Argument/RewindableGenerator.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Argument; /** * @internal */ class RewindableGenerator implements \IteratorAggregate, \Countable { private $generator; private $count; /** * @param int|callable $count */ public function __construct(callable $generator, $count) { $this->generator = $generator; $this->count = $count; } public function getIterator() { $g = $this->generator; return $g(); } public function count() { if (\is_callable($count = $this->count)) { $this->count = $count(); } return $this->count; } } PK!bm,AALsymfony/dependency-injection/Exception/ServiceCircularReferenceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a circular reference is detected. * * @author Johannes M. Schmitt */ class ServiceCircularReferenceException extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException { private $serviceId; private $path; public function __construct($serviceId, array $path, \Exception $previous = null) { parent::__construct(\sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, \implode(' -> ', $path)), 0, $previous); $this->serviceId = $serviceId; $this->path = $path; } public function getServiceId() { return $this->serviceId; } public function getPath() { return $this->path; } } PK!&  9symfony/dependency-injection/Exception/LogicException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; /** * Base LogicException for Dependency Injection component. */ class LogicException extends \LogicException implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ExceptionInterface { } PK!Y[KK;symfony/dependency-injection/Exception/RuntimeException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; /** * Base RuntimeException for Dependency Injection component. * * @author Johannes M. Schmitt */ class RuntimeException extends \RuntimeException implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ExceptionInterface { } PK!͇Nsymfony/dependency-injection/Exception/ParameterCircularReferenceException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when a circular reference in a parameter is detected. * * @author Fabien Potencier */ class ParameterCircularReferenceException extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException { private $parameters; public function __construct($parameters, \Exception $previous = null) { parent::__construct(\sprintf('Circular reference detected for parameter "%s" ("%s" > "%s").', $parameters[0], \implode('" > "', $parameters), $parameters[0]), 0, $previous); $this->parameters = $parameters; } public function getParameters() { return $this->parameters; } } PK!annCsymfony/dependency-injection/Exception/ServiceNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; use YoastSEO_Vendor\Psr\Container\NotFoundExceptionInterface; /** * This exception is thrown when a non-existent service is requested. * * @author Johannes M. Schmitt */ class ServiceNotFoundException extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException implements \YoastSEO_Vendor\Psr\Container\NotFoundExceptionInterface { private $id; private $sourceId; private $alternatives; public function __construct($id, $sourceId = null, \Exception $previous = null, array $alternatives = [], $msg = null) { if (null !== $msg) { // no-op } elseif (null === $sourceId) { $msg = \sprintf('You have requested a non-existent service "%s".', $id); } else { $msg = \sprintf('The service "%s" has a dependency on a non-existent service "%s".', $sourceId, $id); } if ($alternatives) { if (1 == \count($alternatives)) { $msg .= ' Did you mean this: "'; } else { $msg .= ' Did you mean one of these: "'; } $msg .= \implode('", "', $alternatives) . '"?'; } parent::__construct($msg, 0, $previous); $this->id = $id; $this->sourceId = $sourceId; $this->alternatives = $alternatives; } public function getId() { return $this->id; } public function getSourceId() { return $this->sourceId; } public function getAlternatives() { return $this->alternatives; } } PK!rC?symfony/dependency-injection/Exception/EnvNotFoundException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; /** * This exception is thrown when an environment variable is not found. * * @author Nicolas Grekas */ class EnvNotFoundException extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException { public function __construct($name) { parent::__construct(\sprintf('Environment variable not found: "%s".', $name)); } } PK!*~iiCsymfony/dependency-injection/Exception/InvalidArgumentException.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; /** * Base InvalidArgumentException for Dependency Injection component. * * @author Bulat Shakirzyanov */ class InvalidArgumentException extends \InvalidArgumentException implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ExceptionInterface { } PK!\œ=symfony/dependency-injection/Exception/ExceptionInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception; use YoastSEO_Vendor\Psr\Container\ContainerExceptionInterface; /** * Base ExceptionInterface for Dependency Injection component. * * @author Fabien Potencier * @author Bulat Shakirzyanov */ interface ExceptionInterface extends \YoastSEO_Vendor\Psr\Container\ContainerExceptionInterface { } PK! Csymfony/dependency-injection/ParameterBag/ParameterBagInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; /** * ParameterBagInterface. * * @author Fabien Potencier */ interface ParameterBagInterface { /** * Clears all parameters. * * @throws LogicException if the ParameterBagInterface can not be cleared */ public function clear(); /** * Adds parameters to the service container parameters. * * @param array $parameters An array of parameters * * @throws LogicException if the parameter can not be added */ public function add(array $parameters); /** * Gets the service container parameters. * * @return array An array of parameters */ public function all(); /** * Gets a service container parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws ParameterNotFoundException if the parameter is not defined */ public function get($name); /** * Removes a parameter. * * @param string $name The parameter name */ public function remove($name); /** * Sets a service container parameter. * * @param string $name The parameter name * @param mixed $value The parameter value * * @throws LogicException if the parameter can not be set */ public function set($name, $value); /** * Returns true if a parameter name is defined. * * @param string $name The parameter name * * @return bool true if the parameter name is defined, false otherwise */ public function has($name); /** * Replaces parameter placeholders (%name%) by their values for all parameters. */ public function resolve(); /** * Replaces parameter placeholders (%name%) by their values. * * @param mixed $value A value * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist */ public function resolveValue($value); /** * Escape parameter placeholders %. * * @param mixed $value * * @return mixed */ public function escapeValue($value); /** * Unescape parameter placeholders %. * * @param mixed $value * * @return mixed */ public function unescapeValue($value); } PK!kD%%:symfony/dependency-injection/ParameterBag/ParameterBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * Holds parameters. * * @author Fabien Potencier */ class ParameterBag implements \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface { protected $parameters = []; protected $resolved = \false; private $normalizedNames = []; /** * @param array $parameters An array of parameters */ public function __construct(array $parameters = []) { $this->add($parameters); } /** * Clears all parameters. */ public function clear() { $this->parameters = []; } /** * Adds parameters to the service container parameters. * * @param array $parameters An array of parameters */ public function add(array $parameters) { foreach ($parameters as $key => $value) { $this->set($key, $value); } } /** * {@inheritdoc} */ public function all() { return $this->parameters; } /** * {@inheritdoc} */ public function get($name) { $name = $this->normalizeName($name); if (!\array_key_exists($name, $this->parameters)) { if (!$name) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException($name); } $alternatives = []; foreach ($this->parameters as $key => $parameterValue) { $lev = \levenshtein($name, $key); if ($lev <= \strlen($name) / 3 || \false !== \strpos($key, $name)) { $alternatives[] = $key; } } $nonNestedAlternative = null; if (!\count($alternatives) && \false !== \strpos($name, '.')) { $namePartsLength = \array_map('strlen', \explode('.', $name)); $key = \substr($name, 0, -1 * (1 + \array_pop($namePartsLength))); while (\count($namePartsLength)) { if ($this->has($key)) { if (\is_array($this->get($key))) { $nonNestedAlternative = $key; } break; } $key = \substr($key, 0, -1 * (1 + \array_pop($namePartsLength))); } } throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException($name, null, null, null, $alternatives, $nonNestedAlternative); } return $this->parameters[$name]; } /** * Sets a service container parameter. * * @param string $name The parameter name * @param mixed $value The parameter value */ public function set($name, $value) { $this->parameters[$this->normalizeName($name)] = $value; } /** * {@inheritdoc} */ public function has($name) { return \array_key_exists($this->normalizeName($name), $this->parameters); } /** * Removes a parameter. * * @param string $name The parameter name */ public function remove($name) { unset($this->parameters[$this->normalizeName($name)]); } /** * {@inheritdoc} */ public function resolve() { if ($this->resolved) { return; } $parameters = []; foreach ($this->parameters as $key => $value) { try { $value = $this->resolveValue($value); $parameters[$key] = $this->unescapeValue($value); } catch (\YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException $e) { $e->setSourceKey($key); throw $e; } } $this->parameters = $parameters; $this->resolved = \true; } /** * Replaces parameter placeholders (%name%) by their values. * * @param mixed $value A value * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) * * @return mixed The resolved value * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist * @throws ParameterCircularReferenceException if a circular reference if detected * @throws RuntimeException when a given parameter has a type problem */ public function resolveValue($value, array $resolving = []) { if (\is_array($value)) { $args = []; foreach ($value as $k => $v) { $args[\is_string($k) ? $this->resolveValue($k, $resolving) : $k] = $this->resolveValue($v, $resolving); } return $args; } if (!\is_string($value) || 2 > \strlen($value)) { return $value; } return $this->resolveString($value, $resolving); } /** * Resolves parameters inside a string. * * @param string $value The string to resolve * @param array $resolving An array of keys that are being resolved (used internally to detect circular references) * * @return mixed The resolved string * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist * @throws ParameterCircularReferenceException if a circular reference if detected * @throws RuntimeException when a given parameter has a type problem */ public function resolveString($value, array $resolving = []) { // we do this to deal with non string values (Boolean, integer, ...) // as the preg_replace_callback throw an exception when trying // a non-string in a parameter value if (\preg_match('/^%([^%\\s]+)%$/', $value, $match)) { $key = $match[1]; $lcKey = \strtolower($key); // strtolower() to be removed in 4.0 if (isset($resolving[$lcKey])) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException(\array_keys($resolving)); } $resolving[$lcKey] = \true; return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving); } return \preg_replace_callback('/%%|%([^%\\s]+)%/', function ($match) use($resolving, $value) { // skip %% if (!isset($match[1])) { return '%%'; } $key = $match[1]; $lcKey = \strtolower($key); // strtolower() to be removed in 4.0 if (isset($resolving[$lcKey])) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException(\array_keys($resolving)); } $resolved = $this->get($key); if (!\is_string($resolved) && !\is_numeric($resolved)) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException(\sprintf('A string value must be composed of strings and/or numbers, but found parameter "%s" of type "%s" inside string value "%s".', $key, \gettype($resolved), $value)); } $resolved = (string) $resolved; $resolving[$lcKey] = \true; return $this->isResolved() ? $resolved : $this->resolveString($resolved, $resolving); }, $value); } public function isResolved() { return $this->resolved; } /** * {@inheritdoc} */ public function escapeValue($value) { if (\is_string($value)) { return \str_replace('%', '%%', $value); } if (\is_array($value)) { $result = []; foreach ($value as $k => $v) { $result[$k] = $this->escapeValue($v); } return $result; } return $value; } /** * {@inheritdoc} */ public function unescapeValue($value) { if (\is_string($value)) { return \str_replace('%%', '%', $value); } if (\is_array($value)) { $result = []; foreach ($value as $k => $v) { $result[$k] = $this->unescapeValue($v); } return $result; } return $value; } private function normalizeName($name) { if (isset($this->normalizedNames[$normalizedName = \strtolower($name)])) { $normalizedName = $this->normalizedNames[$normalizedName]; if ((string) $name !== $normalizedName) { @\trigger_error(\sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.4.', $name, $normalizedName), \E_USER_DEPRECATED); } } else { $normalizedName = $this->normalizedNames[$normalizedName] = (string) $name; } return $normalizedName; } } PK!@symfony/dependency-injection/ParameterBag/FrozenParameterBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException; /** * Holds read-only parameters. * * @author Fabien Potencier */ class FrozenParameterBag extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag { /** * For performance reasons, the constructor assumes that * all keys are already lowercased. * * This is always the case when used internally. * * @param array $parameters An array of parameters */ public function __construct(array $parameters = []) { $this->parameters = $parameters; $this->resolved = \true; } /** * {@inheritdoc} */ public function clear() { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException('Impossible to call clear() on a frozen ParameterBag.'); } /** * {@inheritdoc} */ public function add(array $parameters) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException('Impossible to call add() on a frozen ParameterBag.'); } /** * {@inheritdoc} */ public function set($name, $value) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException('Impossible to call set() on a frozen ParameterBag.'); } /** * {@inheritdoc} */ public function remove($name) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException('Impossible to call remove() on a frozen ParameterBag.'); } } PK!ꟿHsymfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException; /** * @author Nicolas Grekas */ class EnvPlaceholderParameterBag extends \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\ParameterBag { private $envPlaceholders = []; private $providedTypes = []; /** * {@inheritdoc} */ public function get($name) { if (0 === \strpos($name, 'env(') && ')' === \substr($name, -1) && 'env()' !== $name) { $env = \substr($name, 4, -1); if (isset($this->envPlaceholders[$env])) { foreach ($this->envPlaceholders[$env] as $placeholder) { return $placeholder; // return first result } } if (!\preg_match('/^(?:\\w++:)*+\\w++$/', $env)) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException(\sprintf('Invalid "%s" name: only "word" characters are allowed.', $name)); } if ($this->has($name)) { $defaultValue = parent::get($name); if (null !== $defaultValue && !\is_scalar($defaultValue)) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException(\sprintf('The default value of an env() parameter must be scalar or null, but "%s" given to "%s".', \gettype($defaultValue), $name)); } } $uniqueName = \md5($name . \uniqid(\mt_rand(), \true)); $placeholder = \sprintf('env_%s_%s', \str_replace(':', '_', $env), $uniqueName); $this->envPlaceholders[$env][$placeholder] = $placeholder; return $placeholder; } return parent::get($name); } /** * Returns the map of env vars used in the resolved parameter values to their placeholders. * * @return string[][] A map of env var names to their placeholders */ public function getEnvPlaceholders() { return $this->envPlaceholders; } /** * Merges the env placeholders of another EnvPlaceholderParameterBag. */ public function mergeEnvPlaceholders(self $bag) { if ($newPlaceholders = $bag->getEnvPlaceholders()) { $this->envPlaceholders += $newPlaceholders; foreach ($newPlaceholders as $env => $placeholders) { $this->envPlaceholders[$env] += $placeholders; } } } /** * Maps env prefixes to their corresponding PHP types. */ public function setProvidedTypes(array $providedTypes) { $this->providedTypes = $providedTypes; } /** * Gets the PHP types corresponding to env() parameter prefixes. * * @return string[][] */ public function getProvidedTypes() { return $this->providedTypes; } /** * {@inheritdoc} */ public function resolve() { if ($this->resolved) { return; } parent::resolve(); foreach ($this->envPlaceholders as $env => $placeholders) { if (!$this->has($name = "env({$env})")) { continue; } if (\is_numeric($default = $this->parameters[$name])) { $this->parameters[$name] = (string) $default; } elseif (null !== $default && !\is_scalar($default)) { throw new \YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException(\sprintf('The default value of env parameter "%s" must be scalar or null, "%s" given.', $env, \gettype($default))); } } } } PK! 3symfony/dependency-injection/ContainerInterface.phpnu[ * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace YoastSEO_Vendor\Symfony\Component\DependencyInjection; use YoastSEO_Vendor\Psr\Container\ContainerInterface as PsrContainerInterface; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; /** * ContainerInterface is the interface implemented by service container classes. * * @author Fabien Potencier * @author Johannes M. Schmitt */ interface ContainerInterface extends \YoastSEO_Vendor\Psr\Container\ContainerInterface { const EXCEPTION_ON_INVALID_REFERENCE = 1; const NULL_ON_INVALID_REFERENCE = 2; const IGNORE_ON_INVALID_REFERENCE = 3; const IGNORE_ON_UNINITIALIZED_REFERENCE = 4; /** * Sets a service. * * @param string $id The service identifier * @param object|null $service The service instance */ public function set($id, $service); /** * Gets a service. * * @param string $id The service identifier * @param int $invalidBehavior The behavior when the service does not exist * * @return object|null The associated service * * @throws ServiceCircularReferenceException When a circular reference is detected * @throws ServiceNotFoundException When the service is not defined * * @see Reference */ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE); /** * Returns true if the given service is defined. * * @param string $id The service identifier * * @return bool true if the service is defined, false otherwise */ public function has($id); /** * Check for whether or not a service has been initialized. * * @param string $id * * @return bool true if the service has been initialized, false otherwise */ public function initialized($id); /** * Gets a parameter. * * @param string $name The parameter name * * @return mixed The parameter value * * @throws InvalidArgumentException if the parameter is not defined */ public function getParameter($name); /** * Checks if a parameter exists. * * @param string $name The parameter name * * @return bool The presence of parameter in container */ public function hasParameter($name); /** * Sets a parameter. * * @param string $name The parameter name * @param mixed $value The parameter value */ public function setParameter($name, $value); } PK!C4$3 "guzzlehttp/promises/src/Create.phpnu[PK!Xa1\ guzzlehttp/promises/src/CancellationException.phpnu[PK!c c  guzzlehttp/promises/src/Each.phpnu[PK!2 .uguzzlehttp/promises/src/AggregateException.phpnu[PK!X4I I ,guzzlehttp/promises/src/PromiseInterface.phpnu[PK!O%)#guzzlehttp/promises/src/TaskQueue.phpnu[PK!1+guzzlehttp/promises/src/Is.phpnu[PK!2).0guzzlehttp/promises/src/RejectionException.phpnu[PK!FB""!5guzzlehttp/promises/src/Utils.phpnu[PK!(Q.Yguzzlehttp/promises/src/TaskQueueInterface.phpnu[PK!/,H[guzzlehttp/promises/src/FulfilledPromise.phpnu[PK!zvv'Udguzzlehttp/promises/src/EachPromise.phpnu[PK!.S-f +"guzzlehttp/promises/src/RejectedPromise.phpnu[PK!..-0guzzlehttp/promises/src/PromisorInterface.phpnu[PK!<$$#guzzlehttp/promises/src/Promise.phpnu[PK!,%  %guzzlehttp/promises/src/Coroutine.phpnu[PK!#c /guzzlehttp/guzzle/src/PrepareBodyMiddleware.phpnu[PK!Nh%h%%Iguzzlehttp/guzzle/src/ClientTrait.phpnu[PK!z-)guzzlehttp/guzzle/src/RetryMiddleware.phpnu[PK!ud++1guzzlehttp/guzzle/src/BodySummarizerInterface.phpnu[PK!B" " 'guzzlehttp/guzzle/src/TransferStats.phpnu[PK!etvv*guzzlehttp/guzzle/src/MessageFormatter.phpnu[PK!s``#1guzzlehttp/guzzle/src/functions.phpnu[PK! e""&Iguzzlehttp/guzzle/src/HandlerStack.phpnu[PK!0j55lguzzlehttp/guzzle/src/Utils.phpnu[PK!}M`guzzlehttp/guzzle/src/Pool.phpnu[PK!(cguzzlehttp/guzzle/src/BodySummarizer.phpnu[PK! | )guzzlehttp/guzzle/src/ClientInterface.phpnu[PK!O .qguzzlehttp/guzzle/src/Cookie/FileCookieJar.phpnu[PK!^4747*Sguzzlehttp/guzzle/src/Cookie/SetCookie.phpnu[PK!B·]%%* guzzlehttp/guzzle/src/Cookie/CookieJar.phpnu[PK!9cJJ10guzzlehttp/guzzle/src/Cookie/SessionCookieJar.phpnu[PK!_| 38guzzlehttp/guzzle/src/Cookie/CookieJarInterface.phpnu[PK!Aj!j!,Dguzzlehttp/guzzle/src/RedirectMiddleware.phpnu[PK!pI6fguzzlehttp/guzzle/src/Handler/CurlFactoryInterface.phpnu[PK!B}aa-;jguzzlehttp/guzzle/src/Handler/CurlFactory.phpnu[PK!5> ,#guzzlehttp/guzzle/src/Handler/EasyHandle.phpnu[PK!"V"V/Bguzzlehttp/guzzle/src/Handler/StreamHandler.phpnu[PK!Zv-.guzzlehttp/guzzle/src/Handler/MockHandler.phpnu[PK!il-Iguzzlehttp/guzzle/src/Handler/CurlHandler.phpnu[PK!ڸp p 25Pguzzlehttp/guzzle/src/Handler/CurlMultiHandler.phpnu[PK!  'qguzzlehttp/guzzle/src/Handler/Proxy.phpnu[PK!WW1zguzzlehttp/guzzle/src/Handler/HeaderProcessor.phpnu[PK! +guzzlehttp/guzzle/src/functions_include.phpnu[PK!m**(πguzzlehttp/guzzle/src/RequestOptions.phpnu[PK!ix5guzzlehttp/guzzle/src/Exception/TransferException.phpnu[PK!V:e3guzzlehttp/guzzle/src/Exception/ServerException.phpnu[PK!4Cguzzlehttp/guzzle/src/Exception/ConnectException.phpnu[PK!].gW3guzzlehttp/guzzle/src/Exception/ClientException.phpnu[PK!;gg8guzzlehttp/guzzle/src/Exception/BadResponseException.phpnu[PK!ǥ3Ⱥguzzlehttp/guzzle/src/Exception/GuzzleException.phpnu[PK!3z4guzzlehttp/guzzle/src/Exception/RequestException.phpnu[PK!aO=)guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.phpnu[PK!2̈@<1guzzlehttp/guzzle/src/Exception/InvalidArgumentException.phpnu[PK!zU3aguzzlehttp/guzzle/src/MessageFormatterInterface.phpnu[PK!ͷX,X,$gguzzlehttp/guzzle/src/Middleware.phpnu[PK!EsvNN guzzlehttp/guzzle/src/Client.phpnu[PK!x{33$wQguzzlehttp/psr7/src/UploadedFile.phpnu[PK!u$$dguzzlehttp/psr7/src/MessageTrait.phpnu[PK!#?05guzzlehttp/psr7/src/Rfc7230.phpnu[PK!f; guzzlehttp/psr7/src/Response.phpnu[PK!.NN$guzzlehttp/psr7/src/NoSeekStream.phpnu[PK! guzzlehttp/psr7/src/FnStream.phpnu[PK! $guzzlehttp/psr7/src/BufferStream.phpnu[PK!#cc9guzzlehttp/psr7/src/Request.phpnu[PK!te guzzlehttp/psr7/src/MimeType.phpnu[PK!N %{guzzlehttp/psr7/src/CachingStream.phpnu[PK![Pc&&%guzzlehttp/psr7/src/ServerRequest.phpnu[PK!Ovv"guzzlehttp/psr7/src/PumpStream.phpnu[PK!X``guzzlehttp/psr7/src/Query.phpnu[PK!\U  &cguzzlehttp/psr7/src/DroppingStream.phpnu[PK!,'guzzlehttp/psr7/src/MultipartStream.phpnu[PK!Ӳ==guzzlehttp/psr7/src/Utils.phpnu[PK!uC$>0guzzlehttp/psr7/src/AppendStream.phpnu[PK!O-""#Hguzzlehttp/psr7/src/UriResolver.phpnu[PK!Nu u ,:kguzzlehttp/psr7/src/StreamDecoratorTrait.phpnu[PK!cSqq% yguzzlehttp/psr7/src/StreamWrapper.phpnu[PK!,*!!щguzzlehttp/psr7/src/Message.phpnu[PK!I6VVguzzlehttp/psr7/src/Uri.phpnu[PK!m5H-nn%guzzlehttp/psr7/src/InflateStream.phpnu[PK!ܴ& guzzlehttp/psr7/src/LazyOpenStream.phpnu[PK!K#guzzlehttp/psr7/src/HttpFactory.phpnu[PK!"ƴ%guzzlehttp/psr7/src/UriComparator.phpnu[PK!L#m$guzzlehttp/psr7/src/LimitStream.phpnu[PK!b9665guzzlehttp/psr7/src/Stream.phpnu[PK! }7Sguzzlehttp/psr7/src/Exception/MalformedUriException.phpnu[PK!# ֖!!%~Tguzzlehttp/psr7/src/UriNormalizer.phpnu[PK!2\qqvguzzlehttp/psr7/src/Header.phpnu[PK!C;3Tleague/oauth2-client/src/Tool/QueryBuilderTrait.phpnu[PK!S6Oleague/oauth2-client/src/Tool/GuardedPropertyTrait.phpnu[PK!Ǵ0ϑleague/oauth2-client/src/Tool/RequestFactory.phpnu[PK! 4league/oauth2-client/src/Tool/ArrayAccessorTrait.phpnu[PK!0[ [ 7league/oauth2-client/src/Tool/MacAuthorizationTrait.phpnu[PK!-N(: : 7league/oauth2-client/src/Tool/ProviderRedirectTrait.phpnu[PK!,8Zleague/oauth2-client/src/Tool/RequiredParameterTrait.phpnu[PK!)ƌ{{:league/oauth2-client/src/Tool/BearerAuthorizationTrait.phpnu[PK! /league/oauth2-client/src/Grant/GrantFactory.phpnu[PK!^ڿU4league/oauth2-client/src/Grant/ClientCredentials.phpnu[PK!IsJ??+Xleague/oauth2-client/src/Grant/Password.phpnu[PK!)g,/league/oauth2-client/src/Grant/RefreshToken.phpnu[PK!F!!4kleague/oauth2-client/src/Grant/AuthorizationCode.phpnu[PK!/? 0league/oauth2-client/src/Grant/AbstractGrant.phpnu[PK! +$$Bleague/oauth2-client/src/Grant/Exception/InvalidGrantException.phpnu[PK!GCleague/oauth2-client/src/OptionProvider/OptionProviderInterface.phpnu[PK!d!!Bleague/oauth2-client/src/OptionProvider/PostAuthOptionProvider.phpnu[PK!G5league/oauth2-client/src/OptionProvider/HttpBasicAuthOptionProvider.phpnu[PK!+447league/oauth2-client/src/Token/AccessTokenInterface.phpnu[PK!ElHHD1league/oauth2-client/src/Token/ResourceOwnerAccessTokenInterface.phpnu[PK!ʾ~~. league/oauth2-client/src/Token/AccessToken.phpnu[PK!V|<#league/oauth2-client/src/Provider/ResourceOwnerInterface.phpnu[PK!h8hh67(league/oauth2-client/src/Provider/AbstractProvider.phpnu[PK!*:league/oauth2-client/src/Provider/GenericResourceOwner.phpnu[PK!>Iؗleague/oauth2-client/src/Provider/Exception/IdentityProviderException.phpnu[PK!65 league/oauth2-client/src/Provider/GenericProvider.phpnu[PK!;Ar1upsr/http-client/src/NetworkExceptionInterface.phpnu[PK!qhh'˷psr/http-client/src/ClientInterface.phpnu[PK!-0psr/http-client/src/ClientExceptionInterface.phpnu[PK!v׭1psr/http-client/src/RequestExceptionInterface.phpnu[PK!yxx,psr/http-factory/src/UriFactoryInterface.phpnu[PK!G&&0psr/http-factory/src/RequestFactoryInterface.phpnu[PK!+}}5 psr/http-factory/src/UploadedFileFactoryInterface.phpnu[PK!/6psr/http-factory/src/ServerRequestFactoryInterface.phpnu[PK!UD/'psr/http-factory/src/StreamFactoryInterface.phpnu[PK!+OUU1psr/http-factory/src/ResponseFactoryInterface.phpnu[PK!V2 2 #=psr/log/Psr/Log/LoggerInterface.phpnu[PK!K]IIpsr/log/Psr/Log/LogLevel.phpnu[PK!Ϯ$Wpsr/log/Psr/Log/LoggerAwareTrait.phpnu[PK!H''epsr/log/Psr/Log/LoggerTrait.phpnu[PK!RR(psr/log/Psr/Log/LoggerAwareInterface.phpnu[PK!nJpsr/log/Psr/Log/NullLogger.phpnu[PK! "psr/log/Psr/Log/AbstractLogger.phpnu[PK!\Ppp, psr/log/Psr/Log/InvalidArgumentException.phpnu[PK!o_//0 psr/container/src/NotFoundExceptionInterface.phpnu[PK!Yo1v psr/container/src/ContainerExceptionInterface.phpnu[PK! YY( psr/container/src/ContainerInterface.phpnu[PK!W&  ( psr/http-message/src/StreamInterface.phpnu[PK! *! psr/http-message/src/ResponseInterface.phpnu[PK!Β), psr/http-message/src/MessageInterface.phpnu[PK!y|7)7)/J psr/http-message/src/ServerRequestInterface.phpnu[PK!NJ)s psr/http-message/src/RequestInterface.phpnu[PK!S33% psr/http-message/src/UriInterface.phpnu[PK!" .y psr/http-message/src/UploadedFileInterface.phpnu[PK!̏||> wordproof/wordpress-sdk/app/Exceptions/ValidationException.phpnu[PK!Ra9p wordproof/wordpress-sdk/app/Config/AppConfigInterface.phpnu[PK!OD  3 wordproof/wordpress-sdk/app/Config/RoutesConfig.phpnu[PK!kG557 wordproof/wordpress-sdk/app/Config/DefaultAppConfig.phpnu[PK!%ͩ4 wordproof/wordpress-sdk/app/Config/ScriptsConfig.phpnu[PK!3+8 wordproof/wordpress-sdk/app/Config/EnvironmentConfig.phpnu[PK!,4 wordproof/wordpress-sdk/app/Config/OptionsConfig.phpnu[PK!͌%- wordproof/wordpress-sdk/app/Config/Config.phpnu[PK!% ? wordproof/wordpress-sdk/app/Controllers/TimestampController.phpnu[PK!m9zI wordproof/wordpress-sdk/app/Controllers/PostEditorTimestampController.phpnu[PK!> wordproof/wordpress-sdk/app/Controllers/IdentityController.phpnu[PK!L --= wordproof/wordpress-sdk/app/Controllers/RestApiController.phpnu[PK!Y#66D*H wordproof/wordpress-sdk/app/Controllers/AuthenticationController.phpnu[PK!YDN wordproof/wordpress-sdk/app/Controllers/PostEditorDataController.phpnu[PK!_ɋA'V wordproof/wordpress-sdk/app/Controllers/CertificateController.phpnu[PK!V;  <#e wordproof/wordpress-sdk/app/Controllers/NoticeController.phpnu[PK!+QQ>p wordproof/wordpress-sdk/app/Controllers/SettingsController.phpnu[PK!?,Qv wordproof/wordpress-sdk/app/WordPressSDK.phpnu[PK!v~n5K wordproof/wordpress-sdk/app/Helpers/OptionsHelper.phpnu[PK!WK..4 wordproof/wordpress-sdk/app/Helpers/EscapeHelper.phpnu[PK!'@y9B wordproof/wordpress-sdk/app/Helpers/CertificateHelper.phpnu[PK!I1TT<[ wordproof/wordpress-sdk/app/Helpers/AuthenticationHelper.phpnu[PK!f+7 wordproof/wordpress-sdk/app/Helpers/TransientHelper.phpnu[PK!~3K wordproof/wordpress-sdk/app/Helpers/AdminHelper.phpnu[PK!,9 wordproof/wordpress-sdk/app/Helpers/EnvironmentHelper.phpnu[PK!ROa4 wordproof/wordpress-sdk/app/Helpers/SchemaHelper.phpnu[PK!9j+ 3 wordproof/wordpress-sdk/app/Helpers/AssetHelper.phpnu[PK!x1ll; wordproof/wordpress-sdk/app/Helpers/ClassicNoticeHelper.phpnu[PK!}+/}}6 wordproof/wordpress-sdk/app/Helpers/SanitizeHelper.phpnu[PK!6 wordproof/wordpress-sdk/app/Helpers/PostTypeHelper.phpnu[PK!b8 wordproof/wordpress-sdk/app/Helpers/PostEditorHelper.phpnu[PK!Ep6D wordproof/wordpress-sdk/app/Helpers/SettingsHelper.phpnu[PK!]%d~~5 wordproof/wordpress-sdk/app/Helpers/RestApiHelper.phpnu[PK!.A 7n wordproof/wordpress-sdk/app/Helpers/TimestampHelper.phpnu[PK!yss6^ wordproof/wordpress-sdk/app/Helpers/PostMetaHelper.phpnu[PK!Yw87! wordproof/wordpress-sdk/app/Helpers/ReflectionHelper.phpnu[PK!3TJJ6# wordproof/wordpress-sdk/app/Helpers/RedirectHelper.phpnu[PK!GG4O% wordproof/wordpress-sdk/app/Helpers/StringHelper.phpnu[PK!N4^7( wordproof/wordpress-sdk/app/Helpers/AppConfigHelper.phpnu[PK!;B. wordproof/wordpress-sdk/app/Translations/TranslationsInterface.phpnu[PK!;m@f0 wordproof/wordpress-sdk/app/Translations/DefaultTranslations.phpnu[PK!˨AA8 wordproof/wordpress-sdk/app/DataTransferObjects/TimestampData.phpnu[PK!L7B B .< wordproof/wordpress-sdk/app/Support/Loader.phpnu[PK!s>C6E wordproof/wordpress-sdk/app/Support/Authentication.phpnu[PK!H ZZ0[ wordproof/wordpress-sdk/app/Support/Settings.phpnu[PK!;WRd0` wordproof/wordpress-sdk/app/Support/Template.phpnu[PK!-0ܡ1q wordproof/wordpress-sdk/app/Support/Timestamp.phpnu[PK!1@'"+v wordproof/wordpress-sdk/app/Support/Api.phpnu[PK!՘%G| wordproof/wordpress-sdk/build/data.jsnu[PK!9 wordproof/wordpress-sdk/build/wordproof-classic-editor.jsnu[PK!yrr; wordproof/wordpress-sdk/build/wordproof-elementor-editor.jsnu[PK!NaO007l wordproof/wordpress-sdk/build/wordproof-block-editor.jsnu[PK!rg*U symfony/deprecation-contracts/function.phpnu[PK!)  = symfony/dependency-injection/ResettableContainerInterface.phpnu[PK![OO* symfony/dependency-injection/Container.phpnu[PK!tf=O> symfony/dependency-injection/Argument/RewindableGenerator.phpnu[PK!bm,AALGB symfony/dependency-injection/Exception/ServiceCircularReferenceException.phpnu[PK!&  9G symfony/dependency-injection/Exception/LogicException.phpnu[PK!Y[KK;yI symfony/dependency-injection/Exception/RuntimeException.phpnu[PK!͇N/L symfony/dependency-injection/Exception/ParameterCircularReferenceException.phpnu[PK!annCP symfony/dependency-injection/Exception/ServiceNotFoundException.phpnu[PK!rC?}X symfony/dependency-injection/Exception/EnvNotFoundException.phpnu[PK!*~iiC[ symfony/dependency-injection/Exception/InvalidArgumentException.phpnu[PK!\œ=^ symfony/dependency-injection/Exception/ExceptionInterface.phpnu[PK! Ca symfony/dependency-injection/ParameterBag/ParameterBagInterface.phpnu[PK!kD%%:l symfony/dependency-injection/ParameterBag/ParameterBag.phpnu[PK!@ symfony/dependency-injection/ParameterBag/FrozenParameterBag.phpnu[PK!ꟿH! symfony/dependency-injection/ParameterBag/EnvPlaceholderParameterBag.phpnu[PK! 3 symfony/dependency-injection/ContainerInterface.phpnu[PKq\·