Code

Apply patch for #5210
[gosa.git] / trunk / gosa-plugins / fai / admin / fai / class_FAI.inc
index e00cca4e6407271163184f374e533c4fa240774f..ef27ae6ffa6dd94e7636096702eef274df932789 100644 (file)
@@ -73,7 +73,7 @@ class FAI
           $name = preg_replace("/".preg_quote($release, '/')."/i","",$attr['dn']);
 
           if(isset($attr['FAIstate'][0])){
-            if(preg_match("/removed$/",$attr['FAIstate'][0])){
+            if(preg_match("/removed/",$attr['FAIstate'][0])){
               if(isset($res[$name])){
                 unset($res[$name]);
               }
@@ -249,17 +249,22 @@ class FAI
 
               /* Check if this Profile uses the source class ($cn)
                */
-              if(preg_match("/".preg_quote($cn, '/')."/",$attrs['FAIclass'])){
-                $attrs['FAIclass'] = preg_replace("/[ ]*".preg_quote($cn, '/')."[ ]*/i"," ",$attrs['FAIclass']);
-                if(empty($attrs['FAIclass'])){
-                  $attrs['FAIclass'] = array();
-                }
-                $ldap->cd($dn['dn']);
-                $ldap->modify($attrs);
-
-                if (!$ldap->success()){
-                  msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
-                }
+              $classlist = split(" ", $attrs['FAIclass']);
+              $new_classlist = "";
+              foreach($classlist as $class){
+                if($class != $cn){
+                  $new_classlist = $new_classlist." ".$class;
+               }
+              } 
+              $attrs['FAIclass'] = $new_classlist;
+              if(empty($attrs['FAIclass'])){
+                $attrs['FAIclass'] = array();
+              }
+              $ldap->cd($dn['dn']);
+              $ldap->modify($attrs);
+              
+              if (!$ldap->success()){
+                msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $this->dn, LDAP_MOD, get_class()));
               }
             }
           }
@@ -501,12 +506,13 @@ class FAI
             }
 
             foreach($r as $key ){
-              if(DEBUG_FAI_FUNC) { 
-                echo "<b>Create an empty placeholder in follwing release</b> ".$key; 
-                print_a($objectAttrs);
-              }
-              /* Only save removed parent objects, not their children */
-              if (FAI::is_parent_object($Current_DN)){
+              /* Only save removed parent objects, not their children, unless
+                 they are a child of a copy-on-write parent in a subrelease */
+              if (FAI::is_parent_object($Current_DN) || FAI::is_child_of_cow_parent($key)){
+                if(DEBUG_FAI_FUNC) { 
+                  echo "<b>Create an empty placeholder in follwing release</b> ".$key; 
+                  print_a($objectAttrs);
+                }
                 FAI::save_FAI_object($key,$objectAttrs);
               }
             }
@@ -517,18 +523,21 @@ class FAI
           if(!empty($r)){
 
             foreach($r as $key ){
-              if(DEBUG_FAI_FUNC) { 
-                echo "<b>Copy current objects original attributes to next release</b> ".$key;
-                print_a($parent_attrs);
-              }
-             
-              /* Only update the freeze tag if the entry actually exists. */
-              $ldap->cat($key);
-              if($ldap->count()){
-                /* Append FAIstate tag to ensure that freezed objects stay freezed
-                 */ 
-                $rTag = FAI::get_release_tag(FAI::get_release_dn($key));
-                $parent_attrs['FAIstate'] = $rTag;
+              /* Append FAIstate tag to ensure that freezed objects stay freezed
+               */ 
+              $rTag = FAI::get_release_tag(FAI::get_release_dn($key));
+              $parent_attrs['FAIstate'] = $rTag;
+              /* Don't copy over subobjects in subreleases if their parent is in "removed" state */
+              if(!FAI::parent_is_removed($key)){
+                /* FAItemplateFile can be binary, therefore it needs to be fetched with
+                 * $ldap->get_attribute */
+                if (isset($parent_attrs['FAItemplateFile'])) {
+                  $parent_attrs['FAItemplateFile'] = $ldap->get_attribute($parent_obj, 'FAItemplateFile');
+                }
+                if(DEBUG_FAI_FUNC) { 
+                  echo "<b>Copy current objects original attributes to next release</b> ".$key;
+                  print_a($parent_attrs);
+                }
                 FAI::save_FAI_object($key,$parent_attrs);
               }
             }
@@ -570,8 +579,9 @@ class FAI
 
 
   /* this function will remove all unused (deleted) objects,
-     that have no parent object */
-  static function clean_up_releases($Current_DN)
+     that have no parent object. If $recursive is set to true,
+     also check sub releases. */
+  static function clean_up_releases($Current_DN, $recursive=true)
   {
     global $config;
     $ldap = $config->get_ldap_link();
@@ -587,11 +597,14 @@ class FAI
     /* We must also include the given release dn */
     $previous_releases[] = $base_release;
 
-    /* Merge parent, current and child releases into one big release to 
-       iterate over */
     $all_releases = $previous_releases;
-    foreach($sub_releases as $sub_release){
-      $all_releases[] = $sub_release;
+
+    if ($recursive) {
+      /* Merge parent, current and child releases into one big release to 
+         iterate over */
+      foreach($sub_releases as $sub_release){
+        $all_releases[] = $sub_release;
+      }
     }
 
     /* Walk through all releases */
@@ -605,7 +618,7 @@ class FAI
 
         /* Ldap search for fai classes specified in this release */
         $ldap->cd($fai_base);
-        $ldap->search("(objectClass=FAIclass)",array("dn","objectClass","FAIstate"));
+        $ldap->search("(|(objectClass=FAIclass)(objectClass=FAIdebconfInfo))",array("dn","objectClass","FAIstate"));
 
         /* check the returned objects, and add/replace them in our return variable */
         while($attr = $ldap->fetch()){
@@ -1285,8 +1298,8 @@ class FAI
     global $config;
     $Current_DN = $dn;
 
-    /* special case partitions, as they don't start with cn= in their DN (schema bug?) */
-    if (preg_match('/^FAIpartitionNr=/', $Current_DN)){
+    /* special case partitions and debconf variables, as they don't start with cn= in their DN */
+    if (preg_match('/^(FAIpartitionNr|FAIvariable)=/', $Current_DN)){
       return false;
     }
 
@@ -1303,7 +1316,7 @@ class FAI
     }
   }
 
-  /* Return child objects, if there are any */
+  /* Return child objects, if there are any */
   static function get_child_objects($dn)
   {
     global $config;
@@ -1312,10 +1325,9 @@ class FAI
 
     if (FAI::is_parent_object($Current_DN)){
       $ldap = $config->get_ldap_link();
-      $ldap->cd($config->current['BASE']);
+      $ldap->cd($dn);
       $ldap->search("(objectClass=FAIclass)",array("dn"));
       while($attrs = $ldap->fetch()){
-        $newdn=$attrs['dn'];
         if(preg_match("/".preg_quote($Current_DN, '/')."/",$attrs['dn']) && $attrs['dn'] != $Current_DN){
           $children[] = $attrs['dn'];
         }
@@ -1324,31 +1336,43 @@ class FAI
     return $children;
   }
 
-  /* Get the DN of the parent object; e.g. the FAIpartitionTable of a FAIpartitionDisk */
-  static function get_parent_object($dn)
+  /* Get the DN of the parent object; e.g. the FAIpartitionTable of a FAIpartitionDisk.
+     If $check is false, do not check whether the parent actually exists in LDAP */
+  static function get_parent_object($dn, $check=true)
   {
     global $config;
     $Current_DN = $dn;
+    $i = 0;
 
     $tmp_dn = $Current_DN;
-    $parent_dn = $tmp_dn;
+    $parent_dn = array();
 
-    /* special case partitions, as they don't start with cn= in their DN (schema bug?) */
-    $tmp_dn = preg_replace('/^FAIpartitionNr=/', 'cn=', $tmp_dn);
+    /* special case partitions and debconf variables, as they don't start with cn= in their DN */
+    $tmp_dn = preg_replace('/^(FAIpartitionNr|FAIvariable)=/', 'cn=', $tmp_dn);
 
-    while (preg_match('/^cn=/', $tmp_dn)){
-      $parent_dn = $tmp_dn;
-      $tmp_dn = preg_replace('/^cn=[^,.]*,/', '', $parent_dn);
+    $tmp_dn = gosa_ldap_explode_dn($tmp_dn);
+    while(preg_match('/^cn=/', $tmp_dn[$i])) {
+      $i++;
     }
-    if ($parent_dn != $Current_DN){
-      $ldap = $config->get_ldap_link();
-      $ldap->cd($config->current['BASE']);
-      $ldap->cat($parent_dn);
+    /* DN part does not start with cn= anymore, remove one from the counter to get the
+       last CN element */
+    $i--;
 
-      /* Check objectClasses and name to check if this is a release department */
-      if($ldap->count()){
-        return $parent_dn;
+    for ($i;$i<$tmp_dn['count'];$i++) {
+      $parent_dn[] = trim($tmp_dn[$i]);
+    }
+    $parent_dn = join($parent_dn, ',');
+
+    if ($parent_dn != $Current_DN){
+      if($check){
+        $ldap = $config->get_ldap_link();
+        $ldap->cd($config->current['BASE']);
+        $ldap->cat($parent_dn);
+        if(!$ldap->count()){
+          return "";
+        }
       }
+      return $parent_dn;
     }
     return "";
   }
@@ -1373,6 +1397,62 @@ class FAI
     } 
     return false;
   }
+
+  /* Check whether this is a child object of a Copy-on-Write parent */
+  static function is_child_of_cow_parent($dn)
+  { 
+    global $config;
+    $Current_DN = $dn;
+    $parent_dn = "";
+
+    if (!FAI::is_parent_object($Current_DN)){
+
+      /* This is a child object; check that the parent object is not 
+         marked as removed */
+      $cow_parent_dn = FAI::get_parent_object($Current_DN, false);
+      if ($cow_parent_dn && !FAI::parent_is_removed($Current_DN)){
+
+        /* This is a child object, check whether the parent object in 
+           the main release exists */
+        $main_parent_dn = FAI::get_parent_release_object($cow_parent_dn);
+        $ldap = $config->get_ldap_link();
+        $ldap->cd($config->current['BASE']);
+        $ldap->cat($main_parent_dn);
+        if($ldap->count()){
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  static function get_leaf_objects($dn, $cn, $subclass, $rdn) {
+    $valid_releases = FAI::get_previous_releases_of_this_release(FAI::get_release_dn($dn), true);
+    /* Remove the last release DN */
+    array_pop($valid_releases);
+    $valid_releases[] = FAI::get_release_dn($dn);
+
+    $objects = FAI::get_all_objects_for_given_base($dn,"(&(objectClass=FAIclass)(objectClass=".$subclass."))");
+    $res = array();
+    /* Strip elements which are not a leaf object of the current dn */
+    foreach($objects as $obj){
+      $keep = FALSE;
+      foreach($valid_releases as $valid_release) {
+        if (preg_match("/cn=".$cn.",".$rdn.$valid_release."$/", $obj['dn'])) {
+          $keep = TRUE;
+          break;
+        }
+      }
+
+      if ($keep) {
+        $res[] = $obj;
+      }
+    }
+
+    return $res;
+  }
+
+    
 }