public function buildHeaderValue(Request $request, array $signatures = null)
{
$policy = array();
if (isset($signatures['script-src'])) {
$signatures['script-src'] = implode(' ', array_map(function ($value) {
return sprintf('\'%s\'', $value);
}, $signatures['script-src']));
}
if (isset($signatures['style-src'])) {
$signatures['style-src'] = implode(' ', array_map(function ($value) {
return sprintf('\'%s\'', $value);
}, $signatures['style-src']));
}
$availableDirectives = $this->policyManager->getAvailableDirective($request);
foreach ($this->directiveValues as $name => $value) {
if (!in_array($name, $availableDirectives, true)) {
continue;
}
if (true === $value) {
$policy[] = $name;
} elseif (isset($signatures[$name])) {
// since a hash / nonce is used (CSP level2)
// In case the browsers support CSP level 2, it would discard the 'unsafe-inline' directive
// let's ensure that it's backward compatible with CSP level 1 (all browsers are not compatible)
// this is the recommended way to deal with this.
if (false === strpos($value, '\'unsafe-inline\'') && $this->level1Fallback) {
$policy[] = $name . ' ' . $value . ' ' . '\'unsafe-inline\' ' . $signatures[$name];
} else {
$policy[] = $name . ' ' . $value . ' ' . $signatures[$name];
}
} elseif ($this->canNotBeFallbackedByDefault($name, $value)) {
$policy[] = $name . ' ' . $value;
}
}
if (!empty($signatures)) {
$defaultSrc = $this->getDirective('default-src');
$isDefaultSrcSet = $defaultSrc !== '';
if ($isDefaultSrcSet && false === strpos($defaultSrc, '\'unsafe-inline\'')) {
$unsafeInline = $this->level1Fallback ? ' \'unsafe-inline\'' : '';
if (empty($this->directiveValues['script-src']) && isset($signatures['script-src'])) {
$policy[] = 'script-src ' . $defaultSrc . $unsafeInline . ' ' . $signatures['script-src'];
}
if (empty($this->directiveValues['style-src']) && isset($signatures['style-src'])) {
$policy[] = 'style-src ' . $defaultSrc . $unsafeInline . ' ' . $signatures['style-src'];
}
}
}
return implode('; ', $policy);
}