xref: /template/strap/action/metacsp.php (revision 21913ab3235d516e2fa19c7e3929b555b3a2bda1)
1*21913ab3SNickeau<?php
2*21913ab3SNickeau
3*21913ab3SNickeauuse ComboStrap\Page;
4*21913ab3SNickeauuse ComboStrap\StringUtility;
5*21913ab3SNickeau
6*21913ab3SNickeauif (!defined('DOKU_INC')) die();
7*21913ab3SNickeau
8*21913ab3SNickeau/**
9*21913ab3SNickeau *
10*21913ab3SNickeau * Adding security directive
11*21913ab3SNickeau *
12*21913ab3SNickeau */
13*21913ab3SNickeauclass action_plugin_combo_metacsp extends DokuWiki_Action_Plugin
14*21913ab3SNickeau{
15*21913ab3SNickeau
16*21913ab3SNickeau
17*21913ab3SNickeau    function __construct()
18*21913ab3SNickeau    {
19*21913ab3SNickeau        // enable direct access to language strings
20*21913ab3SNickeau        // ie $this->lang
21*21913ab3SNickeau        $this->setupLocale();
22*21913ab3SNickeau    }
23*21913ab3SNickeau
24*21913ab3SNickeau    public function register(Doku_Event_Handler $controller)
25*21913ab3SNickeau    {
26*21913ab3SNickeau        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'metaCsp', array());
27*21913ab3SNickeau    }
28*21913ab3SNickeau
29*21913ab3SNickeau    /**
30*21913ab3SNickeau     * Dokuwiki has already a canonical methodology
31*21913ab3SNickeau     * https://www.dokuwiki.org/canonical
32*21913ab3SNickeau     *
33*21913ab3SNickeau     * @param $event
34*21913ab3SNickeau     */
35*21913ab3SNickeau    function metaCsp($event)
36*21913ab3SNickeau    {
37*21913ab3SNickeau
38*21913ab3SNickeau        // meta directives
39*21913ab3SNickeau        $directives = [
40*21913ab3SNickeau            'block-all-mixed-content', // no http, https
41*21913ab3SNickeau        ];
42*21913ab3SNickeau
43*21913ab3SNickeau
44*21913ab3SNickeau
45*21913ab3SNickeau        // Search if the CSP property is already present
46*21913ab3SNickeau        $cspKey = null;
47*21913ab3SNickeau        foreach ($event->data['meta'] as $key => $meta) {
48*21913ab3SNickeau            if (isset($meta["http-equiv"])) {
49*21913ab3SNickeau                if ($meta["http-equiv"] == "Content-Security-Policy") {
50*21913ab3SNickeau                    $cspKey = $key;
51*21913ab3SNickeau                }
52*21913ab3SNickeau            }
53*21913ab3SNickeau        }
54*21913ab3SNickeau        if ($cspKey != null) {
55*21913ab3SNickeau            $actualDirectives = StringUtility::explodeAndTrim($event->data['meta'][$cspKey]["content"], ",");
56*21913ab3SNickeau            $directives = array_merge($actualDirectives, $directives);
57*21913ab3SNickeau            $event->data['meta'][$cspKey] = [
58*21913ab3SNickeau                "http-equiv" => "Content-Security-Policy",
59*21913ab3SNickeau                "content" => join(", ", $directives)
60*21913ab3SNickeau            ];
61*21913ab3SNickeau        } else {
62*21913ab3SNickeau            $event->data['meta'][] = [
63*21913ab3SNickeau                "http-equiv" => "Content-Security-Policy",
64*21913ab3SNickeau                "content" => join(",", $directives)
65*21913ab3SNickeau            ];
66*21913ab3SNickeau        }
67*21913ab3SNickeau
68*21913ab3SNickeau        // http header
69*21913ab3SNickeau        $httpDirectives = [
70*21913ab3SNickeau            "Content-Security-Policy: frame-ancestors 'none'", // the page cannot be used in a iframe (clickjacking),
71*21913ab3SNickeau            "X-Frame-Options: deny" // the page cannot be used in a iframe (clickjacking) - deprecated for frame ancestores
72*21913ab3SNickeau        ];
73*21913ab3SNickeau        foreach($httpDirectives as $httpDirective){
74*21913ab3SNickeau            header($httpDirective);
75*21913ab3SNickeau        }
76*21913ab3SNickeau
77*21913ab3SNickeau    }
78*21913ab3SNickeau
79*21913ab3SNickeau}
80