xref: /plugin/combo/action/pageprotection.php (revision 85e82846b0a214bc35e62864fa49d9cad0723d0e)
15f891b7eSNickeau<?php
25f891b7eSNickeau
35f891b7eSNickeau
4a6bf47aaSNickeauuse ComboStrap\Identity;
521913ab3SNickeauuse ComboStrap\DokuPath;
6*85e82846SNickeauuse ComboStrap\LatePublication;
75f891b7eSNickeauuse ComboStrap\LowQualityPage;
85f891b7eSNickeauuse ComboStrap\Page;
95f891b7eSNickeauuse ComboStrap\PageProtection;
10*85e82846SNickeauuse ComboStrap\Publication;
1121913ab3SNickeauuse ComboStrap\StringUtility;
125f891b7eSNickeau
135f891b7eSNickeaurequire_once(__DIR__ . '/../class/LowQualityPage.php');
145f891b7eSNickeaurequire_once(__DIR__ . '/../class/PageProtection.php');
1521913ab3SNickeaurequire_once(__DIR__ . '/../class/DokuPath.php');
165f891b7eSNickeau
175f891b7eSNickeau/**
185f891b7eSNickeau *
195f891b7eSNickeau */
205f891b7eSNickeauclass action_plugin_combo_pageprotection extends DokuWiki_Action_Plugin
215f891b7eSNickeau{
225f891b7eSNickeau
235f891b7eSNickeau
245f891b7eSNickeau    public function register(Doku_Event_Handler $controller)
255f891b7eSNickeau    {
265f891b7eSNickeau
275f891b7eSNickeau
285f891b7eSNickeau        /**
295f891b7eSNickeau         * https://www.dokuwiki.org/devel:event:pageutils_id_hidepage
305f891b7eSNickeau         */
315f891b7eSNickeau        $controller->register_hook('PAGEUTILS_ID_HIDEPAGE', 'BEFORE', $this, 'handleHiddenCheck', array());
32*85e82846SNickeau
335f891b7eSNickeau        /**
345f891b7eSNickeau         * https://www.dokuwiki.org/devel:event:auth_acl_check
355f891b7eSNickeau         */
365f891b7eSNickeau        $controller->register_hook('AUTH_ACL_CHECK', 'AFTER', $this, 'handleAclCheck', array());
37*85e82846SNickeau
38*85e82846SNickeau        /**
39*85e82846SNickeau         * https://www.dokuwiki.org/devel:event:sitemap_generate
40*85e82846SNickeau         */
41*85e82846SNickeau        $controller->register_hook('SITEMAP_GENERATE', 'BEFORE', $this, 'handleSiteMapGenerate', array());
425f891b7eSNickeau
435f891b7eSNickeau        /**
445f891b7eSNickeau         * https://www.dokuwiki.org/devel:event:search_query_pagelookup
455f891b7eSNickeau         */
465f891b7eSNickeau        $controller->register_hook('SEARCH_QUERY_PAGELOOKUP', 'AFTER', $this, 'handleSearchPageLookup', array());
475f891b7eSNickeau
485f891b7eSNickeau        /**
495f891b7eSNickeau         * https://www.dokuwiki.org/devel:event:search_query_fullpage
505f891b7eSNickeau         */
515f891b7eSNickeau        $controller->register_hook('SEARCH_QUERY_FULLPAGE', 'AFTER', $this, 'handleSearchFullPage', array());
52*85e82846SNickeau
535f891b7eSNickeau        /**
545f891b7eSNickeau         * https://www.dokuwiki.org/devel:event:feed_data_process
555f891b7eSNickeau         */
56*85e82846SNickeau        $controller->register_hook('FEED_DATA_PROCESS', 'BEFORE', $this, 'handleRssFeed', array());
575f891b7eSNickeau
585f891b7eSNickeau        /**
59*85e82846SNickeau         * Add logged in indicator for Javascript
605f891b7eSNickeau         */
615f891b7eSNickeau        $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'handleAnonymousJsIndicator');
625f891b7eSNickeau
63*85e82846SNickeau        /**
64*85e82846SNickeau         * Robots meta
65*85e82846SNickeau         * https://www.dokuwiki.org/devel:event:tpl_metaheader_output
66*85e82846SNickeau         */
67*85e82846SNickeau        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'handleRobotsMeta', array());
68*85e82846SNickeau
695f891b7eSNickeau
705f891b7eSNickeau    }
715f891b7eSNickeau
725f891b7eSNickeau    /**
73*85e82846SNickeau     * Set page has hidden
745f891b7eSNickeau     * @param $event
755f891b7eSNickeau     * @param $param
765f891b7eSNickeau     */
775f891b7eSNickeau    function handleHiddenCheck(&$event, $param)
785f891b7eSNickeau    {
795f891b7eSNickeau
80*85e82846SNickeau        /**
81*85e82846SNickeau         * Only for public
82*85e82846SNickeau         */
83*85e82846SNickeau        if (Identity::isLoggedIn()) {
84*85e82846SNickeau            return;
85*85e82846SNickeau        }
865f891b7eSNickeau
87*85e82846SNickeau        $id = $event->data['id'];
88*85e82846SNickeau        if ($id == null) {
89*85e82846SNickeau            /**
90*85e82846SNickeau             * Happens in test when rendering
91*85e82846SNickeau             * with instructions only
92*85e82846SNickeau             */
93*85e82846SNickeau            return;
94*85e82846SNickeau        }
95*85e82846SNickeau        $page = Page::createPageFromId($id);
96*85e82846SNickeau
97*85e82846SNickeau        if ($page->isLowQualityPage()) {
98*85e82846SNickeau            if (LowQualityPage::getLowQualityProtectionMode() == PageProtection::CONF_VALUE_HIDDEN) {
99*85e82846SNickeau                $event->data['hidden'] = true;
100*85e82846SNickeau                return;
101*85e82846SNickeau            }
102*85e82846SNickeau        }
103*85e82846SNickeau        if ($page->isLatePublication()) {
104*85e82846SNickeau            if (Publication::getLatePublicationProtectionMode() == PageProtection::CONF_VALUE_HIDDEN) {
1055f891b7eSNickeau                $event->data['hidden'] = true;
1065f891b7eSNickeau            }
1075f891b7eSNickeau
1085f891b7eSNickeau        }
1095f891b7eSNickeau
110*85e82846SNickeau    }
111*85e82846SNickeau
1125f891b7eSNickeau    /**
113*85e82846SNickeau     *
114*85e82846SNickeau     * https://www.dokuwiki.org/devel:event:auth_acl_check
1155f891b7eSNickeau     * @param $event
1165f891b7eSNickeau     * @param $param
1175f891b7eSNickeau     */
1185f891b7eSNickeau    function handleAclCheck(&$event, $param)
1195f891b7eSNickeau    {
120*85e82846SNickeau        /**
121*85e82846SNickeau         * Only for public
122*85e82846SNickeau         *
123*85e82846SNickeau         * Note: user is also
124*85e82846SNickeau         * to be found at
125*85e82846SNickeau         * $user = $event->data['user'];
126*85e82846SNickeau         */
127*85e82846SNickeau        if (Identity::isLoggedIn()) {
128*85e82846SNickeau            return;
129*85e82846SNickeau        }
1305f891b7eSNickeau
13132b85071SNickeau        /**
13221913ab3SNickeau         * Are we on a page script
13332b85071SNickeau         */
13421913ab3SNickeau        $imageScript = ["/lib/exe/mediamanager.php", "/lib/exe/detail.php"];
13521913ab3SNickeau        if (in_array($_SERVER['SCRIPT_NAME'], $imageScript)) {
13621913ab3SNickeau            // id may be null or end with a star
13721913ab3SNickeau            // this is not a image
1385f891b7eSNickeau            return;
13921913ab3SNickeau        }
14032b85071SNickeau
14121913ab3SNickeau        $id = $event->data['id'];
14232b85071SNickeau
14321913ab3SNickeau        $dokuPath = DokuPath::createUnknownFromId($id);
14421913ab3SNickeau        if ($dokuPath->isPage()) {
145*85e82846SNickeau
14621913ab3SNickeau            /**
14721913ab3SNickeau             * It should be only a page
14821913ab3SNickeau             * https://www.dokuwiki.org/devel:event:auth_acl_check
14921913ab3SNickeau             */
150*85e82846SNickeau            $page = Page::createPageFromId($id);
151*85e82846SNickeau
152*85e82846SNickeau            if ($page->isLowQualityPage()) {
153*85e82846SNickeau                if ($this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_ENABLE, true)) {
154*85e82846SNickeau                    $securityConf = $this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_MODE, PageProtection::CONF_VALUE_ACL);
155*85e82846SNickeau                    if ($securityConf == PageProtection::CONF_VALUE_ACL) {
1565f891b7eSNickeau                        $event->result = AUTH_NONE;
157*85e82846SNickeau                        return;
158*85e82846SNickeau                    }
159*85e82846SNickeau                }
160*85e82846SNickeau            }
161*85e82846SNickeau            if ($page->isLatePublication()) {
162*85e82846SNickeau                if ($this->getConf(Publication::CONF_LATE_PUBLICATION_PROTECTION_ENABLE, true)) {
163*85e82846SNickeau                    $securityConf = $this->getConf(Publication::CONF_LATE_PUBLICATION_PROTECTION_MODE, PageProtection::CONF_VALUE_ACL);
164*85e82846SNickeau                    if ($securityConf == PageProtection::CONF_VALUE_ACL) {
165*85e82846SNickeau                        $event->result = AUTH_NONE;
166*85e82846SNickeau                        return;
167*85e82846SNickeau                    }
168*85e82846SNickeau                }
169*85e82846SNickeau            }
170*85e82846SNickeau
171*85e82846SNickeau        }
172*85e82846SNickeau
173*85e82846SNickeau    }
174*85e82846SNickeau
175*85e82846SNickeau    function handleSiteMapGenerate(&$event, $param)
176*85e82846SNickeau    {
177*85e82846SNickeau        $pageItems = $event->data["items"];
178*85e82846SNickeau        foreach ($pageItems as $key => $pageItem) {
179*85e82846SNickeau            $url = $pageItem->url;
180*85e82846SNickeau            $dokuPath = DokuPath::createFromUrl($url);
181*85e82846SNickeau            $page = Page::createPageFromId($dokuPath->getId());
182*85e82846SNickeau            if ($page->isLowQualityPage() && LowQualityPage::isProtectionEnabled()) {
183*85e82846SNickeau
184*85e82846SNickeau                unset($event->data["items"][$key]);
185*85e82846SNickeau                continue;
186*85e82846SNickeau
187*85e82846SNickeau            }
188*85e82846SNickeau            if ($page->isLatePublication() && Publication::isLatePublicationProtectionEnabled()) {
189*85e82846SNickeau                unset($event->data["items"][$key]);
1905f891b7eSNickeau            }
1915f891b7eSNickeau        }
1925f891b7eSNickeau
1935f891b7eSNickeau    }
1945f891b7eSNickeau
1955f891b7eSNickeau    /**
1965f891b7eSNickeau     * @param $event
1975f891b7eSNickeau     * @param $param
1985f891b7eSNickeau     * The autocomplete do a search on page name
1995f891b7eSNickeau     */
2005f891b7eSNickeau    function handleSearchPageLookup(&$event, $param)
2015f891b7eSNickeau    {
2025f891b7eSNickeau        $this->excludePageFromSearch($event);
2035f891b7eSNickeau    }
2045f891b7eSNickeau
2055f891b7eSNickeau    /**
2065f891b7eSNickeau     * @param $event
2075f891b7eSNickeau     * @param $param
2085f891b7eSNickeau     * The search page do a search on page name
2095f891b7eSNickeau     */
2105f891b7eSNickeau    function handleSearchFullPage(&$event, $param)
2115f891b7eSNickeau    {
2125f891b7eSNickeau
2135f891b7eSNickeau        $this->excludePageFromSearch($event);
2145f891b7eSNickeau    }
2155f891b7eSNickeau
2165f891b7eSNickeau    /**
2175f891b7eSNickeau     *
2185f891b7eSNickeau     * @param $event
2195f891b7eSNickeau     * @param $param
2205f891b7eSNickeau     * The Rss
2215f891b7eSNickeau     * https://www.dokuwiki.org/syndication
2225f891b7eSNickeau     * Example
2235f891b7eSNickeau     * https://example.com/feed.php?type=rss2&num=5
2245f891b7eSNickeau     */
2255f891b7eSNickeau    function handleRssFeed(&$event, $param)
2265f891b7eSNickeau    {
227*85e82846SNickeau        $isLowQualityProtectionEnabled = LowQualityPage::isProtectionEnabled();
228*85e82846SNickeau        $isLatePublicationProtectionEnabled = Publication::isLatePublicationProtectionEnabled();
229*85e82846SNickeau        if (!$isLatePublicationProtectionEnabled && !$isLowQualityProtectionEnabled) {
230*85e82846SNickeau            return;
231*85e82846SNickeau        }
232*85e82846SNickeau
233*85e82846SNickeau        $pagesToBeAdded = &$event->data["data"];
234*85e82846SNickeau        foreach ($pagesToBeAdded as $key => $data) {
235*85e82846SNickeau
236*85e82846SNickeau            $page = Page::createPageFromId($data["id"]);
237*85e82846SNickeau
238*85e82846SNickeau            if ($page->isLowQualityPage() && $isLowQualityProtectionEnabled) {
239*85e82846SNickeau                $protectionMode = LowQualityPage::getLowQualityProtectionMode();
240*85e82846SNickeau                if ($protectionMode != PageProtection::CONF_VALUE_ROBOT) {
241*85e82846SNickeau                    unset($pagesToBeAdded[$key]);
242*85e82846SNickeau                }
243*85e82846SNickeau            }
244*85e82846SNickeau
245*85e82846SNickeau            if ($page->isLatePublication() && $isLatePublicationProtectionEnabled) {
246*85e82846SNickeau                $protectionMode = Publication::getLatePublicationProtectionMode();
247*85e82846SNickeau                if ($protectionMode != PageProtection::CONF_VALUE_ROBOT) {
248*85e82846SNickeau                    unset($pagesToBeAdded[$key]);
249*85e82846SNickeau                }
250*85e82846SNickeau            }
251*85e82846SNickeau        }
252*85e82846SNickeau
2535f891b7eSNickeau    }
2545f891b7eSNickeau
2555f891b7eSNickeau    /**
2565f891b7eSNickeau     * @param $event
257*85e82846SNickeau     * @param array $protectionModes
2585f891b7eSNickeau     */
2595f891b7eSNickeau    private
260*85e82846SNickeau    function excludePageFromSearch(&$event, $protectionModes = [PageProtection::CONF_VALUE_ACL, PageProtection::CONF_VALUE_HIDDEN])
2615f891b7eSNickeau    {
2625f891b7eSNickeau
2635f891b7eSNickeau        $result = $event->result;
2645f891b7eSNickeau        /**
2655f891b7eSNickeau         * The value is always an array
2665f891b7eSNickeau         * but as we got this error:
2675f891b7eSNickeau         * ```
2685f891b7eSNickeau         * array_keys() expects parameter 1 to be array
2695f891b7eSNickeau         * ```
2705f891b7eSNickeau         */
2715f891b7eSNickeau        if (is_array($result)) {
2725f891b7eSNickeau            foreach (array_keys($result) as $idx) {
273*85e82846SNickeau                $page = Page::createPageFromId($idx);
274*85e82846SNickeau                if ($page->isLowQualityPage()) {
275*85e82846SNickeau                    $securityConf = $this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_MODE);
276*85e82846SNickeau                    if (in_array($securityConf, $protectionModes)) {
277*85e82846SNickeau                        $event->result = AUTH_NONE;
278*85e82846SNickeau                        return;
279*85e82846SNickeau                    }
280*85e82846SNickeau                }
281*85e82846SNickeau                if ($page->isLatePublication()) {
282*85e82846SNickeau                    $securityConf = $this->getConf(Publication::CONF_LATE_PUBLICATION_PROTECTION_MODE);
283*85e82846SNickeau                    if (in_array($securityConf, [PageProtection::CONF_VALUE_ACL, PageProtection::CONF_VALUE_HIDDEN])) {
284*85e82846SNickeau                        $event->result = AUTH_NONE;
285*85e82846SNickeau                        return;
286*85e82846SNickeau                    }
2875f891b7eSNickeau                }
2885f891b7eSNickeau            }
2895f891b7eSNickeau        }
2905f891b7eSNickeau
2915f891b7eSNickeau    }
2925f891b7eSNickeau
293*85e82846SNickeau    /**
294*85e82846SNickeau     * @noinspection SpellCheckingInspection
295*85e82846SNickeau     * Adding an information to know if the user is signed or not
296*85e82846SNickeau     */
2975f891b7eSNickeau    function handleAnonymousJsIndicator(&$event, $param)
2985f891b7eSNickeau    {
2995f891b7eSNickeau
3005f891b7eSNickeau        global $JSINFO;
301*85e82846SNickeau        if (!Identity::isLoggedIn()) {
302*85e82846SNickeau            $navigation = Identity::JS_NAVIGATION_ANONYMOUS_VALUE;
303*85e82846SNickeau        } else {
304*85e82846SNickeau            $navigation = Identity::JS_NAVIGATION_SIGNED_VALUE;
305*85e82846SNickeau        }
306*85e82846SNickeau        $JSINFO[Identity::JS_NAVIGATION_INDICATOR] = $navigation;
3075f891b7eSNickeau
3085f891b7eSNickeau
3095f891b7eSNickeau    }
3105f891b7eSNickeau
311*85e82846SNickeau    /**
312*85e82846SNickeau     * Handle the meta robots
313*85e82846SNickeau     * https://www.dokuwiki.org/devel:event:tpl_metaheader_output
314*85e82846SNickeau     * @param $event
315*85e82846SNickeau     * @param $param
316*85e82846SNickeau     */
317*85e82846SNickeau    function handleRobotsMeta(&$event, $param)
318*85e82846SNickeau    {
319*85e82846SNickeau
320*85e82846SNickeau        global $ID;
321*85e82846SNickeau        if (empty($ID)) {
322*85e82846SNickeau            // $_SERVER['SCRIPT_NAME']== "/lib/exe/mediamanager.php"
323*85e82846SNickeau            // $ID is null
324*85e82846SNickeau            return;
325*85e82846SNickeau        }
326*85e82846SNickeau
327*85e82846SNickeau        $page = Page::createPageFromId($ID);
328*85e82846SNickeau
329*85e82846SNickeau        /**
330*85e82846SNickeau         * No management for slot page
331*85e82846SNickeau         */
332*85e82846SNickeau        if ($page->isSlot()) {
333*85e82846SNickeau            return;
334*85e82846SNickeau        }
335*85e82846SNickeau
336*85e82846SNickeau        $protected = false;
337*85e82846SNickeau        $follow = "nofollow";
338*85e82846SNickeau        if ($page->isLowQualityPage() && LowQualityPage::isProtectionEnabled()) {
339*85e82846SNickeau            $protected = true;
340*85e82846SNickeau            if (LowQualityPage::getLowQualityProtectionMode() == PageProtection::CONF_VALUE_ACL) {
341*85e82846SNickeau                $follow = "nofollow";
342*85e82846SNickeau            } else {
343*85e82846SNickeau                $follow = "follow";
344*85e82846SNickeau            }
345*85e82846SNickeau        }
346*85e82846SNickeau        if ($page->isLatePublication() && Publication::isLatePublicationProtectionEnabled()) {
347*85e82846SNickeau            $protected = true;
348*85e82846SNickeau            if (Publication::getLatePublicationProtectionMode() == PageProtection::CONF_VALUE_ACL) {
349*85e82846SNickeau                $follow = "nofollow";
350*85e82846SNickeau            } else {
351*85e82846SNickeau                $follow = "follow";
352*85e82846SNickeau            }
353*85e82846SNickeau        }
354*85e82846SNickeau        if ($protected) {
355*85e82846SNickeau            foreach ($event->data['meta'] as $key => $meta) {
356*85e82846SNickeau                if (array_key_exists("name", $meta)) {
357*85e82846SNickeau                    /**
358*85e82846SNickeau                     * We may have several properties
359*85e82846SNickeau                     */
360*85e82846SNickeau                    if ($meta["name"] == "robots") {
361*85e82846SNickeau                        $event->data['meta'][$key]["content"] = "noindex,$follow";
362*85e82846SNickeau                    }
363*85e82846SNickeau                }
364*85e82846SNickeau            }
365*85e82846SNickeau        }
366*85e82846SNickeau    }
367*85e82846SNickeau
3685f891b7eSNickeau}
369