Completed
Pull Request — master (#21)
by Thomas
07:43 queued 03:05
created

Policy::reportTo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Spatie\Csp\Policies;
4
5
use Spatie\Csp\Directive;
6
use Illuminate\Http\Request;
7
use Spatie\Csp\Exceptions\InvalidDirective;
8
use Symfony\Component\HttpFoundation\Response;
9
10
abstract class Policy
11
{
12
    protected $directives = [];
13
14
    protected $reportOnly = false;
15
16
    abstract public function configure();
17
18
    /**
19
     * @param string $directive
20
     * @param string|array $values
21
     *
22
     * @return \Spatie\Csp\Policies\Policy
23
     *
24
     * @throws \Spatie\Csp\Exceptions\InvalidDirective
25
     */
26
    public function addDirective(string $directive, $values): self
27
    {
28
        $this->guardAgainstInvalidDirectives($directive);
29
30
        foreach (array_wrap($values) as $value) {
31
            $sanitizedValue = $this->sanitizeValue($value);
32
33
            if (! in_array($sanitizedValue, $this->directives[$directive] ?? [])) {
34
                $this->directives[$directive][] = $sanitizedValue;
35
            }
36
        }
37
38
        return $this;
39
    }
40
41
    public function reportOnly(): self
42
    {
43
        $this->reportOnly = true;
44
45
        return $this;
46
    }
47
48
    public function enforce(): self
49
    {
50
        $this->reportOnly = false;
51
52
        return $this;
53
    }
54
55
    public function reportTo(string $uri): self
56
    {
57
        $this->directives['report-uri'] = [$uri];
58
59
        return $this;
60
    }
61
62
    public function shouldBeApplied(Request $request, Response $response): bool
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $response is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
63
    {
64
        return config('csp.enabled');
65
    }
66
67
    public function addNonceForDirective(string $directive): self
68
    {
69
        return $this->addDirective($directive, "'nonce-".app('csp-nonce')."'");
70
    }
71
72
    /**
73
     * @param string|array $values
74
     *
75
     * @return \Spatie\Csp\Policies\Policy
76
     *
77
     * @throws \Spatie\Csp\Exceptions\InvalidDirective
78
     */
79
    public function addFrame($values): self
80
    {
81
        return $this
82
            ->addDirective(Directive::WORKER, $values)
83
            ->addDirective(Directive::CHILD, $values)
84
            ->addDirective(Directive::FRAME, $values);
85
    }
86
87
    public function applyTo(Response $response)
88
    {
89
        $this->configure();
90
91
        $headerName = $this->reportOnly
92
            ? 'Content-Security-Policy-Report-Only'
93
            : 'Content-Security-Policy';
94
95
        if ($response->headers->has($headerName)) {
96
            return;
97
        }
98
99
        $response->headers->set($headerName, (string) $this);
100
    }
101
102
    public function __toString()
103
    {
104
        return collect($this->directives)
105
            ->map(function (array $values, string $directive) {
106
                $valueString = implode(' ', $values);
107
108
                return "{$directive} {$valueString}";
109
            })
110
            ->implode(';');
111
    }
112
113
    protected function guardAgainstInvalidDirectives(string $directive)
114
    {
115
        if (! Directive::isValid($directive)) {
116
            throw InvalidDirective::notSupported($directive);
117
        }
118
    }
119
120
    protected function sanitizeValue(string $value): string
121
    {
122
        $specialDirectiveValues = [
123
            'none',
124
            'report-sample',
125
            'self',
126
            'strict-dynamic',
127
            'unsafe-eval',
128
            'unsafe-inline',
129
        ];
130
131
        if (in_array($value, $specialDirectiveValues)) {
132
            return "'{$value}'";
133
        }
134
135
        return $value;
136
    }
137
}
138