Passed
Push — master ( e193e1...458ec3 )
by Roeland
62:30 queued 34:10
created
lib/public/AppFramework/Http/EmptyContentSecurityPolicy.php 1 patch
Indentation   +490 added lines, -490 removed lines patch added patch discarded remove patch
@@ -37,494 +37,494 @@
 block discarded – undo
37 37
  * @since 9.0.0
38 38
  */
39 39
 class EmptyContentSecurityPolicy {
40
-	/** @var bool Whether inline JS snippets are allowed */
41
-	protected $inlineScriptAllowed = null;
42
-	/** @var string Whether JS nonces should be used */
43
-	protected $useJsNonce = null;
44
-	/**
45
-	 * @var bool Whether eval in JS scripts is allowed
46
-	 * TODO: Disallow per default
47
-	 * @link https://github.com/owncloud/core/issues/11925
48
-	 */
49
-	protected $evalScriptAllowed = null;
50
-	/** @var array Domains from which scripts can get loaded */
51
-	protected $allowedScriptDomains = null;
52
-	/**
53
-	 * @var bool Whether inline CSS is allowed
54
-	 * TODO: Disallow per default
55
-	 * @link https://github.com/owncloud/core/issues/13458
56
-	 */
57
-	protected $inlineStyleAllowed = null;
58
-	/** @var array Domains from which CSS can get loaded */
59
-	protected $allowedStyleDomains = null;
60
-	/** @var array Domains from which images can get loaded */
61
-	protected $allowedImageDomains = null;
62
-	/** @var array Domains to which connections can be done */
63
-	protected $allowedConnectDomains = null;
64
-	/** @var array Domains from which media elements can be loaded */
65
-	protected $allowedMediaDomains = null;
66
-	/** @var array Domains from which object elements can be loaded */
67
-	protected $allowedObjectDomains = null;
68
-	/** @var array Domains from which iframes can be loaded */
69
-	protected $allowedFrameDomains = null;
70
-	/** @var array Domains from which fonts can be loaded */
71
-	protected $allowedFontDomains = null;
72
-	/** @var array Domains from which web-workers and nested browsing content can load elements */
73
-	protected $allowedChildSrcDomains = null;
74
-	/** @var array Domains which can embed this Nextcloud instance */
75
-	protected $allowedFrameAncestors = null;
76
-	/** @var array Domains from which web-workers can be loaded */
77
-	protected $allowedWorkerSrcDomains = null;
78
-	/** @var array Domains which can be used as target for forms */
79
-	protected $allowedFormActionDomains = null;
80
-
81
-	/** @var array Locations to report violations to */
82
-	protected $reportTo = null;
83
-
84
-	/**
85
-	 * Whether inline JavaScript snippets are allowed or forbidden
86
-	 * @param bool $state
87
-	 * @return $this
88
-	 * @since 8.1.0
89
-	 * @deprecated 10.0 CSP tokens are now used
90
-	 */
91
-	public function allowInlineScript($state = false) {
92
-		$this->inlineScriptAllowed = $state;
93
-		return $this;
94
-	}
95
-
96
-	/**
97
-	 * Use the according JS nonce
98
-	 * This method is only for CSPMiddleware, custom values are ignored in mergePolicies of ContentSecurityPolicyManager
99
-	 *
100
-	 * @param string $nonce
101
-	 * @return $this
102
-	 * @since 11.0.0
103
-	 */
104
-	public function useJsNonce($nonce) {
105
-		$this->useJsNonce = $nonce;
106
-		return $this;
107
-	}
108
-
109
-	/**
110
-	 * Whether eval in JavaScript is allowed or forbidden
111
-	 * @param bool $state
112
-	 * @return $this
113
-	 * @since 8.1.0
114
-	 * @deprecated Eval should not be used anymore. Please update your scripts. This function will stop functioning in a future version of Nextcloud.
115
-	 */
116
-	public function allowEvalScript($state = true) {
117
-		$this->evalScriptAllowed = $state;
118
-		return $this;
119
-	}
120
-
121
-	/**
122
-	 * Allows to execute JavaScript files from a specific domain. Use * to
123
-	 * allow JavaScript from all domains.
124
-	 * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
125
-	 * @return $this
126
-	 * @since 8.1.0
127
-	 */
128
-	public function addAllowedScriptDomain($domain) {
129
-		$this->allowedScriptDomains[] = $domain;
130
-		return $this;
131
-	}
132
-
133
-	/**
134
-	 * Remove the specified allowed script domain from the allowed domains.
135
-	 *
136
-	 * @param string $domain
137
-	 * @return $this
138
-	 * @since 8.1.0
139
-	 */
140
-	public function disallowScriptDomain($domain) {
141
-		$this->allowedScriptDomains = array_diff($this->allowedScriptDomains, [$domain]);
142
-		return $this;
143
-	}
144
-
145
-	/**
146
-	 * Whether inline CSS snippets are allowed or forbidden
147
-	 * @param bool $state
148
-	 * @return $this
149
-	 * @since 8.1.0
150
-	 */
151
-	public function allowInlineStyle($state = true) {
152
-		$this->inlineStyleAllowed = $state;
153
-		return $this;
154
-	}
155
-
156
-	/**
157
-	 * Allows to execute CSS files from a specific domain. Use * to allow
158
-	 * CSS from all domains.
159
-	 * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
160
-	 * @return $this
161
-	 * @since 8.1.0
162
-	 */
163
-	public function addAllowedStyleDomain($domain) {
164
-		$this->allowedStyleDomains[] = $domain;
165
-		return $this;
166
-	}
167
-
168
-	/**
169
-	 * Remove the specified allowed style domain from the allowed domains.
170
-	 *
171
-	 * @param string $domain
172
-	 * @return $this
173
-	 * @since 8.1.0
174
-	 */
175
-	public function disallowStyleDomain($domain) {
176
-		$this->allowedStyleDomains = array_diff($this->allowedStyleDomains, [$domain]);
177
-		return $this;
178
-	}
179
-
180
-	/**
181
-	 * Allows using fonts from a specific domain. Use * to allow
182
-	 * fonts from all domains.
183
-	 * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
184
-	 * @return $this
185
-	 * @since 8.1.0
186
-	 */
187
-	public function addAllowedFontDomain($domain) {
188
-		$this->allowedFontDomains[] = $domain;
189
-		return $this;
190
-	}
191
-
192
-	/**
193
-	 * Remove the specified allowed font domain from the allowed domains.
194
-	 *
195
-	 * @param string $domain
196
-	 * @return $this
197
-	 * @since 8.1.0
198
-	 */
199
-	public function disallowFontDomain($domain) {
200
-		$this->allowedFontDomains = array_diff($this->allowedFontDomains, [$domain]);
201
-		return $this;
202
-	}
203
-
204
-	/**
205
-	 * Allows embedding images from a specific domain. Use * to allow
206
-	 * images from all domains.
207
-	 * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
208
-	 * @return $this
209
-	 * @since 8.1.0
210
-	 */
211
-	public function addAllowedImageDomain($domain) {
212
-		$this->allowedImageDomains[] = $domain;
213
-		return $this;
214
-	}
215
-
216
-	/**
217
-	 * Remove the specified allowed image domain from the allowed domains.
218
-	 *
219
-	 * @param string $domain
220
-	 * @return $this
221
-	 * @since 8.1.0
222
-	 */
223
-	public function disallowImageDomain($domain) {
224
-		$this->allowedImageDomains = array_diff($this->allowedImageDomains, [$domain]);
225
-		return $this;
226
-	}
227
-
228
-	/**
229
-	 * To which remote domains the JS connect to.
230
-	 * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
231
-	 * @return $this
232
-	 * @since 8.1.0
233
-	 */
234
-	public function addAllowedConnectDomain($domain) {
235
-		$this->allowedConnectDomains[] = $domain;
236
-		return $this;
237
-	}
238
-
239
-	/**
240
-	 * Remove the specified allowed connect domain from the allowed domains.
241
-	 *
242
-	 * @param string $domain
243
-	 * @return $this
244
-	 * @since 8.1.0
245
-	 */
246
-	public function disallowConnectDomain($domain) {
247
-		$this->allowedConnectDomains = array_diff($this->allowedConnectDomains, [$domain]);
248
-		return $this;
249
-	}
250
-
251
-	/**
252
-	 * From which domains media elements can be embedded.
253
-	 * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
254
-	 * @return $this
255
-	 * @since 8.1.0
256
-	 */
257
-	public function addAllowedMediaDomain($domain) {
258
-		$this->allowedMediaDomains[] = $domain;
259
-		return $this;
260
-	}
261
-
262
-	/**
263
-	 * Remove the specified allowed media domain from the allowed domains.
264
-	 *
265
-	 * @param string $domain
266
-	 * @return $this
267
-	 * @since 8.1.0
268
-	 */
269
-	public function disallowMediaDomain($domain) {
270
-		$this->allowedMediaDomains = array_diff($this->allowedMediaDomains, [$domain]);
271
-		return $this;
272
-	}
273
-
274
-	/**
275
-	 * From which domains objects such as <object>, <embed> or <applet> are executed
276
-	 * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
277
-	 * @return $this
278
-	 * @since 8.1.0
279
-	 */
280
-	public function addAllowedObjectDomain($domain) {
281
-		$this->allowedObjectDomains[] = $domain;
282
-		return $this;
283
-	}
284
-
285
-	/**
286
-	 * Remove the specified allowed object domain from the allowed domains.
287
-	 *
288
-	 * @param string $domain
289
-	 * @return $this
290
-	 * @since 8.1.0
291
-	 */
292
-	public function disallowObjectDomain($domain) {
293
-		$this->allowedObjectDomains = array_diff($this->allowedObjectDomains, [$domain]);
294
-		return $this;
295
-	}
296
-
297
-	/**
298
-	 * Which domains can be embedded in an iframe
299
-	 * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
300
-	 * @return $this
301
-	 * @since 8.1.0
302
-	 */
303
-	public function addAllowedFrameDomain($domain) {
304
-		$this->allowedFrameDomains[] = $domain;
305
-		return $this;
306
-	}
307
-
308
-	/**
309
-	 * Remove the specified allowed frame domain from the allowed domains.
310
-	 *
311
-	 * @param string $domain
312
-	 * @return $this
313
-	 * @since 8.1.0
314
-	 */
315
-	public function disallowFrameDomain($domain) {
316
-		$this->allowedFrameDomains = array_diff($this->allowedFrameDomains, [$domain]);
317
-		return $this;
318
-	}
319
-
320
-	/**
321
-	 * Domains from which web-workers and nested browsing content can load elements
322
-	 * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
323
-	 * @return $this
324
-	 * @since 8.1.0
325
-	 * @deprecated 15.0.0 use addAllowedWorkerSrcDomains or addAllowedFrameDomain
326
-	 */
327
-	public function addAllowedChildSrcDomain($domain) {
328
-		$this->allowedChildSrcDomains[] = $domain;
329
-		return $this;
330
-	}
331
-
332
-	/**
333
-	 * Remove the specified allowed child src domain from the allowed domains.
334
-	 *
335
-	 * @param string $domain
336
-	 * @return $this
337
-	 * @since 8.1.0
338
-	 * @deprecated 15.0.0 use the WorkerSrcDomains or FrameDomain
339
-	 */
340
-	public function disallowChildSrcDomain($domain) {
341
-		$this->allowedChildSrcDomains = array_diff($this->allowedChildSrcDomains, [$domain]);
342
-		return $this;
343
-	}
344
-
345
-	/**
346
-	 * Domains which can embed an iFrame of the Nextcloud instance
347
-	 *
348
-	 * @param string $domain
349
-	 * @return $this
350
-	 * @since 13.0.0
351
-	 */
352
-	public function addAllowedFrameAncestorDomain($domain) {
353
-		$this->allowedFrameAncestors[] = $domain;
354
-		return $this;
355
-	}
356
-
357
-	/**
358
-	 * Domains which can embed an iFrame of the Nextcloud instance
359
-	 *
360
-	 * @param string $domain
361
-	 * @return $this
362
-	 * @since 13.0.0
363
-	 */
364
-	public function disallowFrameAncestorDomain($domain) {
365
-		$this->allowedFrameAncestors = array_diff($this->allowedFrameAncestors, [$domain]);
366
-		return $this;
367
-	}
368
-
369
-	/**
370
-	 * Domain from which workers can be loaded
371
-	 *
372
-	 * @param string $domain
373
-	 * @return $this
374
-	 * @since 15.0.0
375
-	 */
376
-	public function addAllowedWorkerSrcDomain(string $domain) {
377
-		$this->allowedWorkerSrcDomains[] = $domain;
378
-		return $this;
379
-	}
380
-
381
-	/**
382
-	 * Remove domain from which workers can be loaded
383
-	 *
384
-	 * @param string $domain
385
-	 * @return $this
386
-	 * @since 15.0.0
387
-	 */
388
-	public function disallowWorkerSrcDomain(string $domain) {
389
-		$this->allowedWorkerSrcDomains = array_diff($this->allowedWorkerSrcDomains, [$domain]);
390
-		return $this;
391
-	}
392
-
393
-	/**
394
-	 * Domain to where forms can submit
395
-	 *
396
-	 * @since 17.0.0
397
-	 *
398
-	 * @return $this
399
-	 */
400
-	public function addAllowedFormActionDomain(string $domain) {
401
-		$this->allowedFormActionDomains[] = $domain;
402
-		return $this;
403
-	}
404
-
405
-	/**
406
-	 * Remove domain to where forms can submit
407
-	 *
408
-	 * @return $this
409
-	 * @since 17.0.0
410
-	 */
411
-	public function disallowFormActionDomain(string $domain) {
412
-		$this->allowedFormActionDomains = array_diff($this->allowedFormActionDomains, [$domain]);
413
-		return $this;
414
-	}
415
-
416
-	/**
417
-	 * Add location to report CSP violations to
418
-	 *
419
-	 * @param string $location
420
-	 * @return $this
421
-	 * @since 15.0.0
422
-	 */
423
-	public function addReportTo(string $location) {
424
-		$this->reportTo[] = $location;
425
-		return $this;
426
-	}
427
-
428
-	/**
429
-	 * Get the generated Content-Security-Policy as a string
430
-	 * @return string
431
-	 * @since 8.1.0
432
-	 */
433
-	public function buildPolicy() {
434
-		$policy = "default-src 'none';";
435
-		$policy .= "base-uri 'none';";
436
-		$policy .= "manifest-src 'self';";
437
-
438
-		if(!empty($this->allowedScriptDomains) || $this->inlineScriptAllowed || $this->evalScriptAllowed) {
439
-			$policy .= 'script-src ';
440
-			if(is_string($this->useJsNonce)) {
441
-				$policy .= '\'nonce-'.base64_encode($this->useJsNonce).'\'';
442
-				$allowedScriptDomains = array_flip($this->allowedScriptDomains);
443
-				unset($allowedScriptDomains['\'self\'']);
444
-				$this->allowedScriptDomains = array_flip($allowedScriptDomains);
445
-				if(count($allowedScriptDomains) !== 0) {
446
-					$policy .= ' ';
447
-				}
448
-			}
449
-			if(is_array($this->allowedScriptDomains)) {
450
-				$policy .= implode(' ', $this->allowedScriptDomains);
451
-			}
452
-			if($this->inlineScriptAllowed) {
453
-				$policy .= ' \'unsafe-inline\'';
454
-			}
455
-			if($this->evalScriptAllowed) {
456
-				$policy .= ' \'unsafe-eval\'';
457
-			}
458
-			$policy .= ';';
459
-		}
460
-
461
-		if(!empty($this->allowedStyleDomains) || $this->inlineStyleAllowed) {
462
-			$policy .= 'style-src ';
463
-			if(is_array($this->allowedStyleDomains)) {
464
-				$policy .= implode(' ', $this->allowedStyleDomains);
465
-			}
466
-			if($this->inlineStyleAllowed) {
467
-				$policy .= ' \'unsafe-inline\'';
468
-			}
469
-			$policy .= ';';
470
-		}
471
-
472
-		if(!empty($this->allowedImageDomains)) {
473
-			$policy .= 'img-src ' . implode(' ', $this->allowedImageDomains);
474
-			$policy .= ';';
475
-		}
476
-
477
-		if(!empty($this->allowedFontDomains)) {
478
-			$policy .= 'font-src ' . implode(' ', $this->allowedFontDomains);
479
-			$policy .= ';';
480
-		}
481
-
482
-		if(!empty($this->allowedConnectDomains)) {
483
-			$policy .= 'connect-src ' . implode(' ', $this->allowedConnectDomains);
484
-			$policy .= ';';
485
-		}
486
-
487
-		if(!empty($this->allowedMediaDomains)) {
488
-			$policy .= 'media-src ' . implode(' ', $this->allowedMediaDomains);
489
-			$policy .= ';';
490
-		}
491
-
492
-		if(!empty($this->allowedObjectDomains)) {
493
-			$policy .= 'object-src ' . implode(' ', $this->allowedObjectDomains);
494
-			$policy .= ';';
495
-		}
496
-
497
-		if(!empty($this->allowedFrameDomains)) {
498
-			$policy .= 'frame-src ';
499
-			$policy .= implode(' ', $this->allowedFrameDomains);
500
-			$policy .= ';';
501
-		}
502
-
503
-		if(!empty($this->allowedChildSrcDomains)) {
504
-			$policy .= 'child-src ' . implode(' ', $this->allowedChildSrcDomains);
505
-			$policy .= ';';
506
-		}
507
-
508
-		if(!empty($this->allowedFrameAncestors)) {
509
-			$policy .= 'frame-ancestors ' . implode(' ', $this->allowedFrameAncestors);
510
-			$policy .= ';';
511
-		}
512
-
513
-		if (!empty($this->allowedWorkerSrcDomains)) {
514
-			$policy .= 'worker-src ' . implode(' ', $this->allowedWorkerSrcDomains);
515
-			$policy .= ';';
516
-		}
517
-
518
-		if (!empty($this->allowedFormActionDomains)) {
519
-			$policy .= 'form-action ' . implode(' ', $this->allowedFormActionDomains);
520
-			$policy .= ';';
521
-		}
522
-
523
-		if (!empty($this->reportTo)) {
524
-			$policy .= 'report-uri ' . implode(' ', $this->reportTo);
525
-			$policy .= ';';
526
-		}
527
-
528
-		return rtrim($policy, ';');
529
-	}
40
+    /** @var bool Whether inline JS snippets are allowed */
41
+    protected $inlineScriptAllowed = null;
42
+    /** @var string Whether JS nonces should be used */
43
+    protected $useJsNonce = null;
44
+    /**
45
+     * @var bool Whether eval in JS scripts is allowed
46
+     * TODO: Disallow per default
47
+     * @link https://github.com/owncloud/core/issues/11925
48
+     */
49
+    protected $evalScriptAllowed = null;
50
+    /** @var array Domains from which scripts can get loaded */
51
+    protected $allowedScriptDomains = null;
52
+    /**
53
+     * @var bool Whether inline CSS is allowed
54
+     * TODO: Disallow per default
55
+     * @link https://github.com/owncloud/core/issues/13458
56
+     */
57
+    protected $inlineStyleAllowed = null;
58
+    /** @var array Domains from which CSS can get loaded */
59
+    protected $allowedStyleDomains = null;
60
+    /** @var array Domains from which images can get loaded */
61
+    protected $allowedImageDomains = null;
62
+    /** @var array Domains to which connections can be done */
63
+    protected $allowedConnectDomains = null;
64
+    /** @var array Domains from which media elements can be loaded */
65
+    protected $allowedMediaDomains = null;
66
+    /** @var array Domains from which object elements can be loaded */
67
+    protected $allowedObjectDomains = null;
68
+    /** @var array Domains from which iframes can be loaded */
69
+    protected $allowedFrameDomains = null;
70
+    /** @var array Domains from which fonts can be loaded */
71
+    protected $allowedFontDomains = null;
72
+    /** @var array Domains from which web-workers and nested browsing content can load elements */
73
+    protected $allowedChildSrcDomains = null;
74
+    /** @var array Domains which can embed this Nextcloud instance */
75
+    protected $allowedFrameAncestors = null;
76
+    /** @var array Domains from which web-workers can be loaded */
77
+    protected $allowedWorkerSrcDomains = null;
78
+    /** @var array Domains which can be used as target for forms */
79
+    protected $allowedFormActionDomains = null;
80
+
81
+    /** @var array Locations to report violations to */
82
+    protected $reportTo = null;
83
+
84
+    /**
85
+     * Whether inline JavaScript snippets are allowed or forbidden
86
+     * @param bool $state
87
+     * @return $this
88
+     * @since 8.1.0
89
+     * @deprecated 10.0 CSP tokens are now used
90
+     */
91
+    public function allowInlineScript($state = false) {
92
+        $this->inlineScriptAllowed = $state;
93
+        return $this;
94
+    }
95
+
96
+    /**
97
+     * Use the according JS nonce
98
+     * This method is only for CSPMiddleware, custom values are ignored in mergePolicies of ContentSecurityPolicyManager
99
+     *
100
+     * @param string $nonce
101
+     * @return $this
102
+     * @since 11.0.0
103
+     */
104
+    public function useJsNonce($nonce) {
105
+        $this->useJsNonce = $nonce;
106
+        return $this;
107
+    }
108
+
109
+    /**
110
+     * Whether eval in JavaScript is allowed or forbidden
111
+     * @param bool $state
112
+     * @return $this
113
+     * @since 8.1.0
114
+     * @deprecated Eval should not be used anymore. Please update your scripts. This function will stop functioning in a future version of Nextcloud.
115
+     */
116
+    public function allowEvalScript($state = true) {
117
+        $this->evalScriptAllowed = $state;
118
+        return $this;
119
+    }
120
+
121
+    /**
122
+     * Allows to execute JavaScript files from a specific domain. Use * to
123
+     * allow JavaScript from all domains.
124
+     * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
125
+     * @return $this
126
+     * @since 8.1.0
127
+     */
128
+    public function addAllowedScriptDomain($domain) {
129
+        $this->allowedScriptDomains[] = $domain;
130
+        return $this;
131
+    }
132
+
133
+    /**
134
+     * Remove the specified allowed script domain from the allowed domains.
135
+     *
136
+     * @param string $domain
137
+     * @return $this
138
+     * @since 8.1.0
139
+     */
140
+    public function disallowScriptDomain($domain) {
141
+        $this->allowedScriptDomains = array_diff($this->allowedScriptDomains, [$domain]);
142
+        return $this;
143
+    }
144
+
145
+    /**
146
+     * Whether inline CSS snippets are allowed or forbidden
147
+     * @param bool $state
148
+     * @return $this
149
+     * @since 8.1.0
150
+     */
151
+    public function allowInlineStyle($state = true) {
152
+        $this->inlineStyleAllowed = $state;
153
+        return $this;
154
+    }
155
+
156
+    /**
157
+     * Allows to execute CSS files from a specific domain. Use * to allow
158
+     * CSS from all domains.
159
+     * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
160
+     * @return $this
161
+     * @since 8.1.0
162
+     */
163
+    public function addAllowedStyleDomain($domain) {
164
+        $this->allowedStyleDomains[] = $domain;
165
+        return $this;
166
+    }
167
+
168
+    /**
169
+     * Remove the specified allowed style domain from the allowed domains.
170
+     *
171
+     * @param string $domain
172
+     * @return $this
173
+     * @since 8.1.0
174
+     */
175
+    public function disallowStyleDomain($domain) {
176
+        $this->allowedStyleDomains = array_diff($this->allowedStyleDomains, [$domain]);
177
+        return $this;
178
+    }
179
+
180
+    /**
181
+     * Allows using fonts from a specific domain. Use * to allow
182
+     * fonts from all domains.
183
+     * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
184
+     * @return $this
185
+     * @since 8.1.0
186
+     */
187
+    public function addAllowedFontDomain($domain) {
188
+        $this->allowedFontDomains[] = $domain;
189
+        return $this;
190
+    }
191
+
192
+    /**
193
+     * Remove the specified allowed font domain from the allowed domains.
194
+     *
195
+     * @param string $domain
196
+     * @return $this
197
+     * @since 8.1.0
198
+     */
199
+    public function disallowFontDomain($domain) {
200
+        $this->allowedFontDomains = array_diff($this->allowedFontDomains, [$domain]);
201
+        return $this;
202
+    }
203
+
204
+    /**
205
+     * Allows embedding images from a specific domain. Use * to allow
206
+     * images from all domains.
207
+     * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
208
+     * @return $this
209
+     * @since 8.1.0
210
+     */
211
+    public function addAllowedImageDomain($domain) {
212
+        $this->allowedImageDomains[] = $domain;
213
+        return $this;
214
+    }
215
+
216
+    /**
217
+     * Remove the specified allowed image domain from the allowed domains.
218
+     *
219
+     * @param string $domain
220
+     * @return $this
221
+     * @since 8.1.0
222
+     */
223
+    public function disallowImageDomain($domain) {
224
+        $this->allowedImageDomains = array_diff($this->allowedImageDomains, [$domain]);
225
+        return $this;
226
+    }
227
+
228
+    /**
229
+     * To which remote domains the JS connect to.
230
+     * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
231
+     * @return $this
232
+     * @since 8.1.0
233
+     */
234
+    public function addAllowedConnectDomain($domain) {
235
+        $this->allowedConnectDomains[] = $domain;
236
+        return $this;
237
+    }
238
+
239
+    /**
240
+     * Remove the specified allowed connect domain from the allowed domains.
241
+     *
242
+     * @param string $domain
243
+     * @return $this
244
+     * @since 8.1.0
245
+     */
246
+    public function disallowConnectDomain($domain) {
247
+        $this->allowedConnectDomains = array_diff($this->allowedConnectDomains, [$domain]);
248
+        return $this;
249
+    }
250
+
251
+    /**
252
+     * From which domains media elements can be embedded.
253
+     * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
254
+     * @return $this
255
+     * @since 8.1.0
256
+     */
257
+    public function addAllowedMediaDomain($domain) {
258
+        $this->allowedMediaDomains[] = $domain;
259
+        return $this;
260
+    }
261
+
262
+    /**
263
+     * Remove the specified allowed media domain from the allowed domains.
264
+     *
265
+     * @param string $domain
266
+     * @return $this
267
+     * @since 8.1.0
268
+     */
269
+    public function disallowMediaDomain($domain) {
270
+        $this->allowedMediaDomains = array_diff($this->allowedMediaDomains, [$domain]);
271
+        return $this;
272
+    }
273
+
274
+    /**
275
+     * From which domains objects such as <object>, <embed> or <applet> are executed
276
+     * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
277
+     * @return $this
278
+     * @since 8.1.0
279
+     */
280
+    public function addAllowedObjectDomain($domain) {
281
+        $this->allowedObjectDomains[] = $domain;
282
+        return $this;
283
+    }
284
+
285
+    /**
286
+     * Remove the specified allowed object domain from the allowed domains.
287
+     *
288
+     * @param string $domain
289
+     * @return $this
290
+     * @since 8.1.0
291
+     */
292
+    public function disallowObjectDomain($domain) {
293
+        $this->allowedObjectDomains = array_diff($this->allowedObjectDomains, [$domain]);
294
+        return $this;
295
+    }
296
+
297
+    /**
298
+     * Which domains can be embedded in an iframe
299
+     * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
300
+     * @return $this
301
+     * @since 8.1.0
302
+     */
303
+    public function addAllowedFrameDomain($domain) {
304
+        $this->allowedFrameDomains[] = $domain;
305
+        return $this;
306
+    }
307
+
308
+    /**
309
+     * Remove the specified allowed frame domain from the allowed domains.
310
+     *
311
+     * @param string $domain
312
+     * @return $this
313
+     * @since 8.1.0
314
+     */
315
+    public function disallowFrameDomain($domain) {
316
+        $this->allowedFrameDomains = array_diff($this->allowedFrameDomains, [$domain]);
317
+        return $this;
318
+    }
319
+
320
+    /**
321
+     * Domains from which web-workers and nested browsing content can load elements
322
+     * @param string $domain Domain to whitelist. Any passed value needs to be properly sanitized.
323
+     * @return $this
324
+     * @since 8.1.0
325
+     * @deprecated 15.0.0 use addAllowedWorkerSrcDomains or addAllowedFrameDomain
326
+     */
327
+    public function addAllowedChildSrcDomain($domain) {
328
+        $this->allowedChildSrcDomains[] = $domain;
329
+        return $this;
330
+    }
331
+
332
+    /**
333
+     * Remove the specified allowed child src domain from the allowed domains.
334
+     *
335
+     * @param string $domain
336
+     * @return $this
337
+     * @since 8.1.0
338
+     * @deprecated 15.0.0 use the WorkerSrcDomains or FrameDomain
339
+     */
340
+    public function disallowChildSrcDomain($domain) {
341
+        $this->allowedChildSrcDomains = array_diff($this->allowedChildSrcDomains, [$domain]);
342
+        return $this;
343
+    }
344
+
345
+    /**
346
+     * Domains which can embed an iFrame of the Nextcloud instance
347
+     *
348
+     * @param string $domain
349
+     * @return $this
350
+     * @since 13.0.0
351
+     */
352
+    public function addAllowedFrameAncestorDomain($domain) {
353
+        $this->allowedFrameAncestors[] = $domain;
354
+        return $this;
355
+    }
356
+
357
+    /**
358
+     * Domains which can embed an iFrame of the Nextcloud instance
359
+     *
360
+     * @param string $domain
361
+     * @return $this
362
+     * @since 13.0.0
363
+     */
364
+    public function disallowFrameAncestorDomain($domain) {
365
+        $this->allowedFrameAncestors = array_diff($this->allowedFrameAncestors, [$domain]);
366
+        return $this;
367
+    }
368
+
369
+    /**
370
+     * Domain from which workers can be loaded
371
+     *
372
+     * @param string $domain
373
+     * @return $this
374
+     * @since 15.0.0
375
+     */
376
+    public function addAllowedWorkerSrcDomain(string $domain) {
377
+        $this->allowedWorkerSrcDomains[] = $domain;
378
+        return $this;
379
+    }
380
+
381
+    /**
382
+     * Remove domain from which workers can be loaded
383
+     *
384
+     * @param string $domain
385
+     * @return $this
386
+     * @since 15.0.0
387
+     */
388
+    public function disallowWorkerSrcDomain(string $domain) {
389
+        $this->allowedWorkerSrcDomains = array_diff($this->allowedWorkerSrcDomains, [$domain]);
390
+        return $this;
391
+    }
392
+
393
+    /**
394
+     * Domain to where forms can submit
395
+     *
396
+     * @since 17.0.0
397
+     *
398
+     * @return $this
399
+     */
400
+    public function addAllowedFormActionDomain(string $domain) {
401
+        $this->allowedFormActionDomains[] = $domain;
402
+        return $this;
403
+    }
404
+
405
+    /**
406
+     * Remove domain to where forms can submit
407
+     *
408
+     * @return $this
409
+     * @since 17.0.0
410
+     */
411
+    public function disallowFormActionDomain(string $domain) {
412
+        $this->allowedFormActionDomains = array_diff($this->allowedFormActionDomains, [$domain]);
413
+        return $this;
414
+    }
415
+
416
+    /**
417
+     * Add location to report CSP violations to
418
+     *
419
+     * @param string $location
420
+     * @return $this
421
+     * @since 15.0.0
422
+     */
423
+    public function addReportTo(string $location) {
424
+        $this->reportTo[] = $location;
425
+        return $this;
426
+    }
427
+
428
+    /**
429
+     * Get the generated Content-Security-Policy as a string
430
+     * @return string
431
+     * @since 8.1.0
432
+     */
433
+    public function buildPolicy() {
434
+        $policy = "default-src 'none';";
435
+        $policy .= "base-uri 'none';";
436
+        $policy .= "manifest-src 'self';";
437
+
438
+        if(!empty($this->allowedScriptDomains) || $this->inlineScriptAllowed || $this->evalScriptAllowed) {
439
+            $policy .= 'script-src ';
440
+            if(is_string($this->useJsNonce)) {
441
+                $policy .= '\'nonce-'.base64_encode($this->useJsNonce).'\'';
442
+                $allowedScriptDomains = array_flip($this->allowedScriptDomains);
443
+                unset($allowedScriptDomains['\'self\'']);
444
+                $this->allowedScriptDomains = array_flip($allowedScriptDomains);
445
+                if(count($allowedScriptDomains) !== 0) {
446
+                    $policy .= ' ';
447
+                }
448
+            }
449
+            if(is_array($this->allowedScriptDomains)) {
450
+                $policy .= implode(' ', $this->allowedScriptDomains);
451
+            }
452
+            if($this->inlineScriptAllowed) {
453
+                $policy .= ' \'unsafe-inline\'';
454
+            }
455
+            if($this->evalScriptAllowed) {
456
+                $policy .= ' \'unsafe-eval\'';
457
+            }
458
+            $policy .= ';';
459
+        }
460
+
461
+        if(!empty($this->allowedStyleDomains) || $this->inlineStyleAllowed) {
462
+            $policy .= 'style-src ';
463
+            if(is_array($this->allowedStyleDomains)) {
464
+                $policy .= implode(' ', $this->allowedStyleDomains);
465
+            }
466
+            if($this->inlineStyleAllowed) {
467
+                $policy .= ' \'unsafe-inline\'';
468
+            }
469
+            $policy .= ';';
470
+        }
471
+
472
+        if(!empty($this->allowedImageDomains)) {
473
+            $policy .= 'img-src ' . implode(' ', $this->allowedImageDomains);
474
+            $policy .= ';';
475
+        }
476
+
477
+        if(!empty($this->allowedFontDomains)) {
478
+            $policy .= 'font-src ' . implode(' ', $this->allowedFontDomains);
479
+            $policy .= ';';
480
+        }
481
+
482
+        if(!empty($this->allowedConnectDomains)) {
483
+            $policy .= 'connect-src ' . implode(' ', $this->allowedConnectDomains);
484
+            $policy .= ';';
485
+        }
486
+
487
+        if(!empty($this->allowedMediaDomains)) {
488
+            $policy .= 'media-src ' . implode(' ', $this->allowedMediaDomains);
489
+            $policy .= ';';
490
+        }
491
+
492
+        if(!empty($this->allowedObjectDomains)) {
493
+            $policy .= 'object-src ' . implode(' ', $this->allowedObjectDomains);
494
+            $policy .= ';';
495
+        }
496
+
497
+        if(!empty($this->allowedFrameDomains)) {
498
+            $policy .= 'frame-src ';
499
+            $policy .= implode(' ', $this->allowedFrameDomains);
500
+            $policy .= ';';
501
+        }
502
+
503
+        if(!empty($this->allowedChildSrcDomains)) {
504
+            $policy .= 'child-src ' . implode(' ', $this->allowedChildSrcDomains);
505
+            $policy .= ';';
506
+        }
507
+
508
+        if(!empty($this->allowedFrameAncestors)) {
509
+            $policy .= 'frame-ancestors ' . implode(' ', $this->allowedFrameAncestors);
510
+            $policy .= ';';
511
+        }
512
+
513
+        if (!empty($this->allowedWorkerSrcDomains)) {
514
+            $policy .= 'worker-src ' . implode(' ', $this->allowedWorkerSrcDomains);
515
+            $policy .= ';';
516
+        }
517
+
518
+        if (!empty($this->allowedFormActionDomains)) {
519
+            $policy .= 'form-action ' . implode(' ', $this->allowedFormActionDomains);
520
+            $policy .= ';';
521
+        }
522
+
523
+        if (!empty($this->reportTo)) {
524
+            $policy .= 'report-uri ' . implode(' ', $this->reportTo);
525
+            $policy .= ';';
526
+        }
527
+
528
+        return rtrim($policy, ';');
529
+    }
530 530
 }
Please login to merge, or discard this patch.