mirror of
https://gitlab.com/signalytic/client-external/streamline/streamline-emr.git
synced 2026-09-11 18:51:31 +00:00
Build modified streamline images
The official image from streamline does not currently work for the arm64 platform. As a temporary measure, the source code and docker build scripts have been lifted from the official images and are used to build locally. Some additional modifications are made to reduce overall image size, these are documented in docker/README.md
This commit is contained in:
@@ -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.
|
||||
@@ -0,0 +1,78 @@
|
||||
# CORS for PHP (using the Symfony HttpFoundation)
|
||||
|
||||
[](https://github.com/fruitcake/php-cors/actions)
|
||||
[](https://github.com/fruitcake/php-cors/actions)
|
||||
[](https://github.com/fruitcake/php-cors/actions/workflows/run-coverage.yml)
|
||||
[](http://choosealicense.com/licenses/mit/)
|
||||
[](https://packagist.org/packages/fruitcake/php-cors)
|
||||
[](https://packagist.org/packages/fruitcake/php-cors)
|
||||
[](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
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
+16
@@ -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
|
||||
{
|
||||
}
|
||||
Reference in New Issue
Block a user