first commit

This commit is contained in:
Sampanna Rimal
2024-08-27 17:48:06 +05:45
commit 53c0140f58
10839 changed files with 1125847 additions and 0 deletions

20
vendor/fruitcake/php-cors/LICENSE vendored Normal file
View File

@ -0,0 +1,20 @@
Copyright (c) 2013-2017 Alexander <iam.asm89@gmail.com>
Copyright (c) 2017-2022 Barryvdh <barryvdh@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

78
vendor/fruitcake/php-cors/README.md vendored Normal file
View File

@ -0,0 +1,78 @@
# CORS for PHP (using the Symfony HttpFoundation)
[![Unit Tests](https://github.com/fruitcake/php-cors/actions/workflows/run-tests.yml/badge.svg)](https://github.com/fruitcake/php-cors/actions)
[![PHPStan Level 9](https://img.shields.io/badge/PHPStan-Level%209-blue)](https://github.com/fruitcake/php-cors/actions)
[![Code Coverage](https://img.shields.io/badge/CodeCoverage-100%25-brightgreen)](https://github.com/fruitcake/php-cors/actions/workflows/run-coverage.yml)
[![Packagist License](https://poser.pugx.org/fruitcake/php-cors/license.png)](http://choosealicense.com/licenses/mit/)
[![Latest Stable Version](https://poser.pugx.org/fruitcake/php-cors/version.png)](https://packagist.org/packages/fruitcake/php-cors)
[![Total Downloads](https://poser.pugx.org/fruitcake/php-cors/d/total.png)](https://packagist.org/packages/fruitcake/php-cors)
[![Fruitcake](https://img.shields.io/badge/Powered%20By-Fruitcake-b2bc35.svg)](https://fruitcake.nl/)
Library and middleware enabling cross-origin resource sharing for your
http-{foundation,kernel} using application. It attempts to implement the
[W3C Recommendation] for cross-origin resource sharing.
[W3C Recommendation]: http://www.w3.org/TR/cors/
> Note: This is a standalone fork of https://github.com/asm89/stack-cors and is compatible with the options for CorsService.
## Installation
Require `fruitcake/php-cors` using composer.
## Usage
This package can be used as a library. You can use it in your framework using:
- [Stack middleware](http://stackphp.com/): https://github.com/asm89/stack-cors
- [Laravel](https://laravel.com): https://github.com/fruitcake/laravel-cors
### Options
| Option | Description | Default value |
|------------------------|------------------------------------------------------------|---------------|
| allowedMethods | Matches the request method. | `[]` |
| allowedOrigins | Matches the request origin. | `[]` |
| allowedOriginsPatterns | Matches the request origin with `preg_match`. | `[]` |
| allowedHeaders | Sets the Access-Control-Allow-Headers response header. | `[]` |
| exposedHeaders | Sets the Access-Control-Expose-Headers response header. | `[]` |
| maxAge | Sets the Access-Control-Max-Age response header. | `0` |
| supportsCredentials | Sets the Access-Control-Allow-Credentials header. | `false` |
The _allowedMethods_ and _allowedHeaders_ options are case-insensitive.
You don't need to provide both _allowedOrigins_ and _allowedOriginsPatterns_. If one of the strings passed matches, it is considered a valid origin. A wildcard in allowedOrigins will be converted to a pattern.
If `['*']` is provided to _allowedMethods_, _allowedOrigins_ or _allowedHeaders_ all methods / origins / headers are allowed.
> Note: Allowing a single static origin will improve cacheability.
### Example: using the library
```php
<?php
use Fruitcake\Cors\CorsService;
$cors = new CorsService([
'allowedHeaders' => ['x-allowed-header', 'x-other-allowed-header'],
'allowedMethods' => ['DELETE', 'GET', 'POST', 'PUT'],
'allowedOrigins' => ['http://localhost', 'https://*.example.com'],
'allowedOriginsPatterns' => ['/localhost:\d/'],
'exposedHeaders' => ['Content-Encoding'],
'maxAge' => 0,
'supportsCredentials' => false,
]);
$cors->addActualRequestHeaders(Response $response, $origin);
$cors->handlePreflightRequest(Request $request);
$cors->isActualRequestAllowed(Request $request);
$cors->isCorsRequest(Request $request);
$cors->isPreflightRequest(Request $request);
```
## License
Released under the MIT License, see [LICENSE](LICENSE).
> This package is split-off from https://github.com/asm89/stack-cors and developed as stand-alone library since 2022

49
vendor/fruitcake/php-cors/composer.json vendored Normal file
View File

@ -0,0 +1,49 @@
{
"name": "fruitcake/php-cors",
"description": "Cross-origin resource sharing library for the Symfony HttpFoundation",
"keywords": ["cors", "symfony", "laravel"],
"homepage": "https://github.com/fruitcake/php-cors",
"type": "library",
"license": "MIT",
"authors": [
{
"name": "Fruitcake",
"homepage": "https://fruitcake.nl"
},
{
"name": "Barryvdh",
"email": "barryvdh@gmail.com"
}
],
"require": {
"php": "^7.4|^8.0",
"symfony/http-foundation": "^4.4|^5.4|^6|^7"
},
"require-dev": {
"phpunit/phpunit": "^9",
"squizlabs/php_codesniffer": "^3.5",
"phpstan/phpstan": "^1.4"
},
"autoload": {
"psr-4": {
"Fruitcake\\Cors\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Fruitcake\\Cors\\Tests\\": "tests/"
}
},
"scripts": {
"actions": "composer test && composer analyse && composer check-style",
"test": "phpunit",
"analyse": "phpstan analyse src tests --level=9",
"check-style": "phpcs -p --standard=PSR12 --exclude=Generic.Files.LineLength --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 src tests",
"fix-style": "phpcbf -p --standard=PSR12 --exclude=Generic.Files.LineLength --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 src tests"
},
"extra": {
"branch-alias": {
"dev-master": "1.2-dev"
}
}
}

View File

@ -0,0 +1,285 @@
<?php
/*
* This file is part of fruitcake/php-cors and was originally part of asm89/stack-cors
*
* (c) Alexander <iam.asm89@gmail.com>
* (c) Barryvdh <barryvdh@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Fruitcake\Cors;
use Fruitcake\Cors\Exceptions\InvalidOptionException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* @phpstan-type CorsInputOptions array{
* 'allowedOrigins'?: string[],
* 'allowedOriginsPatterns'?: string[],
* 'supportsCredentials'?: bool,
* 'allowedHeaders'?: string[],
* 'allowedMethods'?: string[],
* 'exposedHeaders'?: string[]|false,
* 'maxAge'?: int|bool|null,
* 'allowed_origins'?: string[],
* 'allowed_origins_patterns'?: string[],
* 'supports_credentials'?: bool,
* 'allowed_headers'?: string[],
* 'allowed_methods'?: string[],
* 'exposed_headers'?: string[]|false,
* 'max_age'?: int|bool|null
* }
*
*/
class CorsService
{
/** @var string[] */
private array $allowedOrigins = [];
/** @var string[] */
private array $allowedOriginsPatterns = [];
/** @var string[] */
private array $allowedMethods = [];
/** @var string[] */
private array $allowedHeaders = [];
/** @var string[] */
private array $exposedHeaders = [];
private bool $supportsCredentials = false;
private ?int $maxAge = 0;
private bool $allowAllOrigins = false;
private bool $allowAllMethods = false;
private bool $allowAllHeaders = false;
/**
* @param CorsInputOptions $options
*/
public function __construct(array $options = [])
{
if ($options) {
$this->setOptions($options);
}
}
/**
* @param CorsInputOptions $options
*/
public function setOptions(array $options): void
{
$this->allowedOrigins = $options['allowedOrigins'] ?? $options['allowed_origins'] ?? $this->allowedOrigins;
$this->allowedOriginsPatterns =
$options['allowedOriginsPatterns'] ?? $options['allowed_origins_patterns'] ?? $this->allowedOriginsPatterns;
$this->allowedMethods = $options['allowedMethods'] ?? $options['allowed_methods'] ?? $this->allowedMethods;
$this->allowedHeaders = $options['allowedHeaders'] ?? $options['allowed_headers'] ?? $this->allowedHeaders;
$this->supportsCredentials =
$options['supportsCredentials'] ?? $options['supports_credentials'] ?? $this->supportsCredentials;
$maxAge = $this->maxAge;
if (array_key_exists('maxAge', $options)) {
$maxAge = $options['maxAge'];
} elseif (array_key_exists('max_age', $options)) {
$maxAge = $options['max_age'];
}
$this->maxAge = $maxAge === null ? null : (int)$maxAge;
$exposedHeaders = $options['exposedHeaders'] ?? $options['exposed_headers'] ?? $this->exposedHeaders;
$this->exposedHeaders = $exposedHeaders === false ? [] : $exposedHeaders;
$this->normalizeOptions();
}
private function normalizeOptions(): void
{
// Normalize case
$this->allowedHeaders = array_map('strtolower', $this->allowedHeaders);
$this->allowedMethods = array_map('strtoupper', $this->allowedMethods);
// Normalize ['*'] to true
$this->allowAllOrigins = in_array('*', $this->allowedOrigins);
$this->allowAllHeaders = in_array('*', $this->allowedHeaders);
$this->allowAllMethods = in_array('*', $this->allowedMethods);
// Transform wildcard pattern
if (!$this->allowAllOrigins) {
foreach ($this->allowedOrigins as $origin) {
if (strpos($origin, '*') !== false) {
$this->allowedOriginsPatterns[] = $this->convertWildcardToPattern($origin);
}
}
}
}
/**
* Create a pattern for a wildcard, based on Str::is() from Laravel
*
* @see https://github.com/laravel/framework/blob/5.5/src/Illuminate/Support/Str.php
* @param string $pattern
* @return string
*/
private function convertWildcardToPattern($pattern)
{
$pattern = preg_quote($pattern, '#');
// Asterisks are translated into zero-or-more regular expression wildcards
// to make it convenient to check if the strings starts with the given
// pattern such as "*.example.com", making any string check convenient.
$pattern = str_replace('\*', '.*', $pattern);
return '#^' . $pattern . '\z#u';
}
public function isCorsRequest(Request $request): bool
{
return $request->headers->has('Origin');
}
public function isPreflightRequest(Request $request): bool
{
return $request->getMethod() === 'OPTIONS' && $request->headers->has('Access-Control-Request-Method');
}
public function handlePreflightRequest(Request $request): Response
{
$response = new Response();
$response->setStatusCode(204);
return $this->addPreflightRequestHeaders($response, $request);
}
public function addPreflightRequestHeaders(Response $response, Request $request): Response
{
$this->configureAllowedOrigin($response, $request);
if ($response->headers->has('Access-Control-Allow-Origin')) {
$this->configureAllowCredentials($response, $request);
$this->configureAllowedMethods($response, $request);
$this->configureAllowedHeaders($response, $request);
$this->configureMaxAge($response, $request);
}
return $response;
}
public function isOriginAllowed(Request $request): bool
{
if ($this->allowAllOrigins === true) {
return true;
}
$origin = (string) $request->headers->get('Origin');
if (in_array($origin, $this->allowedOrigins)) {
return true;
}
foreach ($this->allowedOriginsPatterns as $pattern) {
if (preg_match($pattern, $origin)) {
return true;
}
}
return false;
}
public function addActualRequestHeaders(Response $response, Request $request): Response
{
$this->configureAllowedOrigin($response, $request);
if ($response->headers->has('Access-Control-Allow-Origin')) {
$this->configureAllowCredentials($response, $request);
$this->configureExposedHeaders($response, $request);
}
return $response;
}
private function configureAllowedOrigin(Response $response, Request $request): void
{
if ($this->allowAllOrigins === true && !$this->supportsCredentials) {
// Safe+cacheable, allow everything
$response->headers->set('Access-Control-Allow-Origin', '*');
} elseif ($this->isSingleOriginAllowed()) {
// Single origins can be safely set
$response->headers->set('Access-Control-Allow-Origin', array_values($this->allowedOrigins)[0]);
} else {
// For dynamic headers, set the requested Origin header when set and allowed
if ($this->isCorsRequest($request) && $this->isOriginAllowed($request)) {
$response->headers->set('Access-Control-Allow-Origin', (string) $request->headers->get('Origin'));
}
$this->varyHeader($response, 'Origin');
}
}
private function isSingleOriginAllowed(): bool
{
if ($this->allowAllOrigins === true || count($this->allowedOriginsPatterns) > 0) {
return false;
}
return count($this->allowedOrigins) === 1;
}
private function configureAllowedMethods(Response $response, Request $request): void
{
if ($this->allowAllMethods === true) {
$allowMethods = strtoupper((string) $request->headers->get('Access-Control-Request-Method'));
$this->varyHeader($response, 'Access-Control-Request-Method');
} else {
$allowMethods = implode(', ', $this->allowedMethods);
}
$response->headers->set('Access-Control-Allow-Methods', $allowMethods);
}
private function configureAllowedHeaders(Response $response, Request $request): void
{
if ($this->allowAllHeaders === true) {
$allowHeaders = (string) $request->headers->get('Access-Control-Request-Headers');
$this->varyHeader($response, 'Access-Control-Request-Headers');
} else {
$allowHeaders = implode(', ', $this->allowedHeaders);
}
$response->headers->set('Access-Control-Allow-Headers', $allowHeaders);
}
private function configureAllowCredentials(Response $response, Request $request): void
{
if ($this->supportsCredentials) {
$response->headers->set('Access-Control-Allow-Credentials', 'true');
}
}
private function configureExposedHeaders(Response $response, Request $request): void
{
if ($this->exposedHeaders) {
$response->headers->set('Access-Control-Expose-Headers', implode(', ', $this->exposedHeaders));
}
}
private function configureMaxAge(Response $response, Request $request): void
{
if ($this->maxAge !== null) {
$response->headers->set('Access-Control-Max-Age', (string) $this->maxAge);
}
}
public function varyHeader(Response $response, string $header): Response
{
if (!$response->headers->has('Vary')) {
$response->headers->set('Vary', $header);
} elseif (!in_array($header, explode(', ', (string) $response->headers->get('Vary')))) {
$response->headers->set('Vary', ((string) $response->headers->get('Vary')) . ', ' . $header);
}
return $response;
}
}

View File

@ -0,0 +1,16 @@
<?php
/*
* This file is part of fruitcake/php-cors
*
* (c) Barryvdh <barryvdh@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Fruitcake\Cors\Exceptions;
class InvalidOptionException extends \RuntimeException
{
}