xref: /plugin/diagrams/action/action.php (revision 5f757686d683fd550247221d4a6d2848f21773e6)
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