1<?php 2 3/** 4 * Action component of diagrams plugin 5 * 6 * FIXME move out all mediafile related stuff to a separate class and make it check the mode config 7 */ 8class action_plugin_diagrams_action extends DokuWiki_Action_Plugin 9{ 10 11 /** 12 * Registers a callback function for a given event 13 * 14 * @param \Doku_Event_Handler $controller 15 */ 16 public function register(Doku_Event_Handler $controller) 17 { 18 $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'addJsinfo'); 19 $controller->register_hook('MEDIAMANAGER_STARTED', 'AFTER', $this, 'addJsinfo'); 20 $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'checkConf'); 21 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjaxImages'); 22 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjaxAcl'); 23 $controller->register_hook('MEDIA_SENDFILE', 'BEFORE', $this, 'handleCSP'); 24 } 25 26 /** 27 * Add data to JSINFO: full service URL and security token used for uploading 28 * 29 * @param Doku_Event $event 30 */ 31 public function addJsinfo(Doku_Event $event) 32 { 33 global $JSINFO; 34 $JSINFO['sectok'] = getSecurityToken(); 35 $JSINFO['plugins']['diagrams']['service_url'] = $this->getConf('service_url'); 36 } 37 38 /** 39 * Check if DokuWiki is properly configured to handle SVG diagrams 40 * 41 * @param Doku_Event $event 42 */ 43 public function checkConf(Doku_Event $event) 44 { 45 $mime = getMimeTypes(); 46 if (!array_key_exists('svg', $mime) || $mime['svg'] !== 'image/svg+xml') { 47 msg($this->getLang('missingConfig'), -1); 48 } 49 } 50 51 /** 52 * Check all supplied images and return only editable diagrams 53 * 54 * @param Doku_Event $event 55 */ 56 public function handleAjaxImages(Doku_Event $event) 57 { 58 if ($event->data !== 'plugin_diagrams_images') return; 59 $event->preventDefault(); 60 $event->stopPropagation(); 61 62 global $INPUT; 63 $images = $INPUT->arr('images'); 64 65 echo json_encode($this->editableDiagrams($images)); 66 } 67 68 /** 69 * Check ACL for supplied namespace 70 * 71 * @param Doku_Event $event 72 */ 73 public function handleAjaxAcl(Doku_Event $event) 74 { 75 if ($event->data !== 'plugin_diagrams_acl') return; 76 $event->preventDefault(); 77 $event->stopPropagation(); 78 79 global $INPUT; 80 $ns = $INPUT->str('ns'); 81 82 echo json_encode(auth_quickaclcheck($ns . ':*') >= AUTH_UPLOAD); 83 } 84 85 /** 86 * Add CSP img-src directive to allow loading images from data source 87 * 88 * @param Doku_Event $event 89 * @return void 90 */ 91 public function handleCSP(Doku_Event $event) 92 { 93 if ($this->isDiagram($event->data['media'])) { 94 $event->data['csp']['img-src'] = "self data:"; 95 $event->data['csp']['sandbox'] = "allow-popups allow-top-navigation allow-same-origin"; 96 } 97 } 98 99 100 /** 101 * Return an array of diagrams editable by the current user 102 * 103 * @param array $images 104 * @return array 105 */ 106 protected function editableDiagrams($images) 107 { 108 $editable = []; 109 110 foreach ($images as $image) { 111 if (auth_quickaclcheck(cleanId($image)) >= AUTH_UPLOAD && $this->isDiagram($image)) { 112 $editable[] = $image; 113 } 114 } 115 116 return $editable; 117 } 118 119 /** 120 * Return true if the image is recognized as our diagram 121 * based on content ('embed.diagrams.net' or 'draw.io') 122 * 123 * @param string $image image id 124 * @return bool 125 */ 126 protected function isDiagram($image) 127 { 128 global $conf; 129 // strip nocache parameters from image 130 $image = explode('&', $image); 131 $image = $image[0]; 132 133 // FIXME this should use mediaFN() 134 $file = init_path( 135 $conf['mediadir'] . 136 DIRECTORY_SEPARATOR . 137 preg_replace(['/:/'], [DIRECTORY_SEPARATOR], $image) 138 ); 139 140 // FIXME replace with helper_plugin_diagrams::isDiagram() 141 if (!is_file($file)) return false; 142 $begin = file_get_contents($file, false, null, 0, 500); 143 $confServiceUrl = $this->getConf('service_url'); // like "https://diagrams.xyz.org/?embed=1&..." 144 $serviceHost = parse_url($confServiceUrl, PHP_URL_HOST); // Host-Portion of the Url, e.g. "diagrams.xyz.org" 145 return strpos($begin, 'embed.diagrams.net') || strpos($begin, 'draw.io') || strpos($begin, $serviceHost); 146 } 147} 148