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