load($filename)) { die("Cannot parse $filename!"); } // Move footer information $this->showFooter= ($config->get_cfg_value("listSummary") == "true"); // Register build in filters $this->registerElementFilter("objectType", "listing::filterObjectType"); $this->registerElementFilter("link", "listing::filterLink"); $this->registerElementFilter("actions", "listing::filterActions"); // Initialize pid $this->pid= preg_replace("/[^0-9]/", "", microtime(TRUE)); } function registerElementFilter($name, $call) { if (!isset($this->filters[$name])) { $this->filters[$name]= $call; return true; } return false; } function load($filename) { $contents = file_get_contents($filename); $this->xmlData= xml::xml2array($contents, 1); if (!isset($this->xmlData['list'])) { return false; } $this->xmlData= $this->xmlData["list"]; // Load some definition values foreach (array("departmentBrowser", "departmentRootVisible", "multiSelect") as $token) { if (isset($this->xmlData['definition'][$token]) && $this->xmlData['definition'][$token] == "true"){ $this->$token= true; } } // Fill objectTypes if (isset($this->xmlData['definition']['objectType'])) { foreach ($this->xmlData['definition']['objectType'] as $index => $otype) { $this->objectTypes[]= $this->xmlData['definition']['objectType'][$index]; } } // Parse layout per column $this->colprops= $this->parseLayout($this->xmlData['table']['layout']); // Prepare table headers $this->header= array(); if (isset($this->xmlData['table']['column'])){ foreach ($this->xmlData['table']['column'] as $index => $config) { if (isset($config['label'])) { $this->header[$index]= "colprops[$index].">"._($config['label']).""; } else { $this->header[$index]= "colprops[$index]."> "; } } } // Assign headline/module $this->headline= _($this->xmlData['definition']['label']); $this->module= $this->xmlData['definition']['module']; return true; } function render() { echo "sorting, department browsing, filter base handling, copy'n paste handler, snapshot handler
"; // Initialize list $result= ""; $result.= "
"; $result.= ""; // New table for the real list contents $result.= ""; // Add the footer if requested if ($this->showFooter) { $result.= ""; } $result.= "
"; $num_cols= count($this->colprops) + ($this->multiSelect?1:0); // Build list header $result.= ""; if ($this->multiSelect) { $result.= ""; } foreach ($this->header as $header) { $result.= $header; } // Add 13px for scroller $result.= "
 
"; // No results? Just take an empty colspanned row if (count($this->entries) == 0) { $result.= ""; } // Fill with contents foreach ($this->entries as $row => $entry){ $result.=""; // Render multi select if needed if ($this->multiSelect) { $result.=""; } foreach ($this->xmlData['table']['column'] as $index => $config) { $result.=""; } $result.=""; } // Need to fill the list if it's not full (nobody knows why this is 22 ;-)) $emptyListStyle= (count($this->entries) == 0)?"border:0;":""; if (count($this->entries) < 22) { $result.= ""; for ($i= 0; $i<$num_cols; $i++) { if ($i == 0) { $result.= ""; continue; } if ($i != $num_cols-1) { $result.= ""; } else { $result.= ""; } } $result.= ""; } $result.= "
 
colprops[$index]." class='list0'>".$this->renderCell($config['value'], $entry, $row)."
   
"; foreach ($this->objectTypes as $objectType) { if (isset($this->objectTypeCount[$objectType['label']])) { $label= _($objectType['label']); $result.= "$label ".$this->objectTypeCount[$objectType['label']]."    "; } } $result.= " 
"; $smarty= get_smarty(); $smarty->assign("FILTER", $this->filter->render()); $smarty->assign("LIST", $result); // Assign navigation elements $nav= $this->renderNavigation(); foreach ($nav as $key => $html) { $smarty->assign($key, $html); } // Assign action menu $smarty->assign("ACTIONS", $this->renderActionMenu()); // Assign separator $smarty->assign("SEPARATOR", "-"); // Assign summary $smarty->assign("HEADLINE", $this->headline); return ($smarty->fetch(get_template_path($this->xmlData['definition']['template'], true))); } function setFilter($filter) { $this->filter= &$filter; $this->entries= $this->filter->query(); } function update() { // Do not do anything if this is not our PID # DISABLED because the object is not in the session #if(isset($_REQUEST['PID']) && $_REQUEST['PID'] != $this->pid) { # return; #} $this->entries= $this->filter->query(); } function parseLayout($layout) { $result= array(); $layout= preg_replace("/^\|/", "", $layout); $layout= preg_replace("/\|$/", "", $layout); $cols= split("\|", $layout); foreach ($cols as $index => $config) { if ($config != "") { $components= split(';', $config); $config= ""; foreach ($components as $part) { if (preg_match("/^r$/", $part)) { $config.= "text-align:right;"; continue; } if (preg_match("/^l$/", $part)) { $config.= "text-align:left;"; continue; } if (preg_match("/^c$/", $part)) { $config.= "text-align:center;"; continue; } if (preg_match("/^[0-9]+(|px|%)$/", $part)) { $config.= "width:$part;"; continue; } } $result[$index]= " style='$config' "; } else { $result[$index]= null; } } return $result; } function renderCell($data, $config, $row) { // Replace flat attributes in data string for ($i= 0; $i<$config['count']; $i++) { $attr= $config[$i]; $value= ""; if (is_array($config[$attr])) { $value= $config[$attr][0]; } else { $value= $config[$attr]; } $data= preg_replace("/%\{$attr\}/", $value, $data); } // Watch out for filters and prepare to execute them $data= $this->processElementFilter($data, $config, $row); return $data; } function processElementFilter($data, $config, $row) { preg_match_all("/%\{filter:([^(]+)\((.*)\)\}/", $data, $matches, PREG_SET_ORDER); foreach ($matches as $match) { if (!isset($this->filters[$match[1]])) { continue; } $cl= preg_replace('/::.*$/', '', $this->filters[$match[1]]); $method= preg_replace('/^.*::/', '', $this->filters[$match[1]]); // Prepare params for function call $params= array(); preg_match_all('/"[^"]+"|[^,]+/', $match[2], $parts); foreach ($parts[0] as $param) { // Row is replaced by the row number if ($param == "row") { $params[]= $row; } // pid is replaced by the current PID if ($param == "pid") { $params[]= $this->pid; } // Fixie with "" is passed directly if (preg_match('/^".*"$/', $param)){ $params[]= preg_replace('/"/', '', $param); } // LDAP variables get replaced by their objects for ($i= 0; $i<$config['count']; $i++) { if ($param == $config[$i]) { $values= $config[$config[$i]]; if (is_array($values)){ unset($values['count']); } $params[]= $values; } } // Move dn if needed if ($param == "dn") { $params[]= LDAP::fix($config["dn"]); } } // Replace information if ($cl == "listing") { // Non static call - seems to result in errors $data= @preg_replace('/'.preg_quote($match[0]).'/', call_user_func_array(array($this, "$method"), $params), $data); } else { // Static call $data= preg_replace('/'.preg_quote($match[0]).'/', call_user_func_array(array($cl, $method), $params), $data); } } return $data; } function getObjectType($types, $classes) { // Walk thru types and see if there's something matching foreach ($types as $objectType) { $ocs= $objectType['objectClass']; if (!is_array($ocs)){ $ocs= array($ocs); } $found= true; foreach ($ocs as $oc){ if (preg_match('/^!(.*)$/', $oc, $match)) { $oc= $match[1]; if (in_array($oc, $classes)) { $found= false; } } else { if (!in_array($oc, $classes)) { $found= false; } } } if ($found) { return $objectType; } } return null; } function filterObjectType($dn, $classes) { // Walk thru classes and return on first match $result= " "; $objectType= $this->getObjectType($this->objectTypes, $classes); if ($objectType) { $result= ""; if (!isset($this->objectTypeCount[$objectType['label']])) { $this->objectTypeCount[$objectType['label']]= 0; } $this->objectTypeCount[$objectType['label']]++; } return $result; } function filterActions($dn, $row, $classes) { // Do nothing if there's no menu defined if (!isset($this->xmlData['actiontriggers']['action'])) { return " "; } // Go thru all actions $result= ""; $actions= $this->xmlData['actiontriggers']['action']; foreach($actions as $action) { // Skip the entry completely if there's no permission to execute it if (!$this->hasActionPermission($action, $dn)) { continue; } // If there's an objectclass definition and we don't have it // add an empty picture here. if (isset($action['objectclass'])){ $objectclass= $action['objectclass']; if (preg_match('/^!(.*)$/', $objectclass, $m)){ $objectclass= $m[1]; if(in_array($objectclass, $classes)) { $result.= " "; continue; } } else { if(!in_array($objectclass, $classes)) { $result.= " "; continue; } } } // Render normal entries as usual if ($action['type'] == "entry") { $label= $this->processElementFilter($action['label'], $this->entries[$row], $row); $image= $this->processElementFilter($action['image'], $this->entries[$row], $row); $result.=""; } // Handle special types if ($action['type'] == "snapshot") { #TODO #echo "actiontriggers: snapshot missing
"; } if ($action['type'] == "copypaste") { #TODO #echo "actiontriggers: copypaste missing
"; } if ($action['type'] == "daemon") { #TODO #echo "actiontriggers: daemon missing
"; } } return $result; } function filterLink() { $result= " "; $row= func_get_arg(0); $pid= func_get_arg(1); $dn= LDAP::fix(func_get_arg(2)); $params= array(func_get_arg(3)); // Collect sprintf params for ($i = 4;$i < func_num_args();$i++) { $val= func_get_arg($i); if (is_array($val)){ $params[]= $val[0]; continue; } $params[]= $val; } $result= " "; $trans= call_user_func_array("sprintf", $params); if ($trans != "") { return("$trans"); } return $result; } function renderNavigation() { $result= array(); $enableBack = true; $enableRoot = true; $enableHome = true; $ui = get_userinfo(); /* Check if base = first available base */ $deps = $ui->get_module_departments($this->module); if(!count($deps) || $deps[0] == $this->filter->base){ $enableBack = false; $enableRoot = false; } $listhead =""; /* Check if we are in users home department */ if(!count($deps) ||$this->filter->base == get_base_from_people($ui->dn)){ $enableHome = false; } /* Draw root button */ if($enableRoot){ $result["ROOT"]= ""; }else{ $result["ROOT"]= ""._("Root").""; } /* Draw back button */ if($enableBack){ $result["BACK"]= ""; }else{ $result["BACK"]= ""._("Up").""; } /* Draw home button */ if($enableHome){ $result["HOME"]= ""; }else{ $result["HOME"]= ""._("Home").""; } /* Draw reload button, this button is enabled everytime */ $result["RELOAD"]= ""; return ($result); } function getAction() { // Do not do anything if this is not our PID # DISABLED because the object is not in the session #if(isset($_REQUEST['PID']) && $_REQUEST['PID'] != $this->pid) { # return; #} $result= array("targets" => array(), "action" => ""); // Filter GET with "act" attributes if (isset($_GET['act'])) { $key= validate($_GET['act']); $target= preg_replace('/^listing_[a-zA-Z_]+_([0-9]+)$/', '$1', $key); if (isset($this->entries[$target]['dn'])) { $result['action']= preg_replace('/^listing_([a-zA-Z_]+)_[0-9]+$/', '$1', $key); $result['targets'][]= $this->entries[$target]['dn']; } // Drop targets if empty if (count($result['targets']) == 0) { unset($result['targets']); } return $result; } // Filter POST with "listing_" attributes foreach ($_POST as $key => $prop) { // Capture selections if (preg_match('/^listing_selected_[0-9]+$/', $key)) { $target= preg_replace('/^listing_selected_([0-9]+)$/', '$1', $key); if (isset($this->entries[$target]['dn'])) { $result['targets'][]= $this->entries[$target]['dn']; } continue; } // Capture action with target - this is a one shot if (preg_match('/^listing_[a-zA-Z_]+_[0-9]+(|_x)$/', $key)) { $target= preg_replace('/^listing_[a-zA-Z_]+_([0-9]+)(|_x)$/', '$1', $key); if (isset($this->entries[$target]['dn'])) { $result['action']= preg_replace('/^listing_([a-zA-Z_]+)_[0-9]+(|_x)$/', '$1', $key); $result['targets']= array($this->entries[$target]['dn']); } break; } // Capture action without target if (preg_match('/^listing_[a-zA-Z_]+(|_x)$/', $key)) { $result['action']= preg_replace('/^listing_([a-zA-Z_]+)(|_x)$/', '$1', $key); continue; } } // Filter POST with "act" attributes -> posted from action menu if (isset($_POST['act']) && $_POST['act'] != '') { $result['action']= validate($_POST['act']); } // Drop targets if empty if (count($result['targets']) == 0) { unset($result['targets']); } return $result; } function renderActionMenu() { // Don't send anything if the menu is not defined if (!isset($this->xmlData['actionmenu']['action'])){ return ""; } // Load shortcut $actions= &$this->xmlData['actionmenu']['action']; $result= "". "
"; } function recurseActions($actions) { static $level= 2; $result= ""; return $result; } function hasActionPermission($action, $dn) { $ui= get_userinfo(); if (isset($action['acl'])) { $acls= $action['acl']; if (!is_array($acls)) { $acls= array($acls); } // Every ACL has to pass foreach ($acls as $acl) { $module= $this->module; $acllist= array(); // Split for category and plugins if needed // match for "[rw]" style entries if (preg_match('/^\[([rwcdm]+)\]$/', $acl, $match)){ $aclList= array($match[1]); } // match for "users[rw]" style entries if (preg_match('/^([a-zA-Z0-9]+)\[([rwcdm]+)\]$/', $acl, $match)){ $module= $match[1]; $aclList= array($match[2]); } // match for "users/user[rw]" style entries if (preg_match('/^([a-zA-Z0-9]+\/[a-zA-Z0-9]+)\[([rwcdm]+)\]$/', $acl, $match)){ $module= $match[1]; $aclList= array($match[2]); } // match "users/user[userPassword:rw(,...)*]" style entries if (preg_match('/^([a-zA-Z0-9]+\/[a-zA-Z0-9]+)\[([a-zA-Z0-9]+:[rwcdm]+(,[a-zA-Z0-9]+:[rwcdm]+)*)\]$/', $acl, $match)){ $module= $match[1]; $aclList= split(',', $match[2]); } // Walk thru prepared ACL by using $module foreach($aclList as $sAcl) { $checkAcl= ""; // Category or detailed permission? if (strpos('/', $module) === false) { if (preg_match('/([a-zA-Z0-9]+):([rwcdm]+)/', $sAcl, $m) ) { $checkAcl= $ui->get_permissions($dn, $module, $m[1]); $sAcl= $m[2]; } else { $checkAcl= $ui->get_permissions($dn, $module, '0'); } } else { $checkAcl= $ui->get_category_permissions($dn, $module); } // Split up remaining part of the acl and check if it we're // allowed to do something... $parts= str_split($sAcl); foreach ($parts as $part) { if (strpos($checkAcl, $part) === false){ return false; } } } } } return true; } } ?>