xref: /plugin/diagrams/action/mediafile.php (revision dce55f69c0abede1c1a16c969551e8f3fe04b18f)
1<?php
2
3use dokuwiki\plugin\diagrams\Diagrams;
4
5/**
6 * Action component of diagrams plugin
7 *
8 * This handles operations related to mediafile based diagrams
9 *
10 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
11 * @author  Innovakom + CosmoCode <dokuwiki@cosmocode.de>
12 */
13class action_plugin_diagrams_mediafile extends DokuWiki_Action_Plugin
14{
15
16    /** @var helper_plugin_diagrams */
17    protected $helper;
18
19    /** @inheritDoc */
20    public function register(Doku_Event_Handler $controller)
21    {
22        // only register if mediafile mode is enabled
23        if (!($this->getConf('mode') & Diagrams::MODE_MEDIA)) return;
24
25        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleEditCheck');
26        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleNamespaceCheck');
27        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleIsDiagramCheck');
28        $controller->register_hook('MEDIA_SENDFILE', 'BEFORE', $this, 'handleCSP');
29
30        $this->helper = plugin_load('helper', 'diagrams');
31    }
32
33    /**
34     * Check all supplied diagrams and return only editable diagrams
35     *
36     * @param Doku_Event $event AJAX_CALL_UNKNOWN
37     */
38    public function handleEditCheck(Doku_Event $event)
39    {
40        if ($event->data !== 'plugin_diagrams_mediafile_editcheck') return;
41        $event->preventDefault();
42        $event->stopPropagation();
43
44        global $INPUT;
45        $diagrams = (array)json_decode($INPUT->str('diagrams'));
46
47        $editable = [];
48        foreach ($diagrams as $image) {
49            $image = cleanID($image);
50            $file = mediaFN($image);
51
52            if (
53                file_exists($file) &&
54                auth_quickaclcheck($image) >= AUTH_UPLOAD &&
55                $this->helper->isDiagramFile($file)
56            ) {
57                $editable[] = $image;
58            }
59        }
60
61        echo json_encode($editable);
62    }
63
64    /**
65     * Check if the given media ID is a diagram
66     *
67     * @param Doku_Event $event AJAX_CALL_UNKNOWN
68     */
69    public function handleIsDiagramCheck(Doku_Event $event)
70    {
71        if ($event->data !== 'plugin_diagrams_mediafile_isdiagramcheck') return;
72        $event->preventDefault();
73        $event->stopPropagation();
74
75        global $INPUT;
76        $diagram = $INPUT->str('diagram');
77
78        $file = mediaFN(cleanID($diagram));
79        if (!file_exists($file)) {
80            http_status(404);
81            echo 0;
82            return;
83        }
84
85        if (!$this->helper->isDiagramFile($file)) {
86            http_status(403);
87            echo 0;
88        }
89
90        echo 1;
91    }
92
93    /**
94     * Check ACL for supplied namespace
95     *
96     * @param Doku_Event $event AJAX_CALL_UNKNOWN
97     */
98    public function handleNamespaceCheck(Doku_Event $event)
99    {
100        if ($event->data !== 'plugin_diagrams_mediafile_nscheck') return;
101        $event->preventDefault();
102        $event->stopPropagation();
103
104        global $INPUT;
105        $ns = $INPUT->str('ns');
106
107        echo json_encode(auth_quickaclcheck($ns . ':*') >= AUTH_UPLOAD);
108    }
109
110    /**
111     * Add CSP img-src directive to allow loading images from data source
112     *
113     * @param Doku_Event $event MEDIA_SENDFILE
114     */
115    public function handleCSP(Doku_Event $event)
116    {
117        if ($event->data['ext'] === 'svg' && $this->helper->isDiagramFile($event->data['file'])) {
118            $event->data['csp']['img-src'] = "self data:";
119            $event->data['csp']['sandbox'] = "allow-popups allow-top-navigation allow-same-origin";
120        }
121    }
122}
123