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