1<?php 2/** 3 * Userhomepage plugin main file 4 * Previous authors: James GuanFeng Lin, Mikhail I. Izmestev, Daniel Stonier 5 * @author Simon DELAGE <sdelage@gmail.com> 6 * @license: CC Attribution-Share Alike 3.0 Unported <http://creativecommons.org/licenses/by-sa/3.0/> 7 */ 8 9// must be run within Dokuwiki 10if (!defined('DOKU_INC')) die(); 11if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/'); 12 13require_once (DOKU_PLUGIN . 'action.php'); 14require_once (DOKU_PLUGIN . '/acl/admin.php'); 15 16class action_plugin_userhomepage extends DokuWiki_Action_Plugin{ 17 18 function register(Doku_Event_Handler $controller) { 19 $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'init',array()); 20 $controller->register_hook('DETAIL_STARTED', 'AFTER', $this, 'init',array()); 21 $controller->register_hook('ACTION_ACT_PREPROCESS', 'AFTER', $this, 'redirect',array()); 22 $controller->register_hook('ACTION_ACT_PREPROCESS', 'AFTER', $this, 'acl',array()); 23 $controller->register_hook('COMMON_USER_LINK', 'AFTER', $this, 'replaceUserLink',array()); 24 } 25 26 function init(&$event, $param) { 27 global $conf; 28 global $INFO; 29 30 // If there's no conflict between private and public space 31 if ($this->multiNsOk(true)) { 32 $this->helper = plugin_load('helper','userhomepage'); 33 // If templates_path option starts with 'data/pages' it can automatically be adapted but should be changed 34 if (substr($this->getConf('templates_path'),0,10) == 'data/pages') { 35 $dest = str_replace("data/pages", "./pages", $this->getConf('templates_path')); 36 msg("Userhomepage option [<code>templates_path</code>] should be changed to a path relative to data folder (as set by Dokuwiki's [<code>savedir</code>] setting). Current value is based on former default (i.e. <code>data/pages/...</code>) and will still work but this message will keep appearing until the value is corrected, check <a href='https://www.dokuwiki.org/plugin:userhomepage'>this page</a> for details.",2); 37 } else { 38 $dest = $this->getConf('templates_path'); 39 } 40 if (!plugin_isdisabled('avatar')) { 41 $avatarHelper = plugin_load('helper','avatar'); 42 $avatarsFolder = $avatarHelper->getConf('namespace'); 43 if (($avatarsFolder == "user") && ($avatarsFolder == $this->getConf('users_namespace')) && (isadmin)) { 44 msg($this->getLang('avatarsconflict'), -1); 45 } 46 } 47 //if ($event == "DETAIL_STARTED") { return false; } 48 $this->dataDir = $conf['savedir']; 49 // CREATE PRIVATE NAMESPACE START PAGE TEMPLATES IF NEEDED (is required by options, doesn't exist yet and a known user is logged in and not showing image details page) 50 if (($this->getConf('create_private_ns')) && (!is_file($this->dataDir.'/'.$this->getConf('templates_path').'/userhomepage_private.txt')) && ($this->userOk()) && ($event != "DETAIL_STARTED")) { 51 // If a template exists in path as builded before 2015/05/14 version, use it as source to create userhomepage_private.txt in new templates_path 52 if ((is_file(DOKU_CONF.'../'.$this->getConf('templates_path').'/userhomepage_private.txt')) && ($this->getConf('templatepath') != null)) { 53 $source = DOKU_CONF.'../'.$this->getConf('templates_path').'/userhomepage_private.txt'; 54 // If a template from version 3.0.4 exists, use it as source to create userhomepage_private.txt in templates_path 55 } elseif ((is_file(DOKU_INC.$this->getConf('templatepath'))) && ($this->getConf('templatepath') != null)) { 56 $source = $this->getConf('templatepath'); 57 // Otherwise, we're on a fresh install 58 } else { 59 if (is_file('lib/plugins/userhomepage/lang/'.$conf['lang'].'/userhomepage_private.default')) { 60 $source = 'lib/plugins/userhomepage/lang/'.$conf['lang'].'/userhomepage_private.default'; 61 } else { 62 $source = 'lib/plugins/userhomepage/lang/en/userhomepage_private.default'; 63 } 64 } 65 $this->copyFile($source, $dest, 'userhomepage_private.txt'); 66 } 67 // CREATE PUBLIC PAGE TEMPLATES IF NEEDED (is required by options, doesn't exist yet and a known user is logged in and not showing image details page) 68 if (($this->getConf('create_public_page')) and (!is_file($this->dataDir.'/'.$this->getConf('templates_path').'/userhomepage_public.txt')) and ($this->userOk()) && ($event != "DETAIL_STARTED")) { 69 // If a template exists in path as builded before 2015/05/14 version, use it as source to create userhomepage_private.txt in new templates_path 70 if ((is_file(DOKU_CONF.'../'.$this->getConf('templates_path').'/userhomepage_public.txt')) && ($this->getConf('templatepath') != null)) { 71 $source = DOKU_CONF.'../'.$this->getConf('templates_path').'/userhomepage_public.txt'; 72 } else { 73 if (is_file('lib/plugins/userhomepage/lang/'.$conf['lang'].'/userhomepage_public.default')) { 74 $source = 'lib/plugins/userhomepage/lang/'.$conf['lang'].'/userhomepage_public.default'; 75 } else { 76 $source = 'lib/plugins/userhomepage/lang/en/userhomepage_public.default'; 77 } 78 } 79 $this->copyFile($source, $dest, 'userhomepage_public.txt'); 80 } 81 // CREATE PUBLIC NAMESPACE START PAGE TEMPLATES IF NEEDED (is required by options, doesn't exist yet and a known user is logged in and not showing image details page) 82 if (($this->getConf('create_public_page')) and (strpos($this->getConf('public_pages_ns'),':%NAME%:%START%') !== false) and (!is_file($this->dataDir.'/'.$this->getConf('templates_path').'/userhomepage_publicspace.txt')) and ($this->userOk()) && ($event != "DETAIL_STARTED")) { 83 // If a template exists in path as builded before 2015/05/14 version, use it as source to create userhomepage_private.txt in new templates_path 84 if ((is_file(DOKU_CONF.'../'.$this->getConf('templates_path').'/userhomepage_publicspace.txt')) && ($this->getConf('templatepath') != null)) { 85 $source = DOKU_CONF.'../'.$this->getConf('templates_path').'/userhomepage_publicspace.txt'; 86 } else { 87 $source = 'lib/plugins/userhomepage/lang/'.$conf['lang'].'/userhomepage_publicspace.default'; 88 } 89 $this->copyFile($source, $dest, 'userhomepage_publicspace.txt'); 90 } 91 // TARGETS 92 // ...:start.txt or ...:simon_delage.txt 93 $this->private_page = $this->helper->getPrivateID(); 94 // user:simon.txt 95 $this->public_page = $this->helper->getPublicID(); 96 // If a user is logged in, store timestamp (if it wasn't stored yet) 97 if (($_SERVER['REMOTE_USER'] != null) && (!isset($_SESSION['uhptimestamp']))) { 98 $_SESSION['uhptimestamp'] = time(); 99 // If no user is logged in and a timestamp exists, set timestamp to null (ensures that redirection will work if user just logged out and comes back before closing browser) 100 } elseif (($_SERVER['REMOTE_USER'] == null) && (isset($_SESSION['uhptimestamp']))) { 101 $_SESSION['uhptimestamp'] = null; 102 } 103 } else { 104 return false; 105 } 106 } 107 108 function redirect(&$event, $param) { 109 global $conf; 110 global $lang; 111 global $ID; 112 113 // If there's no conflict between private and public space and if user did not request an action page 114// if ($this->multiNsOk()) { 115 if (($this->multiNsOk()) and ($_GET['do'] == null)) { 116// if (($this->multiNsOk()) and ($_GET['do'] != 'admin')) { 117 $created = array(); 118 // If a user is logged in and not allready requesting his private namespace start page 119 if (($this->userOk())&&($_REQUEST['id']!=$this->private_page)) { 120 // if private page doesn't exists, create it (from template) 121 if ($this->getConf('create_private_ns') && is_file($this->dataDir.'/'.$this->getConf('templates_path').'/userhomepage_private.txt') && !page_exists($this->private_page) && !checklock($this->private_page) && !checkwordblock() && ($this->userOk('private'))) { 122 // Target private start page template 123 $this->private_page_template = $this->dataDir.'/'.$this->getConf('templates_path').'/userhomepage_private.txt'; 124 // Create private page 125 lock($this->private_page); 126 saveWikiText($this->private_page,$this->applyTemplate('private'),$this->getLang('uhpcreated')); 127 unlock($this->private_page); 128 // Announce private namespace was created 129 msg($this->getLang('createdprivatens').' ('.$this->private_page.')', 1); 130 // Note that we created private page 131 $created['private'] = page_exists($this->private_page); 132 } 133 // If private ns is managed by plugin, check for any template from skeleton that doesn't exist yet 134 if ($this->getConf('create_private_ns') && (is_dir($this->dataDir.'/'.$this->getConf('templates_path').'/uhp_private_skeleton')) && ($this->userOk('private'))) { 135 //$files = scandir($this->dataDir.'/'.$this->getConf('templates_path').'/uhp_private_skeleton/'); 136 $path = realpath($this->dataDir.'/'.$this->getConf('templates_path').'/uhp_private_skeleton/'); 137 $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST); 138 if ($this->getConf('group_by_name')) { 139 // private:s:simon or private:s:simon_delage 140 $this->private_ns = cleanID($this->getConf('users_namespace').':'.substr($this->privateNamespace(), 0, 1).':'. $this->privateNamespace()); 141 } else { 142 // private:simon or private:simon_delage 143 $this->private_ns = cleanID($this->getConf('users_namespace').':'. $this->privateNamespace()); 144 } 145 foreach($objects as $objectName => $object){ 146 $file = str_replace($path, '', $objectName); 147 if ((is_file($this->dataDir.'/'.$this->getConf('templates_path').'/uhp_private_skeleton'.$file)) and (strpos($file, '.txt') !== false)) { 148 $custom_page_id = cleanID(str_replace('.txt', '', str_replace('/', ':', str_replace('\\', ':', $file)))); 149 $this->custom_target = $this->private_ns.':'.$custom_page_id; 150 if (!page_exists($this->custom_target)) { 151 $this->custom_page_template = $this->dataDir.'/'.$this->getConf('templates_path').'/uhp_private_skeleton'.$file; 152 lock($this->custom_target); 153 saveWikiText($this->custom_target,$this->applyTemplate($this->custom_page_template),$this->getLang('uhpcreated')); 154 msg($this->getLang('fromskeleton').' '.$this->custom_target,0); 155 unlock($this->custom_target); 156 } 157 } 158 } 159 } 160 // Public page? 161 // If public page doesn't exists, create it (from template) 162 if ($this->getConf('create_public_page') && is_file($this->dataDir.'/'.$this->getConf('templates_path').'/userhomepage_public.txt') && !page_exists($this->public_page) && !checklock($this->public_page) && !checkwordblock() && ($this->userOk('public'))) { 163 // Target public page template or public namespace start page template 164 if (strpos($this->getConf('public_pages_ns'),':%NAME%:%START%') !== false) { 165 $this->public_page_template = $this->dataDir.'/'.$this->getConf('templates_path').'/userhomepage_publicspace.txt'; 166 } else { 167 $this->public_page_template = $this->dataDir.'/'.$this->getConf('templates_path').'/userhomepage_public.txt'; 168 } 169 // Create public page 170 lock($this->public_page); 171 saveWikiText($this->public_page,$this->applyTemplate('public'),$this->getLang('uhpcreated')); 172 unlock($this->public_page); 173 // Announce plubic page was created 174 msg($this->getLang('createdpublicpage').' ('.$this->public_page.')', 1); 175 // Note that we created public page 176 $created['public'] = page_exists($this->public_page); 177 } 178 // If public page is in fact a public namespace and is managed by plugin, check for any template from skeleton that doesn't exist yet 179 if ($this->getConf('create_public_page') && (is_dir($this->dataDir.'/'.$this->getConf('templates_path').'/uhp_public_skeleton')) && ($this->userOk('public'))) { 180 $path = realpath($this->dataDir.'/'.$this->getConf('templates_path').'/uhp_public_skeleton/'); 181 $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST); 182 $this->public_ns = cleanID(getNS($this->public_page)); 183 foreach($objects as $objectName => $object){ 184 $file = str_replace($path, '', $objectName); 185 if ((is_file($this->dataDir.'/'.$this->getConf('templates_path').'/uhp_public_skeleton'.$file)) and (strpos($file, '.txt') !== false)) { 186 $custom_page_id = cleanID(str_replace('.txt', '', str_replace('/', ':', str_replace('\\', ':', $file)))); 187 $this->custom_target = $this->public_ns.':'.$custom_page_id; 188 if (!page_exists($this->custom_target)) { 189 $this->custom_page_template = $this->dataDir.'/'.$this->getConf('templates_path').'/uhp_public_skeleton'.$file; 190 lock($this->custom_target); 191 saveWikiText($this->custom_target,$this->applyTemplate($this->custom_page_template),$this->getLang('uhpcreated')); 192 msg($this->getLang('fromskeleton').' '.$this->custom_target,0); 193 unlock($this->custom_target); 194 } 195 } 196 } 197 } 198 // List IDs that can match wiki start 199 $wikistart = array($conf['start'], ':'.$conf['start']); 200 // If Translation plugin is active, wiki start page can also be '??:start' 201 if (!plugin_isdisabled('translation')) { 202 // For each language in Translation settings 203 foreach (explode(' ',$conf['plugin']['translation']['translations']) as $language){ 204 array_push($wikistart, $language.':'.$conf['start'], ':'.$language.':'.$conf['start']); 205 } 206 } 207 // If user isn't on public or private page yet, check for redirection conditions 208 if (($ID != $this->public_page) && ($ID != $this->private_page)) { 209 // If Public page was just created, redirect to it and edit (or show) 210 if (($created['public']) && (page_exists($this->public_page))) { 211 send_redirect(wl($this->public_page, array('do='.$this->getConf('action')), true)); 212//msg('Public page creation redirection: id '.$_GET['id'].'; do '.$_GET['do'], 1); 213 // Else if private start page was just created and edit option is set, redirect to it and edit 214 } elseif (($created['private']) && (page_exists($this->private_page)) && ($this->getConf('edit_before_create'))) { 215 send_redirect(wl($this->private_page, array('do='.$this->getConf('action')), true)); 216//msg('Private page creation redirection: id '.$_GET['id'].'; do '.$_GET['do'], 1); 217 // Else if redirection is enabled and user's private page exists AND [(user isn't requesting a specific page OR he's requesting wiki start page) AND logged in 2sec ago max] 218 } elseif (($this->getConf('redirection')) && (page_exists($this->private_page)) && (((!isset($_GET['id'])) or (in_array($_GET['id'], $wikistart))) && (time()-$_SESSION["uhptimestamp"] <= 2))) { 219//msg('Default redirection: id '.$_GET['id'].'; do '.$_GET['do'], 1); 220 send_redirect(wl($this->private_page, '', true)); 221 } 222 } 223 } 224 } else { 225 return false; 226 } 227 } 228 229 function acl(&$event, $param) { 230 global $conf; 231 232 // If there's no conflict between private and public space 233 if ($this->multiNsOk()) { 234 if ((!$this->getConf('no_acl')) && ($conf['useacl']) && ($this->userOk())) { 235 global $config_cascade; 236 $existingLines = file($config_cascade['acl']['default']); 237 $newLines = array(); 238 // ACL 239 $acl = new admin_plugin_acl(); 240 // On private namespace 241 if ($this->getConf('create_private_ns')) { 242 // For known users 243 // If use_name_string or group_by_name is enabled, we can't use ACL wildcards so let's create ACL for current user on his private ns 244 if (($this->getConf('use_name_string')) or ($this->getConf('group_by_name'))) { 245 $where = $this->private_ns.':*'; 246 $who = strtolower($_SERVER['REMOTE_USER']); 247 // Otherwise we can set ACL for all known users at once 248 } else { 249 $where = cleanID($this->getConf('users_namespace')).':%USER%:*'; 250 $who = '%USER%'; 251 } 252 $perm = AUTH_DELETE; 253 if (!in_array("$where\t$who\t$perm\n", $existingLines)) { $newLines[] = array('where' => $where, 'who' => $who, 'perm' => $perm); } 254 // For @ALL 255 if ($this->getConf('acl_all_private') != 'noacl') { 256 $where = cleanID($this->getConf('users_namespace')).':*'; 257 $who = '@ALL'; 258 $perm = (int)$this->getConf('acl_all_private'); 259 if (!in_array("$where\t$who\t$perm\n", $existingLines)) { $newLines[] = array('where' => $where, 'who' => $who, 'perm' => $perm); } 260 } 261 // For @user 262 if (($this->getConf('acl_user_private') != 'noacl') && ($this->getConf('acl_user_private') !== $this->getConf('acl_all_private'))) { 263 $where = cleanID($this->getConf('users_namespace')).':*'; 264 $who = '@user'; 265 $perm = (int)$this->getConf('acl_user_private'); 266 if (!in_array("$where\t$who\t$perm\n", $existingLines)) { $newLines[] = array('where' => $where, 'who' => $who, 'perm' => $perm); } 267 } 268 } // end of private namespaces acl 269 // On public user pages 270 if ($this->getConf('create_public_page')) { 271 // For known users 272 if (strpos($this->getConf('public_pages_ns'),':%NAME%:%START%') !== false) { 273 $where = str_replace('%NAME%:%START%', '%USER%', $this->getConf('public_pages_ns')).':*'; 274 $perm = AUTH_DELETE; 275 } else { 276 $where = cleanID($this->getConf('public_pages_ns')).':%USER%'; 277 $perm = AUTH_EDIT; 278 } 279 $who = '%USER%'; 280 if (!in_array("$where\t$who\t$perm\n", $existingLines)) { $newLines[] = array('where' => $where, 'who' => $who, 'perm' => $perm); } 281 // For others 282 if ($this->getConf('acl_all_public') != 'noacl') { 283 // If both private and public namespaces are identical, we need to force rights for @ALL and/or @user on each public page 284 if ($this->getConf('users_namespace') == $this->getConf('public_pages_ns')) { 285 $files = scandir($this->dataDir.'/pages/'.$this->getConf('public_pages_ns')); 286 foreach($files as $file) { 287 if (is_file($this->dataDir.'/pages/'.$this->getConf('public_pages_ns').'/'.$file)) { 288 // ACL on templates will be managed another way 289 if (strpos($file, 'userhomepage_p') !== 0) { 290 // @ALL 291 if ($this->getConf('acl_all_public') != 'noacl') { 292 $where = $this->getConf('public_pages_ns').':'.substr($file, 0, -4); 293 $who = '@ALL'; 294 $perm = $this->getConf('acl_all_public'); 295 if (!in_array("$where\t$who\t$perm\n", $existingLines)) { $newLines[] = array('where' => $where, 'who' => $who, 'perm' => $perm); } 296 } 297 // @user 298 if ($this->getConf('acl_user_public') != 'noacl') { 299 $where = $this->getConf('public_pages_ns').':'.substr($file, 0, -4); 300 $who = '@user'; 301 $perm = $this->getConf('acl_user_public'); 302 if (!in_array("$where\t$who\t$perm\n", $existingLines)) { $newLines[] = array('where' => $where, 'who' => $who, 'perm' => $perm); } 303 } 304 } 305 } 306 } 307 // Otherwise we just need to give the right permission to each group on public pages namespace 308 } else { 309 // @ALL 310 if ($this->getConf('acl_all_public') != 'noacl') { 311 $where = cleanID(str_replace(':%NAME%:%START%', '', $this->getConf('public_pages_ns'))).':*'; 312 $who = '@ALL'; 313 $perm = $this->getConf('acl_all_public'); 314 if (!in_array("$where\t$who\t$perm\n", $existingLines)) { $newLines[] = array('where' => $where, 'who' => $who, 'perm' => $perm); } 315 } 316 // @user 317 if ($this->getConf('acl_user_public') != 'noacl') { 318 $where = cleanID(str_replace(':%NAME%:%START%', '', $this->getConf('public_pages_ns'))).':*'; 319 $who = '@user'; 320 $perm = $this->getConf('acl_user_public'); 321 if (!in_array("$where\t$who\t$perm\n", $existingLines)) { $newLines[] = array('where' => $where, 'who' => $who, 'perm' => $perm); } 322 } 323 } 324 } 325 } // end for public pages acl 326 // On templates if they're in data/pages 327 if (strpos($this->getConf('templates_path'),'/pages') !== false) { 328 // For @ALL 329 if (($this->getConf('acl_all_templates') != 'noacl') && (($this->getConf('create_private_ns')) or ($this->getConf('create_public_page')))) { 330 $where = end(explode('/',$this->getConf('templates_path'))).':userhomepage_private'; 331 $who = '@ALL'; 332 $perm = (int)$this->getConf('acl_all_templates'); 333 if (!in_array("$where\t$who\t$perm\n", $existingLines)) { $newLines[] = array('where' => $where, 'who' => $who, 'perm' => $perm); } 334 $where = end(explode('/',$this->getConf('templates_path'))).':userhomepage_public'; 335 $who = '@ALL'; 336 $perm = (int)$this->getConf('acl_all_templates'); 337 if (!in_array("$where\t$who\t$perm\n", $existingLines)) { $newLines[] = array('where' => $where, 'who' => $who, 'perm' => $perm); } 338 } 339 // For @user 340 if (($this->getConf('acl_user_templates') != 'noacl') && ($this->getConf('acl_user_templates') !== $this->getConf('acl_all_templates')) && (($this->getConf('create_private_ns')) or ($this->getConf('create_public_page')))) { 341 $where = end(explode('/',$this->getConf('templates_path'))).':userhomepage_private'; 342 $who = '@user'; 343 $perm = (int)$this->getConf('acl_user_templates'); 344 if (!in_array("$where\t$who\t$perm\n", $existingLines)) { $newLines[] = array('where' => $where, 'who' => $who, 'perm' => $perm); } 345 $where = end(explode('/',$this->getConf('templates_path'))).':userhomepage_public'; 346 $who = '@user'; 347 $perm = (int)$this->getConf('acl_user_templates'); 348 if (!in_array("$where\t$who\t$perm\n", $existingLines)) { $newLines[] = array('where' => $where, 'who' => $who, 'perm' => $perm); } 349 } 350 } // end of templates acl 351 $i = count($newLines); 352 if ($i > 0) { 353 msg($this->getLang('aclupdate').' '.$i, 1); 354 foreach($newLines as $line) { 355 if (($line['where'] != null) && ($line['who'] != null)) { 356 // delete potential ACL rule with same scope (aka 'where') and same user (aka 'who') 357 $acl->deleteACL($line['where'], $line['who']); 358 $acl->addOrUpdateACL($line['where'], $line['who'], $line['perm']); 359 } 360 } 361 } 362 } 363 } else { 364 return false; 365 } 366 } 367 368 function copyFile($source = null, $target_dir = null, $target_file = null) { 369 if (!is_file($this->dataDir.DIRECTORY_SEPARATOR.$target_dir.DIRECTORY_SEPARATOR.$target_file)) { 370 if(!is_dir($this->dataDir.DIRECTORY_SEPARATOR.$target_dir)){ 371 io_mkdir_p($this->dataDir.DIRECTORY_SEPARATOR.$target_dir) || msg($this->getLang('mkdirfailure').' '.$target_dir,-1); 372 } 373 $source = str_replace('/', DIRECTORY_SEPARATOR, $source); 374 copy($source, $this->dataDir.DIRECTORY_SEPARATOR.$target_dir.DIRECTORY_SEPARATOR.$target_file); 375 if (is_file($this->dataDir.DIRECTORY_SEPARATOR.$target_dir.DIRECTORY_SEPARATOR.$target_file)) { 376 msg($this->getLang('copysuccess').' ('.$source.' > '.$this->dataDir.DIRECTORY_SEPARATOR.$target_dir.DIRECTORY_SEPARATOR.$target_file.')', 1); 377 } else { 378 msg($this->getLang('copyerror').' ('.$source.' > '.$this->dataDir.DIRECTORY_SEPARATOR.$target_dir.DIRECTORY_SEPARATOR.$target_file.')', -1); 379 } 380 } else { 381 msg($this->getLang('copynotneeded').' ('.$source.' > '.$this->dataDir.DIRECTORY_SEPARATOR.$target_dir.DIRECTORY_SEPARATOR.$target_file.')', 0); 382 } 383 } 384 385 function privateNamespace() { 386 if ( $this->getConf('use_name_string')) { 387 global $INFO; 388 $raw_string = cleanID($INFO['userinfo']['name']); 389 // simon_delage 390 return $raw_string; 391 } else { 392 // simon 393 return strtolower($_SERVER['REMOTE_USER']); 394 } 395 } 396 397 function privateStart() { 398 if ($this->getConf('use_start_page')) { 399 global $conf; 400 return cleanID($conf['start']); 401 } else { 402 return $this->privateNamespace(); 403 } 404 } 405 406 function applyTemplate($type) { 407 global $conf; 408 if ($type == 'private') { 409 $content = io_readFile($this->private_page_template, false); 410 } elseif ($type == 'public') { 411 $content = io_readFile($this->public_page_template, false); 412 } else { 413 $content = io_readFile($type, false); 414 } 415 // If template is absolutely empty (ie. is NULL), target file will not be created but plugin will pretend it did and will keep trying over next page load 416 if ($content == NULL) { 417 // fill empty template with a simple space to work around the problem 418 $content = " "; 419 } 420 421 $content = str_replace('@TARGETPRIVATEPAGE@', $this->helper->getPrivateID(), $content); 422 $content = str_replace('@TARGETPRIVATENS@', cleanID(str_replace(':'.$conf['start'], '', $this->helper->getPrivateID())), $content); 423 $content = str_replace('@TARGETPUBLICPAGE@', $this->helper->getPublicID(), $content); 424 $content = str_replace('@TARGETPUBLICNS@', cleanID(str_replace(':'.$conf['start'], '', $this->helper->getPublicID())), $content); 425 // Improved template process to use standard replacement patterns from https://www.dokuwiki.org/namespace_templates based on code proposed by Christian Nancy 426 // Build a fake data structure for the parser 427 $data = array('tpl' => $content, 'id' => $this->private_page); 428 // Use the built-in parser 429 $content = parsePageTemplate($data); 430 return $content; 431 } 432 433 function replaceUserLink(&$event, $param) { 434 global $INFO; 435 global $conf; 436 437 // If there's no conflict between private and public space 438 if ($this->multiNsOk()) { 439 if (($conf['showuseras'] == "username_link") and ($this->getConf('userlink_replace'))) { 440 $classes = $this->getConf('userlink_classes'); 441 $classes = str_replace(',', ' ', $classes); 442 //if ($this->getConf('userlink_fa')) { 443 // $classes = str_replace('interwiki', '', $classes); 444 //} 445 $this->username = $event->data['username']; 446 $this->name = $event->data['name']; 447 $this->link = $event->data['link']; 448 $this->userlink = $event->data['userlink']; 449 $this->textonly = $event->data['textonly']; 450 // Logged in as... 451 if (strpos($this->name, '<bdi>') !== false) { 452 $privateId = $this->helper->getPrivateID(); 453 $publicId = $this->helper->getPublicID(); 454 if ((page_exists($privateId)) && (page_exists($publicId))) { 455 if ($this->getConf('userlink_fa')) { 456 $return = '<a href="'.wl($privateId).'" class="'.$classes.' uhp_fa" rel="nofollow" title="'.$this->getLang('privatenamespace').' ('.$privateId.')'.'"><bdi><i class="fa fa-user-secret"></i>'.$INFO['userinfo']['name'].'</bdi></a> (<a href="'.wl($publicId).'" class="'.$classes.' uhp_fa" rel="nofollow" title="'.$this->getLang('publicpage').' ('.$publicId.')'.'"><bdi><i class="fa fa-user"></i>'.$_SERVER['REMOTE_USER'].'</bdi></a>)'; 457 } else { 458 $return = '<a href="'.wl($privateId).'" class="'.$classes.' uhp_private_'.$this->getConf('userlink_icons').'" rel="nofollow" title="'.$this->getLang('privatenamespace').' ('.$privateId.')'.'"><bdi>'.$INFO['userinfo']['name'].'</bdi></a> (<a href="'.wl($publicId).'" class="'.$classes.' uhp_public_'.$this->getConf('userlink_icons').'" rel="nofollow" title="'.$this->getLang('publicpage').' ('.$publicId.')'.'"><bdi>'.$_SERVER['REMOTE_USER'].'</bdi></a>)'; 459 } 460 } elseif (page_exists($publicId)) { 461 if ($this->getConf('userlink_fa')) { 462 $return = '</a> (<a href="'.wl($publicId).'" class="'.$classes.' uhp_fa" rel="nofollow" title="'.$this->getLang('publicpage').'('.$publicId.')'.'"><bdi><i class="fa fa-user"></i>'.$_SERVER['REMOTE_USER'].'</bdi></a>)'; 463 } else { 464 $return = '<bdi>'.$INFO['userinfo']['name'].'</bdi> (<a href="'.wl($publicId).'" class="'.$classes.' uhp_public_'.$this->getConf('userlink_icons').'" rel="nofollow" title="'.$this->getLang('publicpage').' ('.$publicId.')'.'"><bdi>'.$_SERVER['REMOTE_USER'].'</bdi></a>)'; 465 } 466 } elseif (page_exists($privateId)) { 467 if ($this->getConf('userlink_fa')) { 468 $return = '<a href="'.wl($privateId).'" class="'.$classes.' uhp_fa" rel="nofollow" title="'.$this->getLang('privatenamespace').' ('.$privateId.')'.'"><bdi><i class="fa fa-user-secret"></i>'.$INFO['userinfo']['name'].'</bdi></a>'; 469 } else { 470 $return = '<a href="'.wl($privateId).'" class="'.$classes.' uhp_private_'.$this->getConf('userlink_icons').'" rel="nofollow" title="'.$this->getLang('privatenamespace').' ('.$privateId.')'.'"><bdi>'.$INFO['userinfo']['name'].'</bdi></a> (<bdi>'.$_SERVER['REMOTE_USER'].'</bdi>)'; 471 } 472 } else { 473 $return = null; 474 } 475 // ... or Last modified... 476 } else { 477 // No change for this right now 478 $return = null; 479 } 480 if ($return != null) { 481 $event->data = array( 482 'username' => $this->username, 483 'name' => $this->name, 484 'link' => $this->link, 485 'userlink' => $return, 486 'textonly' => $this->textonly 487 ); 488 } 489 } 490 } else { 491 return false; 492 } 493 } 494 495 function multiNsOk($msg=false) { 496 // Error: Public page switched to namespace and is in conflict with Private namespace 497 if (strpos($this->getConf('public_pages_ns'),':%NAME%:%START%') !== false) { 498 $PublicNS = str_replace(':%NAME%:%START%', '', $this->getConf('public_pages_ns')); 499 $PublicNS = str_replace(':', '', $PublicNS); 500 $PrivateNS = str_replace(':', '', $this->getConf('users_namespace')); 501 if ($PublicNS == $PrivateNS) { 502 if ($msg) { 503 msg($this->getLang('settingsconflict'), -1); 504 } 505 return false; 506 } else { 507 return true; 508 } 509 } else { 510 return true; 511 } 512 } 513 514 function userOk($check = null) { 515 global $INFO; 516 517 // Proceed only if named user is connected... 518 if ($_SERVER['REMOTE_USER'] != null) { 519 // Check if user is member of a group in 'groups_private' or 'groups_public' (depending on $check) 520 if (($check == 'private') or ($check == 'public')) { 521 // Stop if 'groups_private' is set and and user is not member of at least one of said groups 522 $groups = $this->getConf('groups_'.$check); 523 $groups = str_replace(' ','', $groups); 524 $groups = explode(',', $groups); 525 $userGroups = $INFO['userinfo']['grps']; 526 // If UHP is set to check user's group(s) 527 if (($groups != null) and ($groups[0] != null) and ($userGroups != null)) { 528 $test = array_intersect($groups, $userGroups); 529 // Proceed if user is member of at least one group set UHP's corresponding setting 530 if (count($test) > 0) { 531 return true; 532 } else { 533 return false; 534 } 535 // If UHP isn't set to ckeck user's group(s) we can proceed 536 } else { 537 return true; 538 } 539 // If $check is null, we only need to know that a named user is connected (wich we allready know if we went that far) 540 } else { 541 return true; 542 } 543 // ... else stop 544 } else { 545 return false; 546 } 547 } 548 549} 550