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