Skip to content

Commit

Permalink
Added support for Permissions-Policy: as a separate signature and tog…
Browse files Browse the repository at this point in the history
…gle for `features`

`report-uri` is now sent only if flag is provided
Fix for `Allow-Origin` headers when supplying an array
Minor adjustments as per PHPStorm suggestions
  • Loading branch information
Simbiat committed Dec 14, 2021
1 parent efe88a6 commit 783a0bb
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 81 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# HTTP20
Set of classes/functions that may be universally useful for websites (or some parts of them, at least).
They are provided in single library and not separately, not only because of some inter-dependencies, but also because if you are building a website from scratch, most likely, you will be interested in a bunch of them at the same time either way.
They are provided in single library and not separately, not only because of some interdependencies, but also because if you are building a website from scratch, most likely, you will be interested in a bunch of them at the same time either way.

_Notice:_ While some functions (like `zEcho` or different `Headers`) can replace respective logic in server software (like Apache, nginx and such), it's not recommended using them for that because of performance downside. Only use them only if you do not have access to server settings, want to pre-generate the headers to then use in server settings, or you want to customize some of them for specific pages, that you can't target by the server software.

- [HTTP20](#HTTP20)
* [Atom](doc/Atom.md)
Expand Down
10 changes: 6 additions & 4 deletions doc/Headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ performance(int $keepalive = 0, array $clientHints = []);
```
Sends some headers that may improve performance on client side.
`$keepalive` is used for `Keep-Alive` header governing how long the connection should stay up. Header will be sent only if server is using HTTP version other than 2.0.
`$clientHints` instructs clients, that your server supports Client Hints (https://developer.mozilla.org/en-US/docs/Glossary/Client_hints) like DPR, Width, Viewport-Width, Downlink, .etc and client should cache the output accordingly, in order to increase allow cache hitting and thus improve performance.
`$clientHints` instructs clients, that your server supports Client Hints (https://developer.mozilla.org/en-US/docs/Glossary/Client_hints) like DPR, Width, Viewport-Width, Downlink, etc. and client should cache the output accordingly, in order to increase allow cache hitting and thus improve performance.

## security
```php
Expand Down Expand Up @@ -113,19 +113,21 @@ default:

## contentPolicy
```php
contentPolicy(array $cspDirectives = [], bool $reportOnly = false);
contentPolicy(array $cspDirectives = [], bool $reportOnly = false, bool $reportUri = false);
```
Sends Content-Security-Policy header, that improves your page security. It's done separately from other security stuff, because unlike the rest of the headers this is usable only for HTML.
`$cspDirectives` (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) allows you to provide a list of directives and their settings (with validation) to control CSP headers. By default, essentially everything is either disabled or allowed only from `self`, which give you a solid base in terms of restricting access.
`$reportOnly` allows you to control, whether you only report (`Content-Security-Policy-Report-Only`) CPS violations or report **and** block them. Be default it's set as `false` for security enforcement. Note, that if it's set to `true`, but you do not provide `report-to` directive **no** CSP header will be sent, reducing your security. For that reason, if you do want to report, I can suggest using https://rapidsec.com/ which is free. Also note, that while `report-uri` is **temporary** added until `report-to` is supported by all browsers, `report-uri` **will be discarded** if it's provided without `report-to` to encourage the use of a modern directive.
`$reportUri` will add `report-uri` in the headers as well. It is deprecated, thus defaults to `false`, but if you want to support still - you can.

## features
```php
features(array $features = [], bool $forceCheck = true);
features(array $features = [], bool $forceCheck = true, bool $permissions = false);
```
Allows controlling different features through Feature-Policy header. It should only be used, when sending HTML.
Allows controlling different features through `Feature-Policy` header. It should only be used, when sending HTML.
`$features` expects associative array, where each key is name of the policy in lower case and value - expected `allow list`. If an empty array is sent, default values will be applied (most features are disabled).
`$forceCheck` is added for futureproofing, but is enabled by default. If set to `true` will check if the feature is "supported" (present in default array) and value complies with the standard. Setting it to `false` will allow you to utilize a feature or value not yet supported by the library.
`$permissions` is a flag to toggle `Permissions-Policy`, which is replacement for `Feature-Policy` header. Alternatively you can use `features(array $features = [], bool $forceCheck = true)` signature, which will call `features` internally.

## secFetch
```php
Expand Down
42 changes: 21 additions & 21 deletions src/HTTP20/Common.php
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ public function emailValidator(string $string): bool
}
}

#Function to check if string is an URI as per RFC 3986
#Function to check if string is a URI as per RFC 3986
public function uriValidator(string $string): bool
{
if (preg_match('/^(?<scheme>[a-z][a-z0-9+.-]+):(?<authority>\/\/(?<user>[^@]+@)?(?<host>[\p{L}0-9.\-_~]+)(?<port>:\d+)?)?(?<path>(?:[\p{L}0-9-._~]|%[a-f0-9]{2}|[!$&\'()*+,;=:@])+(?:\/(?:[\p{L}0-9-._~]|%[a-f0-9]{2}|[!$&\'()*+,;=:@])*)*|(?:\/(?:[\p{L}0-9-._~]|%[a-f0-9]{2}|[!$&\'()*+,;=:@])+)*)?(?<query>\?(?:[\p{L}0-9-._~]|%[a-f0-9]{2}|[!$&\'()*+,;=:@]|[\/?])+)?(?<fragment>#(?:[\p{L}0-9-._~]|%[a-f0-9]{2}|[!$&\'()*+,;=:@]|[\/?])+)?$/iu', $this->htmlToRFC3986($string)) === 1) {
Expand Down Expand Up @@ -907,15 +907,15 @@ public function reductor(string|array $files, string $type, bool $minify = false
$content = preg_replace(
[
// Remove comment(s)
'#\s*("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')\s*|\s*\/\*(?!\!|@cc_on)(?>[\s\S]*?\*\/)\s*|\s*(?<![\:\=])\/\/.*(?=[\n\r]|$)|^\s*|\s*$#',
'#\s*("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')\s*|\s*/\*(?!!|@cc_on)(?>[\s\S]*?\*/)\s*|\s*(?<![:=])//.*(?=[\n\r]|$)|^\s*|\s*$#',
// Remove white-space(s) outside the string and regex
'#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\'|\/\*(?>.*?\*\/)|\/(?!\/)[^\n\r]*?\/(?=[\s.,;]|[gimuy]|$))|\s*([!%&*\(\)\-=+\[\]\{\}|;:,.<>?\/])\s*#s',
'#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\'|/\*(?>.*?\*/)|/(?!/)[^\n\r]*?/(?=[\s.,;]|[gimuy]|$))|\s*([!%&*()\-=+\[\]{}|;:,.<>?/])\s*#s',
// Remove the last semicolon
'#;+\}#',
'#;+}#',
// Minify object attribute(s) except JSON attribute(s). From `{'foo':'bar'}` to `{foo:'bar'}`
'#([\{,])([\'])(\d+|[a-z_][a-z0-9_]*)\2(?=\:)#i',
'#([{,])([\'])(\d+|[a-z_][a-z0-9_]*)\2(?=:)#i',
// --ibid. From `foo['bar']` to `foo.bar`
'#([a-z0-9_\)\]])\[([\'"])([a-z_][a-z0-9_]*)\2\]#i'
'#([a-z0-9_)\]])\[([\'"])([a-z_][a-z0-9_]*)\2]#i'
],
[
'$1',
Expand All @@ -930,26 +930,26 @@ public function reductor(string|array $files, string $type, bool $minify = false
$content = preg_replace(
[
// Remove comment(s)
'#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')|\/\*(?!\!)(?>.*?\*\/)|^\s*|\s*$#s',
'#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')|/\*(?!!)(?>.*?\*/)|^\s*|\s*$#s',
// Remove unused white-space(s)
'#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\'|\/\*(?>.*?\*\/))|\s*+;\s*+(})\s*+|\s*+([*$~^|]?+=|[{};,>~]|\s(?![0-9\.])|!important\b)\s*+|([[(:])\s++|\s++([])])|\s++(:)\s*+(?!(?>[^{}"\']++|"(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')*+{)|^\s++|\s++\z|(\s)\s+#si',
'#("(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\'|/\*(?>.*?\*/))|\s*+;\s*+(})\s*+|\s*+([*$~^|]?+=|[{};,>~]|\s(?![0-9.])|!important\b)\s*+|([[(:])\s++|\s++([])])|\s++(:)\s*+(?!(?>[^{}"\']++|"(?:[^"\\\]++|\\\.)*+"|\'(?:[^\'\\\\]++|\\\.)*+\')*+{)|^\s++|\s++\z|(\s)\s+#si',
// Replace `0(cm|em|ex|in|mm|pc|pt|px|vh|vw|%)` with `0`
'#(?<=[\s:])(0)(cm|em|ex|in|mm|pc|pt|px|vh|vw|%)#si',
// Replace `:0 0 0 0` with `:0`
'#:(0\s+0|0\s+0\s+0\s+0)(?=[;\}]|\!important)#i',
'#:(0\s+0|0\s+0\s+0\s+0)(?=[;}]|!important)#i',
// Replace `background-position:0` with `background-position:0 0`
'#(background-position):0(?=[;\}])#si',
'#(background-position):0(?=[;}])#si',
// Replace `0.6` with `.6`, but only when preceded by `:`, `,`, `-` or a white-space
'#(?<=[\s:,\-])0+\.(\d+)#s',
// Minify string value
'#(\/\*(?>.*?\*\/))|(?<!content\:)([\'"])([a-z_][a-z0-9\-_]*?)\2(?=[\s\{\}\];,])#si',
'#(\/\*(?>.*?\*\/))|(\burl\()([\'"])([^\s]+?)\3(\))#si',
'#(/\*(?>.*?\*/))|(?<!content:)([\'"])([a-z_][a-z0-9\-_]*?)\2(?=[\s{}\];,])#si',
'#(/\*(?>.*?\*/))|(\burl\()([\'"])([^\s]+?)\3(\))#si',
// Minify HEX color code
'#(?<=[\s:,\-]\#)([a-f0-6]+)\1([a-f0-6]+)\2([a-f0-6]+)\3#i',
// Replace `(border|outline):none` with `(border|outline):0`
'#(?<=[\{;])(border|outline):none(?=[;\}\!])#',
'#(?<=[{;])(border|outline):none(?=[;}!])#',
// Remove empty selector(s)
'#(\/\*(?>.*?\*\/))|(^|[\{\}])(?:[^\s\{\}]+)\{\}#s'
'#(/\*(?>.*?\*/))|(^|[{}])(?:[^\s{}]+){}#s'
],
[
'$1',
Expand Down Expand Up @@ -980,15 +980,15 @@ function($matches) {
'#<(img|input)(>| .*?>)#s',
// Remove a line break and two or more white-space(s) between tag(s)
'#(<!--.*?-->)|(>)(?:\n*|\s{2,})(<)|^\s*|\s*$#s',
'#(<!--.*?-->)|(?<!\>)\s+(<\/.*?>)|(<[^\/]*?>)\s+(?!\<)#s', // t+c || o+t
'#(<!--.*?-->)|(<[^\/]*?>)\s+(<[^\/]*?>)|(<\/.*?>)\s+(<\/.*?>)#s', // o+o || c+c
'#(<!--.*?-->)|(<\/.*?>)\s+(\s)(?!\<)|(?<!\>)\s+(\s)(<[^\/]*?\/?>)|(<[^\/]*?\/?>)\s+(\s)(?!\<)#s', // c+t || t+o || o+t -- separated by long white-space(s)
'#(<!--.*?-->)|(<[^\/]*?>)\s+(<\/.*?>)#s', // empty tag
'#<(img|input)(>| .*?>)<\/\1>#s', // reset previous fix
'#(<!--.*?-->)|(?<!>)\s+(</.*?>)|(<[^/]*?>)\s+(?!<)#s', // t+c || o+t
'#(<!--.*?-->)|(<[^/]*?>)\s+(<[^/]*?>)|(</.*?>)\s+(</.*?>)#s', // o+o || c+c
'#(<!--.*?-->)|(</.*?>)\s+(\s)(?!<)|(?<!>)\s+(\s)(<[^/]*?/?>)|(<[^/]*?/?>)\s+(\s)(?!<)#s', // c+t || t+o || o+t -- separated by long white-space(s)
'#(<!--.*?-->)|(<[^/]*?>)\s+(</.*?>)#s', // empty tag
'#<(img|input)(>| .*?>)</\1>#s', // reset previous fix
'#(&nbsp;)&nbsp;(?![<\s])#', // clean up ...
'#(?<=\>)(&nbsp;)(?=\<)#', // --ibid
'#(?<=>)(&nbsp;)(?=<)#', // --ibid
// Remove HTML comment(s) except IE comment(s)
'#\s*<!--(?!\[if\s).*?-->\s*|(?<!\>)\n+(?=\<[^!])#s'
'#\s*<!--(?!\[if\s).*?-->\s*|(?<!>)\n+(?=<[^!])#s'
],
[
'<$1$2</$1>',
Expand Down
2 changes: 1 addition & 1 deletion src/HTTP20/HTML.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public function timeline(array $items, string $format = 'Y-m-d', bool $asc = fal
#Process current events. Doing this here, because it's less important.
if (!empty($current)) {
#Check if there are finished events in timeline. If there are none - do not create links to "current" ones
if (array_search(0, array_column($toOrder, 'start')) !== false) {
if (in_array(0, array_column($toOrder, 'start'))) {
$currentList = '<div class="timeline_shortcut"><b>Ongoing: </b>';
foreach ($current as $item) {
#Generate id
Expand Down
Loading

0 comments on commit 783a0bb

Please sign in to comment.