Code

Added a filter preparation files
authorcajus <cajus@594d385d-05f5-0310-b6e9-bd551577e9d8>
Thu, 6 Aug 2009 12:37:27 +0000 (12:37 +0000)
committercajus <cajus@594d385d-05f5-0310-b6e9-bd551577e9d8>
Thu, 6 Aug 2009 12:37:27 +0000 (12:37 +0000)
git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@13981 594d385d-05f5-0310-b6e9-bd551577e9d8

gosa-core/ihtml/themes/default/filter/users.tpl [new file with mode: 0644]
gosa-core/include/class_filter.inc [new file with mode: 0755]
gosa-core/include/class_filterLDAP.inc [new file with mode: 0755]

diff --git a/gosa-core/ihtml/themes/default/filter/users.tpl b/gosa-core/ihtml/themes/default/filter/users.tpl
new file mode 100644 (file)
index 0000000..7ef964a
--- /dev/null
@@ -0,0 +1,40 @@
+<div class="contentboxh">
+ <p class="contentboxh">
+  <img src="images/launch.png" align="right" alt="[F]">Filter
+ </p>
+</div>
+
+<div class="contentboxb">
+ <div style="border-top:1px solid #AAAAAA"></div>
+ {$ALPHABET}
+ <div style="border-top:1px solid #AAAAAA"></div>
+ {$TEMPLATE}&nbsp;{t}Show templates{/t}<br>
+ {$GENERIC}&nbsp;{t}Show functional users{/t}<br>
+ {$MAIL}&nbsp;{t}Show mail users{/t}<br>
+ {$POSIX}&nbsp;{t}Show POSIX users{/t}<br>
+ {$SAMBA}&nbsp;{t}Show samba users{/t}<br>
+ <div style="border-top:1px solid #AAAAAA"></div>
+ {$SCOPE}
+
+ <table summary="" style="width:100%;border-top:1px solid #B0B0B0;">
+  <tr>
+   <td>
+    <label for="Regex">
+     <img alt="Zeige die Benutzer, auf die Folgendes passt" src="images/lists/search.png" align=middle>
+    </label>
+   </td>
+   <td width="99%">
+    {$NAME}
+   </td>
+  </tr>
+ </table>
+
+ <table summary=""  width="100%"  style="background:#EEEEEE;border-top:1px solid #B0B0B0;">
+  <tr>
+   <td width="100%" align="right">
+    {$APPLY}
+   </td>
+  </tr>
+ </table>
+
+</div>
diff --git a/gosa-core/include/class_filter.inc b/gosa-core/include/class_filter.inc
new file mode 100755 (executable)
index 0000000..b0e8596
--- /dev/null
@@ -0,0 +1,398 @@
+<?php
+
+class filter {
+
+  var $xmlData;
+  var $elements= array();
+  var $elementValues= array();
+  var $alphabetElements= array();
+  var $search;
+  var $definition;
+  var $category= "";
+  var $objectStorage= array();
+  var $objectBase= "";
+  var $base= "";
+  var $bases= array();
+  var $scope= "";
+  var $query;
+  var $baseMode= false;
+  var $scopeMode= "auto";
+  var $alphabet= null;
+  var $templatePath= "";
+  var $target= "";
+
+  function filter($filename)
+  {
+    if (!$this->load($filename)) {
+      die("Cannot parse $filename!");
+    }
+  }
+
+  function load($filename)
+  {
+    // Load data into array
+    $xmlData= simplexml_load_file($filename);
+    if ($xmlData === false) {
+      return false;
+    }
+
+    // Load definition
+    if (isset($xmlData->definition)) {
+      foreach ($xmlData->definition as $entry) {
+        if (!isset($entry->target) || !isset($entry->template)) {
+          return false;
+        }
+
+        // Move information
+        $this->templatePath= (string)$entry->template;
+        $this->target= (string)$entry->target;
+
+        // One is enough
+        break;
+      }
+    }
+
+    // Load filter
+    if (isset($xmlData->search)) {
+      foreach ($xmlData->search as $entry) {
+        if (!isset($entry->query) || !isset($entry->base) || !isset($entry->scope)) {
+          return false;
+        }
+
+        // Move information
+        $this->baseMode= (string)$entry->base;
+        $this->scopeMode= (string)$entry->scope;
+        $this->query= $entry->query;
+
+        // One is enough
+        break;
+      }
+    }
+
+    // Generate formular data
+    if (isset($xmlData->element)) {
+      foreach ($xmlData->element as $element) {
+
+        // Ignore elements without type
+        if (!isset($element->type)) {
+          next;
+        }
+
+        $tag= (string)$element->tag;
+
+        // Store element for quick access
+        $this->elements[$tag] = $element;
+
+        // Preset elementValues with default values if exist
+        if (isset($element->default)) {
+          $this->elementValues[$tag] = (string)$element->default;
+        } else {
+          $this->elementValues[$tag] = "";
+        }
+
+        // Does this element react on alphabet links?
+        if (isset($element->alphabet) && (string)$element->alphabet == "true") {
+          $this->alphabetElements[]= $tag;
+        }
+      }
+    }
+
+    // Save definition
+    if (isset($xmlData->definition)) {
+     $this->definition = $xmlData->definition;
+    }
+
+    // Save search
+    if (isset($xmlData->search)) {
+     $this->search = $xmlData->search;
+    }
+
+    return true;  
+  }
+
+
+  function getTextfield($element)
+  {
+    $result= "<input class='filter_textfield' name='$element' type='text' size='30' maxlength='30' value='".$this->elementValues[$element]."'>";
+    return $result;
+  }
+
+
+  function getCheckbox($element)
+  {
+    $checked= "";
+    if ($this->elementValues[$element] == "true") {
+      $checked= " checked";
+    }
+
+    $result= "<input class='filter_checkbox' name='$element' type='checkbox' onClick='document.mainform.submit();' value='true'$checked>";
+    return $result;
+  }
+
+
+  function getCombobox($element)
+  {
+    $result= "<select name='".$element->tag."' size='1' onClick='document.mainform.submit();'>";
+    foreach ($element->value as $key=>$value) {
+      $selected= "";
+      if ($this->elementValues[(string)$element->tag] == $value->key) {
+        $selected= " selected";
+      }
+      $result.= "<option value='".$value->key."'$selected>{t}".$value->set."{/t}</option>";
+    }
+    $result.= "</select>";
+
+    return $result;
+  }
+
+
+  function getCurrentBase()
+  {
+    if (isset($this->search->base) && (string)$this->search->scope != "auto") {
+      return false;
+    }
+
+    return $this->base;
+  }
+
+
+  function getCurrentScope()
+  {
+    if (isset($this->search->scope) && (string)$this->search->scope != "auto") {
+      return (string)$this->search->scope;
+    }
+
+    return $this->scope;
+  }
+
+
+  function setBases($bases) {
+    $this->bases= $bases;    
+  }
+
+
+  function setObjectStorage($storage) {
+    $this->objectStorage= $storage;    
+  }
+
+
+  function setObjectBase($base) {
+    $this->objectBase= $base;    
+  }
+
+
+  function setCategory($category) {
+    $this->category= $category;    
+  }
+
+
+  function setCurrentBase($base) {
+    $this->base= $base;
+  }
+
+
+  function setCurrentScope($scope) {
+    $this->scope= $scope;
+  }
+
+
+  function renderBase()
+  {
+    $result= "<select name='currentMainBase' onChange='mainform.submit()' size='1'>";
+
+    foreach ($this->bases as $key=>$value) {
+      $selected= "";
+      if ($key == $this->base) {
+        $selected= " selected";
+      }
+      $result.= "<option value='".$key."'$selected>".$value."</option>";
+    }
+    $result.= "</select>";
+
+    return $result;
+  }
+
+
+  function renderAlphabet($columns= 10)
+  {
+    // Return pre-rendered alphabet if available
+    if ($this->alphabet) {
+      return ($this->alphabet);
+    }
+
+    $characters= _("*ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
+    $alphabet= "";
+    $c= 0;
+
+    /* Fill cells with charaters */
+    for ($i= 0, $l= mb_strlen($characters, 'UTF8'); $i<$l; $i++){
+      if ($c == 0){
+        $alphabet.= "<tr>";
+      }
+
+      $ch = mb_substr($characters, $i, 1, "UTF8");
+      $alphabet.= "<td><a class=\"alphaselect\" href=\"main.php?plug=".
+        validate($_GET['plug'])."&amp;filter=".$ch."\">&nbsp;".$ch."&nbsp;</a></td>";
+
+      if ($c++ == $columns){
+        $alphabet.= "</tr>";
+        $c= 0;
+      }
+    }
+
+    /* Fill remaining cells */
+    while ($c++ <= $columns){
+      $alphabet.= "<td>&nbsp;</td>";
+    }
+
+    /* Save alphabet */
+    $this->alphabet= "<table width='100%'>$alphabet</table>";
+
+    return ($this->alphabet);
+  }
+
+
+  function renderApply()
+  {
+    return ("<input type='submit' name='apply' value='"._("Apply filter")."'>");
+  }
+
+
+  function renderScope()
+  {
+    $checked= $this->scope == "sub"?" checked":"";
+    return "<input type='checkbox' name='SCOPE' value='1' onClick='document.mainform.submit();'$checked>&nbsp;"._("Search in subtrees");
+  }
+
+
+  function renderFilter()
+  {
+    $smarty= get_smarty();
+    $smarty->assign("ALPHABET", $this->renderAlphabet());
+    $smarty->assign("APPLY", $this->renderApply());
+    $smarty->assign("SCOPE", $this->renderScope());
+    $smarty->assign("BASE", $this->renderBase());
+
+    // Load template and replace elementsHtml[]
+    foreach ($this->elements as $tag => $element) {
+      $htmlCode= "";
+      switch ($element->type) {
+        case "textfield":
+          $htmlCode = $this->getTextfield($tag);
+          break;
+
+        case "checkbox":
+          $htmlCode = $this->getCheckbox($tag);
+          break;
+
+        case "combobox":
+          $htmlCode = $this->getCombobox($element);
+          break;
+
+        default:
+          die ("Unknown element type specified!");
+      }
+      $smarty->assign("$tag", $htmlCode);
+    }
+
+    // Load template
+    return ("<input type='hidden' name='FILTER_LOADED' value='1'>".$smarty->fetch(get_template_path("filter/$this->templatePath")));
+  }
+
+
+  function query()
+  {
+    global $class_mapping;
+    $result= array();
+
+    // Go thru all queries and merge results
+    foreach ($this->query as $query) {
+      if (!isset($query->backend) || !isset($query->filter) || !isset($query->attribute)) {
+        die("No backend specified in search config.");
+      }
+
+      // Is backend available?
+      $backend= "filter".(string)$query->backend;
+      if (!isset($class_mapping["$backend"])) {
+        die("Invalid backend specified in search config.");
+      }
+
+      // Load filter and attributes
+      $filter= $query->filter;
+      $attributes= array();
+      foreach($query->attribute as $attr) {
+        $attributes[]= (string)$attr;
+      }
+
+      // Generate final filter
+      foreach ($this->elements as $tag => $element) {
+        $e_set= (string)$element->set;
+        $e_unset= (string)$element->unset;
+
+        if ($this->elementValues[$tag] == "") {
+          $e_unset= preg_replace('/\$/', $this->elementValues[$tag], $e_unset);
+          $filter= preg_replace("/\\$$tag/", $e_unset, $filter);
+        } else {
+          $e_set= preg_replace('/\$/', $this->elementValues[$tag], $e_set);
+          $filter= preg_replace("/\\$$tag/", $e_set, $filter);
+        }
+      }
+
+      $result= call_user_func(array($backend, 'query'), $this->base, $this->scope, $filter, $attributes,
+                               $this->category, $this->objectStorage, $this->objectBase);
+    }
+    
+
+    return ($result);
+  }
+
+
+  function isValid()
+  {
+    return (false);
+  }
+
+
+  function update()
+  {
+
+    /* React on alphabet links if needed */
+    if (isset($_GET['filter'])){
+      $s= mb_substr(validate($_GET['filter']), 0, 1, "UTF8")."*";
+      if ($s == "**"){
+        $s= "*";
+      }
+      foreach ($this->alphabetElements as $tag) {
+        $this->elementValues[$tag]= $s;
+      }
+    }
+
+    if (isset($_POST['FILTER_LOADED'])) {
+      // Load post values and adapt filter, base and scope accordingly - but
+      // only if we didn't get a _GET
+      foreach ($this->elements as $tag => $element) {
+        if (isset($_POST[$tag])){
+          $this->elementValues[$tag]= validate($_POST[$tag]);
+        } else {
+          $this->elementValues[$tag]= "";
+        }
+      }
+    }
+
+    // Save base
+    if (isset($_POST['BASE']) && $this->baseMode == "true") {
+      $base= validate($_POST['BASE']);
+      if (isset($this->bases[$base])) {
+        $this->base= $base;
+      }
+    }
+
+    // Save scope if needed
+    if ($this->scopeMode == "auto") {
+      $this->scope= isset($_POST['SCOPE'])?"sub":"one";
+    }
+  }
+
+}
+
+?>
diff --git a/gosa-core/include/class_filterLDAP.inc b/gosa-core/include/class_filterLDAP.inc
new file mode 100755 (executable)
index 0000000..12983d7
--- /dev/null
@@ -0,0 +1,237 @@
+<?php
+
+class filterLDAP {
+
+  static function query($base, $scope, $filter, $attributes, $category, $objectStorage= "", $objectBase= "")
+  {
+    global $config;
+
+    echo "Base: $base<br>";
+    echo "Scope: $scope<br>";
+    echo "filter: $filter<br>";
+    print_a($attributes);
+
+    $ldap= $config->get_ldap_link(TRUE);
+
+    $result= filterLDAP::get_list($base, $scope, $filter, $attributes,
+                                  $category, $objectStorage, $objectBase,
+                                  GL_SUBSEARCH | GL_SIZELIMIT);
+    return $result;
+  }
+
+
+  static function get_list($base, $scope, $filter, $attributes, $category,
+                           $objectStorage= array(), $objectBase= "", $flags= GL_SUBSEARCH)
+  {
+    global $config, $ui;
+    $departments= array();
+
+    /* Get LDAP link */
+    $ldap= $config->get_ldap_link($flags & GL_SIZELIMIT);
+
+    /* If we do no subsearch, adapt */
+    if ($scope != "sub") {
+      if ($objectBase != "") {
+        $base= preg_replace('/,$/', '', $objectBase).",".$base;
+      } elseif (is_string($objectStorage)) {
+        $base= preg_replace('/,$/', '', $objectStorage).",".$base;
+      }
+    }
+  
+    /* Set search base to configured base if $base is empty */
+    if ($base == ""){
+      $base = $config->current['BASE'];
+    }
+    $ldap->cd ($base);
+  
+    /* Ensure we have an array as storage list */
+    if(is_string($objectStorage)){
+      $objectStorage = array($objectStorage);
+    }
+  
+    /* Remove ,.*$ ("ou=1,ou=2.." => "ou=1") */
+    $sub_bases = array();
+    foreach($objectStorage as $key => $sub_base){
+      if(empty($sub_base)){
+  
+        /* Subsearch is activated and we got an empty sub_base.
+         *  (This may be the case if you have empty people/group ous).
+         * Fall back to old get_list().
+         * A log entry will be written. */
+        if($flags & GL_SUBSEARCH){
+          $sub_bases = array();
+          break;
+        }else{
+  
+          /* Do NOT search within subtrees is requested and the sub base is empty.
+           * Append all known departments that matches the base. */
+          $departments[$base] = $base;
+        }
+      }else{
+        $sub_bases[$key] = preg_replace("/,.*$/","",$sub_base);
+      }
+    }
+  
+    // If there is no sub_department specified, fall back to old method, get_list().
+    if(!count($sub_bases) && !count($departments)){
+  
+      // Log this fall back, it may be an unpredicted behaviour.
+      if(!count($sub_bases) && !count($departments)){
+        new log("debug","all",__FILE__,$attributes,
+            sprintf("filterLDAP::get_list(): falling back to filterLDAP::get_list_old() because objectStorage is empty.".
+              " This may slow down GOsa. Filter was: '%s'", $filter));
+      }
+      return (ldapFILTER::get_list_old($filter, $category,$base,$attributes,$flags));
+    }
+  
+    /* Get all deparments matching the given sub_bases */
+    $base_filter= "";
+    foreach($sub_bases as $sub_base){
+      $base_filter .= "(".$sub_base.")";
+    }
+    $base_filter = "(&(objectClass=organizationalUnit)(|".$base_filter."))";
+    $ldap->search($base_filter, array("dn"));
+    while($attrs = $ldap->fetch()){
+      foreach($objectStorage as $sub_dep){
+  
+        /* Only add those departments that match the reuested list of departments.
+         *
+         * e.g.   sub_deps = array("ou=servers,ou=systems,");
+         *
+         * In this case we have search for "ou=servers" and we may have also fetched
+         *  departments like this "ou=servers,ou=blafasel,..."
+         * Here we filter out those blafasel departments.
+         */
+        if(preg_match("/".preg_quote($sub_dep, '/')."/",$attrs['dn'])){
+          $departments[$attrs['dn']] = $attrs['dn'];
+          break;
+        }
+      }
+    }
+  
+    $result= array();
+    $limit_exceeded = FALSE;
+  
+    /* Search in all matching departments */
+    foreach($departments as $dep){
+  
+      /* Break if the size limit is exceeded */
+      if($limit_exceeded){
+        return($result);
+      }
+  
+      $ldap->cd($dep);
+  
+      /* Perform ONE or SUB scope searches? */
+      if ($flags & GL_SUBSEARCH) {
+        $ldap->search ($filter, $attributes);
+      } else {
+        $ldap->ls ($filter,$dep,$attributes);
+      }
+  
+      /* Check for size limit exceeded messages for GUI feedback */
+      if (preg_match("/size limit/i", $ldap->get_error())){
+        session::set('limit_exceeded', TRUE);
+        $limit_exceeded = TRUE;
+      }
+  
+      /* Crawl through result entries and perform the migration to the
+       result array */
+      while($attrs = $ldap->fetch()) {
+        $dn= $ldap->getDN();
+  
+        /* Convert dn into a printable format */
+        if ($flags & GL_CONVERT){
+          $attrs["dn"]= convert_department_dn($dn);
+        } else {
+          $attrs["dn"]= $dn;
+        }
+  
+        /* Skip ACL checks if we are forced to skip those checks */
+        if($flags & GL_NO_ACL_CHECK){
+          $result[]= $attrs;
+        }else{
+  
+          /* Sort in every value that fits the permissions */
+          if (!is_array($category)){
+            $category = array($category);
+          }
+          foreach ($category as $o){
+            if((preg_match("/\//",$o) && preg_match("/r/",$ui->get_permissions($dn,$o))) ||
+                (!preg_match("/\//",$o) && preg_match("/r/",$ui->get_category_permissions($dn, $o)))){
+              $result[]= $attrs;
+              break;
+            }
+          }
+        }
+      }
+    }
+
+    return($result);
+  }
+
+
+  function get_list_old($filter, $category, $base= "", $attributes= array(), $flags= GL_SUBSEARCH)
+  {
+    global $config, $ui;
+  
+    /* Get LDAP link */
+    $ldap= $config->get_ldap_link($flags & GL_SIZELIMIT);
+  
+    /* Set search base to configured base if $base is empty */
+    if ($base == ""){
+      $ldap->cd ($config->current['BASE']);
+    } else {
+      $ldap->cd ($base);
+    }
+  
+    /* Perform ONE or SUB scope searches? */
+    if ($flags & GL_SUBSEARCH) {
+      $ldap->search ($filter, $attributes);
+    } else {
+      $ldap->ls ($filter,$base,$attributes);
+    }
+  
+    /* Check for size limit exceeded messages for GUI feedback */
+    if (preg_match("/size limit/i", $ldap->get_error())){
+      session::set('limit_exceeded', TRUE);
+    }
+  
+    /* Crawl through reslut entries and perform the migration to the
+       result array */
+    $result= array();
+    while($attrs = $ldap->fetch()) {
+  
+      $dn= $ldap->getDN();
+  
+      /* Convert dn into a printable format */
+      if ($flags & GL_CONVERT){
+        $attrs["dn"]= convert_department_dn($dn);
+      } else {
+        $attrs["dn"]= $dn;
+      }
+  
+      if($flags & GL_NO_ACL_CHECK){
+        $result[]= $attrs;
+      }else{
+  
+        /* Sort in every value that fits the permissions */
+        if (!is_array($category)){
+          $category = array($category);
+        }
+        foreach ($category as $o){
+          if((preg_match("/\//",$o) && preg_match("/r/",$ui->get_permissions($dn,$o))) ||
+              (!preg_match("/\//",$o) && preg_match("/r/",$ui->get_category_permissions($dn, $o)))){
+            $result[]= $attrs;
+            break;
+          }
+        }
+      }
+    }
+  
+    return ($result);
+  }
+
+}
+
+?>