diff --git a/ihtml/themes/breezy/simple-filter.tpl b/ihtml/themes/breezy/simple-filter.tpl deleted file mode 100644 index d9dea54f1fece28722e8cdcadb4ecaebc2676836..0000000000000000000000000000000000000000 --- a/ihtml/themes/breezy/simple-filter.tpl +++ /dev/null @@ -1,26 +0,0 @@ -<div class="contentboxh"> - <p>{t}Filter{/t}</p> -</div> - -<div class="contentboxb"> - {if isset($objectFilters)} - {foreach from=$objectFilters item="ofilter"} - <label for="{$ofilter.id}"> - {${$ofilter.id}} {$ofilter.label} - </label> - {/foreach} - {/if} - - <hr/> - {$SCOPE} - <hr/> - - <label for="NAME" title="{$NAMEDESC}"> - <img src="geticon.php?context=actions&icon=system-search&size=16" alt="Search"/> - {$NAME} - </label> - - <div> - {$APPLY} - </div> -</div> diff --git a/ihtml/themes/breezy/simple-list.tpl b/ihtml/themes/breezy/simple-list.tpl deleted file mode 100644 index f2834141ae6a8423e699fb1ccceee9dfb811129f..0000000000000000000000000000000000000000 --- a/ihtml/themes/breezy/simple-list.tpl +++ /dev/null @@ -1,33 +0,0 @@ -<table class="listing-container"> - <tbody> - <tr> - <td class="list"> - <div class="contentboxh"> - <p class="contentboxh"> {$HEADLINE} {$SIZELIMIT}</p> - </div> - - <div class="contentboxb"> - <table> - <tbody> - <tr> - {if $BASE}<td>{$ROOT} </td><td>{$BACK} </td><td>{$HOME} </td>{/if} - <td class="optional">{$RELOAD} </td> - {if $BASE}<td><img src="images/lists/seperator.png" alt="-" height="16" width="1" class="center"/> </td><td>{t}Base{/t} {$BASE} </td>{/if} - {if $ACTIONS}<td><img src="images/lists/seperator.png" alt="-" height="16" width="1" class="center"/> </td><td>{$ACTIONS}</td>{/if} - </tr> - </tbody> - </table> - </div> - - <div style="margin-top:4px;"> - {$LIST} - </div> - </td> - <td class="filter"> - {$FILTER} - </td> - </tr> - </tbody> -</table> - -<input type="hidden" name="ignore"/> diff --git a/ihtml/themes/breezy/simple-select-list.tpl b/ihtml/themes/breezy/simple-select-list.tpl deleted file mode 100644 index 8465f4c00bab32e2895e1e1e0557d0ccedb9b6ba..0000000000000000000000000000000000000000 --- a/ihtml/themes/breezy/simple-select-list.tpl +++ /dev/null @@ -1,9 +0,0 @@ -{include file={filePath file="simple-list.tpl"}} - -<p class="plugbottom"> -{if $MULTISELECT} - <input type="submit" name="add_finish" value="{msgPool type=addButton}"/> - -{/if} - <input type="submit" formnovalidate="formnovalidate" name="add_cancel" value="{msgPool type=cancelButton}"/> -</p> diff --git a/include/class_departmentSortIterator.inc b/include/class_departmentSortIterator.inc deleted file mode 100644 index feea924d02517603fd5cac80e3c6ab3a79a2e5c3..0000000000000000000000000000000000000000 --- a/include/class_departmentSortIterator.inc +++ /dev/null @@ -1,43 +0,0 @@ -<?php -/* - This code is part of FusionDirectory (http://www.fusiondirectory.org/) - Copyright (C) 2003-2010 Cajus Pollmeier - Copyright (C) 2011-2016 FusionDirectory - - 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/*! - * \file class_departmentSortIterator.inc - * Source code for class departmentSortIterator - */ - -/*! - * \brief This class contains all the function needed to sort department - */ -class departmentSortIterator extends listingSortIterator -{ - /*! - * \brief departmentSortIterator constructor - * - * \param array $data departmentSortIterator data - * - * \param $direction Direction - */ - public function __construct ($data, $direction) - { - parent::__construct($data, $direction, 'sort-attribute', 'department'); - } -} diff --git a/include/class_filter.inc b/include/class_filter.inc deleted file mode 100644 index c42e2e85e85d6e1d01dc5591de288f9b6fc4ecff..0000000000000000000000000000000000000000 --- a/include/class_filter.inc +++ /dev/null @@ -1,588 +0,0 @@ -<?php -/* - This code is part of FusionDirectory (http://www.fusiondirectory.org/) - Copyright (C) 2003-2010 Cajus Pollmeier - Copyright (C) 2011-2018 FusionDirectory - - 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/*! - * \file class_filter.inc - * Source code for class filter - */ - -/*! - * \brief This class contains all the function needed to manage filter - */ -class filter -{ - var $xmlData; - var $elements = []; - var $elementValues = []; - var $autocompleter = []; - var $category = ''; - var $objectStorage = []; - var $base = ''; - var $scope = ''; - var $query; - var $initial = FALSE; - var $scopeMode = 'auto'; - var $converter = []; - var $pid; - var $headpage; - - /*! - * \brief Create a filter - * - * \param string $filename - */ - function __construct ($filename) - { - // Load eventually passed filename - if (!$this->load($filename)) { - die("Cannot parse $filename!"); - } - - $this->pid = preg_replace("/[^0-9]/", "", microtime(TRUE)); - } - - /* - * \brief Load a filter - * - * \param string $filename - */ - function load ($filename) - { - $contents = file_get_contents($filename); - $this->xmlData = xml::xml2array($contents, 1); - - if (!isset($this->xmlData['filterdef']['search'])) { - return FALSE; - } - - $this->xmlData = $this->xmlData['filterdef']; - - // Load filter - if (!isset($this->xmlData['search']['query'][0])) { - $this->xmlData['search']['query'] = [$this->xmlData['search']['query']]; - } - - // Move information - $entry = $this->xmlData['search']; - $this->scopeMode = $entry['scope']; - $this->scope = ($entry['scope'] == 'auto' ? 'one' : $entry['scope']); - $this->query = $entry['query']; - - // Transfer initial value - if (isset($this->xmlData['definition']['initial']) && ($this->xmlData['definition']['initial'] == 'true')) { - $this->initial = TRUE; - } - - // Transfer category - if (isset($this->xmlData['definition']['category'])) { - $this->category = $this->xmlData['definition']['category']; - } - - // Generate formular data - if (isset($this->xmlData['element'])) { - if (!isset($this->xmlData['element'][0])) { - $this->xmlData['element'] = [$this->xmlData['element']]; - } - foreach ($this->xmlData['element'] as $element) { - // Ignore elements without type - if (!isset($element['type']) || !isset($element['tag'])) { - continue; - } - - $tag = $element['tag']; - - // Fix arrays - if (isset($element['value']) && !isset($element['value'][0])) { - $element['value'] = [$element['value']]; - } - - // Store element for quick access - $this->elements[$tag] = $element; - - // Preset elementValues with default values if exist - if (isset($element['default']) && !is_array($element['default'])) { - $this->elementValues[$tag] = $element['default']; - } else { - $this->elementValues[$tag] = ''; - } - } - - uasort($this->elements, 'strlenSort'); - $this->elements = array_reverse($this->elements); - } - - return TRUE; - } - - /*! - * \brief Get the text in the field - * - * \param array $element - */ - function getTextfield ($element) - { - $tag = $element['tag']; - $size = 30; - if (isset($element['size'])) { - $size = $element['size']; - } - $maxlength = ''; - if (isset($element['maxlength'])) { - $maxlength = $element['maxlength']; - } - $result = '<input class="filter_textfield" id="'.$tag.'" name="'.$tag.'" type="text" size="'.$size.'"'.(empty($maxlength) ? '' : ' maxlength="'.$maxlength.'"').' value="'.$this->elementValues[$tag].'"/>'; - if (isset($element['autocomplete'])) { - $frequency = "0.5"; - $characters = "1"; - if (isset($element['autocomplete']['frequency'])) { - $frequency = $element['autocomplete']['frequency']; - } - if (isset($element['autocomplete']['characters'])) { - $characters = $element['autocomplete']['characters']; - } - $result .= "<div id='autocomplete$tag' class='autocomplete'></div>". - "<script type='text/javascript'>". - "new Ajax.Autocompleter('$tag', 'autocomplete$tag', 'autocomplete.php', { minChars: $characters, frequency: $frequency });". - "</script>"; - - $this->autocompleters[$tag] = $element['autocomplete']; - } - return $result; - } - - - /*! - * \brief Get the checkbox - * - * \param array $element - */ - function getCheckbox ($element) - { - $tag = $element['tag']; - $checked = ''; - if ($this->elementValues[$tag] == 'true') { - $checked = ' checked="checked"'; - } - - return '<input type="checkbox" class="filter_checkbox" id="'.$tag.'" name="'.$tag.'" onClick="document.mainform.submit();" value="true"'.$checked.'/>'; - } - - /*! - * \brief Get a combobox - * - * \param array $element - */ - function getCombobox ($element) - { - $result = "<select name='".$element['tag']."' size='1' onChange='document.mainform.submit();'>"; - - // Fill with presets - foreach ($element['value'] as $value) { - $selected = ""; - if ($this->elementValues[$element['tag']] == $value['key']) { - $selected = " selected"; - } - - // Handle translations - $result .= "<option value='".$value['key']."'$selected>"._($value['label'])."</option>"; - } - - // Use autocompleter for additional data - if (isset($element['autocomplete'])) { - $list = $this->getCompletitionList($element['autocomplete'], $element['tag']); - foreach ($list as $value) { - $selected = ""; - if ($this->elementValues[$element['tag']] == $value) { - $selected = " selected"; - } - $result .= "<option value='$value'$selected>$value</option>"; - } - } - - $result .= "</select>"; - - return $result; - } - - /*! - * \brief Set the combobox options - * - * \param string $tag - * - * \param array $options - */ - function setComboBoxOptions ($tag, $options) - { - if (isset($this->elements[$tag]) && ($this->elements[$tag]['type'] == "combobox")) { - $this->elements[$tag]['value'] = []; - foreach ($options as $key => $label) { - $this->elements[$tag]['value'][] = ['label' => $label, 'key' => $key]; - } - } - } - - /*! - * \brief Set a converter - * - * \param string $field - * - * \param string $hook - */ - function setConverter ($field, $hook) - { - $this->converter[$field] = $hook; - } - - /*! - * \brief Set a object storage - * - * \param string $storage - */ - function setObjectStorage ($storage) - { - $this->objectStorage = $storage; - } - - - /*! - * \brief Set a base - * - * \param string $base - */ - function setBase ($base) - { - $this->base = $base; - } - - /*! - * \brief Set the current scope - * - * \param string $scope - */ - function setCurrentScope ($scope) - { - $this->scope = $scope; - } - - /*! - * \brief Render apply filter - * - * \return string - */ - function renderApply () - { - return "<input type='submit' name='apply' value='"._("Apply filter")."'>"; - } - - /*! - * \brief Render scope - * - * \return string - */ - function renderScope () - { - $checked = ($this->scope == 'sub' ? ' checked' : ''); - return "<LABEL for='SCOPE'><input type='checkbox' id='SCOPE' name='SCOPE' value='1' onClick='document.mainform.submit();'$checked> "._("Search in subtrees")."</LABEL>"; - } - - /*! - * \brief Render - */ - function render () - { - /* If template is not filled, we display nothing */ - if (!isset($this->xmlData['definition']['template'])) { - return ""; - } - - $smarty = get_smarty(); - $smarty->assign("APPLY", $this->renderApply()); - $smarty->assign("SCOPE", $this->renderScope()); - - // Load template and replace elementsHtml[] - foreach ($this->elements as $tag => $element) { - $htmlCode = ""; - switch ($element['type']) { - case "textfield": - $htmlCode = $this->getTextfield($element); - $smarty->assign($tag.'DESC', sprintf(_('Searches in %s'), implode(', ', $element['autocomplete']['attribute']))); - break; - - case "checkbox": - $htmlCode = $this->getCheckbox($element); - break; - - case "combobox": - $htmlCode = $this->getCombobox($element); - break; - - default: - throw new FusionDirectoryException('Unknown element type specified: '.$element['type'].'!'); - } - $smarty->assign("$tag", $htmlCode); - } - - // Try to load template from plugin the folder first... - $file = get_template_path($this->xmlData['definition']['template'], TRUE); - - // ... if this fails, try to load the file from the theme folder. - if (!file_exists($file)) { - $file = get_template_path($this->xmlData['definition']['template']); - } - - // Load template - return "<input type='hidden' name='FILTER_PID' value='".$this->pid."'/>".$smarty->fetch($file); - } - - /*! - * \brief Query - */ - function query () - { - global $class_mapping; - $result = []; - - // Return empty list if initial is not set - if (!$this->initial) { - $this->initial = TRUE; - return $result; - } - - // Go thru all queries and merge results - foreach ($this->query as $query) { - if (!isset($query['backend']) || !isset($query['filter']) || !isset($query['attribute'])) { - die('No backend specified in search config.'); - } - - // Is backend available? - $backend = 'filter'.$query['backend']; - if (!isset($class_mapping["$backend"])) { - die('Invalid backend specified in search config.'); - } - - // Load filter and attributes - $filter = $query['filter']; - $attributes = $query['attribute']; - - if ($attributes === '*') { - $attributes = [$attributes]; - } else { - if (!is_array($attributes)) { - $attributes = [$attributes]; - } - // ObjectClass is required to check permissions later. - if (!in_array('objectClass', $attributes)) { - $attributes[] = 'objectClass'; - } - } - - // Generate final filter - foreach ($this->elements as $tag => $element) { - if (!isset($element['set']) || !isset($element['unset'])) { - continue; - } - - // Handle converters if present - if (isset($this->converter[$tag])) { - preg_match('/([^:]+)::(.*)$/', $this->converter[$tag], $m); - $e_set = call_user_func([$m[1], $m[2]], preg_replace('/\$/', $this->elementValues[$tag], is_array($element['set']) ? '' : $element['set'])); - $e_unset = call_user_func([$m[1], $m[2]], preg_replace('/\$/', $this->elementValues[$tag], is_array($element['unset']) ? '' : $element['unset'])); - } else { - $e_set = (is_array($element['set']) ? '' : $element['set']); - $e_unset = (is_array($element['unset']) ? '' : $element['unset']); - } - - // Do not replace escaped \$ - This is required to be able to search for e.g. windows machines. - if ($this->elementValues[$tag] == '') { - $e_unset = preg_replace('/([^\\\\])\$/', '${1}'.ldap_escape_f($this->elementValues[$tag]), $e_unset); - $e_unset = preg_replace('/\\\\\$/', '$', $e_unset); - $filter = preg_replace("/\\$$tag/", $e_unset, $filter); - } else { - $e_set = preg_replace('/([^\\\\])\$/', '${1}'.ldap_escape_f($this->elementValues[$tag]), $e_set); - $e_set = preg_replace('/\\\\\$/', '$', $e_set); - $filter = preg_replace("/\\$$tag/", $e_set, $filter); - } - } - - $branches = $this->objectStorage; - - if (isset($this->elements['FILTERTEMPLATE']) && $this->elementValues['FILTERTEMPLATE']) { - $branches = array_merge( - $branches, - array_map( - function ($oc) - { - return 'ou=templates,'.$oc; - }, - $branches - ) - ); - } - // Now call filter method and merge resulting entries. - $result = array_merge($result, call_user_func([$backend, 'query'], - $this, $this->base, $this->scope, $filter, $attributes, $this->category, $branches)); - } - - return $result; - } - - /*! - * \brief Check if a filter is valid - * - * \return TRUE if is valid, FALSE otherwise - */ - function isValid () - { - foreach ($this->elements as $tag => $element) { - if (isset($element->regex) - && !preg_match('/'.(string)$element->regex.'/', $this->elementValues[$tag])) { - return FALSE; - } - } - return TRUE; - } - - /*! - * \brief Update - */ - function update () - { - if (isset($_POST['FILTER_PID']) && $_POST['FILTER_PID'] == $this->pid) { - // Load post values and adapt filter, base and scope accordingly - but - // only if we didn't get a _GET - foreach ($this->elements as $tag => $element) { - if (!empty($_POST[$tag])) { - $this->elementValues[$tag] = validate($_POST[$tag]); - } else { - $this->elementValues[$tag] = ''; - } - } - - // Save scope if needed - if ($this->scopeMode == 'auto') { - $this->scope = (isset($_POST['SCOPE']) ? 'sub' : 'one'); - } - } - } - - /*! - * \brief Get competition list - * - * \param string $cfg - * - * \param string $tag - * - * \param string $value - */ - function getCompletitionList ($cfg, $tag, $value = "*") - { - global $class_mapping; - $res = []; - - // Is backend available? - $backend = "filter".$cfg['backend']; - if (!isset($class_mapping["$backend"])) { - die("Invalid backend specified in search config."); - } - - // Load filter and attributes - $filter = $cfg['filter']; - $attributes = $cfg['attribute']; - if (!is_array($attributes)) { - $attributes = [$attributes]; - } - - // ObjectClass is required to check permissions later. - if (!in_array('objectClass', $attributes)) { - $attributes[] = 'objectClass'; - } - - // Make filter - $filter = preg_replace("/\\$$tag/", ldap_escape_f($value), $filter); - if (isset($cfg['base']) && isset($cfg['scope']) && isset($cfg['category'])) { - $result = call_user_func([$backend, 'query'], $this, $cfg['base'], $cfg['scope'], $filter, $attributes, - $cfg["category"], $cfg["objectStorage"]); - } else { - $result = call_user_func([$backend, 'query'], $this, $this->base, $this->scope, $filter, $attributes, - $this->category, $this->objectStorage); - } - - foreach ($result as $entry) { - foreach ($attributes as $attribute) { - if (is_array($entry[$attribute])) { - for ($i = 0; $i < $entry[$attribute]['count']; $i++) { - if (mb_stristr($entry[$attribute][$i], $value)) { - $res[] = $entry[$attribute][$i]; - } - } - } else { - $res[] = $entry[$attribute]; - } - } - } - - return $res; - } - - /*! - * \brief Auto complete - */ - function processAutocomplete () - { - $result = []; - - // Introduce maximum number of entries - $max = 25; - - foreach ($this->autocompleters as $tag => $cfg) { - if (isset($_POST[$tag])) { - $result = $this->getCompletitionList($cfg, $tag, $_POST[$tag]); - $result = array_unique($result); - asort($result); - - echo '<ul>'; - foreach ($result as $entry) { - echo '<li>'.mark(htmlentities($_POST[$tag], ENT_COMPAT, 'UTF-8'), htmlentities($entry, ENT_COMPAT, 'UTF-8')).'</li>'; - if ($max-- == 0) { - break; - } - } - - echo '</ul>'; - } - } - } -} - -/*! - * \brief Sort elements for element length to allow proper replacing later on - * - * \param array $a - * - * \param array $b - */ -function strlenSort ($a, $b) -{ - if (strlen($a['tag']) == strlen($b['tag'])) { - return 0; - } - return (strlen($a['tag']) < strlen($b['tag']) ? -1 : 1); -} diff --git a/include/class_filterLDAP.inc b/include/class_filterLDAP.inc deleted file mode 100644 index 649729404ef3fbb87541cf5eb0e2c044c0881c42..0000000000000000000000000000000000000000 --- a/include/class_filterLDAP.inc +++ /dev/null @@ -1,174 +0,0 @@ -<?php -/* - This code is part of FusionDirectory (http://www.fusiondirectory.org/) - Copyright (C) 2003-2010 Cajus Pollmeier - Copyright (C) 2011-2016 FusionDirectory - - 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/*! - * \file class_filterLDAP.inc - * Source code for class filterLDAP - */ - - /*! - * \brief This class contains all the function to manage LDAP filter - * - * \see filter - */ -class filterLDAP -{ - /*! - * \brief Query - * - * \param string $parent - * - * \param string $base - * - * \param string $scope - * - * \param string $filter - * - * \param array $attributes - * - * \param string $category - * - * \param array $objectStorage - */ - static function query ($parent, $base, $scope, $filter, $attributes, $category, $objectStorage = [""]) - { - return static::get_list($parent, $base, $filter, $attributes, $category, $objectStorage, (($scope == 'sub') ? 'subtree' : 'one'), TRUE); - } - - /*! - * \brief Get list - * - * \param string $parent - * - * \param string $base - * - * \param string $filter - * - * \param array $attributes - * - * \param string $category - * - * \param array $objectStorage - * - * \param string $scope subtree or one - * - * \param boolean $sizelimit - * - * \param boolean $skipAcl - */ - static function get_list ($parent, $base, $filter, $attributes, $category, $objectStorage, $scope, $sizelimit = TRUE, $skipAcl = FALSE) - { - global $config, $ui; - - // Move to arrays for category and objectStorage - if (!is_array($category)) { - $category = [$category]; - } - - // Initialize search bases - $bases = []; - - foreach ($objectStorage as $oc) { - $oc = preg_replace('/,$/', '', $oc); - if ($scope == 'one') { - if (empty($oc)) { - $bases[$base] = TRUE; - } else { - $bases[$oc.','.$base] = TRUE; - } - } else { - if (empty($oc)) { - /* If we search on the base as well because of an empty storage string, - * it makes no sense to do dn filters */ - $bases[$base] = TRUE; - break; - } - $parts = ldap_explode_dn($oc, 0); - unset($parts['count']); - $dnFilter = []; - foreach ($parts as $part) { - preg_match('/([^=]+)=(.*)$/', $part, $m); - $dnFilter[] = '('.$m[1].':dn:='.$m[2].')'; - } - if (count($dnFilter) > 1) { - $bases[$base][] = '(&'.implode('', $dnFilter).')'; - } else { - $bases[$base][] = $dnFilter[0]; - } - } - } - - // Get LDAP link - $ldap = $config->get_ldap_link($sizelimit); - - // Do search for every base - $result = []; - $limit_exceeded = FALSE; - $ui->getSizeLimitHandler()->setLimitExceeded(FALSE); - - foreach ($bases as $base => $dnFilters) { - // Break if the size limit is exceeded - if ($limit_exceeded) { - return $result; - } - - // Switch to new base and search - if (is_array($dnFilters)) { - $dnFilter = '(|'.implode('', $dnFilters).')'; - } else { - $dnFilter = ''; - } - $ldap->cd($base); - - $ldap->search('(&'.$filter.$dnFilter.')', $attributes, $scope); - - // Check for size limit exceeded messages for GUI feedback - if ($ldap->hitSizeLimit()) { - $ui->getSizeLimitHandler()->setLimitExceeded(); - $limit_exceeded = TRUE; - } - - /* Crawl through result entries and perform the migration to the - result array */ - while ($attrs = $ldap->fetch()) { - $dn = $attrs['dn']; - - /* Skip ACL checks if we are forced to skip those checks */ - if ($skipAcl) { - $result[] = $attrs; - } else { - // Check entry permission - $obj = $parent->headpage->getObjectTypeInfos($dn, $attrs); - if (isset($obj['category'])) { - $o = $obj['category'].'/'.$obj['class']; - if (strpos($ui->get_permissions($dn, $o), 'r') !== FALSE) { - $result[] = $attrs; - } - } else { - trigger_error('Could not find objectType for '.$dn.'!'); - } - } - } - } - - return $result; - } -} diff --git a/include/class_listing.inc b/include/class_listing.inc deleted file mode 100644 index 281a5505aa635cb1834d7e55a9d280cecdf3726c..0000000000000000000000000000000000000000 --- a/include/class_listing.inc +++ /dev/null @@ -1,1824 +0,0 @@ -<?php -/* - This code is part of FusionDirectory (http://www.fusiondirectory.org/) - Copyright (C) 2003-2010 Cajus Pollmeier - Copyright (C) 2011-2016 FusionDirectory - - 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/*! - * \file class_listing.inc - * Source code for class listing - */ - -/*! - * \brief This class contains all the function needed to make the list - * that show the objects inside FusionDirectory - */ -class listing -{ - var $xmlData; - var $entries; - var $departments = []; - var $departmentBrowser = FALSE; - var $departmentRootVisible = FALSE; - var $multiSelect = FALSE; - var $template; - var $headline; - var $base; - var $sortDirection = NULL; - var $sortColumn = NULL; - var $sortAttribute; - var $sortType; - var $numColumns; - var $baseMode = FALSE; - var $bases = []; - var $header = []; - var $colprops = []; - var $filters = []; - var $filter = NULL; - var $pid; - protected $departmentTypes = []; - var $objectTypes = []; - var $objectTypeCount = []; - protected $objectDnMapping = []; - protected $copyPasteHandler = NULL; - protected $snapshotHandler = NULL; - var $exporters = []; - var $exportColumns = []; - var $scrollPosition = 0; - var $baseSelector; - protected $filterCache = []; - protected $parent; - - /*! - * \brief Create a listing - * - * \param string $data either a filename or an array representation of the XML - */ - function __construct ($data) - { - global $config, $class_mapping, $ui; - - // Initialize pid - $this->pid = preg_replace("/[^0-9]/", "", microtime(TRUE)); - - if (!$this->load($data)) { - if (is_array($data)) { - die("Cannot parse data : ".print_r($data, TRUE)); - } else { - die("Cannot parse $data!"); - } - } - - // Set base for filter - if ($this->baseMode) { - $this->base = $ui->getCurrentBase(); - $this->refreshBasesList(); - } else { - $this->base = $config->current['BASE']; - } - - // Move footer information - $this->showFooter = ($config->get_cfg_value("listSummary") == "TRUE"); - - // Register build in filters - $this->registerElementFilter("departmentType", "listing::filterDepartmentType"); - $this->registerElementFilter("departmentLink", "listing::filterDepartmentLink"); - $this->registerElementFilter("objectType", "listing::filterObjectType"); - $this->registerElementFilter("link", "listing::filterLink"); - $this->registerElementFilter("nameLink", "listing::filterNameLink"); - $this->registerElementFilter("actions", "listing::filterActions"); - - // Load exporters - foreach (array_keys($class_mapping) as $class) { - if (preg_match('/Exporter$/', $class)) { - $info = call_user_func([$class, "getInfo"]); - if ($info != NULL) { - $this->exporters = array_merge($this->exporters, $info); - } - } - } - - // Instanciate base selector - $this->baseSelector = new baseSelector($this->bases, $this->base); - } - - function setParent ($parent) - { - $this->parent = $parent; - } - - /*! - * \brief Set a CopyPasteHandler - * - * \param $handler The handler - * - * \see CopyPasteHandler - */ - function setCopyPasteHandler ($handler) - { - $this->copyPasteHandler = $handler; - } - - /*! - * \brief Set a SnapshotHandler - * - * \param $handler The handler - * - * \see SnapshotHandler - */ - function setSnapshotHandler ($handler) - { - if ($handler->enabled()) { - $this->snapshotHandler = $handler; - } else { - $this->snapshotHandler = NULL; - } - } - - /*! - * \brief Set a filter - * - * \param string $filter - * - * \see filter - */ - function setFilter ($filter) - { - $this->filter = $filter; - $filter->headpage = $this; - if ($this->departmentBrowser) { - $this->refreshDepartmentsCache(); - } - $this->filter->setBase($this->base); - } - - /*! - * \brief Save element from a filter - * - * \param string $name - * - * \param string $call - */ - function registerElementFilter ($name, $call) - { - if (!isset($this->filters[$name])) { - $this->filters[$name] = $call; - return TRUE; - } - - return FALSE; - } - - /*! - * \brief Load a file - * - * \param string $data either a filename or an array representation of the XML - */ - function load ($data) - { - if (is_array($data)) { - $this->xmlData = $data; - } else { - $contents = file_get_contents($data); - $this->xmlData = xml::xml2array($contents, 1); - } - - $this->filterCache = []; - - if (!isset($this->xmlData['list'])) { - return FALSE; - } - - $this->xmlData = $this->xmlData["list"]; - - // Load some definition values - foreach (["departmentBrowser", "departmentRootVisible", "multiSelect", "baseMode"] as $token) { - if (isset($this->xmlData['definition'][$token]) && - $this->xmlData['definition'][$token] == "true") { - $this->$token = TRUE; - } - } - - // Fill objectTypes from departments and xml definition - $types = departmentManagement::getDepartmentTypes(); - foreach ($types as $type) { - $i = objects::infos($type); - $this->departmentTypes[strtoupper($type)] = [ - 'label' => $i['name'], - 'image' => $i['icon'], - 'category' => $i['aclCategory'], - 'class' => $i['mainTab'], - 'filter' => objects::getFilterObject($type), - 'nameAttr' => $i['nameAttr'], - ]; - } - $this->categories = []; - if (isset($this->xmlData['definition']['objectType'])) { - if (isset($this->xmlData['definition']['objectType']['label'])) { - $this->xmlData['definition']['objectType'] = [$this->xmlData['definition']['objectType']]; - } - foreach ($this->xmlData['definition']['objectType'] as $index => $otype) { - $this->objectTypes[$otype['objectClass']] = $otype; - if (isset($otype['category'])) { - $this->categories[] = $otype['category']; - } - } - } - $this->categories = array_unique($this->categories); - - // Parse layout per column - $this->colprops = $this->parseLayout($this->xmlData['table']['layout']); - - // Prepare table headers - $this->renderHeader(); - - // Assign headline/Categories - $this->headline = _($this->xmlData['definition']['label']); - if (!is_array($this->categories)) { - $this->categories = [$this->categories]; - } - - // Evaluate columns to be exported - if (isset($this->xmlData['table']['column'])) { - foreach ($this->xmlData['table']['column'] as $index => $cfg) { - if (isset($cfg['export']) && $cfg['export'] == "true") { - $this->exportColumns[] = $index; - } - } - } - - if (isset($this->xmlData['actiontriggers']['action']['type'])) { - $this->xmlData['actiontriggers']['action'] = [$this->xmlData['actiontriggers']['action']]; - } - - return TRUE; - } - - - function renderHeader () - { - $this->header = []; - $this->plainHeader = []; - - // Initialize sort? - $sortInit = FALSE; - if (!$this->sortDirection) { - $this->sortColumn = 0; - if (isset($this->xmlData['definition']['defaultSortColumn'])) { - $this->sortColumn = $this->xmlData['definition']['defaultSortColumn']; - } else { - $this->sortAttribute = ""; - } - $this->sortDirection = []; - $sortInit = TRUE; - } - - if (isset($this->xmlData['table']['column'])) { - foreach ($this->xmlData['table']['column'] as $index => $cfg) { - // Initialize everything to one direction - if ($sortInit) { - $this->sortDirection[$index] = FALSE; - } - - $sorter = ""; - if ($index == $this->sortColumn && isset($cfg['sortAttribute']) && - isset($cfg['sortType'])) { - $this->sortAttribute = $cfg['sortAttribute']; - $this->sortType = $cfg['sortType']; - $sorter = " <img class='center' title='".($this->sortDirection[$index] ? _("Up") : _("Down"))."' src='geticon.php?context=actions&size=16&icon=view-sort-".($this->sortDirection[$index] ? "descending" : "ascending")."' alt='".($this->sortDirection[$index] ? _('Sort up') : _('Sort down'))."'>"; - } - $sortable = (isset($cfg['sortAttribute'])); - - $link = "href='?plug=".$_GET['plug']."&PID=".$this->pid."&act=SORT_$index'"; - if (isset($cfg['label'])) { - if ($sortable) { - $this->header[$index] = "<th ".$this->colprops[$index]."><a $link>"._($cfg['label'])."$sorter</a></th>"; - } else { - $this->header[$index] = "<th ".$this->colprops[$index].">"._($cfg['label'])."</th>"; - } - $this->plainHeader[] = _($cfg['label']); - } else { - if ($sortable) { - $this->header[$index] = "<th ".$this->colprops[$index]."><a $link> $sorter</a></th>"; - } else { - $this->header[$index] = "<th ".$this->colprops[$index]."> </th>"; - } - $this->plainHeader[] = ""; - } - } - } - } - - /*! - * \brief Render - */ - function render () - { - global $ui; - - // Check for exeeded sizelimit - if (($message = $ui->getSizeLimitHandler()->check()) != '') { - return $message; - } - - // Initialize list - $result = '<input type="hidden" value="'.$this->pid.'" name="PID"/>'."\n"; - $result .= '<input type="hidden" name="position_'.$this->pid.'" id="position_'.$this->pid.'"/>'."\n"; - - $result .= '<div id="d_scrollbody" style="width:100%;">'."\n"; - $result .= '<table style="width:100%;" id="t_scrolltable" class="listingTable">'."\n"; - - // Build list header - $result .= '<thead><tr>'."\n"; - if ($this->multiSelect) { - $width = '24px'; - $result .= '<th style="text-align:center;padding:0;width:'.$width.';"><input type="checkbox" id="select_all" name="select_all" title="'._('Select all').'" onClick=\'toggle_all_("listing_selected_[0-9]*$","select_all");\' /></th>'."\n"; - } - foreach ($this->header as $header) { - $result .= $header; - } - $result .= '</tr></thead>'."\n"; - - // Build list body - $result .= '<tbody id="t_nscrollbody">'."\n"; - - // No results? Just take an empty colspanned row - if (count($this->entries) + count($this->departments) == 0) { - $result .= '<tr><td colspan="'.($this->numColumns + ($this->multiSelect ? 1 : 0)).'" style="height:100%;width:100%;"> </td></tr>'."\n"; - } - - // Draw department browser if configured and we're not in sub mode - if ($this->departmentBrowser && ($this->filter->scope != 'sub')) { - // Fill with department browser if configured this way - $departmentIterator = new departmentSortIterator($this->departments, $this->sortDirection[$this->sortColumn]); - foreach ($departmentIterator as $row => $entry) { - $result .= '<tr>'; - - // Render multi select if needed - if ($this->multiSelect) { - $result .= '<td> </td>'; - } - - // Render defined department columns, fill the rest with some stuff - $rest = $this->numColumns; - foreach ($this->xmlData['table']['department'] as $index => $cfg) { - $colspan = 1; - if (isset($cfg['span'])) { - $colspan = $cfg['span']; - } - $result .= '<td colspan="'.$colspan.'" '.$this->colprops[$index].'>'.$this->renderCell('department', $index, $cfg['value'], $entry, $row).'</td>'; - $rest -= $colspan; - } - - // Fill remaining cols with nothing - for ($i = $this->numColumns - $rest; $i < $this->numColumns; $i++) { - $result .= '<td '.$this->colprops[$i].'> </td>'; - } - $result .= '</tr>'; - } - } - - // Fill with contents, sort as configured - foreach ($this->entries as $row => $entry) { - $trow = ''; - - // Render multi select if needed - if ($this->multiSelect) { - $trow .= '<td style="text-align:center;width:20px;"><input type="checkbox" id="listing_selected_'.$row.'" name="listing_selected_'.$row.'"/></td>'."\n"; - } - - foreach ($this->xmlData['table']['column'] as $index => $cfg) { - $renderedCell = $this->renderCell('column', $index, $cfg['value'], $entry, $row); - $trow .= '<td '.$this->colprops[$index].'>'.$renderedCell.'</td>'."\n"; - - // Save rendered column - $sort = preg_replace('/.*>([^<]+)<.*$/', '$1', $renderedCell); - $sort = str_replace(' ', '', $sort); - if (strpos($sort, '<') !== FALSE) { - $sort = ''; - } - $this->entries[$row]['_sort'.$index] = $sort; - } - - // Save rendered entry - $this->entries[$row]['_rendered'] = $trow; - } - - // Complete list by sorting entries for _sort$index and appending them to the output - $entryIterator = new listingSortIterator($this->entries, $this->sortDirection[$this->sortColumn], "_sort".$this->sortColumn, $this->sortType); - foreach ($entryIterator as $row => $entry) { - // Apply custom class to row? - if (preg_match("/<rowClass:([a-z0-9_-]*)\/>/i", $entry['_rendered'], $matches)) { - $result .= "<tr class='".$matches[1]."'>\n"; - $result .= preg_replace("/<rowClass[^>]+>/", '', $entry['_rendered']); - } else { - $result .= "<tr>\n"; - $result .= $entry['_rendered']; - } - - $result .= "</tr>\n"; - } - - // Close list body - $result .= "</tbody></table></div>"; - - // Add the footer if requested - if ($this->showFooter) { - $result .= '<div class="nlistFooter">'; - - if ($this->departmentBrowser && ($this->filter->scope != 'sub')) { - foreach ($this->departmentTypes as $objectType) { - if (isset($this->objectTypeCount[$objectType['label']])) { - $result .= '<img class="center" src="'.htmlentities($objectType['image'], ENT_COMPAT, 'UTF-8').'" title="'.$objectType['label'].'" alt="'.$objectType['label'].'"/> '.$this->objectTypeCount[$objectType['label']]." "; - } - } - } - - foreach ($this->objectTypes as $objectType) { - if (isset($this->objectTypeCount[$objectType['label']])) { - $result .= '<img class="center" src="'.htmlentities($objectType['image'], ENT_COMPAT, 'UTF-8').'" title="'.$objectType['label'].'" alt="'.$objectType['label'].'"/> '.$this->objectTypeCount[$objectType['label']]." "; - } - } - - $result .= '</div>'; - } - - // Close list - $result .= ''; - - // Add scroll positioner - $result .= '<script type="text/javascript">'; - $result .= '$("t_nscrollbody").scrollTop= '.$this->scrollPosition.';'; - $result .= 'var box = $("t_nscrollbody").onscroll= function() {$("position_'.$this->pid.'").value= this.scrollTop;}'; - $result .= '</script>'; - - $smarty = get_smarty(); - $smarty->assign("usePrototype", "true"); - $smarty->assign("FILTER", $this->filter->render()); - $smarty->assign("SIZELIMIT", $ui->getSizeLimitHandler()->renderWarning()); - $smarty->assign("LIST", $result); - $smarty->assign("MULTISELECT", $this->multiSelect); - - // Assign navigation elements - $nav = $this->renderNavigation(); - foreach ($nav as $key => $html) { - $smarty->assign($key, $html); - } - - // Assign action menu / base - $smarty->assign("ACTIONS", $this->renderActionMenu()); - $smarty->assign("BASE", $this->renderBase()); - - // Assign summary - $smarty->assign("HEADLINE", $this->headline); - - // Try to load template from plugin the folder first... - $file = get_template_path($this->xmlData['definition']['template'], TRUE); - - // ... if this fails, try to load the file from the theme folder. - if (!file_exists($file)) { - $file = get_template_path($this->xmlData['definition']['template']); - } - - return $smarty->fetch($file); - } - - /*! - * \brief Update a listing - */ - function update () - { - $ui = get_userinfo(); - - // Take care of base selector - if ($this->baseMode) { - $this->baseSelector->update(); - // Check if a wrong base was supplied - if (!$this->baseSelector->checkLastBaseUpdate()) { - msg_dialog::display(_("Error"), msgPool::check_base(), ERROR_DIALOG); - } - } - - // Save base - $refresh = FALSE; - if ($this->baseMode) { - $this->base = $this->baseSelector->getBase(); - $ui->setCurrentBase($this->base); - $refresh = TRUE; - } - - // Reset object counter / DN mapping - $this->objectTypeCount = []; - $this->objectDnMapping = []; - - // Do not do anything if this is not our PID - if ($refresh || !(isset($_REQUEST['PID']) && $_REQUEST['PID'] != $this->pid)) { - - // Save position if set - if (isset($_POST['position_'.$this->pid]) && is_numeric($_POST['position_'.$this->pid])) { - $this->scrollPosition = $_POST['position_'.$this->pid]; - } - - // Override the base if we got a message from the browser navigation - if ($this->departmentBrowser && isset($_GET['act']) - && preg_match('/^department_([0-9]+)$/', validate($_GET['act']), $match) - && isset($this->departments[$match[1]])) { - $this->setBase($this->departments[$match[1]]['dn']); - } - - // Filter POST with "act" attributes -> posted from action menu - if (isset($_POST['exec_act']) && ($_POST['act'] != '') - && preg_match('/^export.*$/', $_POST['act']) && isset($this->exporters[$_POST['act']])) { - $exporter = $this->exporters[$_POST['act']]; - $userinfo = ", "._("created by")." ".$ui->cn." - ".strftime('%A, %d. %B %Y, %H:%M:%S'); - $entryIterator = new listingSortIterator($this->entries, $this->sortDirection[$this->sortColumn], "_sort".$this->sortColumn, $this->sortType); - $sortedEntries = []; - foreach ($entryIterator as $entry) { - $sortedEntries[] = $entry; - } - $instance = new $exporter['class']($this->headline.$userinfo, $this->plainHeader, $sortedEntries, $this->exportColumns); - $type = call_user_func([$exporter['class'], "getInfo"]); - $type = $type[$_POST['act']]; - send_binary_content($instance->query(), $type['filename'], $type = $type['mime']); - } - - // Filter GET with "act" attributes - if (isset($_GET['act'])) { - $key = validate($_GET['act']); - if (preg_match('/^SORT_([0-9]+)$/', $key, $match)) { - // Switch to new column or invert search order? - $column = $match[1]; - if ($this->sortColumn != $column) { - $this->sortColumn = $column; - } else { - $this->sortDirection[$column] = !$this->sortDirection[$column]; - } - - // Allow header to update itself according to the new sort settings - $this->renderHeader(); - } - } - - if ($this->baseMode) { - // Override base if we got signals from the navigation elements - $action = ''; - foreach (array_keys($_POST) as $key) { - if (preg_match('/^(ROOT|BACK|HOME)_x$/', $key, $match)) { - $action = $match[1]; - break; - } - } - - // Navigation handling - if ($action == 'ROOT') { - $deps = $ui->get_module_departments($this->categories); - $this->setBase($deps[0]); - } elseif ($action == 'BACK') { - $this->tryAndSetBase(preg_replace('/^[^,]+,/', '', $this->base)); - } elseif ($action == 'HOME') { - $this->tryAndSetBase($ui->getBase()); - } - } - } - - // Reload departments - if ($this->departmentBrowser) { - $this->refreshDepartmentsCache(); - } - - // Update filter and refresh entries - $this->filter->setBase($this->base); - $this->entries = $this->filter->query(); - - // Fix filter if querie returns NULL - if ($this->entries == NULL) { - $this->entries = []; - } - - $this->dnToRow = []; - foreach ($this->entries as $row => $entry) { - $this->dnToRow[$entry['dn']] = $row; - } - - // Init snapshot list for renderSnapshotActions - if (is_object($this->snapshotHandler)) { - $this->snapshotHandler->initSnapshotCache($this->base); - } - } - - /*! - * \brief Set a new base valor - * - * \param string $base - */ - function setBase ($base) - { - global $ui; - $this->base = $base; - if ($this->baseMode) { - $this->baseSelector->setBase($this->base); - $ui->setCurrentBase($this->base); - } - } - - function tryAndSetBase ($base) - { - $ui = get_userinfo(); - $deps = $ui->get_module_departments($this->categories); - if (in_array_ics($base, $deps)) { - $this->setBase($base); - } - } - - /*! - * \brief Accessor of the base - * - * \return the base - */ - function getBase () - { - return $this->base; - } - - /*! - * \brief Parse a layout - * - * \param string $layout - */ - function parseLayout ($layout) - { - $result = []; - $layout = preg_replace("/^\|/", "", $layout); - $layout = preg_replace("/\|$/", "", $layout); - $cols = explode("|", $layout); - - foreach ($cols as $index => $cfg) { - if ($cfg != "") { - $res = ""; - $classes = ""; - $components = explode(';', $cfg); - foreach ($components as $part) { - switch ($part) { - case 'r': - $res .= 'text-align:right;'; - break; - case 'l': - $res .= 'text-align:left;'; - break; - case 'c': - $res .= 'text-align:center;'; - break; - case 'o': - $classes .= 'optional '; - break; - default: - if (preg_match('/^[0-9]+(|px|%)(-d)?$/', $part)) { - if (!preg_match('/-d$/', $part)) { - /* d suffix means dynamic, ie no fixed width */ - $res .= "width:$part;"; - } else { - /* Remove the -d suffix */ - $part = preg_replace('/-d$/', '', $part); - } - $res .= "min-width:$part;"; - } - } - } - - $result[$index] = " style='$res'"; - if ($classes != "") { - $result[$index] .= " class='$classes'"; - } - } else { - $result[$index] = ""; - } - } - - // Save number of columns for later use - $this->numColumns = count($cols); - - return $result; - } - - - function renderCell ($table, $index, $data, $cfg, $row) - { - // Replace flat attributes in data string - $offset = 0; - while (preg_match('/%{([^}:]+)}/', $data, $m, PREG_OFFSET_CAPTURE, $offset)) { - if (isset($cfg[$m[1][0]])) { - $replace = $cfg[$m[1][0]]; - if (is_array($replace)) { - $replace = $replace[0]; - } - $replace = htmlentities($replace, ENT_COMPAT, 'UTF-8'); - } else { - $replace = ' '; - } - $data = substr_replace($data, $replace, $m[0][1], strlen($m[0][0])); - $offset = $m[0][1] + strlen($replace); - } - - // Watch out for filters and prepare to execute them - return $this->processElementFilter($table, $index, $data, $cfg, $row); - } - - - function renderBase () - { - if (!$this->baseMode) { - return; - } - - return $this->baseSelector->render(); - } - - - function processElementFilter ($type, $index, $data, $cfg, $row) - { - if (isset($this->filterCache[$type.$index])) { - $filtersData = $this->filterCache[$type.$index]; - } else { - preg_match_all('/%{filter:([^(]+)\((.*)\)}/', $data, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE); - - $filtersData = []; - foreach ($matches as $match) { - $cl = ''; - $method = ''; - if (!preg_match('/^(.*)::(.*)$/', $match[1][0], $m) - && (!isset($this->filters[$match[1][0]]) || !preg_match('/^(.*)::(.*)$/', $this->filters[$match[1][0]], $m))) { - trigger_error('Unknown filter '.$match[1][0]); - continue; - } - $cl = $m[1]; - $method = $m[2]; - - // Prepare params for function call - preg_match_all('/"[^"]+"|[^,]+/', $match[2][0], $parts); - - $filtersData[$match[0][0]] = [$cl, $method, $parts[0], $match[0][1]]; - } - - $this->filterCache[$type.$index] = $filtersData; - } - - foreach ($filtersData as $filterstring => $filter) { - list ($cl, $method, $parts, $offset) = $filter; - $params = []; - foreach ($parts as $param) { - switch ($param) { - case 'row': - $params[] = $row; - break; - case 'pid': - $params[] = $this->pid; - break; - case 'base': - $params[] = $this->getBase(); - break; - case 'entry': - $params[] = $cfg; - break; - case 'objectType': - $params[] = $this->getObjectType($cfg['dn'], $cfg); - break; - case 'dn': - $params[] = $cfg['dn']; - break; - default: - if (preg_match('/^"(.*)"$/', $param, $m)) { - // Fixie with "" is passed directly - $params[] = $m[1]; - } elseif (isset($cfg[$param])) { - // LDAP variables get replaced by their objects - $values = $cfg[$param]; - if (is_array($values)) { - unset($values['count']); - } - $params[] = $values; - } else { - $params[] = ''; - } - break; - } - } - - // Replace information - if ($cl == 'listing') { - // Non static call - $data = substr_replace($data, call_user_func_array([$this, $method], $params), $offset, strlen($filterstring)); - } else { - // Static call - $data = substr_replace($data, call_user_func_array([$cl, $method], $params), $offset, strlen($filterstring)); - } - } - - return $data; - } - - /*! - * \brief Get the object type - * - * \param string $dn dn of the object - * \param string $attrs LDAP attributes of the object - */ - function getObjectType ($dn, $attrs) - { - return $this->genericGetType($dn, $attrs, $this->objectTypes); - } - - /*! - * \brief Get the department type - * - * \param string $dn dn of the object - * \param string $attrs LDAP attributes of the object - */ - function getDepartmentType ($dn, $attrs) - { - return $this->genericGetType($dn, $attrs, $this->departmentTypes); - } - - /*! - * \brief Get the object or department type - */ - protected function genericGetType ($dn, $attrs, $types) - { - if (isset($this->objectDnMapping[$dn])) { - return $this->objectDnMapping[$dn]; - } - $classes = $attrs['objectClass']; - // Walk thru types and see if there's something matching - foreach ($types as $type => $objectType) { - if (isset($objectType['filter'])) { - if ($objectType['filter']($attrs)) { - $this->objectDnMapping[$dn] = $type; - return $this->objectDnMapping[$dn]; - } else { - continue; - } - } - $ocs = $objectType['objectClass']; - if (!is_array($ocs)) { - $ocs = [$ocs]; - } - - $found = TRUE; - foreach ($ocs as $oc) { - if (preg_match('/^!(.*)$/', $oc, $match)) { - $oc = $match[1]; - if (in_array($oc, $classes)) { - $found = FALSE; - } - } else { - if (!in_array($oc, $classes)) { - $found = FALSE; - } - } - } - - if ($found) { - $this->objectDnMapping[$dn] = $type; - return $this->objectDnMapping[$dn]; - } - } - - return NULL; - } - - function getObjectTypeInfos ($dn, $attrs) - { - $type = $this->getObjectType($dn, $attrs); - if ($type === NULL) { - return NULL; - } - return $this->objectTypes[$type]; - } - - /*! - * \brief Icon of the object type - * - * \param string $row The row - * - * \param string $dn The DN - */ - function filterObjectType ($row, $dn) - { - return $this->filterGenericType($dn, $this->objectTypes, $this->getObjectType($dn, $this->entries[$row])); - } - - /*! - * \brief Generic method for department and objects once type is known - */ - protected function filterGenericType ($dn, $types, $type) - { - $result = " "; - - if ($type) { - $result = '<img class="center" title="'.$dn.'" src="'.htmlentities($types[$type]['image'], ENT_COMPAT, 'UTF-8').'" alt="'.$type.'"/>'; - if (!isset($this->objectTypeCount[$types[$type]['label']])) { - $this->objectTypeCount[$types[$type]['label']] = 0; - } - $this->objectTypeCount[$types[$type]['label']]++; - } - - return $result; - } - - /*! - * \brief Icon of the department type - * - * \param string $row The row - * - * \param string $dn The DN - */ - function filterDepartmentType ($row, $dn) - { - return $this->filterGenericType($dn, $this->departmentTypes, $this->getDepartmentType($dn, $this->departments[$row])); - } - - /*! - * \brief Filter actions - * - * \param string $dn The DN - * - * \param string $row - * - * \param string $classes - */ - function filterActions ($dn, $row, $classes) - { - // Do nothing if there's no menu defined - if (!isset($this->xmlData['actiontriggers']['action'])) { - return ' '; - } - - // Go thru all actions - $result = ''; - $emptyimg = '<img src="images/empty.png" alt=" " class="center optional"/>'; - foreach ($this->xmlData['actiontriggers']['action'] as $action) { - // If there's an objectclass definition and we don't have it - // add an empty picture here. - if (isset($action['objectclass'])) { - $objectclass = $action['objectclass']; - $skip = FALSE; - if (preg_match('/^!(.*)$/', $objectclass, $m)) { - $objectclass = $m[1]; - if (in_array($objectclass, $classes)) { - $skip = TRUE; - } - } elseif (is_string($objectclass)) { - if (!in_array($objectclass, $classes)) { - $skip = TRUE; - } - } elseif (is_array($objectclass)) { - if (count(array_intersect($objectclass, $classes)) != count($objectclass)) { - $skip = TRUE; - } - } - if ($skip) { - $result .= $emptyimg; - if ($action['type'] == 'snapshot') { - $result .= $emptyimg; - } - continue; - } - } - - // Skip the entry completely if there's no permission to execute it - if (!$this->hasActionPermission($action, $dn, $row)) { - $result .= $emptyimg; - continue; - } - - // Skip entry if the pseudo filter does not fit - if (isset($action['filter']) && preg_match('/^[a-z0-9_]+!?=[a-z0-9_]+$/i', $action['filter'])) { - list($fa, $fv) = explode('=', $action['filter']); - if (preg_match('/^(.*)!$/', $fa, $m)) { - $fa = $m[1]; - if (isset($this->entries[$row][$fa]) && $this->entries[$row][$fa][0] == $fv) { - $result .= $emptyimg; - continue; - } - } else { - if (!isset($this->entries[$row][$fa]) && !$this->entries[$row][$fa][0] == $fv) { - $result .= $emptyimg; - continue; - } - } - } - - if ($action['type'] == 'entry') { - // Render normal entries as usual - $label = $this->processElementFilter('label', $action['name'], $action['label'], $this->entries[$row], $row); - $image = $this->processElementFilter('image', $action['name'], $action['image'], $this->entries[$row], $row); - $result .= '<input class="center" type="image" src="'.htmlentities($image, ENT_COMPAT, 'UTF-8').'" title="'.$label.'" alt="'.$label.'" '. - 'name="listing_'.$action['name'].'_'.$row.'"/>'; - } elseif (($action['type'] == 'copypaste') || ($action['type'] == 'snapshot')) { - // Handle special types - $objectType = $this->getObjectTypeInfos($dn, $this->entries[$row]); - $category = $class = NULL; - if ($objectType) { - $category = $objectType['category']; - $class = $objectType['class']; - } - - if ($action['type'] == 'copypaste') { - $copy = (!isset($action['copy']) || ($action['copy'] == 'true')); - $cut = (!isset($action['cut']) || ($action['cut'] == 'true')); - $result .= $this->renderCopyPasteActions($row, $this->entries[$row]['dn'], $category, $class, $copy, $cut); - } else { - $result .= $this->renderSnapshotActions($row, $this->entries[$row]['dn'], $category); - } - } - } - - return $result; - } - - /*! - * \brief Filter the department link - * - * \param string $row - * - * \param string $dn The DN - * - * \param array $description - */ - function filterDepartmentLink ($row, $dn, $description) - { - $attr = $this->departments[$row]['sort-attribute']; - $name = $this->departments[$row][$attr]; - if (is_array($name)) { - $name = $name[0]; - } - $result = htmlentities(sprintf("%s [%s]", $name, $description[0]), ENT_COMPAT, 'UTF-8'); - return "<a href='?plug=".$_GET['plug']."&PID=$this->pid&act=department_$row' title='$dn'>$result</a>"; - } - - /*! - * \brief Filter link with object name - */ - function filterNameLink ($row, $dn) - { - $infos = $this->getObjectTypeInfos($dn, $this->entries[$row]); - $value = $this->entries[$row][$infos['nameAttr']]; - if (is_array($value)) { - unset($value['count']); - } - return $this->filterLink($row, $dn, "%s", $value); - } - - /*! - * \brief Filter link - */ - function filterLink ($row, $dn, $mask, ...$vals) - { - $params = [$mask]; - - // Collect sprintf params - foreach ($vals as $val) { - if (empty($val)) { - continue; - } - if (!is_array($val)) { - $val = [$val]; - } - $val = array_map( - function ($v) - { - return htmlentities($v, ENT_COMPAT, 'UTF-8'); - }, - $val - ); - $params[] = implode("<br/>\n", $val); - } - - $result = ' '; - if (count($params) > 1) { - $trans = sprintf(...$params); - if ($trans != '') { - return '<a href="?plug='.$_GET['plug'].'&PID='.$this->pid.'&act=listing_edit_'.$row.'" title="'.$dn.'">'.$trans.'</a>'; - } - } - - return $result; - } - - - function renderNavigation () - { - $result = []; - $enableBack = TRUE; - $enableRoot = TRUE; - $enableHome = TRUE; - - $ui = get_userinfo(); - - /* Check if base = first available base */ - $deps = $ui->get_module_departments($this->categories); - - if (!count($deps) || $deps[0] == $this->filter->base) { - $enableBack = FALSE; - $enableRoot = FALSE; - } - - /* Check if we are in users home department */ - if (!count($deps) || ($this->filter->base == $ui->getBase()) || !in_array_ics($ui->getBase(), $deps)) { - $enableHome = FALSE; - } - - /* Draw root button */ - if ($enableRoot) { - $result["ROOT"] = "<input class='center' type='image' src='geticon.php?context=actions&icon=go-first&size=16' ". - "title='"._("Go to root department")."' name='ROOT' alt='"._("Root")."'>"; - } else { - $result["ROOT"] = "<img src='geticon.php?context=actions&icon=go-first&size=16&disabled=1' class='center' alt='"._("Root")."'>"; - } - - /* Draw back button */ - if ($enableBack) { - $result["BACK"] = "<input class='center' type='image' src='geticon.php?context=actions&icon=go-up&size=16' ". - "title='"._("Go up one department")."' alt='"._("Up")."' name='BACK'>"; - } else { - $result["BACK"] = "<img src='geticon.php?context=actions&icon=go-up&size=16&disabled=1' class='center' alt='"._("Up")."'>"; - } - - /* Draw home button */ - if ($enableHome) { - $result["HOME"] = '<input class="center" type="image" src="geticon.php?context=actions&icon=go-home&size=16"'. - ' title="'._("Go to user's department").'" alt="'._('Home').'" name="HOME"/>'; - } else { - $result["HOME"] = "<img src='geticon.php?context=actions&icon=go-home&size=16&disabled=1' class='center' alt='"._("Home")."'>"; - } - - /* Draw reload button, this button is enabled everytime */ - $result["RELOAD"] = "<input class='center optional' type='image' src='geticon.php?context=actions&icon=view-refresh&size=16' ". - "title='"._("Reload list")."' name='REFRESH' alt='"._("Reload list")."'>"; - - return $result; - } - - /*! - * \brief Get action - */ - function getAction () - { - global $config, $ui; - - // Do not do anything if this is not our PID, or there's even no PID available... - if (!isset($_REQUEST['dn']) && (!isset($_REQUEST['PID']) || $_REQUEST['PID'] != $this->pid)) { - return; - } - - // Save position if set - if (isset($_POST['position_'.$this->pid]) && is_numeric($_POST['position_'.$this->pid])) { - $this->scrollPosition = $_POST['position_'.$this->pid]; - } - - $result = ["targets" => [], "action" => ""]; - - // Filter GET with "act" attributes - if (isset($_GET['act'])) { - $key = validate($_GET['act']); - if (preg_match('/^listing_([a-zA-Z_]+)_([0-9]+)$/', $key, $m)) { - $action = $m[1]; - $target = $m[2]; - if (isset($this->entries[$target]['dn'])) { - $result['action'] = $action; - $result['targets'][] = $this->entries[$target]['dn']; - } - } elseif (isset($_REQUEST['dn']) && preg_match('/^listing_([a-zA-Z_]+)$/', $key, $m)) { - /* Pre-render list to init things if a dn is gonna be opened on first load */ - $dn = urldecode($_REQUEST['dn']); - $action = $m[1]; - if ($this->baseMode) { - /* Detect the longer base valid for this dn */ - $longerBase = ''; - foreach (array_keys($this->bases) as $base) { - if (preg_match('/'.preg_quote($base, '/').'$/i', $dn) - && (strlen($base) > strlen($longerBase))) { - $longerBase = $base; - } - } - $this->setBase($longerBase); - /* Search for its main attr value */ - if (isset($this->filter->elementValues['NAME']) && preg_match('/^[^=]+=([^,]+)/', $dn, $m)) { - $this->filter->elementValues['NAME'] = $m[1]; - } - $this->filter->setCurrentScope('one'); - } - /* Bypass size limit just to be sure */ - $oldsizelimit = $ui->getSizeLimitHandler()->getSizeLimit(); - $ui->getSizeLimitHandler()->setSizeLimit(0); - $this->update(); - $this->render(); - $ui->getSizeLimitHandler()->setSizeLimit($oldsizelimit); - $this->filter->elementValues['NAME'] = ''; - - $result['action'] = $action; - $result['targets'][] = $dn; - - // Make sure no other management class intercept the same dn - unset($_REQUEST['dn']); - } - - // Drop targets if empty - if (count($result['targets']) == 0) { - unset($result['targets']); - } - if (preg_match('/^(edit)_([a-zA-Z_]+)$/', $result['action'], $m)) { - $result['action'] = $m[1]; - $result['subaction'] = $m[2]; - } - return $result; - } - - // Filter POST with "listing_" attributes - foreach (array_keys($_POST) as $key) { - - // Capture selections - if (preg_match('/^listing_selected_[0-9]+$/', $key)) { - $target = preg_replace('/^listing_selected_([0-9]+)$/', '$1', $key); - if (isset($this->entries[$target]['dn'])) { - $result['targets'][] = $this->entries[$target]['dn']; - } - continue; - } - - // Capture action with target - this is a one shot - if (preg_match('/^listing_[a-zA-Z_]+_[0-9]+(|_x)$/', $key)) { - $target = preg_replace('/^listing_[a-zA-Z_]+_([0-9]+)(|_x)$/', '$1', $key); - if (isset($this->entries[$target]['dn'])) { - $result['action'] = preg_replace('/^listing_([a-zA-Z_]+)_[0-9]+(|_x)$/', '$1', $key); - $result['targets'] = [$this->entries[$target]['dn']]; - } - break; - } - - // Capture action without target - if (preg_match('/^listing_[a-zA-Z_]+(|_x)$/', $key)) { - $result['action'] = preg_replace('/^listing_([a-zA-Z_]+)(|_x)$/', '$1', $key); - continue; - } - } - - // Filter POST with "act" attributes -> posted from action menu - if (isset($_POST['act']) && ($_POST['act'] != '') - && !preg_match('/^export.*$/', $_POST['act'])) { - $result['action'] = validate($_POST['act']); - } - - // Drop targets if empty - if (count($result['targets']) == 0) { - unset($result['targets']); - } - if (preg_match('/^(edit)_([a-zA-Z_]+)/', $result['action'], $m)) { - $result['action'] = $m[1]; - $result['subaction'] = $m[2]; - } - return $result; - } - - - function renderActionMenu () - { - // Don't send anything if the menu is not defined - if (!isset($this->xmlData['actionmenu']['action'])) { - return ""; - } - - // Make sure we got an array of actions - if (isset($this->xmlData['actionmenu']['action']['type'])) { - $this->xmlData['actionmenu']['action'] = [$this->xmlData['actionmenu']['action']]; - } - - // Load shortcut - $result = '<input type="hidden" name="act" id="actionmenu" value="">'. - '<div style="display:none"><input type="submit" formnovalidate="formnovalidate" name="exec_act" id="exec_act" value=""/></div>'. - '<ul class="level1" id="root"><li><a href="#">'._('Actions'). - ' <img class="center optional" src="images/down-arrow.png" alt=""/></a>'; - - // Build ul/li list - $result .= $this->recurseActions($this->xmlData['actionmenu']['action']); - - return '<div id="pulldown">'.$result.'</li></ul></div>'; - } - - function renderActionMenuActionLink ($separator, $action, $name, $icon) - { - return '<li'.$separator.' id="actionmenu_'.$action.'">' - .'<a href="#" onClick="' - ."document.getElementById('actionmenu').value='$action';document.getElementById('exec_act').click();" - .'">' - .'<img src="'.htmlentities($icon, ENT_COMPAT, 'UTF-8').'" alt="" class="center"/> '.$name.'</a>' - .'</li>'; - } - - function recurseActions (&$actions) - { - global $class_mapping; - static $level = 2; - $result = "<ul class='level$level'>"; - $separator = ""; - - foreach ($actions as &$action) { - - // Skip the entry completely if there's no permission to execute it - if (!$this->hasActionPermission($action, $this->filter->base)) { - continue; - } - - // Skip entry if there're missing dependencies - if (isset($action['depends'])) { - $deps = is_array($action['depends']) ? $action['depends'] : [$action['depends']]; - foreach ($deps as $clazz) { - if (!isset($class_mapping[$clazz])) { - continue 2; - } - } - } - - if ($action['type'] == "separator") { - $separator = " style='border-top:1px solid #AAA' "; - continue; - } - - // Dive into subs - if ($action['type'] == "sub" && isset($action['action'])) { - $level++; - if (isset($action['label'])) { - $img = ""; - if (isset($action['image'])) { - $img = "<img class='center' src='".htmlentities($action['image'], ENT_COMPAT, 'UTF-8')."' alt=''/> "; - } - $result .= "<li id='actionmenu_".strtolower($action['label'])."'$separator><a href='#'>$img"._($action['label'])." <img src='images/forward-arrow.png' alt='forward arrow'/></a>"; - } - - // Ensure we've an array of actions, this enables sub menus with only one action. - if (isset($action['action']['type'])) { - $action['action'] = [$action['action']]; - } - - $result .= $this->recurseActions($action['action'])."</li>"; - $level--; - $separator = ""; - continue; - } - - // Render entry elseways - if (isset($action['label'])) { - $result .= $this->renderActionMenuActionLink($separator, $action['name'], _($action['label']), $action['image']); - } - - // Check for special types - switch ($action['type']) { - case 'copypaste': - $cut = !isset($action['cut']) || $action['cut'] != "false"; - $copy = !isset($action['copy']) || $action['copy'] != "false"; - $result .= $this->renderCopyPasteMenu($separator, $copy, $cut); - break; - - case 'snapshot': - $result .= $this->renderSnapshotMenu($separator); - break; - - case 'exporter': - $result .= $this->renderExporterMenu($separator); - break; - - case 'daemon': - $result .= $this->renderDaemonMenu($separator); - break; - - default: - } - - $separator = ""; - } - unset($action); - - $result .= "</ul>"; - return $result; - } - - /*! - * \brief Check if user have action permission - * - * \param string $action - * - * \param string $dn The DN - * - * \param string $row - * - */ - function hasActionPermission (&$action, $dn, $row = NULL) - { - global $ui; - - if (isset($action['acl'])) { - if (isset($action['aclInfos'])) { - $aclInfos = $action['aclInfos']; - } else { - /* First time we check permission for this action */ - if ($row !== NULL) { - $otype = $this->getObjectTypeInfos($dn, $this->entries[$row]); - } else { - $otype = FALSE; - } - $acls = $action['acl']; - if (!is_array($acls)) { - $acls = [$acls]; - } - $aclInfos = []; - - // Every ACL has to pass - foreach ($acls as $acl) { - $module = $this->categories; - $aclList = []; - - // Replace %acl if available - if ($otype) { - $acl = str_replace('%acl', $otype['category'].'/'.$otype['class'], $acl); - } - - // Split for category and plugins if needed - if (preg_match('/^\[([rwcdm]+)\]$/', $acl, $match)) { - // match for "[rw]" style entries - $aclList = [$match[1]]; - } elseif (preg_match('/^([a-zA-Z0-9]+\/?[a-zA-Z0-9]+)\[([rwcdm]+)\]$/', $acl, $match)) { - // match for "user[rw]" style entries - // match for "user/user[rw]" style entries - $module = $match[1]; - $aclList = [$match[2]]; - } elseif (preg_match('/^([a-zA-Z0-9]+\/[a-zA-Z0-9]+)\[([a-zA-Z0-9]+:[rwcdm]+(,[a-zA-Z0-9]+:[rwcdm]+)*)\]$/', $acl, $match)) { - // match "user/user[userPassword:rw(,...)*]" style entries - $module = $match[1]; - $aclList = explode(',', $match[2]); - } - - $modules = $module; - if (!is_array($modules)) { - $modules = [$modules]; - } - - $aclInfos[] = [$aclList, $modules]; - } - $action['aclInfos'] = $aclInfos; - } - - foreach ($aclInfos as $aclInfo) { - list ($aclList, $modules) = $aclInfo; - // Walk thru prepared ACL by using $module - foreach ($aclList as $sAcl) { - $checkAcl = ''; - - // Category or detailed permission? - foreach ($modules as $module) { - if (strpos($module, '/') !== FALSE) { - if (preg_match('/([a-zA-Z0-9]+):([rwcdm]+)/', $sAcl, $m)) { - $checkAcl .= $ui->get_permissions($dn, $module, $m[1]); - $sAcl = $m[2]; - } else { - $checkAcl .= $ui->get_permissions($dn, $module, '0'); - } - } else { - $checkAcl .= $ui->get_category_permissions($dn, $module); - } - } - - // Split up remaining part of the acl and check if it we're - // allowed to do something... - $parts = str_split($sAcl); - foreach ($parts as $part) { - if (strpos($checkAcl, $part) === FALSE) { - return FALSE; - } - } - } - } - } - - return TRUE; - } - - /*! - * \brief Refresh the bases list - */ - function refreshBasesList () - { - global $config; - $ui = get_userinfo(); - - // Fill internal bases list - $this->bases = []; - $deps = $ui->get_module_departments($this->categories); - $departmentTree = $config->getDepartmentTree(); - foreach ($departmentTree as $key => $dep) { - if (in_array_ics($key, $deps)) { - $this->bases[$key] = $dep; - } - } - - if (!empty($this->bases) && !isset($this->bases[$this->base])) { - $this->base = key($this->bases); - } - - // Populate base selector if already present - if ($this->baseSelector && $this->baseMode) { - $this->baseSelector->setBases($this->bases); - $this->baseSelector->setBase($this->base); - $this->baseSelector->update(TRUE); - } - } - - /*! \brief Cache the departments */ - function refreshDepartmentsCache () - { - $ui = get_userinfo(); - - $this->departments = []; - - // Get list of supported department types - $types = departmentManagement::getDepartmentTypes(); - - // Load departments allowed by ACL - $validDepartments = $ui->get_module_departments($this->categories); - - /* Fetch departments and their informations */ - foreach ($types as $type) { - $i = objects::infos($type); - $deps = objects::ls( - $type, - [ - 'dn' => 'raw', - 'objectClass' => 'raw', - 'description' => 'raw', - $i['mainAttr'] => 'raw' - ], - $this->base, - '', - FALSE, - 'one' - ); - - // Analyze list of departments - foreach ($deps as $department) { - if (!in_array($department['dn'], $validDepartments)) { - continue; - } - - /* php-ldap like indexes are needed for renderCell */ - $count = 0; - foreach ($department as $key => $values) { - if ($key != 'dn') { - $department[$count++] = $key; - } - } - $department['count'] = $count; - - // Add the attribute where we use for sorting - $department['sort-attribute'] = $i['mainAttr']; - - // Move to the result list - $this->departments[] = $department; - } - } - } - - - function renderCopyPasteMenu ($separator, $copy = TRUE, $cut = TRUE) - { - // We can only provide information if we've got a copypaste handler - // instance - if (!is_object($this->copyPasteHandler)) { - return ''; - } - - // Presets - $result = ""; - $read = FALSE; - $paste = FALSE; - $ui = get_userinfo(); - - // Switch flags to on if there's at least one category which allows read/paste - foreach ($this->categories as $category) { - $read = $read || (strpos($ui->get_category_permissions($this->base, $category), 'r') !== FALSE); - $paste = $paste || ($ui->is_pasteable($this->base, $category) == 1); - } - - // Draw entries that allow copy and cut - if ($read) { - // Copy entry - if ($copy) { - $result .= $this->renderActionMenuActionLink($separator, 'copy', _('Copy'), 'geticon.php?context=actions&icon=edit-copy&size=16'); - $separator = ''; - } - - // Cut entry - if ($cut) { - $result .= $this->renderActionMenuActionLink($separator, 'cut', _('Cut'), 'geticon.php?context=actions&icon=edit-cut&size=16'); - $separator = ''; - } - } - - // Draw entries that allow pasting entries - if ($paste) { - if ($this->copyPasteHandler->entries_queued()) { - $result .= $this->renderActionMenuActionLink($separator, 'paste', _('Paste'), 'geticon.php?context=actions&icon=edit-paste&size=16'); - } else { - $result .= "<li$separator>".'<a href="#"><img src="geticon.php?context=actions&icon=edit-paste&size=16&disabled=1" alt="" class="center"/> '._('Paste').'</a></li>'; - } - } - - return $result; - } - - - function renderCopyPasteActions ($row, $dn, $category, $class, $copy = TRUE, $cut = TRUE) - { - // We can only provide information if we've got a copypaste handler - // instance - if (!is_object($this->copyPasteHandler)) { - return ''; - } - - // Presets - $ui = get_userinfo(); - $result = ""; - - // Render cut entries - if ($cut) { - if ($ui->is_cutable($dn, $category, $class)) { - $result .= '<input class="center" type="image"'. - ' src="geticon.php?context=actions&icon=edit-cut&size=16"'. - ' alt="'._('Cut').'" name="listing_cut_'.$row.'" title="'._('Cut this entry').'"'. - '/>'; - } else { - $result .= '<img src="images/empty.png" alt=" " class="center optional"/>'; - } - } - - // Render copy entries - if ($copy) { - if ($ui->is_copyable($dn, $category)) { - $result .= '<input class="center" type="image"'. - ' src="geticon.php?context=actions&icon=edit-copy&size=16"'. - ' alt="'._('Copy').'" name="listing_copy_'.$row.'" title="'._('Copy this entry').'"'. - '/>'; - } else { - $result .= '<img src="images/empty.png" alt=" " class="center optional"/>'; - } - } - - return $result; - } - - - function renderSnapshotMenu ($separator) - { - // We can only provide information if we've got a snapshot handler instance - if (!is_object($this->snapshotHandler)) { - return ''; - } - - // Presets - $result = ""; - $ui = get_userinfo(); - - if ($ui->allow_snapshot_restore($this->base, $this->categories, TRUE)) { - // Draw icons according to the restore flag - if ($this->snapshotHandler->hasDeletedSnapshots($this->parent->getSnapshotBases())) { - $result .= $this->renderActionMenuActionLink($separator, 'restore', _('Restore snapshots'), 'geticon.php?context=actions&icon=document-restore&size=16'); - } else { - $result .= "<li$separator><a href='#'><img src='geticon.php?context=actions&icon=document-restore&size=16&disabled=1' alt='' class='center'> "._("Restore snapshots")."</a></li>"; - } - } - - return $result; - } - - - function renderExporterMenu ($separator) - { - // Presets - $result = ""; - - // Draw entries - $result .= "<li$separator id='actionmenu_exportList'><a href='#'><img class='center' src='geticon.php?context=actions&icon=document-export&size=16' alt=''> "._("Export list")." <img src='images/forward-arrow.png' alt='arrow'></a><ul class='level3'>"; - - // Render export actions - foreach ($this->exporters as $action => $exporter) { - $result .= $this->renderActionMenuActionLink('', $action, $exporter['label'], $exporter['image']); - } - - // Finalize list - $result .= "</ul></li>"; - - return $result; - } - - - function renderSnapshotActions ($row, $dn, $category) - { - /* We can only provide information if we've got a snapshot handler instance */ - if (!is_object($this->snapshotHandler)) { - return ''; - } - - // Presets - $result = ''; - $ui = get_userinfo(); - - if ($ui->allow_snapshot_restore($dn, $category, FALSE)) { - /* Draw restore button */ - - if ($this->snapshotHandler->hasSnapshots($dn)) { - /* We have snapshots for this dn */ - $result .= '<input class="center" type="image"'. - ' src="geticon.php?context=actions&icon=document-restore&size=16"'. - ' alt="'._('Restore snapshot').'" name="listing_restore_'.$row.'"'. - ' title="'._('Restore snapshot').'"/>'; - } else { - $result .= '<img class="center"'. - ' src="geticon.php?context=actions&icon=document-restore&size=16&disabled=1"'. - ' alt="'._('Restore snapshot').'"/>'; - } - } - - if ($ui->allow_snapshot_create($dn, $category)) { - /* Draw snapshot button */ - $result .= '<input class="center" type="image"'. - ' src="geticon.php?context=actions&icon=snapshot&size=16"'. - ' alt="'._('Create snapshot').'" name="listing_snapshot_'.$row.'"'. - ' title="'._('Create a new snapshot from this object').'"/>'; - } else { - $result .= '<img src="images/empty.png" alt=" " class="center optional"/>'; - } - - return $result; - } - - - function renderDaemonMenu ($separator) - { - $result = ""; - - // If there is a daemon registered, draw the menu entries - if (class_available("DaemonEvent")) { - $events = DaemonEvent::get_event_types_by_category($this->categories); - if (isset($events['BY_CLASS']) && count($events['BY_CLASS'])) { - foreach ($events['BY_CLASS'] as $name => $event) { - $result .= "<li$separator><a href='#' onClick='document.getElementById(\"actionmenu\").value=\"$name\";document.getElementById(\"exec_act\").click();'>".$event['MenuImage']." ".$event['s_Menu_Name']."</a></li>"; - $separator = ""; - } - } - } - - return $result; - } - - - function getEntry ($dn) - { - if (isset($this->dnToRow[$dn])) { - return $this->entries[$this->dnToRow[$dn]]; - } - return NULL; - } - - /*! - * \brief Get listing entries - */ - function getEntries () - { - return $this->entries; - } - - /*! - * \brief Get type - * - * \param string $dn The DN - */ - function getType ($dn) - { - if (isset($this->objectDnMapping[$dn])) { - return $this->objectDnMapping[$dn]; - } - return NULL; - } -} diff --git a/include/class_listingSortIterator.inc b/include/class_listingSortIterator.inc deleted file mode 100644 index 1c9a77e9df30fe37d3380b84546a9fae855660e6..0000000000000000000000000000000000000000 --- a/include/class_listingSortIterator.inc +++ /dev/null @@ -1,175 +0,0 @@ -<?php -/* - This code is part of FusionDirectory (http://www.fusiondirectory.org/) - Copyright (C) 2003-2010 Cajus Pollmeier - Copyright (C) 2011-2016 FusionDirectory - - 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/*! - * \file class_listingSortIterator.inc - * Source code for class listingSortIterator - */ - -/*! - * \brief This class contains all the function needed to sort list - * go up, go down , back , next. etc... - */ -class listingSortIterator implements Iterator -{ - protected $data; - - /*! - * \brief listingSortIterator constructor - * - * \param array $data listingSortIterator data - * - * \param $direction Direction - * - * \param $attribute Attribute - * - * \param string $type - */ - public function __construct ($data, $direction, $attribute, $type = 'string') - { - // Sort for attribute - if ($attribute != '') { - uasort( - $data, - function ($ao, $bo) use ($attribute, $type) - { - if ($attribute == 'sort-attribute') { - // Override sort attribute from data if needed - $attribute_a = $ao['sort-attribute']; - $attribute_b = $bo['sort-attribute']; - } else { - $attribute_a = $attribute; - $attribute_b = $attribute; - } - - // Extract values from ao and bo - $a = $b = ''; - if (isset($ao[$attribute_a])) { - $a = $ao[$attribute_a]; - if (is_array($a)) { - $a = $a[0]; - } - } - if (isset($bo[$attribute_b])) { - $b = $bo[$attribute_b]; - if (is_array($b)) { - $b = $b[0]; - } - } - - // Take a look at the several types - switch ($type) { - case 'department': - return strnatcmp($a, $b); - - case 'integer': - return $b - $a; - - case 'date': - if ($a == '') { - $a = '31.12.0000'; - } - if ($b == '') { - $b = '31.12.0000'; - } - list($d, $m, $y) = explode('.', $a); - $a = (int)sprintf('%04d%02d%02d', $y, $m, $d); - list($d, $m, $y) = explode('.', $b); - $b = (int)sprintf('%04d%02d%02d', $y, $m, $d); - return $b - $a; - - case 'ip': - $parts_a = explode('.', $a, 4); - $parts_b = explode('.', $b, 4); - for ($i = 0; $i < 4; $i++) { - if ((int)($parts_a[$i]) != (int)($parts_b[$i])) { - return (int)($parts_a[$i]) - (int)($parts_b[$i]); - } - } - return 0; - - // Sort for string by default - case 'string': - default: - return strcoll($a, $b); - } - } - ); - } - - // Invert if direction is set - if ($direction) { - $this->data = array_reverse($data, TRUE); - } else { - $this->data = $data; - } - } - - /*! - * \brief Put the array pointer to the first element - * - * \return the first element of the array - */ - function rewind () - { - return reset($this->data); - } - - /*! - * \brief Get the current data element - * - * \return The current element pointed by array pointer - */ - function current () - { - return current($this->data); - } - - /*! - * \brief Get the key element - * - * \return the key element of the array - */ - function key () - { - return key($this->data); - } - - /*! - * \brief Get the next data element - * - * \return The next element pointed by array pointer - */ - function next () - { - return next($this->data); - } - - /*! - * \brief Check if the data array is valid - * - * \return TRUE if the array is valid, return FALSE otherwise - */ - function valid () - { - return (key($this->data) !== NULL); - } -} diff --git a/include/management/class_templateDialog.inc b/include/management/class_templateDialog.inc index 00be48579eca005a963be81f6cd8ffde65b07fd2..dc881e1b5a49ed3563db3a55b1f1d8cea82674c6 100644 --- a/include/management/class_templateDialog.inc +++ b/include/management/class_templateDialog.inc @@ -23,7 +23,7 @@ */ class templateDialog { - protected $simpleManagement; + protected $management; protected $type; protected $template = NULL; protected $templates; @@ -34,9 +34,9 @@ class templateDialog protected $post_finish = 'template_continue'; protected $post_cancel = 'template_cancel'; - function __construct ($simpleManagement, $type, $dn = NULL, $target = NULL) + function __construct ($management, $type, $dn = NULL, $target = NULL) { - $this->simpleManagement = $simpleManagement; + $this->management = $management; $this->type = $type; $this->templates = objects::getTemplates($this->type); if ($dn !== NULL) { @@ -75,8 +75,8 @@ class templateDialog } if (is_object($this->template)) { if ($this->target !== NULL) { - $this->simpleManagement->openTabObject($this->template->apply($this->target)); - $this->simpleManagement->handleTemplateApply(); + $this->management->openTabObject($this->template->apply($this->target)); + $this->management->handleTemplateApply(); return FALSE; } else { $this->template->save_object(); @@ -111,15 +111,15 @@ class templateDialog function handle_finish () { - $this->simpleManagement->closeDialogs(); - $this->simpleManagement->openTabObject($this->template->apply()); + $this->management->closeDialogs(); + $this->management->openTabObject($this->template->apply()); return FALSE; } function handle_cancel () { - $this->simpleManagement->remove_lock(); - $this->simpleManagement->closeDialogs(); + $this->management->remove_lock(); + $this->management->closeDialogs(); return FALSE; } } diff --git a/include/select/class_filterLDAPBlacklist.inc b/include/select/class_filterLDAPBlacklist.inc deleted file mode 100644 index d2e719d66d5b78999673291ab9384762590f5d5e..0000000000000000000000000000000000000000 --- a/include/select/class_filterLDAPBlacklist.inc +++ /dev/null @@ -1,72 +0,0 @@ -<?php - -/* - This code is part of FusionDirectory (http://www.fusiondirectory.org/) - Copyright (C) 2003 Cajus Pollmeier - Copyright (C) 2011-2016 FusionDirectory - - 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/*! - * \brief filterLDAP backend with blacklist/whitelist handling - */ -class filterLDAPBlacklist -{ - static function query ($parent, $base, $scope, $filter, $attributes, $category, $objectStorage = "") - { - $result = filterLDAP::query($parent, $base, $scope, $filter, $attributes, $category, $objectStorage); - return filterLDAPBlacklist::filterByBlacklist($result); - } - - static function filterByBlacklist ($entries) - { - if (session::is_set('filterWhitelist')) { - $wlist = session::get('filterWhitelist'); - if (!empty($wlist)) { - foreach ($entries as $id => $entry) { - if (in_array($entry['dn'], $wlist['dn'])) { - continue; - } - foreach ($wlist['branches'] as $branch) { - if (preg_match('/'.preg_quote($branch, '/').'$/', $entry['dn'])) { - continue 2; - } - } - unset($entries[$id]); - } - } - } - if (session::is_set('filterBlacklist')) { - $blist = session::get('filterBlacklist'); - foreach ($blist as $attr_name => $attr_values) { - foreach ($attr_values as $match) { - foreach ($entries as $id => $entry) { - if (isset($entry[$attr_name])) { - $test = $entry[$attr_name]; - if (!is_array($test)) { - $test = [$test]; - } - if (in_array($match, $test)) { - unset($entries[$id]); - } - } - } - } - } - } - return array_values($entries); - } -} diff --git a/include/simpleplugin/class_dialogAttributes.inc b/include/simpleplugin/class_dialogAttributes.inc index 6cafad705c85288e4731ddd00f324938a805c29e..e1966cd00af8aff9ada0b2f4d40c0d36da89c56a 100644 --- a/include/simpleplugin/class_dialogAttributes.inc +++ b/include/simpleplugin/class_dialogAttributes.inc @@ -63,15 +63,16 @@ class GenericDialog } } -/*! \brief Generic dialog for selection using a simpleSelectManagement based class +/*! \brief Generic dialog for selection using a selectManagement class */ -class GenericSelectDialog extends GenericDialog +class GenericSelectManagementDialog extends GenericDialog { - function dialog_execute () + protected $dialogClass = 'selectManagement'; + + function __construct ($simplePlugin, $attribute) { - session::set('filterBlacklist', $this->attribute->getFilterBlackList()); - session::set('filterWhitelist', $this->attribute->getFilterWhiteList()); - return parent::dialog_execute(); + $this->attribute = $attribute; + $this->dialog = new $this->dialogClass(...$this->attribute->getSelectManagementParameters()); } function handle_finish () @@ -452,24 +453,6 @@ class GenericDialogAttribute extends DialogAttribute } } -/*! \brief Generic dialog for selection using a selectManagement class - */ -class GenericSelectManagementDialog extends GenericSelectDialog -{ - protected $dialogClass = 'selectManagement'; - - function __construct ($simplePlugin, $attribute) - { - $this->attribute = $attribute; - $this->dialog = new $this->dialogClass(...$this->attribute->getSelectManagementParameters()); - } - - function dialog_execute () - { - return GenericDialog::dialog_execute(); - } -} - /*! \brief Object selection dialog allowing only one object to get selected */ class GenericSingleSelectManagementDialog extends GenericSelectManagementDialog diff --git a/include/simpleplugin/class_simpleManagement.inc b/include/simpleplugin/class_simpleManagement.inc deleted file mode 100644 index aa99423ed843bd4f2c973b5594ac66827a977e03..0000000000000000000000000000000000000000 --- a/include/simpleplugin/class_simpleManagement.inc +++ /dev/null @@ -1,1252 +0,0 @@ -<?php -/* - This code is part of FusionDirectory (http://www.fusiondirectory.org/) - Copyright (C) 2013-2016 FusionDirectory - - 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/*! - * \brief Management base class - */ -class simpleManagement -{ - // The currently used object(s) (e.g. in edit, removal) - // $dn is public due to some compatibility problems with class plugin.. - public $dn = ''; - protected $dns = []; - - // The last used object(s). - protected $last_dn = ''; - protected $last_dns = []; - - // The common places the displayed objects are stored in. (e.g. array("ou=groups,","..")) - protected $storagePoints = []; - - // The opened object. - protected $tabObject = NULL; - protected $dialogObject = NULL; - - // The last opened object. - protected $last_tabObject = NULL; - protected $last_dialogObject = NULL; - - // Whether to display the apply button or not - protected $displayApplyBtn = FALSE; - - // Whether to display a header or not. - protected $skipHeader = FALSE; - - // Whether to display a footer or not. - protected $skipFooter = FALSE; - - // Copy&Paste handler - protected $cpHandler = NULL; - - // Indicates that we want to paste objects right now. - protected $cpPastingStarted = FALSE; - - // The Snapshot handler class. - protected $snapHandler = NULL; - - // The listing handlers - protected $headpage = NULL; - protected $filter = NULL; - - // A list of configured actions/events - protected $actions = []; - - // Some management classes are used in tab groups and needs this - public $is_template = FALSE; - public $attributes = []; - - /* Attributes that child classes should override */ - protected $objectTypes = []; - - /* Attributes that child classes can override */ - protected $departmentBrowser = TRUE; - protected $departmentRootVisible = TRUE; - protected $baseMode = TRUE; - protected $multiSelect = TRUE; - - protected $filterXMLPath = NULL; - protected $listXMLPath = NULL; - protected $autoFilter = TRUE; - protected $autoActions = TRUE; - protected $skipCpHandler = FALSE; - - protected $autoFilterAttributes = ['dn', 'cn', 'description']; - - protected $headpageClass = "listing"; - - public static $skipTemplates = TRUE; - public static $skipSnapshots = FALSE; - - function __construct () - { - global $config; - - if ($this->filterXMLPath === NULL) { - $this->filterXMLPath = get_template_path('simple-filter.xml', TRUE, dirname(__FILE__)); - } - if ($this->listXMLPath === NULL) { - $this->listXMLPath = get_template_path('simple-list.xml', TRUE, dirname(__FILE__)); - } - - foreach ($this->objectTypes as &$object) { - $object = strtoupper($object); - } - unset($object); - - $this->storagePoints = []; - foreach ($this->objectTypes as $key => $object) { - try { - $i = objects::infos($object); - } catch (NonExistingObjectTypeException $e) { - /* Remove objectTypes which are not existing */ - unset($this->objectTypes[$key]); - continue; - } - if ($i['ou'] !== NULL) { - $this->storagePoints[] = $i['ou']; - } - } - $this->storagePoints = array_unique($this->storagePoints); - if (count($this->storagePoints) == 0) { - $this->storagePoints[] = ''; - } - - // Build filter - if (session::is_set(get_class($this).'_filter')) { - $filter = session::get(get_class($this).'_filter'); - } else { - $filter = new filter($this->filterXMLPath); - $filter->setObjectStorage($this->storagePoints); - } - $this->setFilter($filter); - - // Build headpage - $this->headpage = new $this->headpageClass($this->parseXML($this->listXMLPath)); - $this->headpage->setFilter($filter); - $this->headpage->setParent($this); - - // Add copy&paste and snapshot handler. - if (!$this->skipCpHandler) { - $this->cpHandler = new CopyPasteHandler(); - $this->headpage->setCopyPasteHandler($this->cpHandler); - $this->registerAction('copy', 'copyPasteHandler'); - $this->registerAction('cut', 'copyPasteHandler'); - $this->registerAction('paste', 'copyPasteHandler'); - } - if (!self::$skipSnapshots && ($config->get_cfg_value('enableSnapshots') == 'TRUE')) { - $this->snapHandler = new SnapshotHandler(); - $this->headpage->setSnapshotHandler($this->snapHandler); - $this->registerAction('snapshot', 'createSnapshotDialog'); - $this->registerAction('restore', 'restoreSnapshotDialog'); - } - - // Register default actions - $this->registerAction('new', 'newEntry'); - $this->registerAction('edit', 'editEntry'); - $this->registerAction('apply', 'applyChanges'); - $this->registerAction('save', 'saveChanges'); - - $this->registerAction('cancel', 'cancelEdit'); - $this->registerAction('cancelDelete', 'cancelEdit'); - - $this->registerAction('remove', 'removeEntryRequested'); - $this->registerAction('removeConfirmed', 'removeEntryConfirmed'); - - $this->configureHeadpage(); - $this->configureFilter(); - if ($this->baseMode === FALSE) { - $this->headpage->setBase($config->current['BASE']); - } - } - - /* Build the action menu, fill the object definition, etc, based on objectTypes info */ - function configureHeadpage () - { - if ($this->autoActions) { - if (static::$skipTemplates) { - $this->headpage->xmlData['actionmenu']['action'][0]['action'] = []; - } else { - $this->headpage->xmlData['actionmenu']['action'][0]['action'] = [ - [ - 'type' => 'sub', - 'image' => 'geticon.php?context=devices&icon=template&size=16', - 'label' => _('Template'), - 'action' => [], - ], - [ - 'type' => 'sub', - 'image' => 'geticon.php?context=actions&icon=document-new&size=16', - 'label' => _('From template'), - 'action' => [], - ], - ]; - } - } - $this->configureHeadline(); - foreach ($this->objectTypes as $object) { - $i = objects::infos($object); - - if (!isset($i['icon'])) { - trigger_error('Missing icon for type '.$object); - $i['icon'] = ''; - } - - $filterObject = objects::getFilterObject($object); - $this->headpage->objectTypes[$object] = - [ - 'label' => $i['name'], - 'category' => $i['aclCategory'], - 'class' => $i['mainTab'], - 'image' => $i['icon'], - 'filter' => $filterObject, - 'nameAttr' => $i['nameAttr'], - ]; - if (!static::$skipTemplates) { - $this->headpage->objectTypes['template_'.$object] = - [ - 'label' => sprintf(_('%s template'), $i['name']), - 'category' => $i['aclCategory'], - 'class' => 'template', - 'image' => 'geticon.php?context=devices&icon=template&size=16', - 'filter' => - new ldapFilter( - '&', - [ - new ldapFilterLeaf('objectClass', '=', 'fdTemplate'), - fdTemplateFilter($filterObject), - ] - ), - 'nameAttr' => $i['nameAttr'], - ]; - } - $this->headpage->categories[] = $i['aclCategory']; - if ($this->autoActions) { - $this->registerAction('new_'.$object, 'newEntry'); - $icon = 'geticon.php?context=actions&icon=document-new&size=16'; - if (isset($i['icon'])) { - $icon = $i['icon']; - } else { - $infos = pluglist::pluginInfos($i['mainTab']); - if (isset($infos['plIcon'])) { - $icon = $infos['plIcon']; - } - } - $this->headpage->xmlData['actionmenu']['action'][0]['action'][] = [ - 'name' => 'new_'.$object, - 'type' => 'entry', - 'image' => $icon, - 'label' => $i['name'], - 'acl' => $i['aclCategory'].'/'.$i['mainTab'].'[c]', - ]; - if (!static::$skipTemplates) { - $this->registerAction('new_template_'.$object, 'newEntryTemplate'); - $this->registerAction('template_apply_'.$object, 'newEntryFromTemplate'); - $this->headpage->xmlData['actionmenu']['action'][0]['action'][0]['action'][] = [ - 'name' => 'new_template_'.$object, - 'type' => 'entry', - 'image' => $icon, - 'label' => $i['name'], - 'acl' => $i['aclCategory'].'/template[c]', - ]; - $this->headpage->xmlData['actionmenu']['action'][0]['action'][1]['action'][] = [ - 'name' => 'template_apply_'.$object, - 'type' => 'entry', - 'image' => $icon, - 'label' => $i['name'], - 'acl' => $i['aclCategory'].'/'.$i['mainTab'].'[c]', - ]; - } - } - } - if ($this->autoActions && !static::$skipTemplates) { - $this->registerAction('template_apply', 'newEntryFromTemplate'); - } - $this->headpage->refreshBasesList(); - } - - function configureHeadline () - { - $pInfos = pluglist::pluginInfos(get_class($this)); - $this->headpage->headline = $pInfos['plShortName']; - } - - function configureFilterCategory () - { - $pInfos = pluglist::pluginInfos(get_class($this)); - $cat = NULL; - if (isset($pInfos['plCategory'])) { - $cat = key($pInfos['plCategory']); - if (is_numeric($cat)) { - $cat = $pInfos['plCategory'][$cat]; - } - } elseif (isset($pInfos['plObjectType'])) { - $ot = key($pInfos['plObjectType']); - if (is_numeric($ot)) { - $ot = $pInfos['plObjectType'][$ot]; - } - $infos = objects::infos($ot); - $cat = $infos['aclCategory']; - } - if ($cat === NULL) { - trigger_error('Could not find a category for '.get_class($this)); - } - $this->filter->category = $cat; - } - - /* Build the filter(s) based on objectTypes info */ - function configureFilter () - { - if ($this->autoFilter) { - $this->configureFilterCategory(); - $attributes = $this->autoFilterAttributes; - $filter = '(|'; - foreach ($this->objectTypes as $object) { - $tag = 'FILTER'.$object; - $filter .= '$'.$tag; - $i = objects::infos($object); - $this->filter->elements[$tag] = [ - 'type' => 'checkbox', - 'tag' => $tag, - 'default' => TRUE, - 'unset' => [], - 'set' => preg_replace('/\$/', '\\\$', $i['filter']) - ]; - $this->filter->elementValues[$tag] = TRUE; - - if ($i['mainAttr']) { - $attributes[] = $i['mainAttr']; - } - if ($i['nameAttr']) { - $attributes[] = $i['nameAttr']; - } - } - if (!static::$skipTemplates) { - $tag = 'FILTERTEMPLATE'; - $filter .= '$'.$tag; - $this->filter->elements[$tag] = [ - 'type' => 'checkbox', - 'tag' => $tag, - 'default' => TRUE, - 'unset' => [], - 'set' => '(objectClass=fdTemplate)' - ]; - $this->filter->elementValues[$tag] = TRUE; - - $attributes[] = 'fdTemplateField'; - } - $filter .= ')'; - $attributes = array_values(array_unique($attributes)); - $this->filter->query[0]['filter'] = '(&'.$filter.'$NAME)'; - $this->filter->query[0]['attribute'] = $attributes; - $this->filter->elements['NAME']['set'] = '(|('.join('=*$*)(', $attributes).'=*$*))'; - $this->filter->elements['NAME']['autocomplete']['filter'] = '(&'.$filter.'(|('.join('=*$NAME*)(', $attributes).'=*$NAME*))'.')'; - $this->filter->elements['NAME']['autocomplete']['attribute'] = $attributes; - uasort($this->filter->elements, 'strlenSort'); - $this->filter->elements = array_reverse($this->filter->elements); - } - } - - function parseXML ($file) - { - $contents = file_get_contents($file); - $data = xml::xml2array($contents, 1); - foreach (['departmentBrowser','departmentRootVisible','baseMode','multiSelect'] as $var) { - $data['list']['definition']["$var"] = ($this->$var ? 'true' : 'false'); - } - return $data; - } - - function getHeadpage () - { - return $this->headpage; - } - - function getFilter () - { - return $this->filter; - } - - /*! - * \brief Set a new filter - * - * \param object $filter The new filter - */ - function setFilter ($filter) - { - $this->filter = $filter; - } - - /*! - * \brief Every click in the list user interface sends an event - * here can we connect those events to a method. - * eg. see simpleManagement::registerEvent('new','createUser') - * When the action/event new is send, the method 'createUser' - * will be called. - */ - function registerAction ($action, $target) - { - $this->actions[$action] = $target; - } - - function getType ($dn) - { - return $this->getHeadpage()->getType($dn); - } - - function renderList () - { - global $config; - $smarty = get_smarty(); - $filters = []; - foreach ($this->objectTypes as $object) { - $filters[] = [ - 'id' => 'FILTER'.$object, - 'label' => sprintf(_('Show %s'), $config->data['OBJECTS'][$object]['name']) - ]; - } - if (!static::$skipTemplates) { - $filters[] = [ - 'id' => 'FILTERTEMPLATE', - 'label' => sprintf(_('Show %s'), _('Template')) - ]; - } - $smarty->assign('objectFilters', $filters); - $this->headpage->update(); - $display = $this->headpage->render(); - return $this->getHeader().$display; - } - - /*! - * \brief Execute this plugin - * Handle actions/events, locking, snapshots, dialogs, tabs,... - */ - function execute () - { - // Ensure that html posts and gets are kept even if we see a 'Entry islocked' dialog. - $vars = ['/^act$/','/^listing/','/^PID$/']; - session::set('LOCK_VARS_TO_USE', $vars); - - /* Display the copy & paste dialog, if it is currently open */ - $ret = $this->copyPasteHandler(); - if ($ret) { - return $this->getHeader().$ret; - } - - // Update filter - if ($this->filter) { - $this->filter->update(); - session::set(get_class($this).'_filter', $this->filter); - session::set('autocomplete', $this->filter); - if (!$this->filter->isValid()) { - msg_dialog::display(_('Filter error'), _('The filter is incomplete!'), ERROR_DIALOG); - } - } - - // Handle actions (POSTs and GETs) - $str = $this->handleActions($this->detectPostActions()); - if ($str) { - return $this->getHeader().$str; - } - - /* Save tab or dialog object */ - if ($this->tabObject instanceOf simpleTabs) { - $this->tabObject->save_object(); - } elseif (is_object($this->dialogObject) && method_exists($this->dialogObject, 'save_object')) { - $this->dialogObject->save_object(); - } - - /* Display tab object */ - if ($this->tabObject instanceOf simpleTabs) { - $display = $this->tabObject->execute(); - $display .= $this->getTabFooter(); - return $this->getHeader().$display; - } - - /* Display dialog object */ - if (is_object($this->dialogObject) && method_exists($this->dialogObject, 'execute')) { - $display = $this->dialogObject->execute(); - $display .= $this->getTabFooter(); - return $this->getHeader().$display; - } - - // Display list - return $this->renderList(); - } - - /*! - * \brief Generates the plugin header which is displayed whenever a tab object is opened. - */ - protected function getHeader () - { - global $smarty; - - if ($this->skipHeader) { - return ''; - } - - $plInfos = pluglist::pluginInfos(get_class($this)); - $plTitle = $plInfos['plTitle']; - $plIcon = $plInfos['plIcon']; - - if (!preg_match('/^geticon/', $plIcon)) { - $plIcon = get_template_path($plIcon); - } - $smarty->assign('headline', $plTitle); - $smarty->assign('headline_image', $plIcon); - - if (is_object($this->tabObject) && ($this->dn != '')) { - return '<div class="pluginfo">'.$this->dn."</div>\n"; - } - return ''; - } - - /*! - * \brief Generates the footer which is used whenever a tab object is displayed. - */ - protected function getTabFooter () - { - // Do not display tab footer for non tab objects - if (!($this->tabObject instanceOf simpleTabs)) { - return ''; - } - - // Check if there is a dialog opened - We don't need any buttons in this case. - if ($this->tabObject->dialogOpened()) { - return ''; - } - - // Skip footer if requested; - if ($this->skipFooter) { - return ''; - } - - // In case an of locked entry, we may have opened a read-only tab. - $str = ''; - if ($this->tabObject->readOnly()) { - $str .= '<p class="plugbottom">'."\n". - '<input type="submit" formnovalidate="formnovalidate" name="edit_cancel" value="'.msgPool::cancelButton().'">'."\n". - '</p>'; - return $str; - } else { - // Display ok, (apply) and cancel buttons - $str .= '<p class="plugbottom">'."\n"; - $str .= '<input type="submit" name="edit_finish" style="width:80px" value="'.msgPool::okButton().'"/>'."\n"; - $str .= " \n"; - if ($this->displayApplyBtn) { - $str .= '<input type="submit" name="edit_apply" value="'.msgPool::applyButton().'"/>'."\n"; - $str .= " \n"; - } - $str .= '<input type="submit" formnovalidate="formnovalidate" name="edit_cancel" value="'.msgPool::cancelButton().'"/>'."\n"; - $str .= '</p>'; - } - return $str; - } - - /*! - * \brief This method intiates the object creation. - * - * \param String $action The name of the action which was the used as trigger. - * - * \param Array $target A list of object dns, which should be affected by this method. - * - * \param Array $all A combination of both 'action' and 'target'. - */ - function newEntry ($action, array $target, array $all) - { - $type = strtoupper(preg_replace('/^new_/', '', $action)); - - $this->displayApplyBtn = FALSE; - $this->dn = 'new'; - $this->is_single_edit = FALSE; - - // Open object - $this->openTabObject(objects::open($this->dn, $type)); - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dn, "Create new entry initiated!"); - } - - function newEntryTemplate ($action, array $target, array $all) - { - if (static::$skipTemplates) { - return; - } - $action = preg_replace('/^new_template_/', 'new_', $action); - $this->newEntry($action, $target, $all); - $this->tabObject->setTemplateMode('template_cn'); - } - - function newEntryFromTemplate ($action, array $target, array $all) - { - if (static::$skipTemplates) { - return; - } - if (isset($target[0])) { - $dn = $target[0]; - } else { - $dn = NULL; - } - if ($action == 'template_apply') { - if ($dn === NULL) { - return; - } - $type = $this->getType($dn); - $type = preg_replace('/^template_/', '', $type); - } else { - $type = preg_replace('/^template_apply_/', '', $action); - } - $this->dialogObject = new templateDialog($this, $type, $dn); - } - - function applyTemplateToEntry ($action, array $target, array $all) - { - global $ui; - if (static::$skipTemplates) { - return; - } - if (empty($target)) { - return; - } - $type = preg_replace('/^template_apply_to_/', '', $action); - $this->dns = $target; - - // check locks - if ($locks = get_locks($this->dns)) { - return gen_locked_message($locks, $this->dns); - } - - // Add locks - add_lock($this->dns, $ui->dn); - - $this->dn = array_shift($this->dns); - $this->dialogObject = new templateDialog($this, $type, NULL, $this->dn); - } - - function handleTemplateApply ($cancel = FALSE) - { - if (static::$skipTemplates) { - return; - } - if ($cancel) { - $msgs = []; - } else { - $msgs = $this->tabObject->save(); - } - if (count($msgs)) { - msg_dialog::displayChecks($msgs); - return; - } else { - if (!$cancel) { - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dn, 'Template applied!'); - } - del_lock($this->dn); - if (empty($this->dns)) { - $this->closeDialogs(); - } else { - $this->last_tabObject = $this->tabObject; - $this->tabObject = NULL; - $this->dn = array_shift($this->dns); - $this->dialogObject->setNextTarget($this->dn); - $this->dialogObject->save_object(); - } - } - } - - /*! - * \brief Save object modifications and closes dialogs (returns to object listing). - * - Calls 'simpleTabs::save' to save back object modifications (e.g. to ldap). - * - Calls 'simpleManagement::closeDialogs' to return to the object listing. - */ - protected function saveChanges () - { - if (($this->tabObject instanceOf simpleTabs) && ($this->dialogObject instanceOf templateDialog)) { - $this->tabObject->save_object(); - $this->handleTemplateApply(); - return; - } - if ($this->tabObject instanceOf simpleTabs) { - $this->tabObject->save_object(); - $msgs = $this->tabObject->save(); - if (count($msgs)) { - msg_dialog::displayChecks($msgs); - return; - } else { - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dns, 'Entry saved!'); - $this->remove_lock(); - $this->closeDialogs(); - } - } elseif ($this->dialogObject instanceOf simplePlugin) { - $this->dialogObject->save_object(); - $msgs = $this->dialogObject->check(); - if (count($msgs)) { - msg_dialog::displayChecks($msgs); - return; - } else { - $this->dialogObject->save(); - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dns, 'Entry saved!'); - $this->remove_lock(); - $this->closeDialogs(); - } - } - } - - /*! - * \brief Save object modifications and keep dialogs opened - */ - protected function applyChanges () - { - if ($this->tabObject instanceOf simpleTabs) { - $this->tabObject->save_object(); - $msgs = $this->tabObject->save(); - if (count($msgs)) { - msg_dialog::displayChecks($msgs); - } else { - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dns, 'Modifications applied!'); - $this->tabObject->re_init(); - } - } - } - - /*! - * \brief Editing an object was caneled. - * Close dialogs/tabs and remove locks. - */ - protected function cancelEdit () - { - if (($this->tabObject instanceOf simpleTabs) && ($this->dialogObject instanceOf templateDialog)) { - $this->handleTemplateApply(TRUE); - return; - } - $this->remove_lock(); - $this->closeDialogs(); - } - - /*! - * \brief This method opens an existing object or a list of existing objects to be edited. - * - * \param String $action The name of the action which was the used as trigger. - * - * \param Array $target A list of object dns, which should be affected by this method. - * - * \param Array $all A combination of both 'action' and 'target'. - */ - function editEntry ($action, array $target, array $all) - { - global $ui; - // Do not create a new tabObject while there is already one opened, - // the user may have just pressed F5 to reload the page. - if (is_object($this->tabObject)) { - return; - } - - $this->displayApplyBtn = (count($target) == 1); - - // Single edit - we only got one object dn. - if (count($target) == 1) { - $type = $this->getType($target[0]); - if ($type === NULL) { - trigger_error('Could not find type for '.$target[0].', open canceled'); - return; - } - if (preg_match('/^template_/', $type) && !static::$skipTemplates) { - $type = preg_replace('/^template_/', '', $type); - } - - $this->is_single_edit = TRUE; - - // Get the dn of the object and creates lock - $this->dn = array_pop($target); - if ($locks = get_locks($this->dn, TRUE)) { - return gen_locked_message($locks, $this->dn, TRUE); - } - add_lock($this->dn, $ui->dn); - - // Open object - $this->openTabObject(objects::open($this->dn, $type)); - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dn, "Edit entry initiated!"); - if (isset($all['subaction']) && !$this->handleSubAction($all)) { - trigger_error('Was not able to handle subaction: '.$all['subaction']); - } - } - } - - /*! - * \brief Detects actions/events send by the ui - * and the corresponding targets. - */ - function detectPostActions () - { - if (!is_object($this->headpage)) { - trigger_error("No valid headpage given....!"); - return []; - } - $action = $this->headpage->getAction(); - if (isset($_POST['edit_cancel'])) { - $action['action'] = 'cancel'; - } elseif (isset($_POST['edit_finish'])) { - $action['action'] = 'save'; - } elseif (isset($_POST['edit_apply'])) { - $action['action'] = 'apply'; - } - if (!$this->is_modal_dialog()) { - if (isset($_POST['delete_confirmed'])) { - $action['action'] = 'removeConfirmed'; - } - if (isset($_POST['delete_cancel'])) { - $action['action'] = 'cancelDelete'; - } - } - - return $action; - } - - /*! - * \brief Calls the registered method for a given action/event. - */ - function handleActions ($action) - { - // Start action - if (isset($this->actions[$action['action']])) { - $func = $this->actions[$action['action']]; - if (!isset($action['targets'])) { - $action['targets'] = []; - } - return $this->$func($action['action'], $action['targets'], $action); - } - } - - protected function handleSubAction ($all) - { - if (preg_match('/^tab_/', $all['subaction'])) { - $tab = preg_replace('/^tab_/', '', $all['subaction']); - if (isset($this->tabObject->by_object[$tab])) { - $this->tabObject->current = $tab; - } else { - trigger_error('Unknown tab: '.$tab); - } - return TRUE; - } - return FALSE; - } - - function openTabObject ($object) - { - $this->tabObject = $object; - $this->tabObject->parent = &$this; - } - - /*! - * \brief This method closes dialogs - * and cleans up the cached object info and the ui. - */ - public function closeDialogs () - { - $this->last_dn = $this->dn; - $this->dn = ""; - $this->last_dns = $this->dns; - $this->dns = []; - - $this->last_tabObject = $this->tabObject; - $this->tabObject = NULL; - $this->last_dialogObject = $this->dialogObject; - $this->dialogObject = NULL; - - $this->skipFooter = FALSE; - } - - /*! - * \brief Removes ldap object locks created by this class. - * Whenever an object is edited, we create locks to avoid - * concurrent modifications. - * This locks will automatically removed here. - */ - function remove_lock () - { - if (!empty($this->dn) && $this->dn != "new") { - del_lock($this->dn); - } - if (count($this->dns)) { - del_lock($this->dns); - } - } - - function is_modal_dialog () - { - return (is_object($this->tabObject) || is_object($this->dialogObject)); - } - - /*! \brief Queue selected objects to be removed. - * Checks ACLs, Locks and ask for confirmation. - */ - protected function removeEntryRequested ($action, array $target, array $all) - { - global $ui; - $disallowed = []; - $this->dns = []; - - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $target, "Entry removal requested!"); - - // Check permissons for each target - foreach ($target as $dn) { - $type = $this->getType($dn); - if (preg_match('/^template_/', $type) && !static::$skipTemplates) { - $type = preg_replace('/^template_/', '', $type); - } - try { - $info = objects::infos($type); - $acl = $ui->get_permissions($dn, $info['aclCategory'].'/'.$info['mainTab']); - if (preg_match('/d/', $acl)) { - $this->dns[] = $dn; - } else { - $disallowed[] = $dn; - } - } catch (NonExistingObjectTypeException $e) { - trigger_error("Unknown object type received :".$e->getMessage()); - } - } - if (count($disallowed)) { - msg_dialog::display(_('Permission'), msgPool::permDelete($disallowed), INFO_DIALOG); - } - - // We've at least one entry to delete. - if (count($this->dns)) { - - // check locks - if ($locks = get_locks($this->dns)) { - return gen_locked_message($locks, $this->dns); - } - - // Add locks - $objects = []; - foreach ($this->dns as $dn) { - $type = $this->getType($dn); - if (preg_match('/^template_/', $type) && !static::$skipTemplates) { - $type = preg_replace('/^template_/', '', $type); - $info = objects::infos($type); - $info['mainAttr'] = 'cn'; - } else { - $info = objects::infos($type); - } - $entry = $this->getHeadpage()->getEntry($dn); - $objects[] = [ - 'name' => $entry[$info['mainAttr']][0], - 'dn' => $dn, - 'icon' => $info['icon'], - 'type' => $info['name'] - ]; - } - add_lock($this->dns, $ui->dn); - - // Display confirmation dialog. - $smarty = get_smarty(); - $smarty->assign('objects', $objects); - $smarty->assign('multiple', TRUE); - return $smarty->fetch(get_template_path('simple-remove.tpl')); - } - } - - function removeEntryConfirmed ($action, array $target, array $all) - { - global $ui; - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $target, "Entry removal confirmed!"); - - foreach ($this->dns as $dn) { - $type = $this->getType($dn); - if (empty($type)) { - continue; - } - if (preg_match('/^template_/', $type) && !static::$skipTemplates) { - $type = preg_replace('/^template_/', '', $type); - } - $infos = objects::infos($type); - // Check permissions, are we allowed to remove this object? - $acl = $ui->get_permissions($dn, $infos['aclCategory']."/".$infos['mainTab']); - if (preg_match("/d/", $acl)) { - // Delete the object - $this->dn = $dn; - $this->openTabObject(objects::open($this->dn, $type)); - $this->tabObject->delete(); - - // Remove the lock for the current object. - del_lock($this->dn); - } else { - msg_dialog::display(_('Permission error'), msgPool::permDelete($dn), ERROR_DIALOG); - logging::log('security', 'simpleManagement/'.get_class($this), $dn, [], 'Tried to trick deletion.'); - } - } - - // Cleanup - $this->remove_lock(); - $this->closeDialogs(); - } - - /*! - * \brief Opens the snapshot creation dialog for the given target. - * - * \param String $action The name of the action which was the used as trigger. - * - * \param Array $target A list of object dns, which should be affected by this method. - */ - function createSnapshotDialog ($action, array $target) - { - global $config, $ui; - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $target, 'Snapshot creation initiated!'); - - if (count($target) == 1) { - $this->dn = array_pop($target); - if (empty($this->dn)) { - return; - } - $aclCategory = $config->data['OBJECTS'][$this->getType($this->dn)]['aclCategory']; - if ($ui->allow_snapshot_create($this->dn, $aclCategory)) { - $this->dialogObject = new SnapshotCreateDialog($this->dn, $this, $aclCategory); - } else { - msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to create a snapshot for %s.'), $this->dn), - ERROR_DIALOG); - } - } - } - - /*! - * \brief Displays the "Restore snapshot dialog" for a given target. - * If no target is specified, open the restore removed object - * dialog. - * \param String $action The name of the action which was the used as trigger. - * - * \param Array $target A list of object dns, which should be affected by this method. - */ - function restoreSnapshotDialog ($action, array $target) - { - global $config, $ui; - // Set current restore base for snapshot handling. - if (is_object($this->snapHandler)) { - $bases = []; - foreach ($this->storagePoints as $sp) { - $bases[] = $sp.$this->headpage->getBase(); - } - } - - // No bases specified? Try base - if (!count($bases)) { - $bases[] = $this->headpage->getBase(); - } - - if (!count($target)) { - // No target, open the restore removed object dialog. - $this->dn = $this->headpage->getBase(); - $aclCategories = $this->headpage->categories; - } else { - // Display the restore points for a given object. - $this->dn = $target[0]; - if (empty($this->dn)) { - return; - } - $aclCategories = [$config->data['OBJECTS'][$this->getType($this->dn)]['aclCategory']]; - } - - if ($ui->allow_snapshot_restore($this->dn, $aclCategories, !count($target))) { - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $this->dn, 'Snapshot restoring initiated!'); - $this->dialogObject = new SnapshotRestoreDialog($this->dn, $this, !count($target), $aclCategories); - } else { - msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to restore a snapshot for %s.'), $this->dn), - ERROR_DIALOG); - } - } - - /*! \brief This method is used to queue and process copy&paste actions. - * Allows to copy, cut and paste mutliple entries at once. - * @param string $action The name of the action which was the used as trigger. - * @param array $target A list of object dns, which should be affected by this method. - * @param array $all A combination of both 'action' and 'target'. - */ - function copyPasteHandler ($action = '', array $target = [], array $all = []) - { - global $ui; - // Return without any actions while copy&paste handler is disabled. - if (!is_object($this->cpHandler)) { - return FALSE; - } - - // Save user input - $this->cpHandler->save_object(); - - // Add entries to queue - if (($action == 'copy') || ($action == 'cut')) { - $this->cpHandler->cleanup_queue(); - foreach ($target as $dn) { - $type = $this->getType($dn); - if (preg_match('/^template_/', $type) && !static::$skipTemplates) { - $type = preg_replace('/^template_/', '', $type); - } - $infos = objects::infos($type); - - if (($action == 'copy') && $ui->is_copyable($dn, $infos['aclCategory'])) { - $this->cpHandler->add_to_queue($dn, 'copy', $type); - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Entry copied!'); - } - if (($action == 'cut') && $ui->is_cutable($dn, $infos['aclCategory'], $infos['mainTab'])) { - $this->cpHandler->add_to_queue($dn, 'cut', $type); - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Entry cut!'); - } - } - } - - // 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()) { - $data = $this->cpHandler->execute(); - 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; - $this->cpHandler->resetPaste(); - } - return ""; - } - - /* Methods related to Snapshots */ - - /*! - * \brief Creates a new snapshot entry - */ - function createSnapshot ($dn, $description) - { - global $ui; - if ($this->dn !== $dn) { - trigger_error('There was a problem with the snapshot workflow'); - return; - } - if (!empty($dn) && $ui->allow_snapshot_create($dn, $this->dialogObject->aclCategory)) { - $this->snapHandler->createSnapshot($dn, $description); - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snapshot created!'); - } else { - msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to restore a snapshot for %s.'), $dn), - ERROR_DIALOG); - } - } - - /*! - * \brief Restores a snapshot object. - * - * \param String $dn The DN of the snapshot - */ - function restoreSnapshot ($dn) - { - global $ui; - if (!empty($dn) && $ui->allow_snapshot_restore($dn, $this->dialogObject->aclCategory, $this->dialogObject->global)) { - $this->snapHandler->restoreSnapshot($dn); - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snapshot restored'); - $this->closeDialogs(); - } else { - msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to restore a snapshot for %s.'), $dn), - ERROR_DIALOG); - } - } - - function getSnapshotBases () - { - $bases = []; - foreach ($this->storagePoints as $sp) { - $bases[] = $sp.$this->headpage->getBase(); - } - - // No bases specified? Try base - if (!count($bases)) { - $bases[] = $this->headpage->getBase(); - } - - return $bases; - } - - /*! - * \brief Get all deleted snapshots - */ - function getAllDeletedSnapshots () - { - $bases = $this->getSnapshotBases(); - $tmp = []; - foreach ($bases as $base) { - $tmp = array_merge($tmp, $this->snapHandler->getAllDeletedSnapshots($base)); - } - return $tmp; - } - - /* - * \brief Return available snapshots for the given base - * - * \param string $dn The DN - */ - function getAvailableSnapsShots ($dn) - { - return $this->snapHandler->getAvailableSnapsShots($dn); - } - - /*! - * \brief Delete a snapshot - * - * \param string $dn DN of the snapshot - */ - function removeSnapshot ($dn) - { - global $ui; - if (!empty($dn) && $ui->allow_snapshot_delete($dn, $this->dialogObject->aclCategory)) { - $this->snapHandler->removeSnapshot($dn); - @DEBUG(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'Snapshot deleted'); - } else { - msg_dialog::display(_('Permission'), sprintf(_('You are not allowed to delete a snapshot for %s.'), $dn), - ERROR_DIALOG); - } - } - - static function mainInc ($classname) - { - global $remove_lock, $cleanup, $display; - - /* Remove locks */ - if ($remove_lock && session::is_set($classname)) { - $macl = session::get($classname); - $macl->remove_lock(); - } - - if ($cleanup) { - /* Clean up */ - session::un_set($classname); - } else { - if (!session::is_set($classname) || (isset($_GET['reset']) && $_GET['reset'] == 1)) { - /* Create the object if missing or reset requested */ - $managementObject = new $classname(); - } else { - /* Retrieve the object from session */ - $managementObject = session::get($classname); - } - /* Execute and display */ - $display = $managementObject->execute(); - - /* Store the object in the session */ - session::set($classname, $managementObject); - } - } -} diff --git a/include/simpleplugin/class_simpleSelectManagement.inc b/include/simpleplugin/class_simpleSelectManagement.inc deleted file mode 100644 index fb03870ed40040ace71e5e2b9fc3f36835e57066..0000000000000000000000000000000000000000 --- a/include/simpleplugin/class_simpleSelectManagement.inc +++ /dev/null @@ -1,88 +0,0 @@ -<?php -/* - This code is part of FusionDirectory (http://www.fusiondirectory.org/) - Copyright (C) 2013-2016 FusionDirectory - - 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/*! - * \brief Management base class for selection dialogs - */ -class simpleSelectManagement extends simpleManagement -{ - protected $skipFooter = TRUE; - protected $skipHeader = TRUE; - - protected $skipCpHandler = TRUE; - protected $autoActions = FALSE; - - public static $skipSnapshots = TRUE; - - protected $departmentRootVisible = FALSE; - - function __construct () - { - if ($this->listXMLPath === NULL) { - $this->listXMLPath = get_template_path('simple-select-list.xml', TRUE, dirname(__FILE__)); - } - - parent::__construct(); - } - - /* Build the action menu, fill the object definition, etc, based on objectTypes info */ - function configureHeadpage () - { - parent::configureHeadpage(); - $this->headpage->registerElementFilter("selectLink", "simpleSelectManagement::filterSelectLink"); - } - - function configureFilter () - { - parent::configureFilter(); - if ($this->autoFilter) { - $this->filter->query['0']['backend'] = 'LDAPBlacklist'; - } - } - - function configureHeadline () - { - } - - function configureFilterCategory () - { - $infos = objects::infos($this->objectTypes[0]); - $this->filter->category = $infos['aclCategory']; - } - - static function filterSelectLink () - { - if (func_num_args() < 4) { - return ' '; - } - $pid = func_get_arg(0); - $row = func_get_arg(1); - $dn = func_get_arg(2); - $trans = func_get_arg(3); - if (is_array($trans)) { - $trans = $trans[0]; - } - if ($trans != '') { - return '<a href="?plug='.$_GET['plug'].'&PID='.$pid.'&act=listing_select_'.$row.'&add_finish=1" title="'.htmlentities($dn, ENT_COMPAT, 'UTF-8').'">'.htmlentities($trans, ENT_COMPAT, 'UTF-8').'</a>'; - } - - return ''; - } -} diff --git a/include/simpleplugin/simple-filter.xml b/include/simpleplugin/simple-filter.xml deleted file mode 100644 index 511a01af00e6145753a0cd171810250a3bb10994..0000000000000000000000000000000000000000 --- a/include/simpleplugin/simple-filter.xml +++ /dev/null @@ -1,36 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<filterdef> - <definition> - <category>noneyet</category> - <template>simple-filter.tpl</template> - <initial>true</initial> - </definition> - - <search> - <query> - <backend>LDAP</backend> - <filter>FILTER</filter> - <attribute>dn</attribute> - <attribute>cn</attribute> - </query> - <scope>auto</scope> - </search> - - <element> - <type>textfield</type> - <tag>NAME</tag> - <size>20</size> - <default></default> - <unset></unset> - <set>FILTER</set> - <autocomplete> - <backend>LDAP</backend> - <filter>FILTER</filter> - <attribute>cn</attribute> - <attribute>description</attribute> - <frequency>0.5</frequency> - <characters>3</characters> - </autocomplete> - </element> -</filterdef> diff --git a/include/simpleplugin/simple-list.xml b/include/simpleplugin/simple-list.xml deleted file mode 100644 index 84c2fb784a68eb6b17103e38d0ab5caaf7dd01ed..0000000000000000000000000000000000000000 --- a/include/simpleplugin/simple-list.xml +++ /dev/null @@ -1,130 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<list> - <definition> - <departmentBrowser>true</departmentBrowser> - <departmentRootVisible>true</departmentRootVisible> - <baseMode>true</baseMode> - <multiSelect>true</multiSelect> - <template>simple-list.tpl</template> - <module>simple</module> - <label>NO LABEL</label> - <defaultSortColumn>1</defaultSortColumn> - </definition> - - <table> - <layout>|20px;c|||150px;r|</layout> - - <department> - <value>%{filter:departmentType(row,dn)}</value> - </department> - - <department> - <value>%{filter:departmentLink(row,dn,description)}</value> - <span>3</span> - </department> - - <column> - <value>%{filter:objectType(row,dn)}</value> - </column> - - <column> - <label>Name</label> - <sortAttribute>cn</sortAttribute> - <sortType>string</sortType> - <value>%{filter:nameLink(row,dn)}</value> - <export>true</export> - </column> - - <column> - <label>Description</label> - <sortAttribute>description</sortAttribute> - <sortType>string</sortType> - <value>%{filter:link(row,dn,"%s",description)}</value> - <export>true</export> - </column> - - <column> - <label>Actions</label> - <value>%{filter:actions(dn,row,objectClass)}</value> - </column> - - </table> - - <actionmenu> - - <action> - <type>sub</type> - <image>geticon.php?context=actions&icon=document-new&size=16</image> - <label>Create</label> - <acl>[c]</acl> - </action> - - <action> - <name>edit</name> - <type>entry</type> - <image>geticon.php?context=actions&icon=document-edit&size=16</image> - <label>Edit</label> - <acl>[r]</acl> - </action> - - <action> - <name>remove</name> - <type>entry</type> - <image>geticon.php?context=actions&icon=edit-delete&size=16</image> - <label>Remove</label> - <acl>[d]</acl> - </action> - - <action> - <type>separator</type> - </action> - - <action> - <type>exporter</type> - </action> - - <action> - <type>separator</type> - </action> - - <action> - <type>copypaste</type> - </action> - - <action> - <type>snapshot</type> - </action> - - </actionmenu> - - <actiontriggers snapshot="true" copypaste="true"> - - <action> - <name>cp</name> - <type>copypaste</type> - </action> - - <action> - <name>edit</name> - <type>entry</type> - <image>geticon.php?context=actions&icon=document-edit&size=16</image> - <label>Edit</label> - </action> - - <action> - <name>snapshot</name> - <type>snapshot</type> - </action> - - <action> - <name>remove</name> - <type>entry</type> - <image>geticon.php?context=actions&icon=edit-delete&size=16</image> - <acl>%acl[d]</acl> - <label>Remove</label> - </action> - - </actiontriggers> - -</list> diff --git a/include/simpleplugin/simple-select-list.xml b/include/simpleplugin/simple-select-list.xml deleted file mode 100644 index 788cd2103af553fafd444ce387a69cbf968b87af..0000000000000000000000000000000000000000 --- a/include/simpleplugin/simple-select-list.xml +++ /dev/null @@ -1,54 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<list> - <definition> - <departmentBrowser>true</departmentBrowser> - <departmentRootVisible>true</departmentRootVisible> - <baseMode>true</baseMode> - <multiSelect>true</multiSelect> - <template>simple-select-list.tpl</template> - <module>simple</module> - <label>Please select the desired entries</label> - <defaultSortColumn>1</defaultSortColumn> - </definition> - - <table> - <layout>|20px;c|||</layout> - - <department> - <value>%{filter:departmentType(row,dn)}</value> - </department> - - <department> - <value>%{filter:departmentLink(row,dn,description)}</value> - <span>2</span> - </department> - - <column> - <value>%{filter:objectType(row,dn)}</value> - </column> - - <column> - <label>Name</label> - <sortAttribute>cn</sortAttribute> - <sortType>string</sortType> - <value>%{filter:selectLink(pid,row,dn,cn)}</value> - <export>true</export> - </column> - - <column> - <label>Description</label> - <sortAttribute>description</sortAttribute> - <sortType>string</sortType> - <value>%{filter:selectLink(pid,row,dn,description)}</value> - <export>true</export> - </column> - </table> - - <actionmenu> - </actionmenu> - - <actiontriggers snapshot="false" copypaste="false"> - </actiontriggers> - -</list> diff --git a/plugins/admin/departments/dep-list.xml b/plugins/admin/departments/dep-list.xml deleted file mode 100644 index 86cf577d32f8e615f7eb1968b61b585b9aec9633..0000000000000000000000000000000000000000 --- a/plugins/admin/departments/dep-list.xml +++ /dev/null @@ -1,93 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<list> - <definition> - <baseMode>true</baseMode> - <multiSelect>true</multiSelect> - <template>simple-list.tpl</template> - <module>departments</module> - <label>List of departments</label> - <defaultSortColumn>1</defaultSortColumn> - </definition> - - <table> - <layout>|20px;c|||70px;r|</layout> - - <column> - <value>%{filter:objectType(row,dn)}</value> - </column> - - <column> - <label>Department</label> - <sortAttribute>ou</sortAttribute> - <sortType>string</sortType> - <value>%{filter:depLabel(row,dn,"%s",ou,pid,base)}</value> - <export>true</export> - </column> - - <column> - <label>Description</label> - <sortAttribute>description</sortAttribute> - <sortType>string</sortType> - <value>%{filter:depLabel(row,dn,"%s",description,pid,base)}</value> - <export>true</export> - </column> - - <column> - <label>Actions</label> - <value>%{filter:actions(dn,row,objectClass)}</value> - </column> - - </table> - - <actionmenu> - - <action> - <type>sub</type> - <image>geticon.php?context=actions&icon=document-new&size=16</image> - <label>Create</label> - </action> - - <action> - <type>separator</type> - </action> - - <action> - <type>exporter</type> - </action> - - <action> - <type>separator</type> - </action> - - <action> - <name>remove</name> - <type>entry</type> - <image>geticon.php?context=actions&icon=edit-delete&size=16</image> - <label>Remove</label> - </action> - - </actionmenu> - - <actiontriggers snapshot="false" copypaste="false"> - - <action> - <name>edit</name> - <type>entry</type> - <nospan></nospan> - <image>geticon.php?context=actions&icon=document-edit&size=16</image> - <label>Edit</label> - </action> - - <action> - <name>remove</name> - <type>entry</type> - <nospan></nospan> - <image>geticon.php?context=actions&icon=edit-delete&size=16</image> - <acl>department[d]</acl> - <label>Remove</label> - </action> - - </actiontriggers> - -</list>