xref: /plugin/combo/action/pageprotection.php (revision e8b2ff590c848541e718216df3a67061e98c1761)
1<?php
2
3
4use ComboStrap\Identity;
5use ComboStrap\DokuPath;
6use ComboStrap\LatePublication;
7use ComboStrap\LowQualityPage;
8use ComboStrap\Page;
9use ComboStrap\PageProtection;
10use ComboStrap\Publication;
11use ComboStrap\StringUtility;
12
13require_once(__DIR__ . '/../class/LowQualityPage.php');
14require_once(__DIR__ . '/../class/PageProtection.php');
15require_once(__DIR__ . '/../class/DokuPath.php');
16
17/**
18 *
19 */
20class action_plugin_combo_pageprotection extends DokuWiki_Action_Plugin
21{
22
23
24    public function register(Doku_Event_Handler $controller)
25    {
26
27
28        /**
29         * https://www.dokuwiki.org/devel:event:pageutils_id_hidepage
30         */
31        $controller->register_hook('PAGEUTILS_ID_HIDEPAGE', 'BEFORE', $this, 'handleHiddenCheck', array());
32
33        /**
34         * https://www.dokuwiki.org/devel:event:auth_acl_check
35         */
36        $controller->register_hook('AUTH_ACL_CHECK', 'AFTER', $this, 'handleAclCheck', array());
37
38        /**
39         * https://www.dokuwiki.org/devel:event:sitemap_generate
40         */
41        $controller->register_hook('SITEMAP_GENERATE', 'BEFORE', $this, 'handleSiteMapGenerate', array());
42
43        /**
44         * https://www.dokuwiki.org/devel:event:search_query_pagelookup
45         */
46        $controller->register_hook('SEARCH_QUERY_PAGELOOKUP', 'AFTER', $this, 'handleSearchPageLookup', array());
47
48        /**
49         * https://www.dokuwiki.org/devel:event:search_query_fullpage
50         */
51        $controller->register_hook('SEARCH_QUERY_FULLPAGE', 'AFTER', $this, 'handleSearchFullPage', array());
52
53        /**
54         * https://www.dokuwiki.org/devel:event:feed_data_process
55         */
56        $controller->register_hook('FEED_DATA_PROCESS', 'BEFORE', $this, 'handleRssFeed', array());
57
58        /**
59         * Add logged in indicator for Javascript
60         */
61        $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'handleAnonymousJsIndicator');
62
63        /**
64         * Robots meta
65         * https://www.dokuwiki.org/devel:event:tpl_metaheader_output
66         */
67        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'handleRobotsMeta', array());
68
69
70    }
71
72    /**
73     * Set page has hidden
74     * @param $event
75     * @param $param
76     */
77    function handleHiddenCheck(&$event, $param)
78    {
79
80        /**
81         * Only for public
82         */
83        if (Identity::isLoggedIn()) {
84            return;
85        }
86
87        $id = $event->data['id'];
88        if ($id == null) {
89            /**
90             * Happens in test when rendering
91             * with instructions only
92             */
93            return;
94        }
95        $page = Page::createPageFromId($id);
96
97        if ($page->isLowQualityPage()) {
98            if (LowQualityPage::getLowQualityProtectionMode() == PageProtection::CONF_VALUE_HIDDEN) {
99                $event->data['hidden'] = true;
100                return;
101            }
102        }
103        if ($page->isLatePublication()) {
104            if (Publication::getLatePublicationProtectionMode() == PageProtection::CONF_VALUE_HIDDEN) {
105                $event->data['hidden'] = true;
106            }
107
108        }
109
110    }
111
112    /**
113     *
114     * https://www.dokuwiki.org/devel:event:auth_acl_check
115     * @param $event
116     * @param $param
117     */
118    function handleAclCheck(&$event, $param)
119    {
120        /**
121         * Only for public
122         *
123         * Note: user is also
124         * to be found at
125         * $user = $event->data['user'];
126         */
127        if (Identity::isLoggedIn()) {
128            return;
129        }
130
131        /**
132         * Are we on a page script
133         */
134        $imageScript = ["/lib/exe/mediamanager.php", "/lib/exe/detail.php"];
135        if (in_array($_SERVER['SCRIPT_NAME'], $imageScript)) {
136            // id may be null or end with a star
137            // this is not a image
138            return;
139        }
140
141        $id = $event->data['id'];
142
143        $dokuPath = DokuPath::createUnknownFromId($id);
144        if ($dokuPath->isPage()) {
145
146            /**
147             * It should be only a page
148             * https://www.dokuwiki.org/devel:event:auth_acl_check
149             */
150            $page = Page::createPageFromId($id);
151
152            if ($page->isLowQualityPage()) {
153                if ($this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_ENABLE, true)) {
154                    $securityConf = $this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_MODE, PageProtection::CONF_VALUE_ACL);
155                    if ($securityConf == PageProtection::CONF_VALUE_ACL) {
156                        $event->result = AUTH_NONE;
157                        return;
158                    }
159                }
160            }
161            if ($page->isLatePublication()) {
162                if ($this->getConf(Publication::CONF_LATE_PUBLICATION_PROTECTION_ENABLE, true)) {
163                    $securityConf = $this->getConf(Publication::CONF_LATE_PUBLICATION_PROTECTION_MODE, PageProtection::CONF_VALUE_ACL);
164                    if ($securityConf == PageProtection::CONF_VALUE_ACL) {
165                        $event->result = AUTH_NONE;
166                        return;
167                    }
168                }
169            }
170
171        }
172
173    }
174
175    function handleSiteMapGenerate(&$event, $param)
176    {
177        $pageItems = $event->data["items"];
178        foreach ($pageItems as $key => $pageItem) {
179            $url = $pageItem->url;
180            $dokuPath = DokuPath::createFromUrl($url);
181            $page = Page::createPageFromId($dokuPath->getId());
182            if ($page->isLowQualityPage() && LowQualityPage::isProtectionEnabled()) {
183
184                unset($event->data["items"][$key]);
185                continue;
186
187            }
188            if ($page->isLatePublication() && Publication::isLatePublicationProtectionEnabled()) {
189                unset($event->data["items"][$key]);
190            }
191        }
192
193    }
194
195    /**
196     * @param $event
197     * @param $param
198     * The autocomplete do a search on page name
199     */
200    function handleSearchPageLookup(&$event, $param)
201    {
202        $this->excludePageFromSearch($event);
203    }
204
205    /**
206     * @param $event
207     * @param $param
208     * The search page do a search on page name
209     */
210    function handleSearchFullPage(&$event, $param)
211    {
212
213        $this->excludePageFromSearch($event);
214    }
215
216    /**
217     *
218     * @param $event
219     * @param $param
220     * The Rss
221     * https://www.dokuwiki.org/syndication
222     * Example
223     * https://example.com/feed.php?type=rss2&num=5
224     */
225    function handleRssFeed(&$event, $param)
226    {
227        $isLowQualityProtectionEnabled = LowQualityPage::isProtectionEnabled();
228        $isLatePublicationProtectionEnabled = Publication::isLatePublicationProtectionEnabled();
229        if (!$isLatePublicationProtectionEnabled && !$isLowQualityProtectionEnabled) {
230            return;
231        }
232
233        $pagesToBeAdded = &$event->data["data"];
234        foreach ($pagesToBeAdded as $key => $data) {
235
236            // To prevent an Illegal string offset 'id'
237            if(isset($data["id"])) {
238
239                $page = Page::createPageFromId($data["id"]);
240
241                if ($page->isLowQualityPage() && $isLowQualityProtectionEnabled) {
242                    $protectionMode = LowQualityPage::getLowQualityProtectionMode();
243                    if ($protectionMode != PageProtection::CONF_VALUE_ROBOT) {
244                        unset($pagesToBeAdded[$key]);
245                    }
246                }
247
248                if ($page->isLatePublication() && $isLatePublicationProtectionEnabled) {
249                    $protectionMode = Publication::getLatePublicationProtectionMode();
250                    if ($protectionMode != PageProtection::CONF_VALUE_ROBOT) {
251                        unset($pagesToBeAdded[$key]);
252                    }
253                }
254
255            }
256        }
257
258    }
259
260    /**
261     * @param $event
262     * @param array $protectionModes
263     */
264    private
265    function excludePageFromSearch(&$event, $protectionModes = [PageProtection::CONF_VALUE_ACL, PageProtection::CONF_VALUE_HIDDEN])
266    {
267
268        /**
269         * The value is always an array
270         * but as we got this error:
271         * ```
272         * array_keys() expects parameter 1 to be array
273         * ```
274         * The result is a list of page id
275         */
276        if (is_array($event->result)) {
277            foreach (array_keys($event->result) as $idx) {
278                $page = Page::createPageFromId($idx);
279                if ($page->isLowQualityPage()) {
280                    $securityConf = $this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_MODE);
281                    if (in_array($securityConf, $protectionModes)) {
282                        unset($event->result[$idx]);
283                        return;
284                    }
285                }
286                if ($page->isLatePublication()) {
287                    $securityConf = $this->getConf(Publication::CONF_LATE_PUBLICATION_PROTECTION_MODE);
288                    if (in_array($securityConf, [PageProtection::CONF_VALUE_ACL, PageProtection::CONF_VALUE_HIDDEN])) {
289                        unset($event->result[$idx]);
290                        return;
291                    }
292                }
293            }
294        }
295
296    }
297
298    /**
299     * @noinspection SpellCheckingInspection
300     * Adding an information to know if the user is signed or not
301     */
302    function handleAnonymousJsIndicator(&$event, $param)
303    {
304
305        global $JSINFO;
306        if (!Identity::isLoggedIn()) {
307            $navigation = Identity::JS_NAVIGATION_ANONYMOUS_VALUE;
308        } else {
309            $navigation = Identity::JS_NAVIGATION_SIGNED_VALUE;
310        }
311        $JSINFO[Identity::JS_NAVIGATION_INDICATOR] = $navigation;
312
313
314    }
315
316    /**
317     * Handle the meta robots
318     * https://www.dokuwiki.org/devel:event:tpl_metaheader_output
319     * @param $event
320     * @param $param
321     */
322    function handleRobotsMeta(&$event, $param)
323    {
324
325        global $ID;
326        if (empty($ID)) {
327            // $_SERVER['SCRIPT_NAME']== "/lib/exe/mediamanager.php"
328            // $ID is null
329            return;
330        }
331
332        $page = Page::createPageFromId($ID);
333
334        /**
335         * No management for slot page
336         */
337        if ($page->isSlot()) {
338            return;
339        }
340
341        $protected = false;
342        $follow = "nofollow";
343        if ($page->isLowQualityPage() && LowQualityPage::isProtectionEnabled()) {
344            $protected = true;
345            if (LowQualityPage::getLowQualityProtectionMode() == PageProtection::CONF_VALUE_ACL) {
346                $follow = "nofollow";
347            } else {
348                $follow = "follow";
349            }
350        }
351        if ($page->isLatePublication() && Publication::isLatePublicationProtectionEnabled()) {
352            $protected = true;
353            if (Publication::getLatePublicationProtectionMode() == PageProtection::CONF_VALUE_ACL) {
354                $follow = "nofollow";
355            } else {
356                $follow = "follow";
357            }
358        }
359        if ($protected) {
360            foreach ($event->data['meta'] as $key => $meta) {
361                if (array_key_exists("name", $meta)) {
362                    /**
363                     * We may have several properties
364                     */
365                    if ($meta["name"] == "robots") {
366                        $event->data['meta'][$key]["content"] = "noindex,$follow";
367                    }
368                }
369            }
370        }
371    }
372
373}
374