1<?php 2/** 3 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 4 * @author Myron Turner <turnermm02@shaw.ca> 5 */ 6 7// must be run within Dokuwiki 8if (!defined('DOKU_INC')) die(); 9if (!defined('HTMLOK_ACCESS_DIR')) define('HTMLOK_ACCESS_DIR', realpath(dirname(__FILE__)) . '/conf/access'); 10 11class helper_plugin_htmlOKay extends DokuWiki_Plugin { 12 13 var $access_level = 0; 14 var $saved_inf; 15 var $current_file; 16 var $files; 17 var $users; 18 var $groups; 19 var $display; 20 var $namespace; 21 var $db_msg; 22 23 function getMethods(){ 24 $result = array(); 25 $result[] = array( 26 'name' => 'set_permissions', 27 'desc' => "initialize current user's access permissions", 28 'params' =>array() 29 ); 30 $result[] = array( 31 'name' => 'get_namespace', 32 'desc' => 'returns current access namespace', 33 'params' =>array(), 34 'return' => array('namespace' => 'string') 35 ); 36 $result[] = array( 37 'name' => 'get_access_scope', 38 'desc' => 'returns current access scope with namespace colons replaced with hashes: ns#ns2#page', 39 'params' =>array('path' => 'string') , 40 'return' => array('access_scope' => 'string') 41 ); 42 $result[] = array( 43 'name' => 'set_DokuWikiDefault_perm', 44 'desc' => 'sets htmlok=0,$INFO[htmlOK_client] = false', 45 'params' =>array() 46 ); 47 $result[] = array( 48 'name' => 'get_access_file', 49 'desc' => 'returns system path to file holding access data', 50 'params' =>array('access_dir' => 'string', 'namespace' => 'string') , 51 'return' => array('acces_file' => 'string') 52 ); 53 $result[] = array( 54 'name' => 'in_groups', 55 'desc' => 'checks htmlOKay user groups against INFO[userinfo][groups] to see if this is htmlOKay user', 56 'params' =>array('INF0_groups' => 'string', 'groups' => 'string'), 57 'return' => array('in_group' => 'bool') 58 ); 59 $result[] = array( 60 'name' => 'get_permission_level', 61 'desc' => 'checks htmlOKay user groups against INFO[userinfo][groups] to see if this is htmlOKay user', 62 'params' =>array('info' => 'mixed', 'htmlok' => 'mixed'), 63 'return' => array('level' => 'integer') 64 ); 65 $result[] = array( 66 'name' => 'get_access ', 67 'desc' => 'gets current access level', 68 'params' =>array(), 69 'return' => array('level' => 'integer') 70 ); 71 return $result; 72 } 73 74 75 function get_info() 76 { 77 global $conf; 78 global $INFO, $ID; 79 80 if (empty($INFO['namespace'])) { 81 $INFO['namespace'] = getNS($ID); 82 } 83 84 if (!empty($INFO['namespace'])) 85 { 86 $namespace = $INFO['namespace']; 87 } 88 89 else 90 { 91 $namespace = '_ROOT_'; 92 } 93 94 $this->namespace = $namespace; 95 $namespace = str_replace(':', '#', $namespace); 96 97 $access_file = $this->get_access_file(HTMLOK_ACCESS_DIR, $namespace); 98 if (!defined('ACCESS_FILE')) define('ACCESS_FILE', $access_file); 99 $access_file = ACCESS_FILE; 100 if (file_exists($access_file)) 101 { 102 $INFO['htmlOK_access_scope'] = $this->get_access_scope($access_file); 103 $this->saved_inf =file_get_contents ($access_file); 104 105 if (!$this->saved_inf) 106 { 107 return; 108 } 109 $this->saved_inf = unserialize($this->saved_inf); 110 $this->files = $this->saved_inf['filespecs']; 111 $this->users = $this->saved_inf['user']; 112 $this->groups = $this->saved_inf['group']; 113 if(!empty($INFO['filepath'])) { 114 $this->curent_file = basename($INFO['filepath']); 115 } 116 else { 117 $this->curent_file = noNS($ID) . '.txt'; 118 } 119 120 $this->access_file = $access_file; 121 } 122 } 123 124 function get_saved_inf() { 125 return $this->saved_inf; 126 } 127 128 function get_namespace() { 129 return $this->namespace; 130 } 131 132 function set_permissions() 133 { 134 global $INFO; 135 global $ID; 136 global $conf; 137 138 $this->get_info(); 139 $in_group = false; 140 $in_users = false; 141 $file_found = false; 142 // set up defaults 143 $INFO['htmlOK_client'] = $INFO['client']; // set as a flag for use in syntax.php 144 $INFO['htmlOK_displayOnly'] = $this->saved_inf['display']; 145 $INFO['hmtlOK_access_level'] = 0; 146 // have HTML permissions been set for this namespace? 147 148 if (!$this->saved_inf) 149 { 150 $this->set_DokuWikiDefault_perm(); // Not HTML 151 return; 152 } 153 154 // have HTML permissions been set for this file in current namespace? 155 $this->set_dbg_msg("permissions exist"); 156 foreach($this->files as $file) 157 { 158 if ($file == $this->curent_file || $file == 'all') 159 { 160 $file_found = true; 161 break; 162 } 163 } 164 165 if (!$file_found) 166 { 167 $this->set_DokuWikiDefault_perm(); // Not HTML 168 return; 169 } 170 // The current file has access to embedded HTML 171 // Does user belong to a group which has HTML access? 172 if(isset($INFO['userinfo'])) { 173 $INF0_groups = $INFO['userinfo']['grps']; 174 } 175 else { 176 $INF0_groups = ""; 177 } 178 179 if (isset($this->groups) && !empty($this->groups)) 180 { 181 $groups = array_keys($this->groups); 182 // $groups_found will be groups common to user and current page 183 $groups_found = $this->in_groups($INF0_groups, $groups); 184 if ($groups_found !== false) 185 { 186 $in_group = true; 187 } 188 } 189 190 // Does user have individual HTML access? 191 if (isset($this->users) && !empty($this->users)) 192 { 193 $users = array_keys($this->users); 194 if (array_search ($INFO['client'], $users) !== false) 195 { 196 $in_users = true; 197 } 198 } 199 200 if ($in_users) $this->set_dbg_msg("User found: " . $INFO['client']); 201 else $this->set_dbg_msg("User " . $INFO['client'] . ' not found'); 202 203 if ($in_group) 204 { 205 $str = print_r($groups_found, true); 206 $this->set_dbg_msg("Group(s) found: $str"); 207 } 208 // If the user is not among groups or users with access then permissions are according to ACL 209 // check to see if the page uses HTML and has a default HTML access level 210 if (!$in_users && !$in_group) 211 { 212 $INFO['htmlOK_client'] = false; 213 if (isset($this->saved_inf['display'])) 214 { 215 $INFO['hmtlOK_access_level'] = $this->get_permission_level('display', $this->saved_inf); 216 $this->set_dbg_msg("Display: " . $INFO['hmtlOK_access_level']); 217 $conf['htmlok'] = 1; 218 $INFO['htmlOK_visitor'] = true; 219 220 $cache = new cache($ID, ".xhtml"); 221 trigger_event('PARSER_CACHE_USE', $cache); 222 223 return; 224 } 225 $this->set_dbg_msg("Permission denied"); 226 return; 227 } 228 229 // Now we have to check the level of access 230 // and grant the user the highest level of his/her permissions 231 $group_level = 0; 232 $user_level = 0; 233 if ($in_group) 234 { 235 $group_level = $this->get_permission_level($groups_found, $this->groups); 236 } 237 if ($in_users) 238 { 239 $user_level = $this->get_permission_level($INFO['client'], $this->users); 240 } 241 $INFO['hmtlOK_access_level'] = ($group_level > $user_level) ? $group_level : $user_level; 242 243 if ($INFO['hmtlOK_access_level'] == 0) 244 { 245 $this->set_DokuWikiDefault_perm(); 246 return; 247 } 248 $conf['htmlok'] = 1; 249 } 250 251 function get_access_scope($path) { 252 $access_dir = preg_quote(HTMLOK_ACCESS_DIR, '/'); 253 $access_scope = preg_replace('/' . $access_dir . '/', "", $path); 254 $access_scope = trim($access_scope,'/' ); 255 $access_scope = preg_replace('/#/', ':',$access_scope); 256 return $access_scope; 257 } 258 259 function set_DokuWikiDefault_perm() 260 { 261 global $INFO; 262 global $conf; 263 $INFO['htmlOK_client'] = false; // deactivate PARSER_CACHE_USE event, which 264 // disables caching while page is being edited 265 $conf['htmlok'] = 0; // Stop syntax.php from applying rules, this is not HTML 266 267 // So we will let ACL determine write permissions 268 } 269 270 function get_access_file($access_dir, $namespace) 271 { 272 $file = $access_dir . '/' . $namespace; 273 $this->set_dbg_msg("Original access file: $file"); 274 if (file_exists($file)) 275 { 276 $this->set_dbg_msg("Tried Original access file: $file"); 277 return $file; 278 } 279 280 $dirs = explode('#', $namespace); 281 foreach($dirs as $dir) 282 { 283 array_pop($dirs); 284 $new_dir = implode('#', $dirs); 285 $file = $access_dir . '/' . $new_dir; 286 $this->set_dbg_msg("Tried access file: $file"); 287 288 if (file_exists($file)) 289 { 290 $this->set_dbg_msg("File exists: $file"); 291 return $file; 292 } 293 } 294 return $access_dir . '/' . $namespace; 295 } 296 297 function in_groups($INF0_groups, $groups) 298 { 299 $groups_found = array(); 300 $in_group = false; 301 302 if (!isset($INF0_groups)) return false; // no groups assigned to non-registered user 303 if(!is_array($INF0_groups)) return false; 304 foreach($INF0_groups as $grp) 305 { 306 if (array_search ($grp, $groups) !== false) 307 { 308 $in_group = true; 309 $groups_found[] = $grp; 310 } 311 } 312 if ($in_group) return $groups_found; 313 return false; 314 } 315 316 /** 317 * 318 * @param mixed $info either string, which is $INFO['client'] or array of groups common to 319 * both $INFO['userinfo']['grps'] and htmlOK's $saved_inf 320 * @param array $htmlok either user or group array from htmlOK $saved_inf 321 * @return integer the level as an integer 322 */ 323 function get_permission_level($info, $htmlok) 324 { 325 $levels = array('none' => 0, 'strict' => 1, 'medium' => 2, 'lax' => 3, 'su' => 4); 326 327 if (is_string($info)) 328 { 329 if(array_key_exists ( $info , $levels)) { 330 $this->access_level = $levels[$htmlok[$info]]; 331 return $levels[$htmlok[$info]]; 332 } 333 } 334 if(!is_array($info)) return 0; 335 $level = 0; 336 foreach($info as $name) 337 { 338 $temp = $htmlok[$name]; 339 if ($levels[$temp] > $level) 340 { 341 $level = $levels[$temp]; 342 } 343 } 344 345 $this->access_level = $level; 346 return $level; 347 } 348 349 function get_access() { 350 global $INFO; 351 352 if($INFO['hmtlOK_access_level'] ) { 353 return $INFO['hmtlOK_access_level']; 354 } 355 return $this->get_permission_level('display', $this->saved_inf); 356 } 357 358 function set_dbg_msg($msg="") { 359 if(!$msg) return $this->db_msg; 360 $this->db_msg .= $msg . '<br />'; 361 } 362 363} 364