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