Code

Fixed undefined variable GOsa_26_found in setup mirgate
[gosa.git] / gosa-core / setup / class_setupStep_Migrate.inc
index ed52e7cd5ea192f9391c25634d5af4eb5158befa..f1074cbc812ff3c3f78f155002f5c1543dff520e 100644 (file)
@@ -53,7 +53,7 @@ class Step_Migrate extends setup_step
 {
   var $languages      = array();
   var $attributes     = array();
-  var $header_image   = "images/monitoring.png";
+  var $header_image   = "images/setup/migrate.png";
   var $checks         = array();
 
   /* Department migration attributes */
@@ -82,6 +82,18 @@ class Step_Migrate extends setup_step
   var $outside_groups        = array();
   var $outside_groups_dialog = FALSE;
 
+  /* Device migration */
+  var $device_dialog         = FALSE;
+  var $device                = array();
+
+  /* Service migration */
+  var $service_dialog         = FALSE;
+  var $service                = array();
+
+  /* Group menus */
+  var $menu_dialog           = FALSE;
+  var $menu                  = array();
+
   /* Win-Workstations outside to reserved ou */
   var $outside_winstations        = array();
   var $outside_winstations_dialog = FALSE;
@@ -94,7 +106,17 @@ class Step_Migrate extends setup_step
   var $check_gidNumbers        = array();
   var $check_gidNumbers_dialog = FALSE;
 
+  var $group_list              = array();
+
+  /* Migrateable users */
+  var $migrate_users = array();
+  var $acl_migrate_dialog      = FALSE;
+  var $migrate_acl_base_entry  = "";
 
+  /* Root object classes */
+  var $rootOC_migrate_dialog = FALSE;
+  var $rootOC_details = array();
+       
   function Step_Migrate()
   {
     $this->update_strings(); 
@@ -116,6 +138,12 @@ class Step_Migrate extends setup_step
     $this->checks['root']['ERROR_MSG'] = "";
     $this->checkBase();
 
+    $this->checks['rootOC']['TITLE']     = _("Checking object classes for root object");
+    $this->checks['rootOC']['STATUS']    = FALSE;
+    $this->checks['rootOC']['STATUS_MSG']= "";
+    $this->checks['rootOC']['ERROR_MSG'] = "";
+    $this->checkBaseOC();
+
     $this->checks['permissions']['TITLE']     = _("Checking permissions on LDAP database");
     $this->checks['permissions']['STATUS']    = FALSE;
     $this->checks['permissions']['STATUS_MSG']= "";
@@ -126,7 +154,6 @@ class Step_Migrate extends setup_step
     $this->checks['deps_visible']['STATUS']    = FALSE;
     $this->checks['deps_visible']['STATUS_MSG']= "";
     $this->checks['deps_visible']['ERROR_MSG'] = "";
-    $this->check_organizationalUnits();
 
     $this->checks['users_visible']['TITLE']     = _("Checking for invisible users");
     $this->checks['users_visible']['STATUS']    = FALSE;
@@ -134,6 +161,7 @@ class Step_Migrate extends setup_step
     $this->checks['users_visible']['ERROR_MSG'] = "";
     $this->check_gosaAccounts();
 
+    $this->migrate_users = array();
     $this->checks['acls']['TITLE']     = _("Checking for super administrator");
     $this->checks['acls']['STATUS']    = FALSE;
     $this->checks['acls']['STATUS_MSG']= "";
@@ -145,12 +173,13 @@ class Step_Migrate extends setup_step
     $this->checks['outside_users']['STATUS_MSG']= "";
     $this->checks['outside_users']['ERROR_MSG'] = "";
     $this->search_outside_users();
-    
+
     $this->checks['outside_groups']['TITLE']     = _("Checking for groups outside the groups tree");
     $this->checks['outside_groups']['STATUS']    = FALSE;
     $this->checks['outside_groups']['STATUS_MSG']= "";
     $this->checks['outside_groups']['ERROR_MSG'] = "";
     $this->search_outside_groups();
+    $this->check_organizationalUnits();
 
     $this->checks['outside_winstations']['TITLE']     = _("Checking for windows workstations outside the winstation tree");
     $this->checks['outside_winstations']['STATUS']    = FALSE;
@@ -163,12 +192,30 @@ class Step_Migrate extends setup_step
     $this->checks['uidNumber_usage']['STATUS_MSG']= "";
     $this->checks['uidNumber_usage']['ERROR_MSG'] = "";
     $this->check_uidNumber();
-    
+
     $this->checks['gidNumber_usage']['TITLE']     = _("Checking for duplicate GID numbers");
     $this->checks['gidNumber_usage']['STATUS']    = FALSE;
     $this->checks['gidNumber_usage']['STATUS_MSG']= "";
     $this->checks['gidNumber_usage']['ERROR_MSG'] = "";
     $this->check_gidNumber();
+
+    $this->checks['old_style_devices']['TITLE']     = _("Checking for old style USB devices");
+    $this->checks['old_style_devices']['STATUS']    = FALSE;
+    $this->checks['old_style_devices']['STATUS_MSG']= "";
+    $this->checks['old_style_devices']['ERROR_MSG'] = "";
+    $this->check_usb_devices();
+
+    $this->checks['old_style_services']['TITLE']     = _("Checking for old services that have to be migrated");
+    $this->checks['old_style_services']['STATUS']    = FALSE;
+    $this->checks['old_style_services']['STATUS_MSG']= "";
+    $this->checks['old_style_services']['ERROR_MSG'] = "";
+    $this->check_services();
+
+    $this->checks['old_style_menus']['TITLE']     = _("Checking for old style application menus");
+    $this->checks['old_style_menus']['STATUS']    = FALSE;
+    $this->checks['old_style_menus']['STATUS_MSG']= "";
+    $this->checks['old_style_menus']['ERROR_MSG'] = "";
+    $this->check_menus();
   }
 
 
@@ -187,7 +234,7 @@ class Step_Migrate extends setup_step
     $ldap = new ldapMultiplexer($ldap_l);
 
     $ldap->cd($cv['base']);
-    $res = $ldap->search("uidNumber=*",array("dn","uidNumber"));
+    $res = $ldap->search("(&(objectClass=posixAccount)(uidNumber=*))",array("dn","uidNumber"));
     if(!$res){
       $this->checks['uidNumber_usage']['STATUS']    = FALSE;
       $this->checks['uidNumber_usage']['STATUS_MSG']= _("LDAP query failed");
@@ -292,7 +339,7 @@ class Step_Migrate extends setup_step
 
     /* Get winstation ou */
     if($cv['generic_settings']['wws_ou_active']) {
-      $winstation_ou = $cv['generic_settings']['ws_ou'];
+      $winstation_ou = $cv['generic_settings']['wws_ou'];
     }else{
       $winstation_ou = "ou=winstations";
     }
@@ -314,7 +361,7 @@ class Step_Migrate extends setup_step
 
     $this->outside_winstations = array();
     while($attrs = $ldap->fetch()){
-      if((!preg_match("/^[^,]+,".normalizePreg($winstation_ou)."/",$attrs['dn'])) && !preg_match("/,dc=addressbook,/",$attrs['dn'])){
+      if((!preg_match("/^[^,]+,".preg_quote($winstation_ou, '/')."/",$attrs['dn'])) && !preg_match("/,dc=addressbook,/",$attrs['dn'])){
         $attrs['selected'] = FALSE;
         $attrs['ldif']     = "";
         $this->outside_winstations[base64_encode($attrs['dn'])] = $attrs;
@@ -377,19 +424,21 @@ class Step_Migrate extends setup_step
     }
 
     $this->outside_groups = array();
+    $this->groups_list = array();;
     while($attrs = $ldap->fetch()){
-      $group_db_base = preg_replace("/^[^,]+,".normalizePreg($group_ou)."+,/i","",$attrs['dn']);
+      $group_db_base = preg_replace("/^[^,]+,".preg_quote($group_ou, '/')."+,/i","",$attrs['dn']);
 
       /* Check if entry is not an addressbook only user
        *  and verify that he is in a valid department
        */
-      if( !preg_match("/".normalizePreg("dc=addressbook,")."/",$group_db_base) &&
+      if( !preg_match("/".preg_quote("dc=addressbook,", '/')."/",$group_db_base) &&
           !in_array($group_db_base,$valid_deps)
         ){
         $attrs['selected'] = FALSE;
         $attrs['ldif']     = "";
         $this->outside_groups[base64_encode($attrs['dn'])] = $attrs;
       }
+      $this->group_list[] = $attrs['dn'];
     }
 
     if(count($this->outside_groups)){
@@ -455,12 +504,12 @@ class Step_Migrate extends setup_step
     }
 
     while($attrs = $ldap->fetch()){
-      $people_db_base = preg_replace("/^[^,]+,".normalizePreg($people_ou)."/i","",$attrs['dn']);
+      $people_db_base = preg_replace("/^[^,]+,".preg_quote($people_ou, '/')."/i","",$attrs['dn']);
 
       /* Check if entry is not an addressbook only user
        *  and verify that he is in a valid department
        */
-      if( !preg_match("/".normalizePreg("dc=addressbook,")."/",$people_db_base) &&
+      if( !preg_match("/dc=addressbook,/",$people_db_base) &&
           !in_array($people_db_base,$valid_deps)
          ){
         $attrs['selected'] = FALSE;
@@ -645,7 +694,7 @@ class Step_Migrate extends setup_step
 
         /* Create new objectClass array */
         $new_attrs  = array();
-        $new_attrs['objectClass']= array("gosaAccount","inetOrgPerson","organizationalPerson");
+        $new_attrs['objectClass']= array("gosaAccount","inetOrgPerson","organizationalPerson","person");
         for($i = 0 ; $i < $attrs['objectClass']['count']; $i ++ ){
           if(!in_array_ics($attrs['objectClass'][$i], $new_attrs['objectClass'])){
             $new_attrs['objectClass'][]   = $attrs['objectClass'][$i];
@@ -690,7 +739,7 @@ class Step_Migrate extends setup_step
     $ldap = new ldapMultiplexer($ldap_l);
 
     /* Skip GOsa internal departments */
-    $skip_dns = array("/".$cv['peopleou']."/","/".$cv['groupou']."/","/^ou=people,/","/^ou=groups,/",
+    $skip_dns = array("/".$cv['peopleou']."/","/".$cv['groupou']."/","/^ou=people,/","/^ou=groups,/","/^ou=sudoers,/",
         "/(,|)ou=configs,/","/(,|)ou=systems,/",
         "/(,|)ou=apps,/","/(,|)ou=mime,/","/(,|)ou=devices/","/^ou=aclroles,/","/^ou=incoming,/",
         "/ou=snapshots,/","/(,|)dc=addressbook,/","/^(,|)ou=machineaccounts,/",
@@ -717,6 +766,17 @@ class Step_Migrate extends setup_step
     foreach($this->deps_to_migrate as $key => $attrs){
       $dn = $attrs['dn'];
       $skip = false;;
+
+      /* Check if this object is an application release object
+          e.g. groups-> application menus.
+       */
+      if(preg_match("/^.*,[ ]*cn=/",$dn)){
+        $cn_dn = preg_replace("/^.*,[ ]*cn=/","cn=",$dn);
+        if(in_array($cn_dn,$this->group_list)){
+          $skip = true;
+        }
+      }
+    
       foreach($skip_dns as $skip_dn){
         if(preg_match($skip_dn,$dn)){
           $skip = true;
@@ -807,6 +867,13 @@ class Step_Migrate extends setup_step
    */
   function check_administrativeAccount()
   {
+    /* Reset settings 
+     */ 
+    $GOsa_26_found = FALSE;
+    $this->migrate_users = array();
+    $this->acl_migrate_dialog = FALSE;
+    $this->migrate_acl_base_entry  = "";
+
     /* Establish ldap connection */
     $cv = $this->parent->captured_values;
     $ldap_l = new LDAP($cv['admin'],
@@ -818,37 +885,71 @@ class Step_Migrate extends setup_step
     $ldap = new ldapMultiplexer($ldap_l);
     $ldap->cd($cv['base']);
     $res = $ldap->cat($cv['base']);
-    
+   
     if(!$res){
       $this->checks['acls']['STATUS']    = FALSE;
       $this->checks['acls']['STATUS_MSG']= _("LDAP query failed");
       $this->checks['acls']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
     }else{
-      $found = false;
+      $GOsa_26_found = false; // GOsa 2.6 Account found
+      $GOsa_25_found = false; // GOsa 2.5 Account found, allow migration
+
       $username = "";
       $attrs = $ldap->fetch();
+
+      /* Collect a list of available GOsa users and groups 
+       */
+      $users = array();
+      $ldap->search("(&(objectClass=gosaAccount)(objectClass=person)".
+        "(objectClass=inetOrgPerson)(objectClass=organizationalPerson))",array("uid","dn"));
+      while($user_attrs = $ldap->fetch()){
+        $users[$user_attrs['dn']] = $user_attrs['uid'][0];
+        $rusers[$user_attrs['uid'][0]] = $user_attrs['dn'];
+      }
+      $groups = array();
+      $ldap->search("objectClass=posixGroup",array("cn","dn"));
+      while($group_attrs = $ldap->fetch()){
+        $groups[$group_attrs['dn']] = $group_attrs['cn'][0];
+      }
+      
+      /* Check if a valid GOsa 2.6 admin exists 
+          -> gosaAclEntry for an existing and accessible user.
+       */
+      $valid_users = "";
+      $valid_groups = "";
       if(isset($attrs['gosaAclEntry'])){
         $acls = $attrs['gosaAclEntry'];
         for($i = 0 ; $i < $acls['count'] ; $i++){
           $acl = $acls[$i];
           $tmp = split(":",$acl);
+
           if($tmp[1] == "psub"){
             $members = split(",",$tmp[2]);
             foreach($members as $member){
               $member = base64_decode($member);
-
-              /* Check if acl owner is a valid GOsa user account */
-              $ldap->cat($member,array("objectClass","uid","cn"));
-              $ret = $ldap->fetch();
-
-              if(isset($ret['objectClass']) && in_array("posixGroup",$ret['objectClass'])){
-                $found = TRUE;
-                $username .= "ACL-Group:&nbsp;".$ret['cn'][0]."<br>";
-              }elseif(isset($ret['objectClass']) && in_array("gosaAccount",$ret['objectClass']) &&
-                  in_array("organizationalPerson",$ret['objectClass']) &&
-                  in_array("inetOrgPerson",$ret['objectClass'])){
-                $found = TRUE;
-                $username .= "ACL:&nbsp;".$ret['uid'][0]."<br>";
+              if(isset($users[$member])){
+                if(preg_match("/all;cmdrw/i",$tmp[3])){
+                  $valid_users .= $users[$member].", ";
+                  $GOsa_26_found  = TRUE;
+                }
+              }
+              if(isset($groups[$member])){
+                if(preg_match("/all;cmdrw/i",$tmp[3])){
+                  $ldap->cat($member);
+                  $group_attrs = $ldap->fetch();
+                  $val_users = "";
+                  if(isset($group_attrs['memberUid'])){
+                    for($e = 0 ; $e < $group_attrs['memberUid']['count']; $e ++){
+                      if(isset($rusers[$group_attrs['memberUid'][$e]])){
+                        $val_users .= $group_attrs['memberUid'][$e].", ";
+                      }
+                    }
+                  }
+                  if(!empty($val_users)){
+                    $valid_groups .= $groups[$member]."(<i>".trim($val_users,", ")."</i>), ";
+                    $GOsa_26_found  = TRUE;
+                  }
+                }
               }
             }
           }elseif($tmp[1] == "role"){
@@ -868,15 +969,25 @@ class Step_Migrate extends setup_step
                   foreach($members as $member){
                     $member = base64_decode($member);
 
-                    /* Check if acl owner is a valid GOsa user account */
-                    $ldap->cat($member,array("objectClass","uid"));
-                    $ret = $ldap->fetch();
-  
-                    if(isset($ret['objectClass']) && in_array("gosaAccount",$ret['objectClass']) &&
-                        in_array("organizationalPerson",$ret['objectClass']) &&
-                        in_array("inetOrgPerson",$ret['objectClass'])){
-                      $found = TRUE;
-                      $username .= "ACL Role:&nbsp;".$ret['uid'][0]."<br>";
+                    if(isset($users[$member])){
+                      $valid_users .= $users[$member].", ";
+                      $GOsa_26_found  = TRUE;
+                    }
+                    if(isset($groups[$member])){
+                      $ldap->cat($member);
+                      $group_attrs = $ldap->fetch();
+                      $val_users = "";
+                      if(isset($group_attrs['memberUid'])){
+                        for($e = 0 ; $e < $group_attrs['memberUid']['count']; $e ++){
+                          if(isset($rusers[$group_attrs['memberUid'][$e]])){
+                            $val_users .= $group_attrs['memberUid'][$e].", ";
+                          }
+                        }
+                      }
+                      if(!empty($val_users)){
+                        $valid_groups .= $groups[$member]."(<i>".trim($val_users,", ")."</i>), ";
+                        $GOsa_26_found  = TRUE;
+                      }
                     }
                   }
                 }
@@ -886,13 +997,53 @@ class Step_Migrate extends setup_step
         }
       }
 
-      # For debugging
-      #echo $username;
+      /* Try to find an old GOsa 2.5 administrative account that may be migrated 
+       */
+      if(!$GOsa_26_found){
+        $valid_users = "";
+        $valid_groups = "";
+        $ldap->cd($cv['base']);
+        $ldap->search("(&(objectClass=posixGroup)(gosaSubtreeACL=:all)(memberUid=*))",array("memberUid","cn"));
+        while($p_group = $ldap->fetch()){
+          $val_users = "";
+          for($e = 0 ; $e < $p_group['memberUid']['count'] ; $e ++ ){
+            $user = $p_group['memberUid'][$e];
+            if(isset($rusers[$user])){
+              $val_users .= $user.", ";
+            }  
+          }
+          if(!empty($val_users)){
+            $valid_groups .= $groups[$p_group['dn']]."(<i>".trim($val_users,", ")."</i>), ";
+            $GOsa_25_found  = TRUE;
+          }
+        }
+      }
+
 
-      if($found){
+      /* Print out results 
+       */
+      if($GOsa_25_found){
+        $str = "";
+        if(!empty($valid_groups)){
+          $str.= "<i>".sprintf(_("GOsa 2.5 administrative accounts found: %s"),trim($valid_groups,", "))."</i><br>";
+        }
+        $this->checks['acls']['STATUS']    = FALSE;
+        $this->checks['acls']['STATUS_MSG']= _("Failed");
+        $this->checks['acls']['ERROR_MSG'] = $str;
+        $this->checks['acls']['ERROR_MSG'].= _("There is no valid GOsa 2.6 administrator account inside your LDAP.")."&nbsp;";
+        $this->checks['acls']['ERROR_MSG'].= "<input type='submit' name='migrate_acls' value='"._("Migrate")."'>";
+        $this->checks['acls']['ERROR_MSG'].= "<input type='submit' name='create_acls' value='"._("Create")."'>";
+      }elseif($GOsa_26_found){
+        $str = "";
+        if(!empty($valid_users)){
+          $str.= "<b>"._("Users")."</b>:&nbsp;".trim($valid_users,", ")."<br>";
+        }
+        if(!empty($valid_groups)){
+          $str.= "<b>"._("Groups")."</b>:&nbsp;".trim($valid_groups,", ")."<br>";
+        }
         $this->checks['acls']['STATUS']    = TRUE;
         $this->checks['acls']['STATUS_MSG']= _("Ok");
-        $this->checks['acls']['ERROR_MSG'] = "";
+        $this->checks['acls']['ERROR_MSG'] = $str;
       }else{
         $this->checks['acls']['STATUS']    = FALSE;
         $this->checks['acls']['STATUS_MSG']= _("Failed");
@@ -900,7 +1051,7 @@ class Step_Migrate extends setup_step
         $this->checks['acls']['ERROR_MSG'].= "<input type='submit' name='create_acls' value='"._("Create")."'>";
       }
     }
-    return($ldap->count()>=1);
+    return($GOsa_26_found);
   }
 
 
@@ -975,6 +1126,16 @@ class Step_Migrate extends setup_step
   {
     $pw1 = $pw2 = "";
     $uid = "";
+
+    /* On first call check for rid/sid base */
+    $cv = $this->parent->captured_values;
+    $ldap_l = new LDAP($cv['admin'],
+        $cv['password'],
+        $cv['connection'],
+        FALSE,
+        $cv['tls']);
+
+    $ldap = new ldapMultiplexer($ldap_l);
   
     if(isset($_POST['new_user_uid'])){
       $uid = $_POST['new_user_uid'];
@@ -986,6 +1147,14 @@ class Step_Migrate extends setup_step
       $pw2 = $_POST['new_user_password2'];
     }
   
+    
+    $ldap->cd($cv['base']);
+    $ldap->search("(uid=".$uid.")");
+    if($ldap->count()){
+      msg_dialog::display(_("Input error"),msgPool::duplicated(_("Uid")), ERROR_DIALOG);
+      return false;
+    }
+    
     if(empty($pw1) || empty($pw2) | ($pw1 != $pw2)){
       msg_dialog::display(_("Password error"), _("Provided passwords do not match!"), ERROR_DIALOG);
       return false;
@@ -995,17 +1164,8 @@ class Step_Migrate extends setup_step
       msg_dialog::display(_("Input error"), _("Specify a valid user ID!"), ERROR_DIALOG);
       return false;
     }
-    
-    /* On first call check for rid/sid base */
-    $cv = $this->parent->captured_values;
-    $ldap_l = new LDAP($cv['admin'],
-        $cv['password'],
-        $cv['connection'],
-        FALSE,
-        $cv['tls']);
-
-    $ldap = new ldapMultiplexer($ldap_l);
-
     /* Get current base attributes */
     $ldap->cd($cv['base']);
   
@@ -1020,10 +1180,7 @@ class Step_Migrate extends setup_step
       $dn = "uid=".$uid.",".$people_ou.$cv['base'];
     }
 
-    $methods = @passwordMethod::get_available_methods();
-    $p_m = $methods[$cv['encryption']];
-    $p_c = new $p_m(array());
-    $hash = $p_c->generate_hash($pw2);
+    $hash = passwordMethod::make_hash($pw2, $cv['encryption']);
 
     $new_user=array();
     $new_user['objectClass']= array("top","person","gosaAccount","organizationalPerson","inetOrgPerson");
@@ -1245,7 +1402,7 @@ class Step_Migrate extends setup_step
       /* Fix displayed dn syntax */ 
       $tmp = $this->outside_winstations;
       foreach($tmp as $key => $data){
-        $tmp[$key]['dn'] = @LDAP::fix($data['dn']);
+        $tmp[$key]['dn'] = LDAP::fix($data['dn']);
       }
 
       $smarty = get_smarty();
@@ -1291,7 +1448,7 @@ class Step_Migrate extends setup_step
       /* Fix displayed dn syntax */ 
       $tmp = $this->outside_groups;
       foreach($tmp as $key => $data){
-        $tmp[$key]['dn'] = @LDAP::fix($data['dn']);
+        $tmp[$key]['dn'] = LDAP::fix($data['dn']);
       }
 
       $smarty = get_smarty();
@@ -1339,7 +1496,7 @@ class Step_Migrate extends setup_step
       /* Fix displayed dn syntax */ 
       $tmp = $this->outside_users;
       foreach($tmp as $key => $data){
-        $tmp[$key]['dn'] = @LDAP::fix($data['dn']);
+        $tmp[$key]['dn'] = LDAP::fix($data['dn']);
       }
 
       $smarty = get_smarty();
@@ -1362,35 +1519,62 @@ class Step_Migrate extends setup_step
         $this->initialize_checks();
       }
     }
+
     /*************
-     * User Migration handling 
+     * Root object class check  
+     *************/
+  
+    if(isset($_POST['root_add_objectclasses'])){
+      $this->rootOC_migrate_dialog = TRUE;
+      $this->dialog = TRUE;
+    }
+    if(isset($_POST['rootOC_dialog_cancel'])){
+      $this->rootOC_migrate_dialog = FALSE;
+      $this->dialog = FALSE;
+    }
+    if(isset($_POST['rootOC_migrate_start'])){
+      if($this->checkBaseOC(FALSE)){
+        $this->checkBaseOC(); // Update overview info
+        $this->dialog = FALSE;
+        $this->rootOC_migrate_dialog = FALSE;
+      }
+    }
+
+
+    if($this->rootOC_migrate_dialog){
+      $smarty = get_smarty();
+      $smarty->assign("details",$this->rootOC_details);
+      $smarty->assign("method","rootOC_migrate_dialog");
+      return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
+    }
+
+    /*************
+     * Administrative Account -- Migrate/Create 
      *************/
 
     if(isset($_POST['retry_acls'])){
       $this->check_administrativeAccount();
     }
 
+    /* Dialog handling */
     if(isset($_POST['create_acls'])){
       $this->acl_create_dialog = TRUE;
       $this->dialog = TRUE;
     }
+
+    if(isset($_POST['migrate_acls'])){
+      $this->acl_migrate_dialog = TRUE;
+      $this->dialog = TRUE;
+    }
   
-    if(isset($_POST['create_acls_cancel'])){
+    if(isset($_POST['create_acls_cancel']) || isset($_POST['migrate_acls_cancel'])){
       $this->acl_create_dialog = FALSE;
+      $this->acl_migrate_dialog = FALSE;
       $this->dialog = FALSE;
       $this->show_details = FALSE;
     }
 
-#    if(isset($_POST['create_acls_create_confirmed'])){
-#      if($this->create_admin()){
-#        $this->acl_create_dialog = FALSE;
-#        $this->dialog = FALSE;
-#      $this->show_details = FALSE;
-#        $this->initialize_checks();
-#      }
-#    }
-
+    /* Account creation */
     if(isset($_POST['create_acls_create'])){
       $this->create_admin(TRUE);
     }
@@ -1402,14 +1586,43 @@ class Step_Migrate extends setup_step
       }
     }
 
+    /* Add admin acls for the selected users to the ldap base.
+     */
+    if($this->acl_migrate_dialog && isset($_POST['migrate_admin_user'])){
+
+      /* Update ldap and reload check infos 
+       */
+      $this->migrate_selected_admin_users();
+
+    }elseif($this->acl_migrate_dialog){
+
+      /* Display admin migration dialog.
+       */
+      $this->migrate_users();
+      $smarty = get_smarty();
+
+      /* Do we have to display the changes
+       */
+      $details = isset($_POST['details']) && $_POST['details'];
+      if(isset($_POST['migrate_acls_show_changes'])){
+        $details = TRUE;
+      }elseif(isset($_POST['migrate_acls_hide_changes'])){
+        $details = FALSE;
+      }
+
+      $smarty->assign("migrate_acl_base_entry", $this->migrate_acl_base_entry);
+      $smarty->assign("details", $details);
+      $smarty->assign("method","migrate_acls");
+      $smarty->assign("migrateable_users",$this->migrate_users);
+      return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
+    }
+
     if($this->acl_create_dialog){
       $smarty = get_smarty();
-  
       $uid = "admin";
       if(isset($_POST['new_user_uid'])){
         $uid = $_POST['new_user_uid'];
       }
-
       $smarty->assign("new_user_uid",$uid);
       $smarty->assign("new_user_password",@$_POST['new_user_password']);
       $smarty->assign("new_user_password2",@$_POST['new_user_password2']);
@@ -1463,7 +1676,7 @@ class Step_Migrate extends setup_step
       /* Fix displayed dn syntax */ 
       $tmp = $this->users_to_migrate;
       foreach($tmp as $key => $data){
-        $tmp[$key]['dn'] = @LDAP::fix($data['dn']);
+        $tmp[$key]['dn'] = LDAP::fix($data['dn']);
       }
 
       $smarty = get_smarty();
@@ -1519,7 +1732,7 @@ class Step_Migrate extends setup_step
       /* Fix displayed dn syntax */ 
       $tmp = $this->deps_to_migrate;
       foreach($tmp as $key => $data){
-        $tmp[$key]['dn'] = @LDAP::fix($data['dn']);
+        $tmp[$key]['dn'] = LDAP::fix($data['dn']);
       }
 
       $smarty->assign("deps_to_migrate",$tmp);
@@ -1528,6 +1741,138 @@ class Step_Migrate extends setup_step
       return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
     }
 
+
+    /*************
+     * Device migration 
+     *************/
+   
+    if($this->device_dialog) {
+      $this->check_device_posts();
+    }
+    if(isset($_POST['device_dialog_cancel'])){
+      $this->device_dialog = FALSE;
+      $this->show_details = FALSE;
+      $this->dialog = FALSE;
+    }
+   
+    if(isset($_POST['device_dialog_whats_done'])){
+      $this->show_details= TRUE;
+    }
+    if(isset($_POST['device_dialog_refresh'])){
+      $this->show_details= FALSE;
+    }
+
+    if(isset($_POST['migrate_devices'])){
+      $this->migrate_usb_devices();
+#      $this->dialog = FALSE;
+ #     $this->show_details = FALSE;
+  #    $this->device_dialog = FALSE;
+   #   $this->initialize_checks();
+    }
+
+    if(isset($_POST['device_dialog'])){
+      $this->device_dialog = TRUE;
+      $this->dialog = TRUE;
+    }
+    
+    if($this->device_dialog){
+      $smarty = get_smarty();
+      $smarty->assign("method","devices");
+      $smarty->assign("devices",$this->device);
+      $smarty->assign("device_details", $this->show_details);
+      return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
+    }
+
+
+    /*************
+     * Service migration 
+     *************/
+   
+    if($this->service_dialog) {
+      $this->check_service_posts();
+    }
+    if(isset($_POST['service_dialog_cancel'])){
+      $this->service_dialog = FALSE;
+      $this->show_details = FALSE;
+      $this->dialog = FALSE;
+    }
+   
+    if(isset($_POST['service_dialog_whats_done'])){
+      $this->show_details= TRUE;
+    }
+    if(isset($_POST['service_dialog_refresh'])){
+      $this->show_details= FALSE;
+    }
+
+    if(isset($_POST['migrate_services'])){
+      $this->migrate_services();
+#      $this->dialog = FALSE;
+ #     $this->show_details = FALSE;
+  #    $this->service_dialog = FALSE;
+   #   $this->initialize_checks();
+    }
+
+    if(isset($_POST['service_dialog'])){
+      $this->service_dialog = TRUE;
+      $this->dialog = TRUE;
+    }
+    
+    if($this->service_dialog){
+      $smarty = get_smarty();
+      $smarty->assign("method","services");
+      $smarty->assign("services",$this->service);
+      $smarty->assign("service_details", $this->show_details);
+      return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
+    }
+
+
+    /*************
+     * Menu migration 
+     *************/
+   
+    if($this->menu_dialog) {
+      $this->check_menu_posts();
+    }
+    if(isset($_POST['menu_dialog_cancel'])){
+      $this->menu_dialog = FALSE;
+      $this->show_details = FALSE;
+      $this->dialog = FALSE;
+    }
+   
+    if(isset($_POST['menu_dialog_whats_done'])){
+      $this->show_details= TRUE;
+    }
+    if(isset($_POST['menu_dialog_refresh'])){
+      $this->show_details= FALSE;
+    }
+
+    if(isset($_POST['migrate_menus'])){
+      $this->migrate_menus();
+#      $this->dialog = FALSE;
+ #     $this->show_details = FALSE;
+  #    $this->menu_dialog = FALSE;
+   #   $this->initialize_checks();
+    }
+
+    if(isset($_POST['menu_dialog'])){
+      $this->menu_dialog = TRUE;
+      $this->dialog = TRUE;
+    }
+    
+    if($this->menu_dialog){
+      $smarty = get_smarty();
+      $smarty->assign("method","menus");
+      $smarty->assign("menus",$this->menu);
+      $smarty->assign("menu_details", $this->show_details);
+      return($smarty->fetch(get_template_path("setup_migrate.tpl",TRUE,dirname(__FILE__))));
+    }
+
     $smarty = get_smarty();
     $smarty->assign("checks",$this->checks);
     $smarty->assign("method","default");
@@ -1623,7 +1968,9 @@ class Step_Migrate extends setup_step
 
     /* Check if root object exists */
     $ldap->cd($cv['base']);
+    $ldap->set_size_limit(1);
     $res = $ldap->search("(objectClass=*)");
+    $ldap->set_size_limit(0);
     $err = ldap_errno($ldap->cid); 
 
     if( !$res || 
@@ -1661,32 +2008,11 @@ class Step_Migrate extends setup_step
   }
 
 
-  /* Return ldif information for a 
-   * given attribute array 
+  /* Check if the root object includes the required object classes, e.g. gosaDepartment is required for ACLs.
+   * If the parameter just_check is true, then just check for the OCs. 
+   * If the Parameter is false, try to add the required object classes.
    */
-  function array_to_ldif($atts)
-  {
-    $ret = "";
-    unset($atts['count']);
-    unset($atts['dn']);
-    foreach($atts as $name => $value){
-      if(is_numeric($name)) {
-        continue;
-      }
-      if(is_array($value)){
-        unset($value['count']);
-        foreach($value as $a_val){
-          $ret .= $name.": ". $a_val."\n";
-        }
-      }else{
-        $ret .= $name.": ". $value."\n";
-      }
-    }
-    return(preg_replace("/\n$/","",$ret));
-  }
-
-
-  function get_user_list()
+  function checkBaseOC($just_check = TRUE)
   {
     /* Establish ldap connection */
     $cv = $this->parent->captured_values;
@@ -1697,41 +2023,205 @@ class Step_Migrate extends setup_step
         $cv['tls']);
 
     $ldap = new ldapMultiplexer($ldap_l);
+
+    /* Check if root object exists */
     $ldap->cd($cv['base']);
-    $ldap->search("(objectClass=gosaAccount)",array("dn"));
-  
-    $tmp = array();
-    while($attrs = $ldap->fetch()){
-      $tmp[base64_encode($attrs['dn'])] = @LDAP::fix($attrs['dn']);
+    $ldap->cat($cv['base']);
+    if(!$ldap->count()){
+      $this->checks['rootOC']['STATUS']    = FALSE;
+      $this->checks['rootOC']['STATUS_MSG']= _("LDAP query failed");
+      $this->checks['rootOC']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
+      return;
     }
-    return($tmp);
-  }
 
+    $attrs = $ldap->fetch();
 
- function get_all_people_ous()
-  {
-    /* Get collected configuration settings */
-    $cv = $this->parent->captured_values;
-    $people_ou = trim($cv['peopleou']);
-
-    /* Establish ldap connection */
-    $cv = $this->parent->captured_values;
-    $ldap_l = new LDAP($cv['admin'],
-        $cv['password'],
-        $cv['connection'],
-        FALSE,
-        $cv['tls']);
+    /* Root object doesn't exists 
+     */
+    if(!in_array("gosaDepartment",$attrs['objectClass'])){
+      if($just_check){
 
-    $ldap = new ldapMultiplexer($ldap_l);
+        $this->rootOC_details = array();       
+        $mods = array();
 
-    /*****************
-     * If people ou is NOT empty
-     * search for for all objects matching the given container
-     *****************/
-    if(!empty($people_ou)){
-      $ldap->search("(".$people_ou.")",array("dn"));
+        /* Get list of possible container objects, to be able to detect naming 
+         *  attributes and missing attribute types.
+         */
+        if(!class_available("departmentManagement")){
+          $this->checks['rootOC']['STATUS']    = FALSE;
+          $this->checks['rootOC']['STATUS_MSG']= _("Failed");
+          $this->checks['rootOC']['ERROR_MSG'] = sprintf(_("Missing GOsa class %s."),"departmentManagement").
+            "&nbsp;"._("Please check your installation.");
+          return;
+        }
 
-      /* Create people ou if there is currently none */
+        /* Try to detect base class type, e.g. is it a dcObject.
+         */
+        $dep_types = departmentManagement::get_support_departments();
+        $dep_type ="";
+        foreach($dep_types as $dep_name => $dep_class){
+          if(in_array($dep_class['CLASS'], $attrs['objectClass'])){
+            $dep_type = $dep_name;
+            break;
+          }
+        }
+
+        /* If no known base class was detect, abort with message
+         */    
+        if(empty($dep_type)){
+          $this->checks['rootOC']['STATUS']    = FALSE;
+          $this->checks['rootOC']['STATUS_MSG']= _("Failed");
+          $this->checks['rootOC']['ERROR_MSG'] = 
+            sprintf(_("Could not detect the object type of your root object, please try to add the objectClass '%s' manually."),"gosaDepartment");
+          return;
+        }
+
+        /* Create 'current' and 'target' object properties, to be able to display 
+         *  a set of modifications required to create a valid GOsa department.
+         */    
+        $str = "dn: ".$cv['base']."\n";
+        for($i = 0 ; $i<$attrs['objectClass']['count'];$i++){
+          $str .= "objectClass: ".$attrs['objectClass'][$i]."\n";
+        }
+        $this->rootOC_details['current'] = $str;
+
+        /* Create target infos 
+         */
+        $str = "dn: ".$cv['base']."\n";
+        for($i = 0 ; $i<$attrs['objectClass']['count'];$i++){
+          $str .= "objectClass: ".$attrs['objectClass'][$i]."\n";
+          $mods['objectClass'][] = $attrs['objectClass'][$i];
+        }
+        $mods['objectClass'][] = "gosaDepartment";
+        $str .= "<b>objectClass: gosaDepartment</b>\n";
+
+        /* Append attribute 'ou', it is required by gosaDepartment
+         */
+        if(!isset($attrs['ou'])){
+          $val = "GOsa";
+          if(isset($attrs[$dep_types[$dep_type]['ATTR']][0])){
+            $val = $attrs[$dep_types[$dep_type]['ATTR']][0];
+          }
+          $str .= "<b>ou: ".$val."</b>\n";
+          $mods['ou'] =$val;
+        }
+
+        /*Append description, it is required by gosaDepartment too.
+         */
+        if(!isset($attrs['description'])){
+          $val = "GOsa";
+          if(isset($attrs[$dep_types[$dep_type]['ATTR']][0])){
+            $val = $attrs[$dep_types[$dep_type]['ATTR']][0];
+          }
+          $str .= "<b>description: ".$val."</b>\n";
+          $mods['description'] = $val;
+        }
+        $this->rootOC_details['target'] = $str;
+        $this->rootOC_details['mods'] = $mods;
+
+        /*  Add button that allows to open the migration details
+         */
+        $this->checks['rootOC']['STATUS']    = FALSE;
+        $this->checks['rootOC']['STATUS_MSG']= _("Failed");
+        $this->checks['rootOC']['ERROR_MSG'] = "&nbsp;<input type='submit' 
+          name='root_add_objectclasses' value='"._("Migrate")."'>";
+
+        return(FALSE);
+      }else{
+
+        /* Add root object */ 
+        $ldap->cd($cv['base']);
+        if(isset($this->rootOC_details['mods'])){
+          $res  = $ldap->modify($this->rootOC_details['mods']);        
+          if(!$res){
+            msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $source, LDAP_MOD, get_class()));
+          }
+          return($res);
+        }else{
+          trigger_error("No modifications to make... ");
+        }
+      }
+      return(TRUE);
+    }
+
+    /* Create & remove of dummy object was successful */
+    $this->checks['rootOC']['STATUS']    = TRUE;
+    $this->checks['rootOC']['STATUS_MSG']= _("Ok");
+    $this->checks['rootOC']['ERROR_MSG'] = "";
+  }
+
+
+  /* Return ldif information for a 
+   * given attribute array 
+   */
+  function array_to_ldif($atts)
+  {
+    $ret = "";
+    unset($atts['count']);
+    unset($atts['dn']);
+    foreach($atts as $name => $value){
+      if(is_numeric($name)) {
+        continue;
+      }
+      if(is_array($value)){
+        unset($value['count']);
+        foreach($value as $a_val){
+          $ret .= $name.": ". $a_val."\n";
+        }
+      }else{
+        $ret .= $name.": ". $value."\n";
+      }
+    }
+    return(preg_replace("/\n$/","",$ret));
+  }
+
+
+  function get_user_list()
+  {
+    /* Establish ldap connection */
+    $cv = $this->parent->captured_values;
+    $ldap_l = new LDAP($cv['admin'],
+        $cv['password'],
+        $cv['connection'],
+        FALSE,
+        $cv['tls']);
+
+    $ldap = new ldapMultiplexer($ldap_l);
+    $ldap->cd($cv['base']);
+    $ldap->search("(objectClass=gosaAccount)",array("dn"));
+  
+    $tmp = array();
+    while($attrs = $ldap->fetch()){
+      $tmp[base64_encode($attrs['dn'])] = LDAP::fix($attrs['dn']);
+    }
+    return($tmp);
+  }
+
+
+ function get_all_people_ous()
+  {
+    /* Get collected configuration settings */
+    $cv = $this->parent->captured_values;
+    $people_ou = trim($cv['peopleou']);
+
+    /* Establish ldap connection */
+    $cv = $this->parent->captured_values;
+    $ldap_l = new LDAP($cv['admin'],
+        $cv['password'],
+        $cv['connection'],
+        FALSE,
+        $cv['tls']);
+
+    $ldap = new ldapMultiplexer($ldap_l);
+
+    /*****************
+     * If people ou is NOT empty
+     * search for for all objects matching the given container
+     *****************/
+    if(!empty($people_ou)){
+      $ldap->search("(".$people_ou.")",array("dn"));
+
+      /* Create people ou if there is currently none */
       if($ldap->count() == 0 ){
         $add_dn = $cv['peopleou'].",".$cv['base'];
         $naming_attr = preg_replace("/=.*$/","",$add_dn);
@@ -1785,7 +2275,7 @@ class Step_Migrate extends setup_step
 
     /* Get winstation ou */
     if($cv['generic_settings']['wws_ou_active']) {
-      $winstation_ou = $cv['generic_settings']['ws_ou'];
+      $winstation_ou = $cv['generic_settings']['wws_ou'];
     }else{
       $winstation_ou = "ou=winstations";
     }
@@ -1896,7 +2386,7 @@ class Step_Migrate extends setup_step
   
     $tmp = array();
     while($attrs = $ldap->fetch()){
-      $tmp[base64_encode($attrs['dn'])] = @LDAP::fix($attrs['dn']);
+      $tmp[base64_encode($attrs['dn'])] = LDAP::fix($attrs['dn']);
     }
     return($tmp);
   }
@@ -1954,7 +2444,7 @@ class Step_Migrate extends setup_step
     }
   }
 
-  
+
   /* Cleanup ldap result to be able to write it be to ldap */
   function cleanup_array($attrs)
   {
@@ -1968,7 +2458,829 @@ class Step_Migrate extends setup_step
     }
     return($attrs);
   }
-}
 
+
+  /*! \brief  Act in posts from the device migration dialog 
+   */
+  function check_device_posts()
+  {
+    foreach($this->device as $key => $device){
+      if(isset($_POST["migrate_".$key])){
+        $this->device[$key]['DETAILS'] =TRUE;
+      }else{
+        $this->device[$key]['DETAILS'] =FALSE;
+      }
+    }
+  }
+
+
+  /*! \brief  Check for old style (gosa-2.5) devices.
+              Save readable informations and a list of migratable devices 
+               in $this->devices.
+   */
+  function check_usb_devices ()
+  {
+    /* Establish ldap connection */
+    $cv = $this->parent->captured_values;
+    $ldap_l = new LDAP($cv['admin'],
+        $cv['password'],
+        $cv['connection'],
+        FALSE,
+        $cv['tls']);
+
+    $ldap = new ldapMultiplexer($ldap_l);
+    $ldap->cd($cv['base']);
+    $res = $ldap->search("(&(|(objectClass=posixAccount)(objectClass=posixGroup))(gotoHotplugDevice=*))",
+        array("cn","gotoHotplugDevice","gosaUnitTag"));
+
+    if(!$res){
+      $this->checks['old_style_devices']['STATUS']    = FALSE;
+      $this->checks['old_style_devices']['STATUS_MSG']= _("LDAP query failed");
+      $this->checks['old_style_devices']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
+      return;
+    }
+
+
+    /* If adding failed, tell the user */
+    if($ldap->count()){
+  
+      $this->device = array();
+      while($attrs = $ldap->fetch()){
+
+        for ($j= 0; $j < $attrs['gotoHotplugDevice']['count']; $j++){
+
+          $after  = "";
+          $current= "";
+
+          $entry= $attrs['gotoHotplugDevice'][$j];
+
+          @list($name,$desc,$serial,$vendor,$product) = explode('|', $entry);
+  
+          $add = 1;
+          $new_name  = $name;
+          while(isset($dest[$new_name])){
+            $new_name = $name."_".$add;
+            $add ++;
+          }
+          $name = $new_name;
+          $newdn= "cn=$name,ou=devices,".preg_replace('/^[^,]+,/', '', $attrs['dn']);
+
+          if (!isset($dest[$name])){
+            $dest[$name]= $newdn;
+
+            $current.= "dn: ".$attrs['dn']."\n"; 
+    
+            for ($c= 0; $c < $attrs['gotoHotplugDevice']['count']; $c++){
+              if($c == $j){
+                $current.= "<b>gotoHotplugDevice: ".$attrs['gotoHotplugDevice'][$c]."</b>\n"; 
+              }else{
+                $current.= "gotoHotplugDevice: ".$attrs['gotoHotplugDevice'][$c]."\n"; 
+              }
+            }
+
+            $after.= "dn: $newdn\n";
+            $after.= "changetype: add\n";
+            $after.= "objectClass: top\n";
+            $after.= "objectClass: gotoDevice\n";
+            if (isset($attrs['gosaunittag'][0])){
+              $after.= "objectClass: gosaAdminiafter\n";
+              $after.= "gosaUnitTag: ".$attrs['gosaunittag'][0]."\n";
+            }
+            $after.= "cn: $name\n";
+            $after.= "gotoHotplugDevice: $desc|$serial|$vendor|$product\n\n";
+
+            $this->device[] = array(
+                'CURRENT'     =>  $current,
+                'AFTER'       => $after,
+                'OLD_DEVICE'  => $entry,
+                'DN'          => $attrs['dn'],
+                'NEW_DN'      => $newdn,
+                'DEVICE_NAME' => $name,
+                'DETAILS'     => FALSE);
+          }
+        }
+      }
+
+      $this->checks['old_style_devices']['STATUS']    = FALSE;
+      $this->checks['old_style_devices']['STATUS_MSG']= "<font style='color:#F0A500'>"._("Warning")."</font>";
+      $this->checks['old_style_devices']['ERROR_MSG'] = 
+        sprintf(_("There are %s devices that need to be migrated."),count($this->device)).
+          "<input type='submit' name='device_dialog' value='"._("Migrate")."'>";
+    }else{
+      $this->checks['old_style_devices']['STATUS']    = TRUE;
+      $this->checks['old_style_devices']['STATUS_MSG']= _("Ok");
+      $this->checks['old_style_devices']['ERROR_MSG'] = "";
+    }
+  }
+
+
+  /*! \brief  Migrate all selected devices. 
+              Execute all required ldap actions to migrate the 
+               selected devices.
+   */
+  function migrate_usb_devices ()
+  {
+    /* Establish ldap connection */
+    $cv = $this->parent->captured_values;
+    $ldap_l = new LDAP($cv['admin'],
+        $cv['password'],
+        $cv['connection'],
+        FALSE,
+        $cv['tls']);
+
+    $ldap = new ldapMultiplexer($ldap_l);
+
+    /* Walk through migrateable devices and initiate migration for all 
+        devices that are checked (DETAILS==TRUE) 
+     */
+    foreach($this->device as $key => $device){
+      if($device['DETAILS']){
+
+        /* Get source object and verify that the specified device is a 
+            member attribute of it. 
+         */
+        $ldap->cd($cv['base']);
+        $ldap->cat($device['DN']);
+        $attrs = $ldap->fetch();
+        if(in_array($device['OLD_DEVICE'],$attrs['gotoHotplugDevice'])){
+
+          /* Create new hotplug device object 'gotoDevice'
+           */ 
+          @list($name,$desc,$serial,$vendor,$product) = explode('|', $device['OLD_DEVICE']);    
+          $newdn = $device['NEW_DN'];
+          $new_attr = array();
+          $new_attr['cn'] = $device['DEVICE_NAME'];
+          $new_attr['objectClass'] = array('top','gotoDevice');
+          $new_attr['gotoHotplugDevice'] = "$desc|$serial|$vendor|$product";
+
+          /* Add new object 
+           */
+          $ldap->cd($cv['base']);
+          $ldap->create_missing_trees(preg_replace("/^[^,]+,/","",$newdn));
+          $ldap->cd($newdn);
+          $ldap->add($new_attr);
+
+          /* Throw an error message if the action failed. 
+           */
+          if(!$ldap->success()){
+            msg_dialog::display(_("LDAP error"), 
+                sprintf(_("Adding '%s' to the LDAP failed: %s"),
+                  "<b>".LDAP::fix($newdn)."</b>", 
+                  "<br><br><i>".$ldap->get_error()."</i>"), ERROR_DIALOG);
+          }else{
+
+            /* Remove old style device definition from source object. 
+             */
+            $update['gotoHotplugDevice'] = array();
+            for($i = 0 ; $i < $attrs['gotoHotplugDevice']['count'] ; $i++){
+              if($attrs['gotoHotplugDevice'][$i] == $device['OLD_DEVICE']){
+                 continue;
+              }
+              $update['gotoHotplugDevice'][] = $attrs['gotoHotplugDevice'][$i];
+            }
+
+            $ldap->cd($device['DN']);
+            $ldap->modify($update);
+            $ldap->cat($device['DN'],array("gotoHotplugDevice"));
+            if(!$ldap->success()){
+              msg_dialog::display(_("LDAP error"), 
+                  sprintf(_("Updating '%s' failed: %s"),
+                    "<b>".LDAP::fix($device['DN'])."</b>", 
+                    "<br><br><i>".$ldap->get_error()."</b>"), ERROR_DIALOG);
+            }else{
+              unset($this->device[$key]);
+            }
+          }
+        }
+      }
+    }
+    $this->check_usb_devices();
+  }
+
+
+  /*! \brief  Check for old style (gosa-2.5) services that have to be migrated
+               to be useable in gosa-2.6.
+              All required changes are stored in $this->service, also some
+               readable informations describing the actions required 
+               to migrate the service
+   */
+  function check_services()
+  {
+    /* Establish ldap connection */
+    $cv = $this->parent->captured_values;
+    $ldap_l = new LDAP($cv['admin'],
+        $cv['password'],
+        $cv['connection'],
+        FALSE,
+        $cv['tls']);
+
+    $ldap = new ldapMultiplexer($ldap_l);
+    $this->service = array();
+
+    /* Check for Ldap services that must be migrated 
+     */ 
+    $ldap->cd($cv['base']);
+    $res = $ldap->search("(objectClass=goLdapServer)", array("goLdapBase", "cn"));
+
+    /* Check if we were able to query the ldap server 
+     */
+    if(!$res){
+      $this->checks['old_style_services']['STATUS']    = FALSE;
+      $this->checks['old_style_services']['STATUS_MSG']= _("LDAP query failed");
+      $this->checks['old_style_services']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
+      return;
+    }
+
+    /* Walk through each configured ldap server 
+        and check if it is configured correctly.
+     */
+    while($attrs = $ldap->fetch()){
+      $dn= $attrs['dn'];
+      $uri= $attrs['goLdapBase'][0];
+      if (! preg_match("!^ldaps?://!", $uri)){
+        $this->service[] = array(
+            "TYPE"    => "modify" , 
+            "DN"      => $dn, 
+            "DETAILS" => FALSE, 
+            "ATTRS"   => array("goLdapBase" => "ldap://".$attrs['cn'][0]."/$uri"),
+            "CURRENT" => "goLdapBase: ".$uri,
+            "AFTER"   => "goLdapBase: "."ldap://".$attrs['cn'][0]."/$uri");
+      }
+    }
+
+    /* Other sevices following here later ...maybe
+     */
+
+    /*  Update status message
+     */
+    if(count($this->service)){
+      $this->checks['old_style_services']['STATUS']    = FALSE;
+      $this->checks['old_style_services']['STATUS_MSG']= "<font style='color:#F0A500'>"._("Warning")."</font>";
+      $this->checks['old_style_services']['ERROR_MSG'] =
+        sprintf(_("There are %s services that need to be migrated."),
+            count($this->service)).
+        "<input type='submit' name='service_dialog' value='"._("Migrate")."'>";
+    }else{
+      $this->checks['old_style_services']['STATUS']    = TRUE;
+      $this->checks['old_style_services']['STATUS_MSG']= _("Ok");
+      $this->checks['old_style_services']['ERROR_MSG'] = "";
+    }
+  }
+
+
+  
+  /*! \brief  Migrate selected services.
+              This function executes the commands collected by the 
+               service_check() function.
+   */
+  function migrate_services()
+  {
+    /* Establish ldap connection 
+     */
+    $cv = $this->parent->captured_values;
+    $ldap_l = new LDAP($cv['admin'],
+        $cv['password'],
+        $cv['connection'],
+        FALSE,
+        $cv['tls']);
+
+    $ldap = new ldapMultiplexer($ldap_l);
+
+    /* Handle each service 
+     */
+    foreach($this->service as $key => $service){
+      if($service['DETAILS']){
+
+        /* Handle modify requests 
+         */
+        if($service['TYPE'] == "modify"){
+          $ldap->cd($service['DN']);
+          $ldap->modify($service['ATTRS']);
+
+          /* Check if everything done was successful 
+           */
+          if(!$ldap->success()){
+            msg_dialog::display(_("LDAP error"), 
+                sprintf(_("Updating '%s' failed: %s"),
+                  "<b>".LDAP::fix($service['DN'])."</b>", 
+                  "<br><br><i>".$ldap->get_error()."</b>"), ERROR_DIALOG);
+          }else{
+        
+            /* Remove action from list 
+             */
+            unset($this->service[$key]);
+          }
+        }
+      }
+    }
+
+    /* Update the service migration status 
+     */
+    $this->check_services();
+  }
+
+
+  /*! \brief  Ensure that posts made on the service migration dialog 
+               are processed.
+   */
+  function check_service_posts()
+  {
+    foreach($this->service as $key => $service){
+      if(isset($_POST["migrate_".$key])){
+        $this->service[$key]['DETAILS'] =TRUE;
+      }else{
+        $this->service[$key]['DETAILS'] =FALSE;
+      }
+    }
+  }
+
+
+  /*! \brief  This function checks the given ldap for old style (gosa-2.5) 
+               menu entries and will prepare a list of actions that are required
+               to migrate them to gosa-2.6.
+              All required actions and some readable informations are stored in 
+               $this->menu.
+   */
+  function check_menus()
+  {
+    /* Establish ldap connection
+     */
+    $cv = $this->parent->captured_values;
+    $ldap_l = new LDAP($cv['admin'],
+        $cv['password'],
+        $cv['connection'],
+        FALSE,
+        $cv['tls']);
+
+    $ldap = new ldapMultiplexer($ldap_l);
+
+    /* First detect all release names 
+     */
+    $ldap->cd($cv['base']);
+    $res = $ldap->search("(&(objectClass=organizational)(objectClass=FAIbranch))",array("ou","objectClass"));
+
+    /* Check if we were able to query the ldap server
+     */
+    if(!$res){
+      $this->checks['old_style_menus']['STATUS']    = FALSE;
+      $this->checks['old_style_menus']['STATUS_MSG']= _("LDAP query failed");
+      $this->checks['old_style_menus']['ERROR_MSG'] = _("Possibly the 'root object' is missing.");
+      return;
+    }
+
+    /* Create application -> parameter mapping, used later to detect 
+        which configured parameter belongs to which application entry.
+     */
+    $amap= array();
+    $todo = array();
+    $ldap->cd($cv['base']);
+    $ldap->search("(objectClass=gosaApplication)", array("cn", "gosaApplicationParameter"));
+    while($info = $ldap->fetch()){
+      if (isset($info['gosaApplicationParameter']['count'])){
+        for ($j= 0; $j < $info['gosaApplicationParameter']['count']; $j++){
+          $p= preg_replace("/^([^:]+):.*$/", "$1", $info['gosaApplicationParameter'][$j]);
+
+          if(!isset($amap[$info['cn'][0]]) || !in_array($p, $amap[$info['cn'][0]])){
+            $amap[$info['cn'][0]][]= $p;
+          }
+        }
+      } else {
+        $amap[$info['cn'][0]]= array();
+      }
+    }
+
+    /* Search for all groups that have an old style application menu configured.
+     */  
+    $appgroups = array();
+    $ldap->cd($cv['base']);
+    $ldap->search("(&(objectClass=gosaApplicationGroup)(objectClass=posixGroup)(FAIrelease=*))",
+        array("gosaMemberApplication","gosaApplicationParameter","FAIrelease","objectClass","gosaUnitTag"));
+
+    /* Create readable prefix for "What will be done" infos 
+     */
+    $s_add = "<i>"._("Add")."</i>\t";
+    $s_del = "<i>"._("Remove")."</i>\t";
+
+    /* Walk through all found old-style menu configurations.
+        -Prepare ldap update list     $data   
+        -Prepare printable changes    $after/$current
+     */
+    while($info = $ldap->fetch()){
+
+      $data = array();
+      $current = "";
+      $after ="";
+
+      /* Get unit tag 
+       */
+      $tag ="";
+      if(isset($info['gosaUnitTag'])){
+        $tag = $info['gosaUnitTag'][0];
+      }
+
+      /* Collect application parameter for this group
+       */
+      $params= array();
+      if(isset($info['gosaApplicationParameter'])){
+        for ($i= 0; $i < $info['gosaApplicationParameter']['count']; $i++){
+          $name= preg_replace("/^([^:]+):.*$/", "$1", $info['gosaApplicationParameter'][$i]);
+          $params[$name]= $info['gosaApplicationParameter'][$i];
+        }
+      }
+
+      /* Create release container for each release/subrelease.
+         eg.   "sisa/1.0.0":
+         .       "ou=siga, ..."
+         .       "ou=1.0.0,ou=siga, .."
+       */ 
+      $release = "";
+      $r = $info['FAIrelease'][0];
+      $z = split("/",$r);
+      foreach($z as $part){
+
+        if(!empty($part)){
+          $release = "ou=".$part.",".$release;
+
+          /* Append release department information to "What will be done" info
+           */
+          $release_dn = $release.$info['dn'];
+          $after   .=  $s_add."dn: $release_dn\n";
+          $after   .=  $s_add."objectClass: top\n";
+          $after   .=  $s_add."objectClass: FAIbranch\n";
+          $after   .=  $s_add."objectClass: organizationalUnit\n";
+         
+          /* Append UnitTag 
+           */ 
+          if($tag != ""){ 
+            $after   .=  $s_add."objectClass: gosaAdministrativeUnitTag\n";
+            $after   .=  $s_add."gosaUnitTag: $tag\n";
+          }
+          $after   .=  $s_add."ou: $part\n";
+
+          /* Append release data to ldap actions 
+           */
+          $d = array();
+          $d['objectClass'] = array("top","FAIbranch","organizationalUnit");
+          if(!empty($tag)){
+            $d['objectClass'][] = "gosaAdministrativeUnitTag";
+            $d['gosaUnitTag']   = $tag;
+          }
+          $d['ou']          = $part;
+          $data['ADD'][$release_dn]= $d;
+        }
+      }
+
+      /* Add member applications to the array.
+       */ 
+      $current .= "dn: ".$info['dn']."\n";
+      $menu_structure = array();
+      for ($i= 0; $i < $info['gosaMemberApplication']['count']; $i++){
+        list($name, $location, $priority)= explode("|", $info['gosaMemberApplication'][$i]);
+
+        /* Create location dn 
+         */
+        $location_dn ="";
+        if(!empty($location)){
+          $location_dn ="cn=".$location.",";
+        }
+
+        /* Append old style element to current detail informations 
+         */      
+        $current .= $s_del."gosaMemberApplication: ".$info['gosaMemberApplication'][$i]."\n";
+
+        /* Append ldap update action to remove the old menu entry attributes 
+         */
+        unset($info['objectClass']['count']);
+        $d = array();
+        $d['gosaMemberApplication']      = array();
+        $d['gosaApplicationParameter']  = array();
+        if(isset($info['FAIrelease'])){
+          $d['FAIrelease'] = array();
+        }
+        $d['objectClass']               = array_remove_entries(array("gosaApplicationGroup","FAIreleaseTag"),$info['objectClass']);
+        $data['MODIFY'][$info['dn']]    = $d;
+
+        /* Create new application menu structure 
+         */
+        if (isset($amap[$name])){
+
+          /* Append missing menu structure to "What is done info"
+           */
+          if(!isset($menu_structure[$location]) && !empty($location)){
+            $menu_structure[$location] = TRUE;
+            $after .= "\n";
+            $after .= $s_add."dn: $location_dn$release_dn\n";
+            $after .= $s_add."objectClass: gotoSubmenuEntry\n";
+
+            /* Append UnitTag
+             */
+            if($tag != ""){
+              $after   .=  $s_add."objectClass: gosaAdministrativeUnitTag\n";
+              $after   .=  $s_add."gosaUnitTag: $tag\n";
+            }
+            $after .= $s_add."cn: $location\n";
+  
+            /* Create ldap entry to append 
+             */
+            $d = array();
+            $d['cn'] = $location;
+            $d['objectClass'] = array("gotoSubmenuEntry");
+            if(!empty($tag)){
+              $d['objectClass'][] = "gosaAdministrativeUnitTag";
+              $d['gosaUnitTag']   = $tag;
+            }
+            $data['ADD'][$location_dn.$release_dn] = $d;
+          }
+
+
+          /* Append missing menu entry for "What is done info".
+           */
+          if(!empty($name)){
+            $after .= "\n";
+            $after .= $s_add."dn: cn=$name,$location_dn$release_dn\n";
+            $after .= $s_add."objectClass: gotoMenuEntry\n";
+            if($tag != ""){
+              $after   .=  $s_add."objectClass: gosaAdministrativeUnitTag\n";
+              $after   .=  $s_add."gosaUnitTag: $tag\n";
+            }
+            $after .= $s_add."cn: $name\n";
+            $after .= $s_add."gosaApplicationPriority: $priority\n";
+
+            /* Create ldap entry 
+             */
+            $d= array();
+            $d['objectClass'] = array("gotoMenuEntry");
+            if(!empty($tag)){
+              $d['objectClass'][] = "gosaAdministrativeUnitTag";
+              $d['gosaUnitTag']   = $tag;
+            }
+            $d['cn']          = $name;
+            $d['gosaApplicationPriority'] = $priority;
+
+            foreach ($amap[$name] as $n){
+              if (isset($params[$n])){
+                $after .= $s_add."gosaApplicationParameter: ".$params[$n]."\n";
+                $d['gosaApplicationParameter'][] = $params[$n];
+              }
+            }
+            $data['ADD']["cn=$name,$location_dn$release_dn"] = $d;
+          }         
+        }
+      }
+
+      /* Updated todo list 
+       */ 
+      $todo[] = array(
+          "DETAILS" => FALSE,
+          "DN"      => $info['dn'],
+          "AFTER"   => $after,
+          "CURRENT" => $current,
+          "TODO"    => $data
+          );
+    }
+
+    /* Remember checks.
+     */
+    $this->menu = $todo;
+
+    /* Check if we were able to query the ldap server
+     */
+    if(count($this->menu)){
+      $this->checks['old_style_menus']['STATUS']    = FALSE;
+      $this->checks['old_style_menus']['STATUS_MSG']= "<font style='color:#F0A500'>"._("Warning")."</font>";
+      $this->checks['old_style_menus']['ERROR_MSG'] = sprintf(_("There are %s application menus which have to be migrated."),
+                                                      count($this->menu))."<input type='submit' name='menu_dialog' value='"._("Migrate")."'>";
+    }else{
+      $this->checks['old_style_menus']['STATUS']    = TRUE;
+      $this->checks['old_style_menus']['STATUS_MSG']= _("Ok");
+      $this->checks['old_style_menus']['ERROR_MSG'] = "";
+    }
+  }
+
+  
+  /*! \brief  Handle posts for the menu_dialog 
+              Ensure that checked checkboxes stay checked.
+   */
+  function check_menu_posts()
+  {
+    foreach($this->menu as $key => $menu){
+      if(isset($_POST["migrate_".$key])){
+        $this->menu[$key]['DETAILS'] =TRUE;
+      }else{
+        $this->menu[$key]['DETAILS'] =FALSE;
+      }
+    }
+  }
+
+
+  /*! \brief  This function updates old-style application menus to
+               valid 2.6 application menus.
+              All selected menus will be converted (DETAILS = TRUE). 
+              The ldap actions collected by check_menus() will be executed. 
+   */
+  function migrate_menus()
+  {
+
+    /* Establish ldap connection
+     */
+    $cv = $this->parent->captured_values;
+    $ldap_l = new LDAP($cv['admin'],
+        $cv['password'],
+        $cv['connection'],
+        FALSE,
+        $cv['tls']);
+
+    $ldap = new ldapMultiplexer($ldap_l);
+    $ldap->cd($cv['base']);
+
+    /* Walk through menus and detect selected menu 
+     */
+    foreach($this->menu as $key => $menu){
+      if($menu['DETAILS']) {
+
+        /* Excute all LDAP-ADD actions 
+         */
+        $success = TRUE;
+        foreach($menu['TODO']['ADD'] as $dn => $data){
+          $ldap->cd($cv['base']);
+          if(!$ldap->dn_exists($dn)){
+            $ldap->cd($dn);
+            $ldap->add($data);
+            if (!$ldap->success()){
+              msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_ADD, get_class()));
+              $success = FALSE;
+            }
+          }
+        }
+
+        /* Execute all LDAP-MODIFY actions 
+         */
+        foreach($menu['TODO']['MODIFY'] as $dn => $data){
+          $ldap->cd($cv['base']);
+          if($ldap->dn_exists($dn)){
+            $ldap->cd($dn);
+            $ldap->modify($data);
+            if (!$ldap->success()){
+              msg_dialog::display(_("LDAP error"), msgPool::ldaperror($ldap->get_error(), $dn, LDAP_MOD, get_class()));
+              $success = FALSE;
+            }
+          }
+        }
+  
+        /* If every action was successful, remove this entry from the list 
+         */
+        if($success){
+          unset($this->menu[$key]);
+        }
+      }
+    }
+
+    /* Udpate migration status for application menus
+     */
+    $this->check_menus();
+  }
+
+
+  function migrate_selected_admin_users()
+  {
+    /* Updated ui selection */
+    $this->migrate_users();
+
+    /* Establish ldap connection */
+    $cv = $this->parent->captured_values;
+    $ldap_l = new LDAP($cv['admin'],
+        $cv['password'],
+        $cv['connection'],
+        FALSE,
+        $cv['tls']);
+
+    $ldap = new ldapMultiplexer($ldap_l);
+    $ldap->cd($cv['base']);
+
+    /* Get current ACL configuration for the ldap base 
+     */
+    $ldap->cat($cv['base']);
+    $base_attrs = $ldap->fetch();
+    $acl_entries= array();
+    $acl_id = -1;
+    if(isset($base_attrs['gosaAclEntry'])){
+      for($i=0; $i < $base_attrs['gosaAclEntry']['count']; $i ++){
+        $acl_entries[] = $base_attrs['gosaAclEntry'][$i];
+        $cur_id = preg_replace("/^([0-9]*):.*$/","\\1",$base_attrs['gosaAclEntry'][$i]);
+        if($cur_id > $acl_id){
+          $acl_id = $cur_id;
+        }
+      }
+    }
+
+    /* Append ACLs selected in the migrate admin account dialog 
+     */
+    foreach($this->migrate_users as $entry){
+      if($entry['checked']){
+        $acl_id ++;
+        $acl_entries[] = $acl_id.$entry['change'];
+      }
+    }
+   
+    /* Check if the required objectClasses are available 
+     */
+    $ocs = array();     
+    for($i=0;$i< $base_attrs['objectClass']['count']; $i++){
+      $ocs[] = $base_attrs['objectClass'][$i];
+    }
+    if(!in_array("gosaACL",$ocs)){
+      $ocs[] = "gosaACL";
+    }
+
+    /* Try to write changes 
+     */
+    if(count($acl_entries)){
+      $new_entry['gosaAclEntry'] = $acl_entries;
+      $new_entry['objectClass'] = $ocs;
+      $ldap->cd($cv['base']);
+      $ldap->modify($new_entry);
+      if(!$ldap->success()){
+        $this->checks['acls']['TITLE']     = _("Checking for super administrator");
+        $this->checks['acls']['STATUS']    = FALSE;
+        $this->checks['acls']['STATUS_MSG']= _("Failed");
+        $this->checks['acls']['ERROR_MSG'] = "<br>".msgPool::ldaperror($cv['base'],$ldap->get_error(),LDAP_MOD);
+      }else{
+        $this->check_administrativeAccount();
+      }     
+    }
+  }
+  
+
+  function migrate_users()
+  {
+    /* Collect a list of available GOsa users and groups 
+     */
+
+    /* Establish ldap connection */
+    $cv = $this->parent->captured_values;
+    $ldap_l = new LDAP($cv['admin'],
+        $cv['password'],
+        $cv['connection'],
+        FALSE,
+        $cv['tls']);
+
+    $ldap = new ldapMultiplexer($ldap_l);
+    $ldap->cd($cv['base']);
+
+    $users = array();
+    $ldap->search("(&(objectClass=gosaAccount)(objectClass=person)".
+        "(objectClass=inetOrgPerson)(objectClass=organizationalPerson))",array("uid","dn"));
+    while($user_attrs = $ldap->fetch()){
+      $users[$user_attrs['dn']] = $user_attrs['uid'][0];
+      $rusers[$user_attrs['uid'][0]] = $user_attrs['dn'];
+    }
+    $groups = array();
+    $ldap->search("objectClass=posixGroup",array("cn","dn"));
+    while($group_attrs = $ldap->fetch()){
+      $groups[$group_attrs['dn']] = $group_attrs['cn'][0];
+    }
+
+    foreach($this->migrate_users as $id => $data){
+      $this->migrate_users[$id]['checked'] = isset($_POST['migrate_admin_'.$id]);
+    }
+
+    /* Try to find an old GOsa 2.5 administrative account that may be migrated
+     */
+    if(!count($this->migrate_users)){
+      $ldap->cat($cv['base']);
+      $base_data = $ldap->fetch();
+      $base_entry = "dn: ".$base_data['dn']."\n";
+      for($i=0;$i<$base_data['objectClass']['count'];$i++){
+        $base_entry .= "objectClass: ".$base_data['objectClass'][$i]."\n";
+      }
+      if(!in_array("gosaACL",$base_data['objectClass'])){
+        $base_entry .= "<b>objectClass: gosaACL</b>\n";
+      }
+      if(isset($base_data['gosaAclEntry'])){
+        for($i=0;$i<$base_data['gosaAclEntry']['count'];$i++){
+          $base_entry .= "gosaAclEntry: ".$base_data['gosaAclEntry'][$i]."\n";
+        }
+      }
+      $this->migrate_acl_base_entry = $base_entry;
+      $ldap->cd($cv['base']);
+      $ldap->search("(&(objectClass=posixGroup)(gosaSubtreeACL=:all)(memberUid=*))",array("memberUid","cn"));
+      while($p_group = $ldap->fetch()){
+        for($e = 0 ; $e < $p_group['memberUid']['count'] ; $e ++ ){
+          $user = $p_group['memberUid'][$e];
+          if(isset($rusers[$user])){
+            $bsp_acl_entry = "gosaAclEntry: #:psub:".base64_encode($rusers[$user]).":all;cmdrw\n";
+            $entry = array();
+            $entry['uid'] = $user; 
+            $entry['dn'] = $rusers[$user]; 
+            $entry['details'] = $bsp_acl_entry; 
+            $entry['checked'] = FALSE;
+            $entry['change'] = ":psub:".base64_encode($rusers[$user]).":all;cmdrw";
+            $this->migrate_users[] = $entry;
+          }
+        }
+      }
+    }
+  }
+}
 // vim:tabstop=2:expandtab:shiftwidth=2:filetype=php:syntax:ruler:
 ?>