Code

Moved property editor
authorhickert <hickert@594d385d-05f5-0310-b6e9-bd551577e9d8>
Tue, 18 May 2010 09:47:45 +0000 (09:47 +0000)
committerhickert <hickert@594d385d-05f5-0310-b6e9-bd551577e9d8>
Tue, 18 May 2010 09:47:45 +0000 (09:47 +0000)
git-svn-id: https://oss.gonicus.de/repositories/gosa/trunk@18529 594d385d-05f5-0310-b6e9-bd551577e9d8

20 files changed:
gosa-core/plugins/addons/configViewer/class_commandVerifier.inc [deleted file]
gosa-core/plugins/addons/configViewer/class_configViewer.inc [deleted file]
gosa-core/plugins/addons/configViewer/class_filterProperties.inc [deleted file]
gosa-core/plugins/addons/configViewer/commandVerifier.tpl [deleted file]
gosa-core/plugins/addons/configViewer/main.inc [deleted file]
gosa-core/plugins/addons/configViewer/migrate.tpl [deleted file]
gosa-core/plugins/addons/configViewer/migration/class_migrateRDN.inc [deleted file]
gosa-core/plugins/addons/configViewer/property-filter.xml [deleted file]
gosa-core/plugins/addons/configViewer/property-list.tpl [deleted file]
gosa-core/plugins/addons/configViewer/property-list.xml [deleted file]
gosa-core/plugins/addons/propertyEditor/class_commandVerifier.inc [new file with mode: 0644]
gosa-core/plugins/addons/propertyEditor/class_configViewer.inc [new file with mode: 0644]
gosa-core/plugins/addons/propertyEditor/class_filterProperties.inc [new file with mode: 0644]
gosa-core/plugins/addons/propertyEditor/commandVerifier.tpl [new file with mode: 0644]
gosa-core/plugins/addons/propertyEditor/main.inc [new file with mode: 0644]
gosa-core/plugins/addons/propertyEditor/migrate.tpl [new file with mode: 0644]
gosa-core/plugins/addons/propertyEditor/migration/class_migrateRDN.inc [new file with mode: 0644]
gosa-core/plugins/addons/propertyEditor/property-filter.xml [new file with mode: 0644]
gosa-core/plugins/addons/propertyEditor/property-list.tpl [new file with mode: 0644]
gosa-core/plugins/addons/propertyEditor/property-list.xml [new file with mode: 0644]

diff --git a/gosa-core/plugins/addons/configViewer/class_commandVerifier.inc b/gosa-core/plugins/addons/configViewer/class_commandVerifier.inc
deleted file mode 100644 (file)
index 3ddcd86..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-class commandVerifier
-{
-    private $property = NULL;
-    private $config = NULL;
-    private $command = "";
-
-    function __construct($config, $property)
-    {
-        $this->config = &$config;
-        $this->property = &$property;
-        $this->command  = $this->property->getValue(TRUE);
-    }
-
-    function execute()
-    {
-        $smarty = get_smarty();      
-        $output= "";
-
-        if(isset($_POST['execute'])){
-
-
-            $descriptorSpec = array(0 => array("pipe", "r"),
-                    1 => array('pipe', 'w'),
-                    2 => array('pipe', 'w'));
-            $process = proc_open($this->command, $descriptorSpec, $pipes);
-            $txOff = 0; $txLen = strlen($stdin);
-
-            $stdout = ''; $stdoutDone = FALSE;
-            $stderr = ''; $stderrDone = FALSE;
-            stream_set_blocking($pipes[0], 0); // Make stdin/stdout/stderr non-blocking
-            stream_set_blocking($pipes[1], 0);
-            stream_set_blocking($pipes[2], 0);
-            if ($txLen == 0) fclose($pipes[0]);
-            while (TRUE) {
-                $rx = array(); // The program's stdout/stderr
-                if (!$stdoutDone) $rx[] = $pipes[1];
-                if (!$stderrDone) $rx[] = $pipes[2];
-                foreach ($rx as $r) {
-                    if ($r == $pipes[1]) {
-                        $stdout .= fread($pipes[1], 8192);
-                        if (feof($pipes[1])) { fclose($pipes[1]); $stdoutDone = TRUE; }
-                    } else if ($r == $pipes[2]) {
-                        $stderr .= fread($pipes[2], 8192);
-                        if (feof($pipes[2])) { fclose($pipes[2]); $stderrDone = TRUE; }
-                    }
-                }
-                if (!is_resource($process)) break;
-                if ($txOff >= $txLen && $stdoutDone && $stderrDone) break;
-            }
-            $code = proc_close($process);
-
-            if(!empty($stdout)) $stdout = "<pre>".htmlentities($stdout,ENT_COMPAT,'UTF-8')."</pre>";
-            if(!empty($stderr)) $stderr = "<pre>".htmlentities($stderr,ENT_COMPAT,'UTF-8')."</pre>";
-            $output = "
-                <table summary='"._("Results")."'>
-                <tr><td><b>Result:</b></td><td>$stdout</td></tr>
-                <tr><td><b>Error:</b></td><td>$stderr</td></tr>
-                <tr><td><b>Return code:</b></td><td>$code</td></tr>
-                </table>";
-        }
-        $smarty->assign('value', htmlentities($this->command,ENT_COMPAT,'UTF-8'));
-        $smarty->assign('output', $output);
-        return($smarty->fetch(get_template_path('commandVerifier.tpl', 'TRUE')));
-    }
-
-    function save_object()
-    {
-        if(isset($_POST['command'])) $this->command = get_post('command');
-    }
-
-    function save()
-    {
-        $this->property->setValue($this->command);
-    }
-}
-?>
diff --git a/gosa-core/plugins/addons/configViewer/class_configViewer.inc b/gosa-core/plugins/addons/configViewer/class_configViewer.inc
deleted file mode 100644 (file)
index 1af7547..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-<?php
-
-
-class propertyEditor extends management
-{
-    var $plHeadline= "Preferences";
-    var $plDescription= "Configure global and special GOsa settings like hooks and plugin parameters";
-    var $plIcon  = "plugins/propertyEditor/images/plugin.png";
-
-    var $toBeMigrated = array();
-
-    function __construct($config,$ui)
-    {
-        $this->config = $config;
-        $this->ui = $ui;
-
-        // 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("property-filter.xml", true));
-            $filter->setObjectStorage($this->storagePoints);
-        }
-        $this->setFilter($filter);
-
-        // Build headpage
-        $headpage = new listing(get_template_path("property-list.xml", true));
-        $headpage->registerElementFilter("propertyName", "propertyEditor::propertyName");
-        $headpage->registerElementFilter("propertyGroup", "propertyEditor::propertyGroup");
-        $headpage->registerElementFilter("propertyClass", "propertyEditor::propertyClass");
-        $headpage->registerElementFilter("propertyValue", "propertyEditor::propertyValue");
-        $headpage->setFilter($filter);
-        parent::__construct($config, $ui, "property", $headpage);
-
-        $this->registerAction("saveProperties","saveProperties");
-        $this->registerAction("cancelProperties","cancelProperties");
-    }
-
-
-    function execute()
-    {
-        // Walk trough all properties and check if there posts for us.
-        $all = $this->config->configRegistry->getAllProperties();
-        foreach($all as $prop){
-            $post = "{$prop->getClass()}:{$prop->getName()}";
-            if(isset($_POST[$post]) && $prop->getStatus() != 'removed'){
-                $prop->setValue(get_post($post));
-            }
-
-            // Open the command verify dialog
-            if(isset($_POST["testCommand_{$post}"])){
-                $this->dialogObject = new commandVerifier($this->config,$prop);
-            }
-        }
-        if(isset($_POST['commandVerifier_save'])){
-            $this->dialogObject->save();
-            $this->closeDialogs();
-        }
-        if(isset($_POST['commandVerifier_cancel'])){
-            $this->closeDialogs();
-        }
-
-
-        // Execute registered management event listeners.
-        $this->handleActions($this->detectPostActions());
-
-        // Handle properties that have to be migrated 
-        if(isset($_POST['propertyMigrate_cancel']) && count($this->toBeMigrated)){
-            unset($this->toBeMigrated[0]);
-            $this->toBeMigrated = array_values($this->toBeMigrated);
-        }
-        if(isset($_POST['propertyMigrate_save']) && count($this->toBeMigrated)){
-            $first = $this->toBeMigrated[0]->getMigrationClass();
-            $first->save_object();
-            $msgs = $first->check();
-            if(!count($msgs)){
-                $this->toBeMigrated[0]->save();
-                unset($this->toBeMigrated[0]);
-                $this->toBeMigrated = array_values($this->toBeMigrated);
-
-                // Nothing to migrate and everything is fine, reload the list now.
-                if(!count($this->toBeMigrated)){
-                    $this->config->configRegistry->reload($force=TRUE);
-                }
-            }
-        }
-        if(count($this->toBeMigrated)){
-            $first = $this->toBeMigrated[0]->getMigrationClass();
-            $first->save_object();
-    
-            // We've no problems with this property anymore.
-            while($first instanceOf propertyMigration && !$first->checkForIssues()){
-                $this->toBeMigrated[0]->save();
-                unset($this->toBeMigrated[0]);
-                $this->toBeMigrated = array_values($this->toBeMigrated);
-                if(count($this->toBeMigrated)){
-                    $first = $this->toBeMigrated[0]->getMigrationClass();
-                }else{
-                    $first = NULL;
-                    
-                    // Nothing to migrate and everything is fine, reload the list now.
-                    if(!count($this->toBeMigrated)){
-                        $this->config->configRegistry->reload($force=TRUE);
-                    }
-                }
-            }
-
-            if($first){
-                $content =  $first->execute();
-                $smarty = get_smarty();
-                $smarty->assign('content', $content);
-                $smarty->assign('leftSteps', count($this->toBeMigrated));
-                return($smarty->fetch(get_template_path('migrate.tpl',TRUE)));
-            }
-        }
-
-        return(management::execute());
-    }
-
-    function renderList()
-    {
-        // Walk trough all properties and check if we have modified something
-        $all = $this->config->configRegistry->getAllProperties();
-        foreach($all as $prop){
-            $modified = in_array($prop->getStatus(),array('modified','removed'));
-            if($modified) break;
-        }
-       
-        $smarty = get_smarty();
-        $smarty->assign('is_modified', $modified);
-        return(management::renderList());
-    }
-
-
-    function cancelProperties()
-    {
-        $this->config->configRegistry->reload($force=TRUE);
-    }
-
-    function saveProperties()
-    {
-        // Check if we've misconfigured properties and skip saving in this case.
-        $all = $this->config->configRegistry->getAllProperties();
-        $valid = TRUE;
-        foreach($all as $prop){
-            $valid &= $prop->check();
-        }
-
-        // Now save the properties.
-        if($valid){
-            $this->toBeMigrated = $this->config->configRegistry->saveChanges();
-
-            // Nothing to migrate and everything is fine, reload the list now.
-            if(!count($this->toBeMigrated)){
-                $this->config->configRegistry->reload($force=TRUE);
-            }
-        }
-    }
-
-    function detectPostActions()
-    {
-        $action = management::detectPostActions();
-        if(isset($_POST['saveProperties']))  $action['action'] = 'saveProperties';
-        if(isset($_POST['cancelProperties']))  $action['action'] = 'cancelProperties';
-        return($action);
-    }
-
-    protected function removeEntryRequested($action="",$target=array(),$all=array())
-    {
-        foreach($target as $dn){
-            list($class,$name) = preg_split("/:/", $dn);
-            if($this->config->configRegistry->propertyExists($class,$name)){
-                $prop = $this->config->configRegistry->getProperty($class,$name);
-                $prop->restoreDefault();
-            }
-        }
-    } 
-
-    static function propertyGroup($group, $description = array())
-    {
-        return($group[0]);
-    }
-    static function propertyClass($class, $description = array())
-    {
-        global $config;
-        if(isset($config->configRegistry->classToName[$class[0]])){
-            $class = $config->configRegistry->classToName[$class[0]];
-        }else{
-            $class = $class[0];
-        }
-        return($class);
-    }
-    static function propertyName($class,$cn, $description,$mandatory)
-    {
-        $id = "{$class[0]}_{$cn[0]}";
-
-        $title = _("No description");
-        if(isset($description[0])) $title = htmlentities($description[0],ENT_COMPAT, 'UTF-8');
-        $title = preg_replace("/\n/", "<br>", $title);
-        $tooltip = "<div id='tooltip_{$id}' class='tooltip' style='display:none'>".$title."</div>";
-
-        $must = ($mandatory[0]) ? "<span class='required'>*</span>" : "";
-
-        return($tooltip."<span title='tooltip_{$id}'>{$cn[0]}{$must}</span>");
-    }
-    static function propertyValue($class,$cn,$value,$type,$default,$defaults,$check,$mandatory)
-    {
-        $ssize  = "208px";
-        $isize  = "200px";
-        $name  = "{$class[0]}:{$cn[0]}";
-        $value = htmlentities($value[0],ENT_QUOTES      ,'UTF-8');
-
-        // Add slashes to keep escaped values escaped after passing them to smarty.
-        $value = addslashes($value);
-
-        switch($type[0]){
-            case 'bool':
-                $res = "<select size=1 name=\"{$name}\" style='width:{$ssize}'>";
-                $false = (preg_match('/true/i', $value)) ? '' : "selected";
-                $true  = (preg_match('/true/i', $value)) ? "selected" : '';
-                $res.= "<option {$false} value='false'>"._("FALSE")."</option>";
-                $res.= "<option {$true} value='true'>"._("TRUE")."</option>";
-                $res.= "</select>";
-            case 'switch':
-                if(!empty($defaults[0])){
-                    $data = call_user_func(preg_split("/::/", $defaults[0]), $class[0],$cn[0],$value, $type[0]);
-                    if(is_array($data)){
-                        $res = "<select size=1 name=\"{$name}\" style='width:{$ssize}'>";
-                        foreach($data as $oValue => $oDesc){
-                            if($oValue == $value){
-                                $res.="<option selected value=\"{$oValue}\">{$oDesc}</option>\n";
-                            }else{
-                                $res.="<option value=\"{$oValue}\">{$oDesc}</option>\n";
-                            }
-                        }
-                        $res.= "</select>";
-                    }
-                }
-                break;
-            case 'command':
-                $res = "<input style='width:{$isize}' type='text' value=\"{$value}\" name=\"{$name}\">";
-                $res.= image('images/lists/edit.png', "testCommand_{$name}", _("Test the given command."));
-                break;
-            case 'dn':
-            case 'rdn':
-            case 'uri':
-            case 'path':
-            case 'file':
-            case 'string':
-            case 'integer':
-                $res = "<input style='width:{$isize}' type='text' value=\"{$value}\" name=\"{$name}\">";
-                break;
-            default: echo $type[0].$name."  ";$res = ""; 
-        }
-       
-        // Check if it is a required value. 
-        if($mandatory[0] && empty($value)){
-           $res.= "<rowClass:entry-error/>";
-        }
-
-        // Color row in red if the check methods returns false.
-        if(!empty($check[0]) && !empty($value)){
-            $check = call_user_func(preg_split("/::/", $check[0]),$displayMessage=FALSE, $class[0], $cn[0], $value, $type[0]);
-            if(!$check){
-                $res.= "<rowClass:entry-error/>";
-            }
-        }
-
-        return($res);
-    }
-}
-?>
diff --git a/gosa-core/plugins/addons/configViewer/class_filterProperties.inc b/gosa-core/plugins/addons/configViewer/class_filterProperties.inc
deleted file mode 100644 (file)
index 4bb74f0..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-
-class filterCONFIGPROPERTIES {
-
-  static function query($base, $scope, $filter, $attributes, $category, $objectStorage= "")
-  {
-    global $config;
-    
-    $all = $config->configRegistry->getAllProperties();
-    $ret = array();
-    foreach($all as $property){
-
-        $entry = array();
-        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'cn', $property->getName());
-        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'objectClass', $property->getStatus());
-        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'status', $property->getStatus());
-        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'description', $property->getDescription());
-        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'value', $property->getValue($temporary = TRUE));
-        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'mandatory', $property->isMandatory());
-        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'default', $property->getDefault());
-        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'defaults', $property->getDefaults());
-        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'check', $property->getCheck());
-        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'class', $property->getClass());
-        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'type', $property->getType());
-        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'migrate', $property->getMigrate());
-        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'group', $property->getGroup());
-        $entry['dn'] = $property->getClass().":".$property->getName();
-
-        $found =TRUE;
-        if(!empty($filter)){
-            $tests = preg_split("/§/", $filter);
-            foreach($tests as $test){
-                list($name,$value) = preg_split("/=/",$test);
-                $value =preg_replace("/\*/",'',$value);
-                if(empty($value)) $value='.*';
-                if(!isset($entry[$name][0]) || !preg_match("/{$value}/",$entry[$name][0])){
-                    $found = false;
-                }
-            } 
-        }
-       if($found) $ret[] = $entry; 
-    }
-
-    return($ret);
-  }
-
-    static function fakeLdapResult($result,$name, $value){
-        if(!is_array($value)){
-            $value = array($value);
-        }
-        $value['count'] = count($value);
-        $result[] = $name;
-        $result[$name] = $value;
-        if(!isset($result['count'])){
-            $result['count'] =0;
-        }
-        $result['count'] ++;
-        return($result);
-    }
-
-  static function unifyResult($result)
-  {
-    $res=array();
-    foreach($result as $entry){
-      if(!isset($res[$entry['dn']])){
-        $res[$entry['dn']]=$entry;
-      }
-    }
-    return(array_values($res)); 
-  }
-}
-
-?>
diff --git a/gosa-core/plugins/addons/configViewer/commandVerifier.tpl b/gosa-core/plugins/addons/configViewer/commandVerifier.tpl
deleted file mode 100644 (file)
index 58f4b05..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<h3>{t}Command verifier{/t}</h3>
-<p>
- {t}Here you can execute commands in the way GOsa does and check the generated results or errors. This can be very usefull especially for the post events (postcreate, postmodify and postremove) due to the fact that these hook are executed silently.{/t}
-</p>
-
-<p>
- <b>
-  {t}Please be carefull here, all commands will really be executed on your machine and may break things!{/t}
- </b>
-</p>
-
-<hr>
-
-<p>
- {t}The command to check for{/t}
- <input type='text' name='command' value="{$value}" style='width: 600px;'>
- <button type='submit' name='execute'>{t}Test{/t}</button> 
-</p>
-
-{if $output}
- <hr>
- {$output}
-{/if}
-
-<hr>
-
-<div class="plugin-actions">
-    <button type='submit' name='commandVerifier_save'>{msgPool type='okButton'}</button>
-    <button type='submit' name='commandVerifier_cancel'>{msgPool type='cancelButton'}</button>
-</div>
diff --git a/gosa-core/plugins/addons/configViewer/main.inc b/gosa-core/plugins/addons/configViewer/main.inc
deleted file mode 100644 (file)
index c449889..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-/*
-  This code is part of GOsa (https://gosa.gonicus.de)
-  Copyright (C) 2003  Cajus Pollmeier
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-
-/* Remove locks created by this plugin
-*/
-if ($remove_lock){
-    if(session::is_set('propertyEditor')){
-        $config->configRegistry->reload($force=TRUE);
-    }
-}
-
-
-/* Remove this plugin from session
- */
-if ( $cleanup ){
-    if (session::is_set('propertyEditor')){
-    }
-    session::un_set('propertyEditor');
-}else{
-
-
-    /* Create logview object on demand */
-    if (!session::is_set('propertyEditor')){
-        session::set('propertyEditor',new propertyEditor($config, get_userinfo()));
-    }
-    $propertyEditor = session::get('propertyEditor');
-
-    /* Execute formular */
-    $display= $propertyEditor->execute ();
-
-    /* Store changes  in session */
-    session::set('propertyEditor',$propertyEditor);
-}
-?>
diff --git a/gosa-core/plugins/addons/configViewer/migrate.tpl b/gosa-core/plugins/addons/configViewer/migrate.tpl
deleted file mode 100644 (file)
index ad601ea..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<div id="mainlist">
- <div class="mainlist-header">
-  <p>{t}Property migration assistent{/t} - {t}Migration steps left{/t}: {$leftSteps}</p>
-  <div class="mainlist-nav">
-   <div style='width:100%; height: 400px; overflow: scroll; padding: 5px;'>
-
-   {$content}
-
-   </div>
-   <hr>
-   <div class="plugin-actions">
-    <button name='propertyMigrate_save'>{msgPool type='okButton'}</button>
-    <button name='propertyMigrate_cancel'>{msgPool type='cancelButton'}</button>
-   </div>
-  </div>
- </div>
-</div>
-
diff --git a/gosa-core/plugins/addons/configViewer/migration/class_migrateRDN.inc b/gosa-core/plugins/addons/configViewer/migration/class_migrateRDN.inc
deleted file mode 100644 (file)
index 46c7035..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-<?php
-
-
-
-class migrateRDN implements propertyMigration
-{
-    protected $property = NULL;
-    protected $config = NULL;
-    protected $found = array();
-    protected $filter ="";
-
-    // Additional suffixes or prefixes 
-    // e.g. for 'faiScriptRDN' (ou=scripts,) moving to new destination lets say 
-    //  to 'ou=FAIscripts,' would break stuff with having 'ou=fai,ou=systems,ou=config' 
-    // prepended.
-    // 
-    protected $suffix = ""; 
-    protected $prefix = ""; 
-
-    protected $title = "";
-    protected $description = "";
-
-
-    function __construct($config,$property)
-    {
-        $this->property = &$property;
-        $this->config = &$config;
-
-        //Set a dummy title and description
-        if(empty($this->title)){
-            $this->title = sprintf(_("GOsa migration of property '%s'"), $this->property->getName());
-        }
-        if(empty($this->description)){
-            $this->description = sprintf(_("GOsa has detected objects outside of the configured storage point (%s)."), $this->property->getValue(TRUE));
-        }
-    }   
-
-    function getChanges()
-    {
-        return($this->found);
-    }
-
-    function checkForIssues()
-    {
-        $this->found = array();
-        $ldap= $this->config->get_ldap_link();
-        $ldap->cd($this->config->current['BASE']);
-        $ldap2= $this->config->get_ldap_link();
-        $ldap2->cd($this->config->current['BASE']);
-
-        // Search for possible release deparments/containers - this enables us to
-        //  SKIP release based objects - we cannot move them right now.
-        $releases = array();
-        $ldap->search("objectClass=FAIbranch");
-        while($attrs = $ldap->fetch()){
-            $releases[$attrs['dn']] = $attrs['dn'];
-        }
-
-        // If the userRDN wasn't empty, then only search for users inside of the old userRDN.
-        $initialValue = $this->prefix.$this->property->getValue().$this->suffix;
-        $targetValue = $this->prefix.$this->property->getValue(TRUE).$this->suffix;
-
-        $dnMatch = "";
-        if(!empty($initialValue)){
-            foreach(preg_split("/,/", $initialValue) as $rdnPart){
-                if(empty($rdnPart)) continue;
-                list($namingAttrs, $container) = preg_split("/=/",$rdnPart,2);
-                $container = trim($container,', ');
-                $dnMatch.= "({$namingAttrs}:dn:={$container})";
-            }
-        }
-
-        // Search for users
-        $filter = sprintf($this->filter,$dnMatch);
-        $ldap->search($filter,array('dn'));
-        $found = FALSE;
-        while($attrs = $ldap->fetch()){
-            $dn = $attrs['dn'];
-            $dnTo = $dn;
-
-            // If there intially was no userDN given then just add the new userRDN to the user dns
-            //  and create the new container objects.
-            if(empty($initialValue)){
-                list($namingAttrs, $container) = preg_split("/=/",$targetValue,2);
-                list($name, $container) = preg_split("/,/",$dn,2);
-
-                // Ensure that we handle a valid gosaDepartment container.
-                while(!isset($this->config->idepartments[$container])){
-
-                    // This object is part of a FAI release - we better skip it here.
-                    if(isset($releases[$container])){
-                        break;
-                    }
-
-                    $container = preg_replace("/^[^,]*+,/","",$container);
-                }
-    
-                // We haven't found a valid gosaDepartment in this dn, so skip.
-                if(isset($this->config->idepartments[$container])){
-
-                    // Queue new containuer to be created.
-                    if(!preg_match("/^".preg_quote($targetValue,'/i')."/", $container)){
-                        $dnTo = $name.",".$targetValue.$container;
-                        if(!$ldap->dn_exists($targetValue.$container)){
-                            $this->found['add'][$targetValue.$container] = array(); 
-                        }
-                        if($dn != $dnTo){
-                            $this->found['move'][] = array('from' => $dn, 'to' => $dnTo);
-                            $found = TRUE;
-                        }
-                    }
-                }
-            }
-
-            // If there intially was a userDN given then replace it with the new one.
-            if(!empty($initialValue)){
-
-                list($name, $container) = preg_split("/,/",$dn,2);
-                if(preg_match("/^".preg_quote($initialValue,'/i')."/", $container)){
-                    $container = preg_replace("/^".preg_quote($initialValue,'/')."/",$targetValue,$container);
-
-                    // Ensure that we handle a valid gosaDepartment container.
-                    while(!isset($this->config->idepartments[$container])){
-
-                        // This object is part of a FAI release - we better skip it here.
-                        if(isset($releases[$container])){
-                            break;
-                        }
-
-                        $container = preg_replace("/^[^,]*+,/","",$container);
-                    }
-
-                    // We haven't found a valid gosaDepartment in this dn, so skip.
-                    if(isset($this->config->idepartments[$container])){
-
-
-                        $dnTo = $name.",".$targetValue.$container;
-                        if(!empty($targetValue) && !$ldap->dn_exists($targetValue.$container)){
-                            $this->found['add'][$targetValue.$container] = array(); 
-                        }
-                        if($dn != $dnTo){
-                            $this->found['move'][] = array('from' => $dn, 'to' => $dnTo);
-                            $found = TRUE;
-                        }
-                    }
-                }
-            }    
-        }
-        return($found);
-    }
-
-    function execute()
-    {
-        $str = "<h3>".$this->title."</h3>";
-        $str.= $this->description;
-        $str.= "<hr>";
-        if(count($this->found['add'])) {
-            $str.= "<br>"._("Objects that will be added");
-            $str.= "<ul>";
-            foreach($this->found['add'] as $dn => $attrs){
-                $str.= "<li>".$dn."</li>";
-            }
-            $str.= "</ul>";
-        }
-        if(count($this->found['move'])) {
-            $str.= "<br>"._("Objects that will be moved")."<br>";
-            $str.= "<ul style='list-style:none; padding: 15px;'>";
-            foreach($this->found['move'] as $id => $data){
-                $checked = (!isset($_POST["migrateNow".get_class($this)])) ? 'checked':'';
-                $str.= "<li>
-            
-                <span style='white-space:nowrap;'>
-                <input $checked type='checkbox' value='1' name='migrateEntry_{$id}'>";
-                $str.= sprintf(_("Moving object '%s' to '%s'"), $data['from'], $data['to'])."</span></li>";
-            }
-            $str.="</ul>";
-        }
-        $str.= "<button name='migrateNow".get_class($this)."'>"._("Migrate")."</button>";
-        return($str);
-    }
-   
-    function save_object()
-    {
-        if(isset($_POST["migrateNow".get_class($this)])){
-            $ldap = $this->config->get_ldap_link();
-            $ldap->cd($this->config->current['BASE']);
-
-            // Try to add the new container objects
-            foreach($this->found['add'] as $dn => $data){
-                $ldap->cd($this->config->current['BASE']);
-                $ldap->create_missing_trees(ldap::convert($dn));
-            }
-
-            // Now move the objects to the new traget
-            $tmp = new plugin($this->config,NULL);
-            foreach($this->found['move'] as $id => $data){
-                if(isset($_POST["migrateEntry_{$id}"])){
-                    $tmp->move($data['from'], $data['to']);
-                }
-            }
-            $this->checkForIssues();
-        }
-    } 
-
-    function check()
-    {
-        return(array());
-    }
-} 
-
-
-?>
diff --git a/gosa-core/plugins/addons/configViewer/property-filter.xml b/gosa-core/plugins/addons/configViewer/property-filter.xml
deleted file mode 100644 (file)
index 2a5687d..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<filterdef>
-
-  <definition>
-    <category>all</category>
-    <initial>true</initial>
-    <default>default</default>
-    <scope>one</scope>
-    <attribute>dummy</attribute>
-  </definition>
-
-  <search>
-    <tag>default</tag>
-    <label>Effective properties</label>
-    <query>
-      <backend>CONFIGPROPERTIES</backend>
-      <filter>status=(ldap|file|modified|removed)§cn=$</filter>
-    </query>
-    <autocomplete>
-      <attribute>status</attribute>
-      <frequency>0.5</frequency>
-      <characters>3</characters>
-    </autocomplete>
-  </search>
-
-  <search>
-    <tag>modified</tag>
-    <label>Modified properties</label>
-    <query>
-      <backend>CONFIGPROPERTIES</backend>
-      <filter>status=(modified|removed)§cn=$</filter>
-    </query>
-    <autocomplete>
-      <attribute>status</attribute>
-      <frequency>0.5</frequency>
-      <characters>3</characters>
-    </autocomplete>
-  </search>
-
-  <search>
-    <tag>all</tag>
-    <label>All properties</label>
-    <query>
-      <backend>CONFIGPROPERTIES</backend>
-      <filter>cn=$</filter>
-    </query>
-    <autocomplete>
-      <attribute>status</attribute>
-      <frequency>0.5</frequency>
-      <characters>3</characters>
-    </autocomplete>
-  </search>
-
-  <search>
-    <tag>ldap</tag>
-    <label>LDAP properties</label>
-    <query>
-      <backend>CONFIGPROPERTIES</backend>
-      <filter>status=(ldap|modified|removed)§cn=$</filter>
-    </query>
-    <autocomplete>
-      <attribute>status</attribute>
-      <frequency>0.5</frequency>
-      <characters>3</characters>
-    </autocomplete>
-  </search>
-
-  <search>
-    <tag>byGroup</tag>
-    <label>Search for property groups</label>
-    <query>
-      <backend>CONFIGPROPERTIES</backend>
-      <filter>group=$</filter>
-    </query>
-    <autocomplete>
-      <attribute>status</attribute>
-      <frequency>0.5</frequency>
-      <characters>3</characters>
-    </autocomplete>
-  </search>
-
-</filterdef>
diff --git a/gosa-core/plugins/addons/configViewer/property-list.tpl b/gosa-core/plugins/addons/configViewer/property-list.tpl
deleted file mode 100644 (file)
index 56368e1..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-<script language="javascript" src="include/tooltip.js" type="text/javascript"></script>
-
-<div id="mainlist">
-
-  <div class="mainlist-header">
-   <p>{$HEADLINE}&nbsp;{$SIZELIMIT}</p>
-   <div class="mainlist-nav">
-    <table summary="{$HEADLINE}">
-     <tr>
-      <td>{$RELOAD}</td>
-      <td class="left-border">{$ACTIONS}</td>
-      <td class="left-border">{$FILTER}</td>
-     </tr>
-    </table>
-   </div>
-  </div>
-  {$LIST}
-</div>
-
-<script type="text/javascript">
-  Event.observe(window,"load",function() {
-    $$("*").findAll(function(node){
-      return node.getAttribute('title');
-    }).each(function(node){
-        var test = node.title;
-      var t = new Tooltip(node,test);
-      t.options.delta_x = -150;
-      t.options.delta_y = -50;
-      node.removeAttribute("title");
-    });
-  });
-</script>
-
-{if !$is_modified}
-<input type="hidden" name="ignore">
-{/if}
-
-<div class="plugin-actions">
-    <button name='saveProperties'>{msgPool type='okButton'}</button>
-    <button name='cancelProperties'>{msgPool type='cancelButton'}</button>
-</div>
-
diff --git a/gosa-core/plugins/addons/configViewer/property-list.xml b/gosa-core/plugins/addons/configViewer/property-list.xml
deleted file mode 100644 (file)
index 0c861a0..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<list>
-  <definition>
-    <departmentBrowser>false</departmentBrowser>
-    <departmentRootVisible>false</departmentRootVisible>
-    <baseMode>false</baseMode>
-    <multiSelect>true</multiSelect>
-    <template>property-list.tpl</template>
-    <module>all</module>
-    <label>List of configuration settings</label>
-    <defaultSortColumn>1</defaultSortColumn>
-
-    <objectType>
-      <label>Property not used</label>
-      <objectClass>undefined</objectClass>
-      <category>all</category>
-      <class>all</class>
-      <image>images/lists/element.png</image>
-    </objectType>
-
-    <objectType>
-      <label>Property will be restored</label>
-      <objectClass>removed</objectClass>
-      <category>all</category>
-      <class>all</class>
-      <image>images/lists/trash.png</image>
-    </objectType>
-
-    <objectType>
-      <label>Modified property</label>
-      <objectClass>modified</objectClass>
-      <category>all</category>
-      <class>all</class>
-      <image>plugins/propertyEditor/images/ldap.png[new]</image>
-    </objectType>
-
-    <objectType>
-      <label>Property configured in ldap</label>
-      <objectClass>ldap</objectClass>
-      <category>all</category>
-      <class>all</class>
-      <image>plugins/propertyEditor/images/ldap.png</image>
-    </objectType>
-
-    <objectType>
-      <label>Property configured in config file</label>
-      <objectClass>file</objectClass>
-      <category>all</category>
-      <class>all</class>
-      <image>plugins/propertyEditor/images/file.png</image>
-    </objectType>
-
-  </definition>
-
-  <table>
-    <layout>|20px;c|||||60px;r|</layout>
-
-    <column>
-      <value>%{filter:objectType(dn,objectClass)}</value>
-    </column>
-
-    <column>
-      <label>Group</label>
-      <sortAttribute>group</sortAttribute>
-      <sortType>string</sortType>
-      <value>%{filter:propertyGroup(group,description)}</value>
-      <export>true</export>
-    </column>
-
-    <column>
-      <label>Class</label>
-      <sortAttribute>group</sortAttribute>
-      <sortType>string</sortType>
-      <value>%{filter:propertyClass(class,description)}</value>
-      <export>true</export>
-    </column>
-
-    <column>
-      <label>Name</label>
-      <sortAttribute>cn</sortAttribute>
-      <sortType>string</sortType>
-      <value>%{filter:propertyName(class,cn,description,mandatory)}</value>
-      <export>true</export>
-    </column>
-
-    <column>
-      <label>Value</label>
-      <sortAttribute>value</sortAttribute>
-      <sortType>string</sortType>
-      <value>%{filter:propertyValue(class,cn,value,type,default,defaults,check,mandatory)}</value>
-      <export>true</export>
-    </column>
-
-    <column>
-      <label>Actions</label>
-      <value>%{filter:actions(dn,row,objectClass)}</value>
-    </column>
-
-  </table>
-
-  <actionmenu>
-
-    <action>
-      <name>remove</name>
-      <type>entry</type>
-      <image>images/lists/trash.png</image>
-      <label>Remove</label>
-    </action>
-
-    <action>
-      <type>exporter</type>
-    </action>
-
-  </actionmenu>
-
-  <actiontriggers snapshot="false" copypaste="false">
-
-    <action>
-      <name>remove</name>
-      <type>entry</type>
-      <objectclass>ldap</objectclass>
-      <image>images/lists/trash.png</image>
-      <label>Restore to default</label>
-    </action>
-
-  </actiontriggers>
-
-</list>
diff --git a/gosa-core/plugins/addons/propertyEditor/class_commandVerifier.inc b/gosa-core/plugins/addons/propertyEditor/class_commandVerifier.inc
new file mode 100644 (file)
index 0000000..3ddcd86
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+class commandVerifier
+{
+    private $property = NULL;
+    private $config = NULL;
+    private $command = "";
+
+    function __construct($config, $property)
+    {
+        $this->config = &$config;
+        $this->property = &$property;
+        $this->command  = $this->property->getValue(TRUE);
+    }
+
+    function execute()
+    {
+        $smarty = get_smarty();      
+        $output= "";
+
+        if(isset($_POST['execute'])){
+
+
+            $descriptorSpec = array(0 => array("pipe", "r"),
+                    1 => array('pipe', 'w'),
+                    2 => array('pipe', 'w'));
+            $process = proc_open($this->command, $descriptorSpec, $pipes);
+            $txOff = 0; $txLen = strlen($stdin);
+
+            $stdout = ''; $stdoutDone = FALSE;
+            $stderr = ''; $stderrDone = FALSE;
+            stream_set_blocking($pipes[0], 0); // Make stdin/stdout/stderr non-blocking
+            stream_set_blocking($pipes[1], 0);
+            stream_set_blocking($pipes[2], 0);
+            if ($txLen == 0) fclose($pipes[0]);
+            while (TRUE) {
+                $rx = array(); // The program's stdout/stderr
+                if (!$stdoutDone) $rx[] = $pipes[1];
+                if (!$stderrDone) $rx[] = $pipes[2];
+                foreach ($rx as $r) {
+                    if ($r == $pipes[1]) {
+                        $stdout .= fread($pipes[1], 8192);
+                        if (feof($pipes[1])) { fclose($pipes[1]); $stdoutDone = TRUE; }
+                    } else if ($r == $pipes[2]) {
+                        $stderr .= fread($pipes[2], 8192);
+                        if (feof($pipes[2])) { fclose($pipes[2]); $stderrDone = TRUE; }
+                    }
+                }
+                if (!is_resource($process)) break;
+                if ($txOff >= $txLen && $stdoutDone && $stderrDone) break;
+            }
+            $code = proc_close($process);
+
+            if(!empty($stdout)) $stdout = "<pre>".htmlentities($stdout,ENT_COMPAT,'UTF-8')."</pre>";
+            if(!empty($stderr)) $stderr = "<pre>".htmlentities($stderr,ENT_COMPAT,'UTF-8')."</pre>";
+            $output = "
+                <table summary='"._("Results")."'>
+                <tr><td><b>Result:</b></td><td>$stdout</td></tr>
+                <tr><td><b>Error:</b></td><td>$stderr</td></tr>
+                <tr><td><b>Return code:</b></td><td>$code</td></tr>
+                </table>";
+        }
+        $smarty->assign('value', htmlentities($this->command,ENT_COMPAT,'UTF-8'));
+        $smarty->assign('output', $output);
+        return($smarty->fetch(get_template_path('commandVerifier.tpl', 'TRUE')));
+    }
+
+    function save_object()
+    {
+        if(isset($_POST['command'])) $this->command = get_post('command');
+    }
+
+    function save()
+    {
+        $this->property->setValue($this->command);
+    }
+}
+?>
diff --git a/gosa-core/plugins/addons/propertyEditor/class_configViewer.inc b/gosa-core/plugins/addons/propertyEditor/class_configViewer.inc
new file mode 100644 (file)
index 0000000..1af7547
--- /dev/null
@@ -0,0 +1,272 @@
+<?php
+
+
+class propertyEditor extends management
+{
+    var $plHeadline= "Preferences";
+    var $plDescription= "Configure global and special GOsa settings like hooks and plugin parameters";
+    var $plIcon  = "plugins/propertyEditor/images/plugin.png";
+
+    var $toBeMigrated = array();
+
+    function __construct($config,$ui)
+    {
+        $this->config = $config;
+        $this->ui = $ui;
+
+        // 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("property-filter.xml", true));
+            $filter->setObjectStorage($this->storagePoints);
+        }
+        $this->setFilter($filter);
+
+        // Build headpage
+        $headpage = new listing(get_template_path("property-list.xml", true));
+        $headpage->registerElementFilter("propertyName", "propertyEditor::propertyName");
+        $headpage->registerElementFilter("propertyGroup", "propertyEditor::propertyGroup");
+        $headpage->registerElementFilter("propertyClass", "propertyEditor::propertyClass");
+        $headpage->registerElementFilter("propertyValue", "propertyEditor::propertyValue");
+        $headpage->setFilter($filter);
+        parent::__construct($config, $ui, "property", $headpage);
+
+        $this->registerAction("saveProperties","saveProperties");
+        $this->registerAction("cancelProperties","cancelProperties");
+    }
+
+
+    function execute()
+    {
+        // Walk trough all properties and check if there posts for us.
+        $all = $this->config->configRegistry->getAllProperties();
+        foreach($all as $prop){
+            $post = "{$prop->getClass()}:{$prop->getName()}";
+            if(isset($_POST[$post]) && $prop->getStatus() != 'removed'){
+                $prop->setValue(get_post($post));
+            }
+
+            // Open the command verify dialog
+            if(isset($_POST["testCommand_{$post}"])){
+                $this->dialogObject = new commandVerifier($this->config,$prop);
+            }
+        }
+        if(isset($_POST['commandVerifier_save'])){
+            $this->dialogObject->save();
+            $this->closeDialogs();
+        }
+        if(isset($_POST['commandVerifier_cancel'])){
+            $this->closeDialogs();
+        }
+
+
+        // Execute registered management event listeners.
+        $this->handleActions($this->detectPostActions());
+
+        // Handle properties that have to be migrated 
+        if(isset($_POST['propertyMigrate_cancel']) && count($this->toBeMigrated)){
+            unset($this->toBeMigrated[0]);
+            $this->toBeMigrated = array_values($this->toBeMigrated);
+        }
+        if(isset($_POST['propertyMigrate_save']) && count($this->toBeMigrated)){
+            $first = $this->toBeMigrated[0]->getMigrationClass();
+            $first->save_object();
+            $msgs = $first->check();
+            if(!count($msgs)){
+                $this->toBeMigrated[0]->save();
+                unset($this->toBeMigrated[0]);
+                $this->toBeMigrated = array_values($this->toBeMigrated);
+
+                // Nothing to migrate and everything is fine, reload the list now.
+                if(!count($this->toBeMigrated)){
+                    $this->config->configRegistry->reload($force=TRUE);
+                }
+            }
+        }
+        if(count($this->toBeMigrated)){
+            $first = $this->toBeMigrated[0]->getMigrationClass();
+            $first->save_object();
+    
+            // We've no problems with this property anymore.
+            while($first instanceOf propertyMigration && !$first->checkForIssues()){
+                $this->toBeMigrated[0]->save();
+                unset($this->toBeMigrated[0]);
+                $this->toBeMigrated = array_values($this->toBeMigrated);
+                if(count($this->toBeMigrated)){
+                    $first = $this->toBeMigrated[0]->getMigrationClass();
+                }else{
+                    $first = NULL;
+                    
+                    // Nothing to migrate and everything is fine, reload the list now.
+                    if(!count($this->toBeMigrated)){
+                        $this->config->configRegistry->reload($force=TRUE);
+                    }
+                }
+            }
+
+            if($first){
+                $content =  $first->execute();
+                $smarty = get_smarty();
+                $smarty->assign('content', $content);
+                $smarty->assign('leftSteps', count($this->toBeMigrated));
+                return($smarty->fetch(get_template_path('migrate.tpl',TRUE)));
+            }
+        }
+
+        return(management::execute());
+    }
+
+    function renderList()
+    {
+        // Walk trough all properties and check if we have modified something
+        $all = $this->config->configRegistry->getAllProperties();
+        foreach($all as $prop){
+            $modified = in_array($prop->getStatus(),array('modified','removed'));
+            if($modified) break;
+        }
+       
+        $smarty = get_smarty();
+        $smarty->assign('is_modified', $modified);
+        return(management::renderList());
+    }
+
+
+    function cancelProperties()
+    {
+        $this->config->configRegistry->reload($force=TRUE);
+    }
+
+    function saveProperties()
+    {
+        // Check if we've misconfigured properties and skip saving in this case.
+        $all = $this->config->configRegistry->getAllProperties();
+        $valid = TRUE;
+        foreach($all as $prop){
+            $valid &= $prop->check();
+        }
+
+        // Now save the properties.
+        if($valid){
+            $this->toBeMigrated = $this->config->configRegistry->saveChanges();
+
+            // Nothing to migrate and everything is fine, reload the list now.
+            if(!count($this->toBeMigrated)){
+                $this->config->configRegistry->reload($force=TRUE);
+            }
+        }
+    }
+
+    function detectPostActions()
+    {
+        $action = management::detectPostActions();
+        if(isset($_POST['saveProperties']))  $action['action'] = 'saveProperties';
+        if(isset($_POST['cancelProperties']))  $action['action'] = 'cancelProperties';
+        return($action);
+    }
+
+    protected function removeEntryRequested($action="",$target=array(),$all=array())
+    {
+        foreach($target as $dn){
+            list($class,$name) = preg_split("/:/", $dn);
+            if($this->config->configRegistry->propertyExists($class,$name)){
+                $prop = $this->config->configRegistry->getProperty($class,$name);
+                $prop->restoreDefault();
+            }
+        }
+    } 
+
+    static function propertyGroup($group, $description = array())
+    {
+        return($group[0]);
+    }
+    static function propertyClass($class, $description = array())
+    {
+        global $config;
+        if(isset($config->configRegistry->classToName[$class[0]])){
+            $class = $config->configRegistry->classToName[$class[0]];
+        }else{
+            $class = $class[0];
+        }
+        return($class);
+    }
+    static function propertyName($class,$cn, $description,$mandatory)
+    {
+        $id = "{$class[0]}_{$cn[0]}";
+
+        $title = _("No description");
+        if(isset($description[0])) $title = htmlentities($description[0],ENT_COMPAT, 'UTF-8');
+        $title = preg_replace("/\n/", "<br>", $title);
+        $tooltip = "<div id='tooltip_{$id}' class='tooltip' style='display:none'>".$title."</div>";
+
+        $must = ($mandatory[0]) ? "<span class='required'>*</span>" : "";
+
+        return($tooltip."<span title='tooltip_{$id}'>{$cn[0]}{$must}</span>");
+    }
+    static function propertyValue($class,$cn,$value,$type,$default,$defaults,$check,$mandatory)
+    {
+        $ssize  = "208px";
+        $isize  = "200px";
+        $name  = "{$class[0]}:{$cn[0]}";
+        $value = htmlentities($value[0],ENT_QUOTES      ,'UTF-8');
+
+        // Add slashes to keep escaped values escaped after passing them to smarty.
+        $value = addslashes($value);
+
+        switch($type[0]){
+            case 'bool':
+                $res = "<select size=1 name=\"{$name}\" style='width:{$ssize}'>";
+                $false = (preg_match('/true/i', $value)) ? '' : "selected";
+                $true  = (preg_match('/true/i', $value)) ? "selected" : '';
+                $res.= "<option {$false} value='false'>"._("FALSE")."</option>";
+                $res.= "<option {$true} value='true'>"._("TRUE")."</option>";
+                $res.= "</select>";
+            case 'switch':
+                if(!empty($defaults[0])){
+                    $data = call_user_func(preg_split("/::/", $defaults[0]), $class[0],$cn[0],$value, $type[0]);
+                    if(is_array($data)){
+                        $res = "<select size=1 name=\"{$name}\" style='width:{$ssize}'>";
+                        foreach($data as $oValue => $oDesc){
+                            if($oValue == $value){
+                                $res.="<option selected value=\"{$oValue}\">{$oDesc}</option>\n";
+                            }else{
+                                $res.="<option value=\"{$oValue}\">{$oDesc}</option>\n";
+                            }
+                        }
+                        $res.= "</select>";
+                    }
+                }
+                break;
+            case 'command':
+                $res = "<input style='width:{$isize}' type='text' value=\"{$value}\" name=\"{$name}\">";
+                $res.= image('images/lists/edit.png', "testCommand_{$name}", _("Test the given command."));
+                break;
+            case 'dn':
+            case 'rdn':
+            case 'uri':
+            case 'path':
+            case 'file':
+            case 'string':
+            case 'integer':
+                $res = "<input style='width:{$isize}' type='text' value=\"{$value}\" name=\"{$name}\">";
+                break;
+            default: echo $type[0].$name."  ";$res = ""; 
+        }
+       
+        // Check if it is a required value. 
+        if($mandatory[0] && empty($value)){
+           $res.= "<rowClass:entry-error/>";
+        }
+
+        // Color row in red if the check methods returns false.
+        if(!empty($check[0]) && !empty($value)){
+            $check = call_user_func(preg_split("/::/", $check[0]),$displayMessage=FALSE, $class[0], $cn[0], $value, $type[0]);
+            if(!$check){
+                $res.= "<rowClass:entry-error/>";
+            }
+        }
+
+        return($res);
+    }
+}
+?>
diff --git a/gosa-core/plugins/addons/propertyEditor/class_filterProperties.inc b/gosa-core/plugins/addons/propertyEditor/class_filterProperties.inc
new file mode 100644 (file)
index 0000000..4bb74f0
--- /dev/null
@@ -0,0 +1,73 @@
+<?php
+
+class filterCONFIGPROPERTIES {
+
+  static function query($base, $scope, $filter, $attributes, $category, $objectStorage= "")
+  {
+    global $config;
+    
+    $all = $config->configRegistry->getAllProperties();
+    $ret = array();
+    foreach($all as $property){
+
+        $entry = array();
+        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'cn', $property->getName());
+        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'objectClass', $property->getStatus());
+        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'status', $property->getStatus());
+        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'description', $property->getDescription());
+        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'value', $property->getValue($temporary = TRUE));
+        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'mandatory', $property->isMandatory());
+        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'default', $property->getDefault());
+        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'defaults', $property->getDefaults());
+        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'check', $property->getCheck());
+        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'class', $property->getClass());
+        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'type', $property->getType());
+        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'migrate', $property->getMigrate());
+        $entry = filterCONFIGPROPERTIES::fakeLdapResult($entry, 'group', $property->getGroup());
+        $entry['dn'] = $property->getClass().":".$property->getName();
+
+        $found =TRUE;
+        if(!empty($filter)){
+            $tests = preg_split("/§/", $filter);
+            foreach($tests as $test){
+                list($name,$value) = preg_split("/=/",$test);
+                $value =preg_replace("/\*/",'',$value);
+                if(empty($value)) $value='.*';
+                if(!isset($entry[$name][0]) || !preg_match("/{$value}/",$entry[$name][0])){
+                    $found = false;
+                }
+            } 
+        }
+       if($found) $ret[] = $entry; 
+    }
+
+    return($ret);
+  }
+
+    static function fakeLdapResult($result,$name, $value){
+        if(!is_array($value)){
+            $value = array($value);
+        }
+        $value['count'] = count($value);
+        $result[] = $name;
+        $result[$name] = $value;
+        if(!isset($result['count'])){
+            $result['count'] =0;
+        }
+        $result['count'] ++;
+        return($result);
+    }
+
+  static function unifyResult($result)
+  {
+    $res=array();
+    foreach($result as $entry){
+      if(!isset($res[$entry['dn']])){
+        $res[$entry['dn']]=$entry;
+      }
+    }
+    return(array_values($res)); 
+  }
+}
+
+?>
diff --git a/gosa-core/plugins/addons/propertyEditor/commandVerifier.tpl b/gosa-core/plugins/addons/propertyEditor/commandVerifier.tpl
new file mode 100644 (file)
index 0000000..58f4b05
--- /dev/null
@@ -0,0 +1,30 @@
+<h3>{t}Command verifier{/t}</h3>
+<p>
+ {t}Here you can execute commands in the way GOsa does and check the generated results or errors. This can be very usefull especially for the post events (postcreate, postmodify and postremove) due to the fact that these hook are executed silently.{/t}
+</p>
+
+<p>
+ <b>
+  {t}Please be carefull here, all commands will really be executed on your machine and may break things!{/t}
+ </b>
+</p>
+
+<hr>
+
+<p>
+ {t}The command to check for{/t}
+ <input type='text' name='command' value="{$value}" style='width: 600px;'>
+ <button type='submit' name='execute'>{t}Test{/t}</button> 
+</p>
+
+{if $output}
+ <hr>
+ {$output}
+{/if}
+
+<hr>
+
+<div class="plugin-actions">
+    <button type='submit' name='commandVerifier_save'>{msgPool type='okButton'}</button>
+    <button type='submit' name='commandVerifier_cancel'>{msgPool type='cancelButton'}</button>
+</div>
diff --git a/gosa-core/plugins/addons/propertyEditor/main.inc b/gosa-core/plugins/addons/propertyEditor/main.inc
new file mode 100644 (file)
index 0000000..c449889
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+/*
+  This code is part of GOsa (https://gosa.gonicus.de)
+  Copyright (C) 2003  Cajus Pollmeier
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+/* Remove locks created by this plugin
+*/
+if ($remove_lock){
+    if(session::is_set('propertyEditor')){
+        $config->configRegistry->reload($force=TRUE);
+    }
+}
+
+
+/* Remove this plugin from session
+ */
+if ( $cleanup ){
+    if (session::is_set('propertyEditor')){
+    }
+    session::un_set('propertyEditor');
+}else{
+
+
+    /* Create logview object on demand */
+    if (!session::is_set('propertyEditor')){
+        session::set('propertyEditor',new propertyEditor($config, get_userinfo()));
+    }
+    $propertyEditor = session::get('propertyEditor');
+
+    /* Execute formular */
+    $display= $propertyEditor->execute ();
+
+    /* Store changes  in session */
+    session::set('propertyEditor',$propertyEditor);
+}
+?>
diff --git a/gosa-core/plugins/addons/propertyEditor/migrate.tpl b/gosa-core/plugins/addons/propertyEditor/migrate.tpl
new file mode 100644 (file)
index 0000000..ad601ea
--- /dev/null
@@ -0,0 +1,18 @@
+<div id="mainlist">
+ <div class="mainlist-header">
+  <p>{t}Property migration assistent{/t} - {t}Migration steps left{/t}: {$leftSteps}</p>
+  <div class="mainlist-nav">
+   <div style='width:100%; height: 400px; overflow: scroll; padding: 5px;'>
+
+   {$content}
+
+   </div>
+   <hr>
+   <div class="plugin-actions">
+    <button name='propertyMigrate_save'>{msgPool type='okButton'}</button>
+    <button name='propertyMigrate_cancel'>{msgPool type='cancelButton'}</button>
+   </div>
+  </div>
+ </div>
+</div>
+
diff --git a/gosa-core/plugins/addons/propertyEditor/migration/class_migrateRDN.inc b/gosa-core/plugins/addons/propertyEditor/migration/class_migrateRDN.inc
new file mode 100644 (file)
index 0000000..46c7035
--- /dev/null
@@ -0,0 +1,212 @@
+<?php
+
+
+
+class migrateRDN implements propertyMigration
+{
+    protected $property = NULL;
+    protected $config = NULL;
+    protected $found = array();
+    protected $filter ="";
+
+    // Additional suffixes or prefixes 
+    // e.g. for 'faiScriptRDN' (ou=scripts,) moving to new destination lets say 
+    //  to 'ou=FAIscripts,' would break stuff with having 'ou=fai,ou=systems,ou=config' 
+    // prepended.
+    // 
+    protected $suffix = ""; 
+    protected $prefix = ""; 
+
+    protected $title = "";
+    protected $description = "";
+
+
+    function __construct($config,$property)
+    {
+        $this->property = &$property;
+        $this->config = &$config;
+
+        //Set a dummy title and description
+        if(empty($this->title)){
+            $this->title = sprintf(_("GOsa migration of property '%s'"), $this->property->getName());
+        }
+        if(empty($this->description)){
+            $this->description = sprintf(_("GOsa has detected objects outside of the configured storage point (%s)."), $this->property->getValue(TRUE));
+        }
+    }   
+
+    function getChanges()
+    {
+        return($this->found);
+    }
+
+    function checkForIssues()
+    {
+        $this->found = array();
+        $ldap= $this->config->get_ldap_link();
+        $ldap->cd($this->config->current['BASE']);
+        $ldap2= $this->config->get_ldap_link();
+        $ldap2->cd($this->config->current['BASE']);
+
+        // Search for possible release deparments/containers - this enables us to
+        //  SKIP release based objects - we cannot move them right now.
+        $releases = array();
+        $ldap->search("objectClass=FAIbranch");
+        while($attrs = $ldap->fetch()){
+            $releases[$attrs['dn']] = $attrs['dn'];
+        }
+
+        // If the userRDN wasn't empty, then only search for users inside of the old userRDN.
+        $initialValue = $this->prefix.$this->property->getValue().$this->suffix;
+        $targetValue = $this->prefix.$this->property->getValue(TRUE).$this->suffix;
+
+        $dnMatch = "";
+        if(!empty($initialValue)){
+            foreach(preg_split("/,/", $initialValue) as $rdnPart){
+                if(empty($rdnPart)) continue;
+                list($namingAttrs, $container) = preg_split("/=/",$rdnPart,2);
+                $container = trim($container,', ');
+                $dnMatch.= "({$namingAttrs}:dn:={$container})";
+            }
+        }
+
+        // Search for users
+        $filter = sprintf($this->filter,$dnMatch);
+        $ldap->search($filter,array('dn'));
+        $found = FALSE;
+        while($attrs = $ldap->fetch()){
+            $dn = $attrs['dn'];
+            $dnTo = $dn;
+
+            // If there intially was no userDN given then just add the new userRDN to the user dns
+            //  and create the new container objects.
+            if(empty($initialValue)){
+                list($namingAttrs, $container) = preg_split("/=/",$targetValue,2);
+                list($name, $container) = preg_split("/,/",$dn,2);
+
+                // Ensure that we handle a valid gosaDepartment container.
+                while(!isset($this->config->idepartments[$container])){
+
+                    // This object is part of a FAI release - we better skip it here.
+                    if(isset($releases[$container])){
+                        break;
+                    }
+
+                    $container = preg_replace("/^[^,]*+,/","",$container);
+                }
+    
+                // We haven't found a valid gosaDepartment in this dn, so skip.
+                if(isset($this->config->idepartments[$container])){
+
+                    // Queue new containuer to be created.
+                    if(!preg_match("/^".preg_quote($targetValue,'/i')."/", $container)){
+                        $dnTo = $name.",".$targetValue.$container;
+                        if(!$ldap->dn_exists($targetValue.$container)){
+                            $this->found['add'][$targetValue.$container] = array(); 
+                        }
+                        if($dn != $dnTo){
+                            $this->found['move'][] = array('from' => $dn, 'to' => $dnTo);
+                            $found = TRUE;
+                        }
+                    }
+                }
+            }
+
+            // If there intially was a userDN given then replace it with the new one.
+            if(!empty($initialValue)){
+
+                list($name, $container) = preg_split("/,/",$dn,2);
+                if(preg_match("/^".preg_quote($initialValue,'/i')."/", $container)){
+                    $container = preg_replace("/^".preg_quote($initialValue,'/')."/",$targetValue,$container);
+
+                    // Ensure that we handle a valid gosaDepartment container.
+                    while(!isset($this->config->idepartments[$container])){
+
+                        // This object is part of a FAI release - we better skip it here.
+                        if(isset($releases[$container])){
+                            break;
+                        }
+
+                        $container = preg_replace("/^[^,]*+,/","",$container);
+                    }
+
+                    // We haven't found a valid gosaDepartment in this dn, so skip.
+                    if(isset($this->config->idepartments[$container])){
+
+
+                        $dnTo = $name.",".$targetValue.$container;
+                        if(!empty($targetValue) && !$ldap->dn_exists($targetValue.$container)){
+                            $this->found['add'][$targetValue.$container] = array(); 
+                        }
+                        if($dn != $dnTo){
+                            $this->found['move'][] = array('from' => $dn, 'to' => $dnTo);
+                            $found = TRUE;
+                        }
+                    }
+                }
+            }    
+        }
+        return($found);
+    }
+
+    function execute()
+    {
+        $str = "<h3>".$this->title."</h3>";
+        $str.= $this->description;
+        $str.= "<hr>";
+        if(count($this->found['add'])) {
+            $str.= "<br>"._("Objects that will be added");
+            $str.= "<ul>";
+            foreach($this->found['add'] as $dn => $attrs){
+                $str.= "<li>".$dn."</li>";
+            }
+            $str.= "</ul>";
+        }
+        if(count($this->found['move'])) {
+            $str.= "<br>"._("Objects that will be moved")."<br>";
+            $str.= "<ul style='list-style:none; padding: 15px;'>";
+            foreach($this->found['move'] as $id => $data){
+                $checked = (!isset($_POST["migrateNow".get_class($this)])) ? 'checked':'';
+                $str.= "<li>
+            
+                <span style='white-space:nowrap;'>
+                <input $checked type='checkbox' value='1' name='migrateEntry_{$id}'>";
+                $str.= sprintf(_("Moving object '%s' to '%s'"), $data['from'], $data['to'])."</span></li>";
+            }
+            $str.="</ul>";
+        }
+        $str.= "<button name='migrateNow".get_class($this)."'>"._("Migrate")."</button>";
+        return($str);
+    }
+   
+    function save_object()
+    {
+        if(isset($_POST["migrateNow".get_class($this)])){
+            $ldap = $this->config->get_ldap_link();
+            $ldap->cd($this->config->current['BASE']);
+
+            // Try to add the new container objects
+            foreach($this->found['add'] as $dn => $data){
+                $ldap->cd($this->config->current['BASE']);
+                $ldap->create_missing_trees(ldap::convert($dn));
+            }
+
+            // Now move the objects to the new traget
+            $tmp = new plugin($this->config,NULL);
+            foreach($this->found['move'] as $id => $data){
+                if(isset($_POST["migrateEntry_{$id}"])){
+                    $tmp->move($data['from'], $data['to']);
+                }
+            }
+            $this->checkForIssues();
+        }
+    } 
+
+    function check()
+    {
+        return(array());
+    }
+} 
+
+
+?>
diff --git a/gosa-core/plugins/addons/propertyEditor/property-filter.xml b/gosa-core/plugins/addons/propertyEditor/property-filter.xml
new file mode 100644 (file)
index 0000000..2a5687d
--- /dev/null
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<filterdef>
+
+  <definition>
+    <category>all</category>
+    <initial>true</initial>
+    <default>default</default>
+    <scope>one</scope>
+    <attribute>dummy</attribute>
+  </definition>
+
+  <search>
+    <tag>default</tag>
+    <label>Effective properties</label>
+    <query>
+      <backend>CONFIGPROPERTIES</backend>
+      <filter>status=(ldap|file|modified|removed)§cn=$</filter>
+    </query>
+    <autocomplete>
+      <attribute>status</attribute>
+      <frequency>0.5</frequency>
+      <characters>3</characters>
+    </autocomplete>
+  </search>
+
+  <search>
+    <tag>modified</tag>
+    <label>Modified properties</label>
+    <query>
+      <backend>CONFIGPROPERTIES</backend>
+      <filter>status=(modified|removed)§cn=$</filter>
+    </query>
+    <autocomplete>
+      <attribute>status</attribute>
+      <frequency>0.5</frequency>
+      <characters>3</characters>
+    </autocomplete>
+  </search>
+
+  <search>
+    <tag>all</tag>
+    <label>All properties</label>
+    <query>
+      <backend>CONFIGPROPERTIES</backend>
+      <filter>cn=$</filter>
+    </query>
+    <autocomplete>
+      <attribute>status</attribute>
+      <frequency>0.5</frequency>
+      <characters>3</characters>
+    </autocomplete>
+  </search>
+
+  <search>
+    <tag>ldap</tag>
+    <label>LDAP properties</label>
+    <query>
+      <backend>CONFIGPROPERTIES</backend>
+      <filter>status=(ldap|modified|removed)§cn=$</filter>
+    </query>
+    <autocomplete>
+      <attribute>status</attribute>
+      <frequency>0.5</frequency>
+      <characters>3</characters>
+    </autocomplete>
+  </search>
+
+  <search>
+    <tag>byGroup</tag>
+    <label>Search for property groups</label>
+    <query>
+      <backend>CONFIGPROPERTIES</backend>
+      <filter>group=$</filter>
+    </query>
+    <autocomplete>
+      <attribute>status</attribute>
+      <frequency>0.5</frequency>
+      <characters>3</characters>
+    </autocomplete>
+  </search>
+
+</filterdef>
diff --git a/gosa-core/plugins/addons/propertyEditor/property-list.tpl b/gosa-core/plugins/addons/propertyEditor/property-list.tpl
new file mode 100644 (file)
index 0000000..56368e1
--- /dev/null
@@ -0,0 +1,42 @@
+<script language="javascript" src="include/tooltip.js" type="text/javascript"></script>
+
+<div id="mainlist">
+
+  <div class="mainlist-header">
+   <p>{$HEADLINE}&nbsp;{$SIZELIMIT}</p>
+   <div class="mainlist-nav">
+    <table summary="{$HEADLINE}">
+     <tr>
+      <td>{$RELOAD}</td>
+      <td class="left-border">{$ACTIONS}</td>
+      <td class="left-border">{$FILTER}</td>
+     </tr>
+    </table>
+   </div>
+  </div>
+  {$LIST}
+</div>
+
+<script type="text/javascript">
+  Event.observe(window,"load",function() {
+    $$("*").findAll(function(node){
+      return node.getAttribute('title');
+    }).each(function(node){
+        var test = node.title;
+      var t = new Tooltip(node,test);
+      t.options.delta_x = -150;
+      t.options.delta_y = -50;
+      node.removeAttribute("title");
+    });
+  });
+</script>
+
+{if !$is_modified}
+<input type="hidden" name="ignore">
+{/if}
+
+<div class="plugin-actions">
+    <button name='saveProperties'>{msgPool type='okButton'}</button>
+    <button name='cancelProperties'>{msgPool type='cancelButton'}</button>
+</div>
+
diff --git a/gosa-core/plugins/addons/propertyEditor/property-list.xml b/gosa-core/plugins/addons/propertyEditor/property-list.xml
new file mode 100644 (file)
index 0000000..0c861a0
--- /dev/null
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<list>
+  <definition>
+    <departmentBrowser>false</departmentBrowser>
+    <departmentRootVisible>false</departmentRootVisible>
+    <baseMode>false</baseMode>
+    <multiSelect>true</multiSelect>
+    <template>property-list.tpl</template>
+    <module>all</module>
+    <label>List of configuration settings</label>
+    <defaultSortColumn>1</defaultSortColumn>
+
+    <objectType>
+      <label>Property not used</label>
+      <objectClass>undefined</objectClass>
+      <category>all</category>
+      <class>all</class>
+      <image>images/lists/element.png</image>
+    </objectType>
+
+    <objectType>
+      <label>Property will be restored</label>
+      <objectClass>removed</objectClass>
+      <category>all</category>
+      <class>all</class>
+      <image>images/lists/trash.png</image>
+    </objectType>
+
+    <objectType>
+      <label>Modified property</label>
+      <objectClass>modified</objectClass>
+      <category>all</category>
+      <class>all</class>
+      <image>plugins/propertyEditor/images/ldap.png[new]</image>
+    </objectType>
+
+    <objectType>
+      <label>Property configured in ldap</label>
+      <objectClass>ldap</objectClass>
+      <category>all</category>
+      <class>all</class>
+      <image>plugins/propertyEditor/images/ldap.png</image>
+    </objectType>
+
+    <objectType>
+      <label>Property configured in config file</label>
+      <objectClass>file</objectClass>
+      <category>all</category>
+      <class>all</class>
+      <image>plugins/propertyEditor/images/file.png</image>
+    </objectType>
+
+  </definition>
+
+  <table>
+    <layout>|20px;c|||||60px;r|</layout>
+
+    <column>
+      <value>%{filter:objectType(dn,objectClass)}</value>
+    </column>
+
+    <column>
+      <label>Group</label>
+      <sortAttribute>group</sortAttribute>
+      <sortType>string</sortType>
+      <value>%{filter:propertyGroup(group,description)}</value>
+      <export>true</export>
+    </column>
+
+    <column>
+      <label>Class</label>
+      <sortAttribute>group</sortAttribute>
+      <sortType>string</sortType>
+      <value>%{filter:propertyClass(class,description)}</value>
+      <export>true</export>
+    </column>
+
+    <column>
+      <label>Name</label>
+      <sortAttribute>cn</sortAttribute>
+      <sortType>string</sortType>
+      <value>%{filter:propertyName(class,cn,description,mandatory)}</value>
+      <export>true</export>
+    </column>
+
+    <column>
+      <label>Value</label>
+      <sortAttribute>value</sortAttribute>
+      <sortType>string</sortType>
+      <value>%{filter:propertyValue(class,cn,value,type,default,defaults,check,mandatory)}</value>
+      <export>true</export>
+    </column>
+
+    <column>
+      <label>Actions</label>
+      <value>%{filter:actions(dn,row,objectClass)}</value>
+    </column>
+
+  </table>
+
+  <actionmenu>
+
+    <action>
+      <name>remove</name>
+      <type>entry</type>
+      <image>images/lists/trash.png</image>
+      <label>Remove</label>
+    </action>
+
+    <action>
+      <type>exporter</type>
+    </action>
+
+  </actionmenu>
+
+  <actiontriggers snapshot="false" copypaste="false">
+
+    <action>
+      <name>remove</name>
+      <type>entry</type>
+      <objectclass>ldap</objectclass>
+      <image>images/lists/trash.png</image>
+      <label>Restore to default</label>
+    </action>
+
+  </actiontriggers>
+
+</list>