1<?php
2
3/**
4 * Action component of diagrams plugin
5 */
6class action_plugin_diagrams extends DokuWiki_Action_Plugin
7{
8
9    /**
10     * Registers a callback function for a given event
11     *
12     * @param \Doku_Event_Handler $controller
13     */
14    public function register(Doku_Event_Handler $controller)
15    {
16        $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'addJsinfo');
17        $controller->register_hook('MEDIAMANAGER_STARTED', 'AFTER', $this, 'addJsinfo');
18        $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'checkConf');
19        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjax');
20    }
21
22    /**
23     * Add data to JSINFO: full service URL and security token used for uploading
24     *
25     * @param Doku_Event $event
26     */
27    public function addJsinfo(Doku_Event $event)
28    {
29        global $JSINFO;
30        $JSINFO['sectok'] = getSecurityToken();
31        $JSINFO['plugins']['diagrams']['service_url'] = $this->getConf('service_url');
32    }
33
34    /**
35     * Check if DokuWiki is properly configured to handle SVG diagrams
36     *
37     * @param Doku_Event $event
38     */
39    public function checkConf(Doku_Event $event)
40    {
41        $mime = getMimeTypes();
42        if (!array_key_exists('svg', $mime) || $mime['svg'] !== 'image/svg+xml') {
43            msg($this->getLang('missingConfig'), -1);
44        }
45    }
46
47    /**
48     * Check all supplied images and return only editable diagrams
49     *
50     * @param Doku_Event $event
51     */
52    public function handleAjax(Doku_Event $event)
53    {
54        if ($event->data !== 'plugin_diagrams') return;
55        $event->preventDefault();
56        $event->stopPropagation();
57
58        global $INPUT;
59        $images = $INPUT->arr('images');
60
61        echo json_encode($this->editableDiagrams($images));
62    }
63
64    /**
65     * Return an array of diagrams editable by the current user
66     *
67     * @param array $images
68     * @return array
69     */
70    protected function editableDiagrams($images)
71    {
72        $editable = [];
73
74        foreach ($images as $image) {
75            if (auth_quickaclcheck($image) >= AUTH_UPLOAD && $this->isDiagram($image)) {
76                $editable[] = $image;
77            }
78        }
79
80        return $editable;
81    }
82
83    /**
84     * Return true if the image is recognized as our diagram
85     * based on content ('embed.diagrams.net' or 'draw.io')
86     *
87     * @param string $image image id
88     * @return bool
89     */
90    protected function isDiagram($image)
91    {
92        global $conf;
93        // strip nocache parameters from image
94        $image = explode('&', $image);
95        $image = $image[0];
96
97        $file = DOKU_INC .
98            $conf['savedir'] .
99            DIRECTORY_SEPARATOR .
100            'media' .
101            DIRECTORY_SEPARATOR .
102            preg_replace(['/:/'], [DIRECTORY_SEPARATOR], $image);
103
104        $begin = file_get_contents($file, false, null, 0, 500);
105        $confServiceUrl = $this->getConf('service_url'); // like "https://diagrams.xyz.org/?embed=1&..."
106        $serviceHost = parse_url($confServiceUrl, PHP_URL_HOST); // Host-Portion of the Url, e.g. "diagrams.xyz.org"
107        return strpos($begin, 'embed.diagrams.net') || strpos($begin, 'draw.io') || strpos($begin, $serviceHost);
108    }
109}
110