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 102 /** 103 * Return true if the image is recognized as our diagram 104 * based on content ('embed.diagrams.net' or 'draw.io') 105 * 106 * @param string $image image id 107 * @return bool 108 */ 109 protected function isDiagram($image) 110 { 111 global $conf; 112 // strip nocache parameters from image 113 $image = explode('&', $image); 114 $image = $image[0]; 115 116 // FIXME this should use mediaFN() 117 $file = init_path( 118 $conf['mediadir'] . 119 DIRECTORY_SEPARATOR . 120 preg_replace(['/:/'], [DIRECTORY_SEPARATOR], $image) 121 ); 122 123 // FIXME replace with helper_plugin_diagrams::isDiagram() 124 if (!is_file($file)) return false; 125 $begin = file_get_contents($file, false, null, 0, 500); 126 $confServiceUrl = $this->getConf('service_url'); // like "https://diagrams.xyz.org/?embed=1&..." 127 $serviceHost = parse_url($confServiceUrl, PHP_URL_HOST); // Host-Portion of the Url, e.g. "diagrams.xyz.org" 128 return strpos($begin, 'embed.diagrams.net') || strpos($begin, 'draw.io') || strpos($begin, $serviceHost); 129 } 130} 131