config = $config; /* Check if the opsi plugin is installed. */ if(class_available("opsi")){ $this->opsi = new opsi($this->config);; } $this->fai_base = get_ou("faiBaseRDN").$this->config->current['BASE']; $this->fai_release = $this->fai_base; $this->acl_base = $this->config->current['BASE']; $this->ui = $ui; $this->storagePoints = array( get_ou('faiPartitionRDN'), get_ou('faiPackageRDN'), get_ou('faiScriptRDN'), get_ou('faiVariableRDN'), get_ou('faiHookRDN'), get_ou('faiProfileRDN'), get_ou('faiTemplateRDN')); // Build filter if (session::global_is_set(get_class($this)."_filter")){ $filter= session::global_get(get_class($this)."_filter"); } else { $filter = new filter(get_template_path("fai-filter.xml", true)); $filter->setObjectStorage($this->storagePoints); } $this->setFilter($filter); // Build headpage $headpage = new listing(get_template_path("fai-list.xml", true)); $headpage->setFilter($filter); $headpage->setBase($this->fai_release); $headpage->registerElementFilter("filterProperties", "faiManagement::filterProperties"); // Add copy&paste and snapshot handler. if ($this->config->boolValueIsTrue("main", "copyPaste")){ $this->cpHandler = new CopyPasteHandler($this->config); } $this->registerAction("remove_multiple","removeEntryRequested"); $this->registerAction("new_profile","newEntry"); $this->registerAction("new_template","newEntry"); $this->registerAction("new_script","newEntry"); $this->registerAction("new_hook","newEntry"); $this->registerAction("new_variable","newEntry"); $this->registerAction("new_package","newEntry"); $this->registerAction("new_partition","newEntry"); $this->registerAction("newClassNameSelected","newClassNameSelected"); $this->registerAction("saveOpsiProperties","saveOpsiProperties"); $this->registerAction("editByGroup","editByGroup"); $this->registerAction("createBranch","createBranch"); $this->registerAction("createFreeze","createFreeze"); $this->registerAction("removeBranch","removeBranch"); $this->registerAction("removeBranchConfirmed","removeBranchConfirmed"); $this->registerAction("saveBranch","saveBranch"); $this->registerAction("PerformBranch","PerformBranch"); parent::__construct($config, $ui, "roles", $headpage); } /*! \brief Act on copy & paste actions here. */ function copyPasteHandler($action="",$target=array(),$all=array(),$altTabClass ="",$altTabType="",$altAclCategory="",$altAclPlugin="") { // Collect real dns, the listed objects are grouped by their cn $headpage = $this->getHeadpage(); if($action == "copy"){ foreach($target as $t){ $entry = $headpage->getEntry($t); // Check for valid FAI objects if(in_array('FAKE_OC_FAI', $entry['objectClass'])){ foreach($entry['GROUPS'] as $g){ $type = $this->get_type($g); $this->cpHandler->add_to_queue($g['dn'],"copy",$type[0],$type[2],'fai',$this); @DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__,$dn,"Entry copied!"); } } } } // Initiate pasting if($action == "paste"){ $this->cpPastingStarted = TRUE; } // Display any c&p dialogs, eg. object modifications required before pasting. if($this->cpPastingStarted && $this->cpHandler->entries_queued()){ $this->cpHandler->SetVar("base",$headpage->getBase()); $data = $this->cpHandler->execute(); FAI::save_release_changes_now(); if(!empty($data)){ return($data); } } // Automatically disable pasting process since there is no entry left to paste. if(!$this->cpHandler->entries_queued()){ $this->cpPastingStarted = FALSE; } return(""); } /*! \brief A new FAI object was requested, let the user specify a name theis object now. */ function newEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="") { $types = array( "new_partition" => "FAIpartitionTable", "new_script" => "FAIscript", "new_hook" => "FAIhook", "new_variable" => "FAIvariable", "new_template" => "FAItemplate", "new_package" => "FAIpackageList"); $types_i18n = array( "new_partition" => _("partition table"), "new_script" => _("script"), "new_hook" => _("hook"), "new_variable" => _("variable"), "new_template" => _("template"), "new_package" => _("package list")); if(isset($types[$action])){ $type_acl_mapping = array( "FAIpartitionTable" => "faiPartitionTable", "FAIpackageList" => "faiPackage", "FAIscript" => "faiScript", "FAIvariable" => "faiVariable", "FAIhook" => "faiHook", "FAIprofile" => "faiProfile", "FAItemplate" => "faiTemplate"); $acl = $this->ui->get_permissions($this->acl_base,"fai/".$type_acl_mapping[$types[$action]]); if(preg_match("/c/",$acl)){ $this->dialogObject = new askClassName($this->config,$this->dn,$this->ui,$types[$action]); $this->dialogObject->parent = &$this; }else{ msg_dialog::display(_("Permission error"), sprintf(_("You have no permission to create a new %s!"), $types_i18n[$action]), ERROR_DIALOG); } } if($action == "new_profile"){ $this->dn = "new" ; $acl = $this->ui->get_permissions($this->acl_base,"fai/faiProfile"); if(preg_match("/c/",$acl)){ $type= $this->get_type(array("objectClass"=>array("FAIprofile"))); $str= management::newEntry('newEntry',array(),array(),$type[0],$type[2],$type[1]); if($str) return($str); $this->tabObject->set_acl_base($this->acl_base); $this->tabObject->by_object[$type[1]]->cn = $name; }else{ msg_dialog::display(_("Permission error"), sprintf(_("You have no permission to create a new %s!"), _("profile")), ERROR_DIALOG); } } } /*! \brief A new FAI class was requested and the user had a specify a name for it. * Here we check if this name is useable and then open the edit dialogs. */ function newClassNameSelected() { $this->dialogObject->save_object(); if(count($this->dialogObject->check())!=0){ foreach($this->dialogObject->check() as $msg){ msg_dialog::display(_("Error"), $msg, ERROR_DIALOG); } }elseif(isset($this->dialogObject->objectClass)){ $this->dn = "new" ; $type= $this->get_type(array("objectClass"=>array($this->dialogObject->objectClass))); $name = $this->dialogObject->save(); if(class_exists($type[0])){ $this->closeDialogs(); $str = management::newEntry('newEntry',array(),array(),$type[0],$type[2],$type[1]); if($str) return($str); $this->tabObject->set_acl_base($this->acl_base); $this->tabObject->by_object[$type[1]]->cn = $name; } } } /*! \brief Edit the selected entry. * If there was a FAI group clicked, display a dialog with all members of the group. */ function editEntry($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="") { $headpage = $this->getHeadpage(); if(count($target) == 1){ $entry = $headpage->getEntry($target[0]); if($entry){ // Edit Opsi objects here if(in_array("opsi_local", $entry['TYPES']) || in_array("opsi_netboot", $entry['TYPES'])){ $name = $entry['cn']; $cfg = $this->opsi->get_product_properties($name); $str = management::editEntry('editEntry',array($name),array(),'tabs_opsiProdConfig','OPSIPRODCONFIG','opsi'); if($str) return($str); if(isset($this->tabObject->by_object['opsiProperties'])){ $this->tabObject->by_object['opsiProperties']->set_cfg($cfg); $this->tabObject->by_object['opsiProperties']->set_product($name); $this->skipFooter = TRUE; }else{ trigger_error("Unknown tab, please check config."); } }else{ // Edit FAI objects here if(count($entry['GROUPS']) == 1){ $data = array_pop($entry['GROUPS']); $type = $this->get_type($data); $str = management::editEntry('editEntry',array($data['dn']),array(),$type[0],$type[2],$type[1]); if($str) return($str); $this->tabObject->by_object[$type[1]]->FAIstate = $data['FAIstate']; $this->tabObject->read_only = preg_match("/freeze/i", $data['FAIstate']); }else{ $this->dialogObject = new faiGroupHandle($entry['GROUPS'],"edit"); } } } } } /*! \brief Save changes made in opsi dialogs. */ function saveOpsiProperties() { if($this->tabObject instanceof tabs_opsiProdConfig && isset($_POST['save_properties'])){ $this->tabObject->save_object(); $op = $this->tabObject->by_object['opsiProperties']; $name = $op->get_product(); $cfg = $op->get_cfg(); $this->opsi->set_product_properties($name,$cfg); if($this->opsi->is_error()){ msg_dialog::display(_("Error"),msgPool::siError($this->opsi->get_error()),ERROR_DIALOG); }else{ $this->remove_lock(); $this->closeDialogs(); } } } /*! \brief Someone wants to remove some object(s) * ask for a confirmation now. */ function removeEntryRequested($action="",$target=array(),$all=array(), $altTabClass ="", $altTabType = "", $altAclCategory="") { $this->closeDialogs(); if($action == "remove_multiple"){ // Collect objects to delete $headpage = $this->getHeadpage(); $to_delete = array(); foreach($target as $id){ $object = $headpage->getEntry($id); if(in_array("FAKE_OC_FAI", $object['objectClass'])){ foreach($object['GROUPS'] as $entry){ array_push($to_delete, $entry); } } } return($this->removeFAIObjects($to_delete)); }else{ // Try to remove a single object, only FAI objects can be removed! $headpage = $this->getHeadpage(); if(count($target) == 1){ $entry = $headpage->getEntry($target[0]); if($entry && in_array("FAKE_OC_FAI",$entry['objectClass'])){ $this->dialogObject = new faiGroupHandle($entry['GROUPS'],"remove"); } } } } /*! \brief Someone wants to remove some object(s) * ask for a confirmation now. */ function removeFAIObjects($to_delete) { // Do not allow to remove objects with state freeezed $errors=array(); foreach($to_delete as $obj){ if(isset($obj['FAIstate']) && preg_match('/^freeze/', $obj['FAIstate'])){ $errors[] = $obj['dn']; }else{ $this->dns[] = $obj['dn']; } } if(count($errors)){ msg_dialog::display(_("Branch locked"), sprintf(_("The following entries are locked, you can't remove them %s."),msgPool::buildList($errors)),INFO_DIALOG); } // Check entry locking if(count($this->dns)){ if ($user= get_multiple_locks($this->dns)){ return(gen_locked_message($user,$this->dns)); } if(count($this->dns)){ $smarty = get_smarty(); $dns_names = array(); foreach($this->dns as $dn){ add_lock ($dn, $this->ui->dn); $dns_names[] = LDAP::fix($dn); } $smarty->assign("info",msgPool::deleteInfo($dns_names,_("FAI object"))); $smarty->assign("multiple", true); return($smarty->fetch(get_template_path('remove.tpl', TRUE))); } } } /*! \brief Entry removal is confirmed, now remove objects */ function removeEntryConfirmed($action="",$target=array(),$all=array(), $altTabClass="",$altTabType="",$altAclCategory="") { $ldap = $this->config->get_ldap_link(); $ldap->cd($this->config->current['BASE']); foreach($this->dns as $key => $dn){ $ldap->cat($dn); if($ldap->count()){ $attrs = $ldap->fetch(); $type= $this->get_type($attrs); $str = management::removeEntryConfirmed($action,array($dn),$all,$type[0],$type[2],$type[1]); if($str) return($str); // Now save changes FAI::save_release_changes_now(); $to_del = FAI::clean_up_releases($dn); foreach($to_del as $dn){ $ldap->rmdir_recursive($dn); } } } } /*! \brief Someone clicked on edit/remove for a grouped FAI object. * We are now going to display a dialog to let the user select the entry * he wants to perform the action on. */ function editByGroup() { if($this->dialogObject instanceOf faiGroupHandle && $this->dialogObject->get_mode() == "edit"){ $this->dialogObject->save_object(); $entry = $this->dialogObject->get_selected(); $this->closeDialogs(); $data = array_pop($entry); $type = $this->get_type($data); $str = management::editEntry('editEntry',array($data['dn']),array(),$type[0],$type[2],$type[1]); if($str) return($str); $this->tabObject->by_object[$type[1]]->FAIstate = $data['FAIstate']; $this->tabObject->read_only = preg_match("/freeze/i", $data['FAIstate']); }elseif($this->dialogObject instanceOf faiGroupHandle && $this->dialogObject->get_mode() == "remove"){ $this->dialogObject->save_object(); $to_delete = $entry = $this->dialogObject->get_selected(); return($this->removeFAIObjects($to_delete)); } } /*! \brief Save dialog/object modifications */ protected function saveChanges() { $str = management::saveChanges(); if($str) return($str); // Now save changes FAI::save_release_changes_now(); $to_del = FAI::clean_up_releases($this->last_dn); foreach($to_del as $dn){ $ldap->rmdir_recursive($dn); } } /*! \brief Save dialog/object modifications but keep the dialogs opened */ protected function applyChanges() { $str = management::applyChanges(); if($str) return($str); // Now save changes FAI::save_release_changes_now(); $to_del = FAI::clean_up_releases($this->last_dn); foreach($to_del as $dn){ $ldap->rmdir_recursive($dn); } } /*! \brief Initiates release removal */ function removeBranch() { /* Check if we have a post remove method configured * else skip this operation. (Skip:Button in the ui should be disabled in this case too) */ if("" != $this->config->search("faiManagement", "POSTREMOVE",array('menu','tabs'))){ /* Load permissions for selected 'dn' and check if we're allowed to remove this 'dn' */ if(preg_match("/d/",$this->ui->get_permissions($this->acl_base,"fai/faiManagement"))){ $smarty=get_smarty(); $smarty->assign("release_hidden",base64_encode($this->fai_release)); $smarty->assign("info", msgPool::deleteInfo(LDAP::fix($this->fai_release),_("FAI branch/freeze"))); return($smarty->fetch(get_template_path('remove_branch.tpl',TRUE))); } else { msg_dialog::display(_("Permission error"), _("You have no permission to delete this release!"), ERROR_DIALOG); } } } /*! \brief Remove a release after removal was confirmed */ function removeBranchConfirmed() { /* Check if we have a post remove method configured * else skip this operation. (Skip:Button in the ui should be disabled in this case too) */ if("" != $this->config->search("faiManagement", "POSTREMOVE",array('menu','tabs'))){ if(!isset($_POST['release_hidden']) || base64_decode($_POST['release_hidden']) != $this->fai_release){ msg_dialog::display(_("Warning"),_("Release remove aborted because the release name check failed!")); }else{ $bb = $this->fai_release; $ldap = $this->config->get_ldap_link(); $br = $this->getBranches(); if(isset($br[$bb]) && preg_match("/d/",$this->ui->get_permissions($this->acl_base,"fai/faiManagement"))){ $name = $br[$bb]; $ldap->cd($bb); $ldap->recursive_remove(); $ldap->cd(preg_replace('/,'.preg_quote(get_ou('faiBaseRDN'), '/').'/i', ','.get_ou('applicationRDN'), $bb)); $ldap->recursive_remove(); $ldap->cd(preg_replace('/,'.preg_quote(get_ou('faiBaseRDN'), '/').'/i', ','.get_ou('mimetypeRDN'), $bb)); $ldap->recursive_remove(); /* Search for all groups with configured application menus. - First search all groups, to ensure that we only remove entries form whithin groups. - The search für menu configuration for the specified release and collect all those dns. - Remove entries */ $release_ou = preg_replace("/".preg_quote(get_ou("faiBaseRDN"), '/').".*$/i","",$bb); $ldap->cd($this->config->current['BASE']); $ldap->search("(objectClass=posixGroup)",array("dn")); /* Collect all group dns */ $groups = array(); while($attrs = $ldap->fetch()){ $groups[] = $attrs['dn']; } /* Collect all group menu release dns that match the release we have removed */ $dns = array(); foreach($groups as $dn){ $ldap->cd($dn); $ldap->search("(objectClass=FAIbranch)",array("dn")); while($attrs = $ldap->fetch()){ if(preg_match("/^".preg_quote($release_ou, '/')."/",$attrs['dn'])){ $dns[] = $attrs['dn']; } } } /* Finally remove collected release dns */ foreach($dns as $dn){ $ldap->cd($dn); $ldap->recursive_remove(); } /* Post remove */ $this->fai_release = $this->fai_base; $this->lock_name = $name; $this->lock_dn = $bb; $this->postremove(); $fai_filter = session::get("fai_filter"); $fai_filter['fai_release'] = $this->fai_release; session::set("fai_filter",$fai_filter); new log("remove","fai/".get_class($this),$br[$bb],array(),"Release removed"); } } } } /*! \brief Initiates release creation */ function createBranch() { $smarty = get_smarty(); $this->dispNewBranch=true; $this->dispNewFreeze=false; $smarty->assign("iframe",false); if(isset($_POST['BranchName'])){ $smarty->assign("BranchName", $_POST['BranchName']); }else{ $smarty->assign("BranchName",""); } return($smarty->fetch(get_template_path('faiNewBranch.tpl', TRUE, dirname(__FILE__)))); } /*! \brief Initiates release creation */ function createFreeze() { $smarty = get_smarty(); $this->dispNewFreeze=true; $this->dispNewBranch=false; $smarty->assign("iframe",false); if(isset($_POST['BranchName'])){ $smarty->assign("BranchName", $_POST['BranchName']); }else{ $smarty->assign("BranchName",""); } return($smarty->fetch(get_template_path('faiNewBranch.tpl', TRUE, dirname(__FILE__)))); } /*! \brief Creates a new branch */ function PerformBranch() { if(!preg_match("/c/",$this->ui->get_permissions($this->acl_base,"fai/faiManagement"))){ msg_dialog::display(_("Permission error"), msgPool::permCreate(_("Branch")), ERROR_DIALOG); }else{ /* In order to see error messages we have to reset the error handler. Due to the exit(); */ restore_error_handler(); $this->dispNewBranch = false; $this->dispNewFreeze = false; $LASTPOST = session::get('LASTPOST'); $base = $LASTPOST['base']; $_POST = session::get('LASTPOST'); $name = $_POST['BranchName']; $type = $LASTPOST['type']; $ldap = $this->config->get_ldap_link(); $baseToUse = $base; if($this->fai_release != $this->fai_base){ $baseToUse = $this->fai_release; } /* Create new Release name to be able to set faidebianRelease for FAIpackageList */ $CurrentReleases = $this->getBranches(); $NewReleaseName = $name; if(isset($CurrentReleases[$this->fai_release])) { if($this->fai_release != $this->fai_base){ $NewReleaseName = $CurrentReleases[$this->fai_release]."/".$name; $NewReleaseName = preg_replace("#\/#","/",$NewReleaseName); }else{ $NewReleaseName = $name; } } $appsrc = preg_replace("/".preg_quote(get_ou('faiBaseRDN'), '/')."/i",get_ou('applicationRDN'),$baseToUse); $appdst = preg_replace("/".preg_quote(get_ou('faiBaseRDN'), '/')."/i",get_ou('applicationRDN'),"ou=".$name.",".$baseToUse) ; $mimesrc = preg_replace("/".preg_quote(get_ou('faiBaseRDN'), '/')."/i",get_ou('mimetypeRDN'),$baseToUse); $mimedst = preg_replace("/".preg_quote(get_ou('faiBaseRDN'), '/')."/i",get_ou('mimetypeRDN'),"ou=".$name.",".$baseToUse) ; /* Check if source depeartments exist */ foreach(array($baseToUse,$appsrc,$mimesrc) as $dep){ $ldap->cd($this->config->current['BASE']); $ldap->cat($dep); if(!$ldap->count()){ $ldap->create_missing_trees($dep); } } /* Print header to have styles included */ echo '