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