15f891b7eSNickeau<?php 25f891b7eSNickeau 35b0932efSgerardnicorequire_once(__DIR__ . '/../vendor/autoload.php'); 45f891b7eSNickeau 565e00826Sgerardnicouse ComboStrap\ExceptionBadArgument; 665e00826Sgerardnicouse ComboStrap\ExceptionBadSyntax; 75b0932efSgerardnicouse ComboStrap\ExceptionNotEnabled; 804fd306cSNickeauuse ComboStrap\ExecutionContext; 965e00826Sgerardnicouse ComboStrap\FetcherPage; 1004fd306cSNickeauuse ComboStrap\FileSystems; 11c3437056SNickeauuse ComboStrap\Identity; 125b0932efSgerardnicouse ComboStrap\LogUtility; 135f891b7eSNickeauuse ComboStrap\LowQualityPage; 1404fd306cSNickeauuse ComboStrap\MarkupPath; 155f891b7eSNickeauuse ComboStrap\PageProtection; 16c3437056SNickeauuse ComboStrap\PagePublicationDate; 175b0932efSgerardnicouse ComboStrap\Robots; 185b0932efSgerardnicouse ComboStrap\Web\Url; 195b0932efSgerardnicouse ComboStrap\WikiPath; 205f891b7eSNickeau 21c3437056SNickeau 225f891b7eSNickeau/** 235f891b7eSNickeau * 245f891b7eSNickeau */ 255f891b7eSNickeauclass action_plugin_combo_pageprotection extends DokuWiki_Action_Plugin 265f891b7eSNickeau{ 275f891b7eSNickeau 285f891b7eSNickeau 295f891b7eSNickeau public function register(Doku_Event_Handler $controller) 305f891b7eSNickeau { 315f891b7eSNickeau 325f891b7eSNickeau 335f891b7eSNickeau /** 345f891b7eSNickeau * https://www.dokuwiki.org/devel:event:pageutils_id_hidepage 355f891b7eSNickeau */ 365f891b7eSNickeau $controller->register_hook('PAGEUTILS_ID_HIDEPAGE', 'BEFORE', $this, 'handleHiddenCheck', array()); 3785e82846SNickeau 385f891b7eSNickeau /** 395f891b7eSNickeau * https://www.dokuwiki.org/devel:event:auth_acl_check 405f891b7eSNickeau */ 415f891b7eSNickeau $controller->register_hook('AUTH_ACL_CHECK', 'AFTER', $this, 'handleAclCheck', array()); 4285e82846SNickeau 4385e82846SNickeau /** 4485e82846SNickeau * https://www.dokuwiki.org/devel:event:sitemap_generate 4585e82846SNickeau */ 4685e82846SNickeau $controller->register_hook('SITEMAP_GENERATE', 'BEFORE', $this, 'handleSiteMapGenerate', array()); 475f891b7eSNickeau 485f891b7eSNickeau /** 495f891b7eSNickeau * https://www.dokuwiki.org/devel:event:search_query_pagelookup 505f891b7eSNickeau */ 515f891b7eSNickeau $controller->register_hook('SEARCH_QUERY_PAGELOOKUP', 'AFTER', $this, 'handleSearchPageLookup', array()); 525f891b7eSNickeau 535f891b7eSNickeau /** 545f891b7eSNickeau * https://www.dokuwiki.org/devel:event:search_query_fullpage 555f891b7eSNickeau */ 565f891b7eSNickeau $controller->register_hook('SEARCH_QUERY_FULLPAGE', 'AFTER', $this, 'handleSearchFullPage', array()); 5785e82846SNickeau 585f891b7eSNickeau /** 595f891b7eSNickeau * https://www.dokuwiki.org/devel:event:feed_data_process 605f891b7eSNickeau */ 6185e82846SNickeau $controller->register_hook('FEED_DATA_PROCESS', 'BEFORE', $this, 'handleRssFeed', array()); 625f891b7eSNickeau 635f891b7eSNickeau 6485e82846SNickeau /** 6585e82846SNickeau * Robots meta 6685e82846SNickeau * https://www.dokuwiki.org/devel:event:tpl_metaheader_output 6785e82846SNickeau */ 6885e82846SNickeau $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'handleRobotsMeta', array()); 6985e82846SNickeau 705f891b7eSNickeau 715f891b7eSNickeau } 725f891b7eSNickeau 735f891b7eSNickeau /** 7485e82846SNickeau * Set page has hidden 755f891b7eSNickeau * @param $event 765f891b7eSNickeau * @param $param 775f891b7eSNickeau */ 785f891b7eSNickeau function handleHiddenCheck(&$event, $param) 795f891b7eSNickeau { 805f891b7eSNickeau 8185e82846SNickeau /** 8285e82846SNickeau * Only for public 8385e82846SNickeau */ 8485e82846SNickeau if (Identity::isLoggedIn()) { 8585e82846SNickeau return; 8685e82846SNickeau } 875f891b7eSNickeau 8885e82846SNickeau $id = $event->data['id']; 8985e82846SNickeau if ($id == null) { 9085e82846SNickeau /** 9185e82846SNickeau * Happens in test when rendering 9285e82846SNickeau * with instructions only 9385e82846SNickeau */ 9485e82846SNickeau return; 9585e82846SNickeau } 9604fd306cSNickeau $page = MarkupPath::createMarkupFromId($id); 9785e82846SNickeau 9885e82846SNickeau if ($page->isLowQualityPage()) { 9985e82846SNickeau if (LowQualityPage::getLowQualityProtectionMode() == PageProtection::CONF_VALUE_HIDDEN) { 10085e82846SNickeau $event->data['hidden'] = true; 10185e82846SNickeau return; 10285e82846SNickeau } 10385e82846SNickeau } 10485e82846SNickeau if ($page->isLatePublication()) { 105c3437056SNickeau if (PagePublicationDate::getLatePublicationProtectionMode() == PageProtection::CONF_VALUE_HIDDEN) { 1065f891b7eSNickeau $event->data['hidden'] = true; 1075f891b7eSNickeau } 1085f891b7eSNickeau 1095f891b7eSNickeau } 1105f891b7eSNickeau 11185e82846SNickeau } 11285e82846SNickeau 1135f891b7eSNickeau /** 11485e82846SNickeau * 11585e82846SNickeau * https://www.dokuwiki.org/devel:event:auth_acl_check 1165f891b7eSNickeau * @param $event 1175f891b7eSNickeau * @param $param 1185f891b7eSNickeau */ 1195f891b7eSNickeau function handleAclCheck(&$event, $param) 1205f891b7eSNickeau { 12185e82846SNickeau /** 12285e82846SNickeau * Only for public 12385e82846SNickeau * 12485e82846SNickeau * Note: user is also 12585e82846SNickeau * to be found at 12685e82846SNickeau * $user = $event->data['user']; 12785e82846SNickeau */ 12885e82846SNickeau if (Identity::isLoggedIn()) { 12985e82846SNickeau return; 13085e82846SNickeau } 1315f891b7eSNickeau 13232b85071SNickeau /** 13321913ab3SNickeau * Are we on a page script 13432b85071SNickeau */ 13521913ab3SNickeau $imageScript = ["/lib/exe/mediamanager.php", "/lib/exe/detail.php"]; 13621913ab3SNickeau if (in_array($_SERVER['SCRIPT_NAME'], $imageScript)) { 13721913ab3SNickeau // id may be null or end with a star 13821913ab3SNickeau // this is not a image 1395f891b7eSNickeau return; 14021913ab3SNickeau } 14132b85071SNickeau 14221913ab3SNickeau $id = $event->data['id']; 14304fd306cSNickeau if ($id == null) { 14404fd306cSNickeau /** 14504fd306cSNickeau * Happens in test when rendering 14604fd306cSNickeau * with instructions only 14704fd306cSNickeau */ 14804fd306cSNickeau return; 14904fd306cSNickeau } 15032b85071SNickeau 15104fd306cSNickeau $dokuPath = WikiPath::createFromUnknownRoot($id); 15221913ab3SNickeau if ($dokuPath->isPage()) { 15385e82846SNickeau 15421913ab3SNickeau /** 15521913ab3SNickeau * It should be only a page 15621913ab3SNickeau * https://www.dokuwiki.org/devel:event:auth_acl_check 15721913ab3SNickeau */ 15804fd306cSNickeau $page = MarkupPath::createMarkupFromId($id); 15985e82846SNickeau 16085e82846SNickeau if ($page->isLowQualityPage()) { 16185e82846SNickeau if ($this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_ENABLE, true)) { 16285e82846SNickeau $securityConf = $this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_MODE, PageProtection::CONF_VALUE_ACL); 16385e82846SNickeau if ($securityConf == PageProtection::CONF_VALUE_ACL) { 1645f891b7eSNickeau $event->result = AUTH_NONE; 16585e82846SNickeau return; 16685e82846SNickeau } 16785e82846SNickeau } 16885e82846SNickeau } 16985e82846SNickeau if ($page->isLatePublication()) { 170c3437056SNickeau if ($this->getConf(PagePublicationDate::CONF_LATE_PUBLICATION_PROTECTION_ENABLE, true)) { 171c3437056SNickeau $securityConf = $this->getConf(PagePublicationDate::CONF_LATE_PUBLICATION_PROTECTION_MODE, PageProtection::CONF_VALUE_ACL); 17285e82846SNickeau if ($securityConf == PageProtection::CONF_VALUE_ACL) { 17385e82846SNickeau $event->result = AUTH_NONE; 17485e82846SNickeau return; 17585e82846SNickeau } 17685e82846SNickeau } 17785e82846SNickeau } 17885e82846SNickeau 17985e82846SNickeau } 18085e82846SNickeau 18185e82846SNickeau } 18285e82846SNickeau 18385e82846SNickeau function handleSiteMapGenerate(&$event, $param) 18485e82846SNickeau { 18585e82846SNickeau $pageItems = $event->data["items"]; 18685e82846SNickeau foreach ($pageItems as $key => $pageItem) { 18765e00826Sgerardnico 18865e00826Sgerardnico try { 18965e00826Sgerardnico $url = Url::createFromString($pageItem->url); 19065e00826Sgerardnico $fetcherPage = FetcherPage::createPageFragmentFetcherFromUrl($url); 19165e00826Sgerardnico } catch (ExceptionBadArgument|ExceptionBadSyntax $e) { 19265e00826Sgerardnico LogUtility::internalError("We were unable to build the page fetcher. Error: " . $e->getMessage(), "sitemap", $e); 19365e00826Sgerardnico continue; 19465e00826Sgerardnico } 19565e00826Sgerardnico 19665e00826Sgerardnico $page = MarkupPath::createPageFromPathObject($fetcherPage->getSourcePath()); 19785e82846SNickeau if ($page->isLowQualityPage() && LowQualityPage::isProtectionEnabled()) { 19885e82846SNickeau 19985e82846SNickeau unset($event->data["items"][$key]); 20085e82846SNickeau continue; 20185e82846SNickeau 20285e82846SNickeau } 203c3437056SNickeau if ($page->isLatePublication() && PagePublicationDate::isLatePublicationProtectionEnabled()) { 20485e82846SNickeau unset($event->data["items"][$key]); 2055f891b7eSNickeau } 20665e00826Sgerardnico /** 20765e00826Sgerardnico * Url rewrite 20865e00826Sgerardnico */ 209*f9161b9dSNico $urlAfterRewrite = $page->getCanonicalUrl()->toAbsoluteUrlString(); 21065e00826Sgerardnico $event->data["items"][$key]->url = $urlAfterRewrite; 2115f891b7eSNickeau } 2125f891b7eSNickeau 2135f891b7eSNickeau } 2145f891b7eSNickeau 2155f891b7eSNickeau /** 2165f891b7eSNickeau * @param $event 2175f891b7eSNickeau * @param $param 2185f891b7eSNickeau * The autocomplete do a search on page name 2195f891b7eSNickeau */ 2205f891b7eSNickeau function handleSearchPageLookup(&$event, $param) 2215f891b7eSNickeau { 2225f891b7eSNickeau $this->excludePageFromSearch($event); 2235f891b7eSNickeau } 2245f891b7eSNickeau 2255f891b7eSNickeau /** 2265f891b7eSNickeau * @param $event 2275f891b7eSNickeau * @param $param 2285f891b7eSNickeau * The search page do a search on page name 2295f891b7eSNickeau */ 2305f891b7eSNickeau function handleSearchFullPage(&$event, $param) 2315f891b7eSNickeau { 2325f891b7eSNickeau 2335f891b7eSNickeau $this->excludePageFromSearch($event); 2345f891b7eSNickeau } 2355f891b7eSNickeau 2365f891b7eSNickeau /** 2375f891b7eSNickeau * 2385f891b7eSNickeau * @param $event 2395f891b7eSNickeau * @param $param 2405f891b7eSNickeau * The Rss 2415f891b7eSNickeau * https://www.dokuwiki.org/syndication 2425f891b7eSNickeau * Example 2435f891b7eSNickeau * https://example.com/feed.php?type=rss2&num=5 2445f891b7eSNickeau */ 2455f891b7eSNickeau function handleRssFeed(&$event, $param) 2465f891b7eSNickeau { 24785e82846SNickeau $isLowQualityProtectionEnabled = LowQualityPage::isProtectionEnabled(); 248c3437056SNickeau $isLatePublicationProtectionEnabled = PagePublicationDate::isLatePublicationProtectionEnabled(); 24985e82846SNickeau if (!$isLatePublicationProtectionEnabled && !$isLowQualityProtectionEnabled) { 25085e82846SNickeau return; 25185e82846SNickeau } 25285e82846SNickeau 25385e82846SNickeau $pagesToBeAdded = &$event->data["data"]; 25485e82846SNickeau foreach ($pagesToBeAdded as $key => $data) { 25585e82846SNickeau 256e8b2ff59SNickeau // To prevent an Illegal string offset 'id' 257e8b2ff59SNickeau if (isset($data["id"])) { 258e8b2ff59SNickeau 25904fd306cSNickeau $page = MarkupPath::createMarkupFromId($data["id"]); 26085e82846SNickeau 26185e82846SNickeau if ($page->isLowQualityPage() && $isLowQualityProtectionEnabled) { 26285e82846SNickeau $protectionMode = LowQualityPage::getLowQualityProtectionMode(); 26385e82846SNickeau if ($protectionMode != PageProtection::CONF_VALUE_ROBOT) { 26485e82846SNickeau unset($pagesToBeAdded[$key]); 26585e82846SNickeau } 26685e82846SNickeau } 26785e82846SNickeau 26885e82846SNickeau if ($page->isLatePublication() && $isLatePublicationProtectionEnabled) { 269c3437056SNickeau $protectionMode = PagePublicationDate::getLatePublicationProtectionMode(); 27085e82846SNickeau if ($protectionMode != PageProtection::CONF_VALUE_ROBOT) { 27185e82846SNickeau unset($pagesToBeAdded[$key]); 27285e82846SNickeau } 27385e82846SNickeau } 274e8b2ff59SNickeau 275e8b2ff59SNickeau } 27685e82846SNickeau } 27785e82846SNickeau 2785f891b7eSNickeau } 2795f891b7eSNickeau 2805f891b7eSNickeau /** 2815f891b7eSNickeau * @param $event 28285e82846SNickeau * @param array $protectionModes 2835f891b7eSNickeau */ 2845f891b7eSNickeau private 28585e82846SNickeau function excludePageFromSearch(&$event, $protectionModes = [PageProtection::CONF_VALUE_ACL, PageProtection::CONF_VALUE_HIDDEN]) 2865f891b7eSNickeau { 2875f891b7eSNickeau 2885f891b7eSNickeau /** 2895f891b7eSNickeau * The value is always an array 2905f891b7eSNickeau * but as we got this error: 2915f891b7eSNickeau * ``` 2925f891b7eSNickeau * array_keys() expects parameter 1 to be array 2935f891b7eSNickeau * ``` 294e8b2ff59SNickeau * The result is a list of page id 2955f891b7eSNickeau */ 296e8b2ff59SNickeau if (is_array($event->result)) { 297e8b2ff59SNickeau foreach (array_keys($event->result) as $idx) { 29804fd306cSNickeau $page = MarkupPath::createMarkupFromId($idx); 29985e82846SNickeau if ($page->isLowQualityPage()) { 30085e82846SNickeau $securityConf = $this->getConf(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_MODE); 30185e82846SNickeau if (in_array($securityConf, $protectionModes)) { 302e8b2ff59SNickeau unset($event->result[$idx]); 30385e82846SNickeau return; 30485e82846SNickeau } 30585e82846SNickeau } 30685e82846SNickeau if ($page->isLatePublication()) { 307c3437056SNickeau $securityConf = $this->getConf(PagePublicationDate::CONF_LATE_PUBLICATION_PROTECTION_MODE); 30885e82846SNickeau if (in_array($securityConf, [PageProtection::CONF_VALUE_ACL, PageProtection::CONF_VALUE_HIDDEN])) { 309e8b2ff59SNickeau unset($event->result[$idx]); 31085e82846SNickeau return; 31185e82846SNickeau } 3125f891b7eSNickeau } 3135f891b7eSNickeau } 3145f891b7eSNickeau } 3155f891b7eSNickeau 3165f891b7eSNickeau } 3175f891b7eSNickeau 3185f891b7eSNickeau 31985e82846SNickeau /** 32085e82846SNickeau * Handle the meta robots 32185e82846SNickeau * https://www.dokuwiki.org/devel:event:tpl_metaheader_output 32285e82846SNickeau * @param $event 32385e82846SNickeau * @param $param 32485e82846SNickeau */ 32585e82846SNickeau function handleRobotsMeta(&$event, $param) 32685e82846SNickeau { 32785e82846SNickeau 3285b0932efSgerardnico $executionContext = ExecutionContext::getActualOrCreateFromEnv(); 3295b0932efSgerardnico $requestedPath = $executionContext->getRequestedPath(); 33004fd306cSNickeau 33104fd306cSNickeau if (!FileSystems::exists($requestedPath)) { 33285e82846SNickeau return; 33385e82846SNickeau } 33485e82846SNickeau 33504fd306cSNickeau $page = MarkupPath::createPageFromPathObject($requestedPath); 3365b0932efSgerardnico try { 3375b0932efSgerardnico $follow = Robots::canBeIndexedAndGetFollowValue($page, $executionContext); 3385b0932efSgerardnico } catch (ExceptionNotEnabled $e) { 3395b0932efSgerardnico // Robots Protection is not Enabled 34085e82846SNickeau return; 34185e82846SNickeau } 34285e82846SNickeau 343cc610584Sgerardnico // header ['X-Robots-Tag'] = 'noindex'; ??? 344cc610584Sgerardnico 34585e82846SNickeau foreach ($event->data['meta'] as $key => $meta) { 34685e82846SNickeau if (array_key_exists("name", $meta)) { 34785e82846SNickeau /** 34885e82846SNickeau * We may have several properties 34985e82846SNickeau */ 35085e82846SNickeau if ($meta["name"] == "robots") { 35185e82846SNickeau $event->data['meta'][$key]["content"] = "noindex,$follow"; 35285e82846SNickeau } 35385e82846SNickeau } 35485e82846SNickeau } 3555b0932efSgerardnico 35685e82846SNickeau } 35785e82846SNickeau 3585f891b7eSNickeau} 359