Lexer->addSpecialPattern('\{\{open>.+?\}\}', $mode, 'plugin_luxtools_open'); } /** @inheritdoc */ public function handle($match, $state, $pos, Doku_Handler $handler) { $match = substr($match, strlen('{{open>'), -2); [$path, $caption] = array_pad(explode('|', $match, 2), 2, ''); $path = trim($path); $caption = trim($caption); if ($caption === '') $caption = $path !== '' ? $path : 'Open'; // Basic scheme filtering to avoid javascript: style injections. // Allow either file:// URLs, or plain paths (Windows/UNC/Linux style). if (preg_match('/^[a-zA-Z][a-zA-Z0-9+.-]*:/', $path)) { if (!str_starts_with(strtolower($path), 'file://')) { return false; } } return [$path, $caption]; } /** @inheritdoc */ public function render($format, Doku_Renderer $renderer, $data) { if ($data === false) return false; [$path, $caption] = $data; if ($format !== 'xhtml') { // no meaningful representation in non-browser formats $renderer->cdata($caption); return true; } if ($path === '') { $renderer->cdata('[n/a]'); return true; } $serviceUrl = trim((string)$this->getConf('open_service_url')); $attrs = ' type="button" class="luxtools-open"' . ' data-path="' . hsc($path) . '"'; if ($serviceUrl !== '') { $attrs .= ' data-service-url="' . hsc($serviceUrl) . '"'; } $renderer->doc .= '' . hsc($caption) . ''; return true; } }