xref: /plugin/combo/action/pageprotection.php (revision 85e82846b0a214bc35e62864fa49d9cad0723d0e)
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            $page = Page::createPageFromId($data["id"]);
237
238            if ($page->isLowQualityPage() && $isLowQualityProtectionEnabled) {
239                $protectionMode = LowQualityPage::getLowQualityProtectionMode();
240                if ($protectionMode != PageProtection::CONF_VALUE_ROBOT) {
241                    unset($pagesToBeAdded[$key]);
242                }
243            }
244
245            if ($page->isLatePublication() && $isLatePublicationProtectionEnabled) {
246                $protectionMode = Publication::getLatePublicationProtectionMode();
247                if ($protectionMode != PageProtection::CONF_VALUE_ROBOT) {
248                    unset($pagesToBeAdded[$key]);
249                }
250            }
251        }
252
253    }
254
255    /**
256     * @param $event
257     * @param array $protectionModes
258     */
259    private
260    function excludePageFromSearch(&$event, $protectionModes = [PageProtection::CONF_VALUE_ACL, PageProtection::CONF_VALUE_HIDDEN])
261    {
262
263        $result = $event->result;
264        /**
265         * The value is always an array
266         * but as we got this error:
267         * ```
268         * array_keys() expects parameter 1 to be array
269         * ```
270         */
271        if (is_array($result)) {
272            foreach (array_keys($result) as $idx) {
273                $page = Page::createPageFromId($idx);
274                if ($page->isLowQualityPage()) {
275                    $securityConf = $this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_MODE);
276                    if (in_array($securityConf, $protectionModes)) {
277                        $event->result = AUTH_NONE;
278                        return;
279                    }
280                }
281                if ($page->isLatePublication()) {
282                    $securityConf = $this->getConf(Publication::CONF_LATE_PUBLICATION_PROTECTION_MODE);
283                    if (in_array($securityConf, [PageProtection::CONF_VALUE_ACL, PageProtection::CONF_VALUE_HIDDEN])) {
284                        $event->result = AUTH_NONE;
285                        return;
286                    }
287                }
288            }
289        }
290
291    }
292
293    /**
294     * @noinspection SpellCheckingInspection
295     * Adding an information to know if the user is signed or not
296     */
297    function handleAnonymousJsIndicator(&$event, $param)
298    {
299
300        global $JSINFO;
301        if (!Identity::isLoggedIn()) {
302            $navigation = Identity::JS_NAVIGATION_ANONYMOUS_VALUE;
303        } else {
304            $navigation = Identity::JS_NAVIGATION_SIGNED_VALUE;
305        }
306        $JSINFO[Identity::JS_NAVIGATION_INDICATOR] = $navigation;
307
308
309    }
310
311    /**
312     * Handle the meta robots
313     * https://www.dokuwiki.org/devel:event:tpl_metaheader_output
314     * @param $event
315     * @param $param
316     */
317    function handleRobotsMeta(&$event, $param)
318    {
319
320        global $ID;
321        if (empty($ID)) {
322            // $_SERVER['SCRIPT_NAME']== "/lib/exe/mediamanager.php"
323            // $ID is null
324            return;
325        }
326
327        $page = Page::createPageFromId($ID);
328
329        /**
330         * No management for slot page
331         */
332        if ($page->isSlot()) {
333            return;
334        }
335
336        $protected = false;
337        $follow = "nofollow";
338        if ($page->isLowQualityPage() && LowQualityPage::isProtectionEnabled()) {
339            $protected = true;
340            if (LowQualityPage::getLowQualityProtectionMode() == PageProtection::CONF_VALUE_ACL) {
341                $follow = "nofollow";
342            } else {
343                $follow = "follow";
344            }
345        }
346        if ($page->isLatePublication() && Publication::isLatePublicationProtectionEnabled()) {
347            $protected = true;
348            if (Publication::getLatePublicationProtectionMode() == PageProtection::CONF_VALUE_ACL) {
349                $follow = "nofollow";
350            } else {
351                $follow = "follow";
352            }
353        }
354        if ($protected) {
355            foreach ($event->data['meta'] as $key => $meta) {
356                if (array_key_exists("name", $meta)) {
357                    /**
358                     * We may have several properties
359                     */
360                    if ($meta["name"] == "robots") {
361                        $event->data['meta'][$key]["content"] = "noindex,$follow";
362                    }
363                }
364            }
365        }
366    }
367
368}
369