1<?php 2 3use dokuwiki\plugin\diagrams\Diagrams; 4 5/** 6 * Action component of diagrams plugin 7 * 8 * This handles operations related to mediafile based diagrams 9 * 10 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 11 * @author Innovakom + CosmoCode <dokuwiki@cosmocode.de> 12 */ 13class action_plugin_diagrams_mediafile extends DokuWiki_Action_Plugin 14{ 15 16 /** @var helper_plugin_diagrams */ 17 protected $helper; 18 19 /** @inheritDoc */ 20 public function register(Doku_Event_Handler $controller) 21 { 22 // only register if mediafile mode is enabled 23 if (!($this->getConf('mode') & Diagrams::MODE_MEDIA)) return; 24 25 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleEditCheck'); 26 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleNamespaceCheck'); 27 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleIsDiagramCheck'); 28 $controller->register_hook('MEDIA_SENDFILE', 'BEFORE', $this, 'handleCSP'); 29 $controller->register_hook('PLUGIN_MOVE_HANDLERS_REGISTER', 'BEFORE', $this, 'registerMoveHandler'); 30 31 $this->helper = plugin_load('helper', 'diagrams'); 32 } 33 34 /** 35 * Check all supplied diagrams and return only editable diagrams 36 * 37 * @param Doku_Event $event AJAX_CALL_UNKNOWN 38 */ 39 public function handleEditCheck(Doku_Event $event) 40 { 41 if ($event->data !== 'plugin_diagrams_mediafile_editcheck') return; 42 $event->preventDefault(); 43 $event->stopPropagation(); 44 45 global $INPUT; 46 $diagrams = (array)json_decode($INPUT->str('diagrams')); 47 48 $editable = []; 49 foreach ($diagrams as $image) { 50 $image = cleanID($image); 51 $file = mediaFN($image); 52 53 if ( 54 file_exists($file) && 55 auth_quickaclcheck($image) >= AUTH_UPLOAD && 56 $this->helper->isDiagramFile($file) 57 ) { 58 $editable[] = $image; 59 } 60 } 61 62 echo json_encode($editable); 63 } 64 65 /** 66 * Check if the given media ID is a diagram 67 * 68 * @param Doku_Event $event AJAX_CALL_UNKNOWN 69 */ 70 public function handleIsDiagramCheck(Doku_Event $event) 71 { 72 if ($event->data !== 'plugin_diagrams_mediafile_isdiagramcheck') return; 73 $event->preventDefault(); 74 $event->stopPropagation(); 75 76 global $INPUT; 77 $diagram = $INPUT->str('diagram'); 78 79 $file = mediaFN(cleanID($diagram)); 80 if (!file_exists($file)) { 81 http_status(404); 82 echo 0; 83 return; 84 } 85 86 if (!$this->helper->isDiagramFile($file)) { 87 http_status(403); 88 echo 0; 89 } 90 91 echo 1; 92 } 93 94 /** 95 * Check ACL for supplied namespace 96 * 97 * @param Doku_Event $event AJAX_CALL_UNKNOWN 98 */ 99 public function handleNamespaceCheck(Doku_Event $event) 100 { 101 if ($event->data !== 'plugin_diagrams_mediafile_nscheck') return; 102 $event->preventDefault(); 103 $event->stopPropagation(); 104 105 global $INPUT; 106 $ns = $INPUT->str('ns'); 107 108 echo json_encode(auth_quickaclcheck($ns . ':*') >= AUTH_UPLOAD); 109 } 110 111 /** 112 * Add CSP img-src directive to allow loading images from data source 113 * 114 * @param Doku_Event $event MEDIA_SENDFILE 115 */ 116 public function handleCSP(Doku_Event $event) 117 { 118 if ($event->data['ext'] === 'svg' && $this->helper->isDiagramFile($event->data['file'])) { 119 $event->data['csp']['img-src'] = "self data:"; 120 $event->data['csp']['sandbox'] = "allow-popups allow-top-navigation allow-same-origin"; 121 $event->data['csp']['style-src'] .= ' fonts.googleapis.com'; // Allow Google fonts 122 $event->data['csp']['font-src'] .= ' fonts.gstatic.com'; // Allow Google fonts 123 } 124 } 125 126 /** 127 * Registers our handler with the move plugin 128 * 129 * @param Doku_Event $event 130 * @return void 131 */ 132 public function registerMoveHandler(Doku_Event $event) 133 { 134 $event->data['handlers']['diagrams_mediafile'] = [new \syntax_plugin_diagrams_mediafile(), 'handleMove']; 135 } 136} 137